Quero gerar uma sequência de números para gerar planetas proceduralmente em um setor de galáxias. Cada planeta deve ser colocado aleatoriamente, no entanto, é muito improvável que dois planetas estejam diretamente próximos um do outro. Como posso conseguir isso?
Eu sei que você pode modificar as chances aplicando uma função de distribuição, mas como posso controlá-las para tornar valores específicos mais ou menos prováveis?
mathematics
procedural-generation
random
API-Beast
fonte
fonte
Respostas:
Se você conhece a distribuição que deseja, pode usar a amostragem por rejeição .
Maneira mais simples: no gráfico acima, escolha pontos aleatoriamente até encontrar um abaixo da curva. Em seguida, basta usar o
x
-coordenate.Para a distribuição real, existem várias abordagens plausíveis. Por exemplo, para o número do planeta
i
no localp
e alguns parâmetros de forçak
(por exemplo0.5
), defina uma funçãof_i(x)=abs(p-x)^k
e use a função de distribuiçãog(x)=f_1(x)*f_2(x)*...*f_n(x)
.Na prática, calcule e armazene os resultados de
g(x)
para arrayt
(t[x]=g(x)
); lembre-se do valor mais alto vistoh
também. Escolher uma posição aleatóriax
not
, escolher um valor aleatórioy
entre0
eh
, repetiçãoif y>t[x]
; caso contrário, o valor de retorno éx
.fonte
Não tenho certeza de que o problema esteja totalmente especificado pela pergunta, mas posso fornecer algumas idéias simples, a segunda delas fornecerá números aproximadamente de acordo com o que sua imagem indica que você deseja.
De qualquer maneira, como você pode perceber, a função de distribuição está mudando após cada número gerado e possui uma memória (isto é: não é markoviana ) e qualquer um desses métodos pode ser impraticável quando a 'memória' (número de números previamente sorteados) é muito grande.
Simples:
Gere números aleatórios a partir de uma distribuição plana, compare com números previamente desenhados e repita se estiver "muito próximo"
Esta resposta é mais parecida com a sua figura (supondo que desejemos desenhar de 0..1):
as caixas de terminais são um caso especial, mas deve ser simples o suficiente para você ver como lidar com elas.
fonte
Pense na diferença entre 1 dado e 3 dados . 1 dado fornece uma probabilidade uniforme para todos os valores, enquanto 3 dados tendem a ter uma probabilidade maior para os valores no meio.
Quanto mais "dados" na sua equação, maior a sua chance de conseguir algo em direção ao centro. Então, vamos definir uma função que possa lidar com qualquer número uniformemente :
Agora podemos definir um exemplo de função para usar isso:
Agora, o primeiro a observar é que esse código realmente não verifica se o selecionador já corresponde a um dos pontos. Se isso acontecer, simplesmente não irá gerar um ponto, possivelmente algo que você possa gostar.
Para explicar o que está acontecendo aqui, o CenterRandom gera uma espécie de curva de sino. Essa função divide o plano em várias curvas de sino, uma por par de pontos existentes. O selecionador nos diz de qual curva de sino gerar. Como escolhemos linearmente, podemos garantir que os pares com intervalos maiores sejam escolhidos com mais frequência, mas ainda o deixamos completamente aleatório.
Espero que isso aponte a direção certa.
fonte
Sei que você está perguntando sobre uma sequência de posições aleatórias, mas se você não está restrito a gerar o conjunto sequencialmente, há outra abordagem: gerar um conjunto de pontos com o espaçamento desejado.
O que eu acho que você deseja é um conjunto de planetas razoavelmente espaçados com alguma aleatoriedade. Em vez de gerar posições do planeta com um gerador de números aleatórios, gere o espaçamento do planeta com um gerador de números aleatórios. Isso permitirá que você controle diretamente a distribuição do espaçamento, usando um gerador de números aleatórios que escolhe essa distribuição. Isso é direto em uma dimensão.
Em duas dimensões, vi algumas abordagens que geram "ruído azul", mas não sei como gerar espaçamento com uma distribuição arbitrária. Este artigo aborda a abordagem padrão "tente colocá-lo e rejeite se estiver muito próximo", mas você pode gerá-los todos de uma vez, com uma solução "mais suave", colocando todos os seus pontos e, em seguida, usando o Lloyd Relaxation para mover todos os planetas para mais posições desejáveis. Isso afastará os planetas muito próximos. Wang Recursive Tiles é outra abordagem que pode ser útil. Este papelestende o problema para gerar planetas com uma densidade e algum outro objeto como asteróides com outra densidade. Você também pode gerar ruído azul usando a série Fourier; Não tenho certeza. A abordagem da série Fourier também permite que você use distribuições arbitrárias em vez de apenas ruído azul.
fonte