Atualmente, estou lidando com um sistema de combate multiplayer em que o dano causado pelos jogadores é sempre multiplicado por um fator aleatório entre 0,8 e 1,2.
Em teoria, um RNG verdadeiramente aleatório pode eventualmente render o mesmo número muitas vezes (veja o dilema de Tetris ). Isso pode resultar em uma partida em que o jogador está sempre causando dano muito alto, enquanto o outro sempre causa dano muito baixo.
O que posso fazer para garantir que isso não aconteça? Alguns RNGs são melhores que outros em evitar repetições?
algorithm
multiplayer
random
Usuário não encontrado
fonte
fonte
Respostas:
Você pode resolvê-lo da mesma maneira que o Tetris, fazendo uma lista predefinida dos resultados dos danos e embaralhando.
Digamos que você saiba que o jogador causará 0,8x a 1,2x de dano com uma distribuição linear. Veja a lista [0.8, 0.9, 1.0, 1.1, 1.2]. Embaralhe aleatoriamente , para obter, por exemplo, [1.2, 1.0, 0.8, 0.9, 1.1].
A primeira vez que o jogador causa dano, ele causa 1.2x. Então 1x. Então, etc, para 1.1x. Somente quando a matriz estiver vazia , você deverá gerar e embaralhar uma nova matriz.
Na prática, você provavelmente desejará fazer isso com mais de 4 matrizes de uma só vez (por exemplo, comece com [0.8,0.8,0.8,0.8,0.9,0.9,0.9,0.9, ...]). Caso contrário, o período da sequência é baixo o suficiente para que os jogadores possam descobrir se o próximo golpe é "bom" ou não. (Embora isso também possa adicionar mais estratégia ao combate, como na tabela Hoimi de Dragon Quest IX , que as pessoas descobriram como investigar observando os números de cura e ajustando até garantir uma queda rara.)
fonte
Na verdade, eu escrevi algum código para fazer isso . A essência disso é usar estatísticas para corrigir riscos infelizes. A maneira de fazer isso é acompanhar quantas vezes o evento ocorreu e usá-lo para influenciar o número gerado pelo PRNG.
Em primeiro lugar, como acompanhamos a porcentagem de eventos? A maneira ingênua de fazer isso seria manter todos os números já gerados na memória e calculá-los em média: o que funcionaria, mas é terrivelmente ineficiente. Depois de pensar um pouco, criei o seguinte (que é basicamente uma média móvel acumulada ).
Pegue as seguintes amostras de PRNG (onde procuramos se a amostra for> = 0,5):
Observe que cada valor contribui para 1/5 do resultado final. Vejamos de outra maneira:
Observe que
0
contribui com 50% do valor e1
contribui com 50% do valor. Levado um pouco mais longe:Agora, os primeiros valores contribuem com 66% do valor e os últimos 33%. Podemos basicamente destilar isso até o seguinte processo:
Agora precisamos polarizar o resultado do valor amostrado no PRNG, porque estamos buscando uma porcentagem de chance aqui, as coisas são muito mais fáceis (em comparação, digamos, quantidades aleatórias de dano em um RTS). Isso vai ser difícil de explicar, porque "apenas me ocorreu". Se a média for menor, significa que precisamos aumentar a chance do evento ocorrer e vice-versa. Então, alguns exemplos
Agora, o que 'me ocorreu' é que, no primeiro exemplo, 83% eram apenas "0,5 de 0,6" (em outras palavras, "0,5 de 0,5 mais 0,1"). Em termos de eventos aleatórios, isso significa:
Portanto, para gerar um evento, você basicamente usaria o seguinte código:
E, portanto, você recebe o código que eu coloquei na essência. Tenho certeza de que tudo isso pode ser usado no cenário de caso de dano aleatório, mas não tomei tempo para descobrir isso.
Isenção de responsabilidade: estas são todas as estatísticas caseiras, não tenho formação em campo. Meus testes de unidade passam embora.
fonte
samples
em seu valor máximo (neste caso, 100) desde o início. Dessa forma, não são necessárias 99 iterações para o RNG se estabilizar. De qualquer forma, a única desvantagem que posso ver com esse método é que ele não garante justiça, simplesmente garante uma média constante.total = (average / 2) + desired
.O que você está pedindo é, na verdade, o oposto da maioria dos PRNGs, uma distribuição não linear. Basta colocar algum tipo de lógica de retorno decrescente em suas regras, supondo que tudo acima de 1,0x seja algum tipo de "golpe crítico", apenas diga que a cada rodada suas chances de conseguir um crítico aumentam por X, até que você consiga um em Nesse ponto, eles são redefinidos para Y. Em seguida, você faz duas jogadas a cada rodada, uma para determinar a crítica ou não, e outra para a magnitude real.
fonte
Sid Meier fez um excelente discurso no GDC 2010 sobre esse tópico e os jogos do Civilization. Vou tentar encontrar e colar o link mais tarde. Em essência - aleatoriedade percebida não é a mesma coisa que aleatoriedade verdadeira. Para fazer as coisas parecerem justas, você precisa analisar os resultados anteriores e prestar atenção à psicologia dos jogadores.
Evite riscos de má sorte a todo custo (se os dois turnos anteriores tiverem azar, o próximo deve ter a sorte). O jogador deve ter sempre mais sorte do que o adversário da IA.
fonte
Use um viés de mudança
A distribuição geral será influenciada pela seguinte fórmula:
O efeito aqui é que quandob for positivo, o número resultante será inclinado para 1 1 . Quandob for negativo, o número resultante será inclinado para 0 0 .
Pegue esse número e dimensione-o adequadamente para o intervalo desejado.
Cada vez que um jogador rola favoravelmente, subtraia o viés. Cada vez que o jogador rola desfavoravelmente, aumenta o viés. A quantia alterada pode ser dimensionada de acordo com a (des) favorável que a rolagem é ou pode ser uma quantia fixa (ou uma combinação). Você precisará ajustar valores específicos para se adequar à sensação que deseja.
fonte