Eu acho que essa pergunta se refere mais a jogos como MMO e jogos do tipo Diablo.
Quais são os designs usuais para implementar uma tabela suspensa, onde um monstro pode soltar tipos diferentes de itens, dependendo de uma porcentagem? Eu acho que a maneira mais simples de se ter um dicionário de 'porcentagem de peso' para os tipos de itens, mas isso é difícil de estender se queremos introduzir novos tipos de itens (por exemplo, quando a expansão D2 inclui runas e novos itens de classe)
game-design
rpg
Extrakun
fonte
fonte
Respostas:
Para um roguelike em que eu estava trabalhando, implementei um sistema orientado a dados bastante flexível para gerar quedas. Eu documentei aqui . É essencialmente um pouco DSL para selecionar vários itens escolhidos aleatoriamente.
Uma gota simples se parece com:
Diz apenas para soltar um número aleatório de moedas de cobre entre 1 e 10. As coisas ficam mais flexíveis quando você adiciona galhos:
Um "um de" seleciona um de seus ramos filhos com base nas probabilidades fornecidas e avalia isso. Gotas podem soltar mais de um item:
Isso avaliará todas as sub-filiais e as descartará se passar uma rolagem contra sua probabilidade. Existem também alguns outros ramos para selecionar um item com base no nível da masmorra e do jogador.
Como elas podem se tornar complexas, também permite definir macros nomeadas, essencialmente funções que expandem uma expressão de ramificação e podem ser reutilizadas em várias descargas. Dessa forma, se, por exemplo, todos os anões descartam o mesmo tipo de pilhagem, é possível criar uma única macro para isso e usá-la em todos esses tipos de monstros, em vez de copiar e colar grandes tabelas de descarte.
Um exemplo da queda de um monstro :
Aqui,
(coins)
,(any-weapon)
, e(any-armor)
são todas as chamadas de macro:que por sua vez chama coisas como:
Você pode aninhar expressões de descarte arbitrariamente profundamente como uma linguagem de programação real. Isso fornece a composição que uma abordagem simples baseada em tabela não oferece.
Como todos os sistemas orientados a dados, você pode se sobrecarregar criando quedas impenetrávelmente complexas, mas ele atende aos meus objetivos:
O código C # que implementa isso está aqui .
fonte
Em Stendhal, nossas tabelas de itens são listas. Cada entrada contém o nome do item, uma quantidade mínima e máxima e a probabilidade. A estrutura interna é muito semelhante à que exibimos na página da criatura .
É importante para nós que os designers de jogos que têm um grande conhecimento do mundo possam definir essas coisas. Ou seja, sem entender a lógica complexa no nível do código do programa. Portanto, não temos as definições de criaturas e itens no código do programa, mas as movemos para arquivos .xml, como elves.xml ou club.xml . Nós temos um editor de GUI para eles, mas a maioria dos designers de jogos modifica o arquivo .xml diretamente.
Para tornar as criaturas e itens facilmente extensíveis, usamos um sistema de blocos de construção: Não há classe de programa para "elfo" ou "elfo arqueiro". Mas existem várias classes relacionadas ao comportamento, como "covarde", "patrulha", "agressivo", "arqueiro", "curandeiro". Designers podem definir novas criaturas selecionando esses comportamentos sem escrever o código do programa: Por exemplo, para criar um "elfo arqueiro" desenhe um sprite elfo com um arco e defina-o como "ofensivo", "arqueiro". Em seguida, defina atributos de nível e similares e adicione alguns itens élficos à tabela de itens.
Para itens, temos uma abordagem semelhante, mas atualmente limitada a um comportamento: um designer pode adicionar um novo item e definir um comportamento como "Item de consumo", "Item de chave" ou "Item de ataque", "Feitiço", "Rolagem" sem ter que programar lógica.
fonte
Nos jogos de mesa de D&D, existe um conceito de tipos de pilhagem. A maioria dos monstros cairá de uma ou mais das tabelas e essas tabelas seriam o que você atualizaria em sua expansão. Os monstros ainda descartariam "65% comuns, 10% gemas, 15% art, 10% ferramentas", mas você atualizaria o que havia em cada uma dessas tabelas.
por exemplo, Gems contém slots com intervalos aleatórios que retornam "1 gema (25%) 2 gemas (50%) 5 gemas (75%) 100 gemas". e quando você quiser adicionar gemas rúnicas especiais, atualize a tabela para "1 gema (25%) 2 gemas (50%) 5 gemas (75%) 100 gemas (95%) 1 runegem".
Mas, por outro lado, se você já possui um percentual de ponderação, por que não atualizar todas as tabelas de monstros em sua expansão? Certamente tabelas como esta são pequenas cargas úteis em comparação com texturas e malhas. Além disso, você também não precisa manter as porcentagens calculando até 100, isso é apenas uma suposição que você fez para começar e pode contabilizar o total real antes de gerar seu valor aleatório. Se as ponderações somam 120, basta gerar um valor de 1-120 em vez de 1-100.
fonte
Na superfície, isso parece o mesmo que o problema da "seleção aleatória ponderada".
Algoritmo para determinar eventos aleatórios
Aloque probabilidades relativas a cada evento, some-as e escolha um número aleatório dentro desse intervalo para decidir qual evento você deseja.
Mesmo se você preferir usar porcentagens - que é o mesmo sistema, apenas escalado para 100 - você está superestimando a dificuldade de adicionar coisas. Se você possui 100% e depois adiciona 20% em uma expansão, basta dividir todos os valores por (120/100) e você volta ao total de 100%.
fonte