(RPGs) Design de tabela suspensa


18

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)


4
Por que é difícil estender dicionários de porcentagem ao adicionar novos itens? Quero dizer, se você não precisa ter todas as porcentagens para fazer uma soma de 100% (e é o caso apenas se você quiser que um monstro sempre solte um único item, o que é bastante estranho para mim), não vejo uma problema.
N 30rd

1
Diga Orc => {'punhal', 'espada' 'armadura'} e eu tenho um novo tipo de item, diga runa; Vou ter que atualizar todos os dicionários associados a cada tipo de monstro diretamente. Claro, isso não é nada que outra camada de indireção não possa resolver. Então a pergunta é: como é que essa camada se parece?
Extrakun

Não sei por que você acha difícil atualizar um dicionário. No Python, estender um dicionário com novos valores é feito com um único método, por exemplo. Você poderia esclarecer onde acha que está a dificuldade?
Kylotan

2
Extrakun, se você der uma olhada na minha resposta abaixo, há uma resposta para a sua pergunta "outra camada de indireção". Em vez de tratar as gotas como uma tabela plana, você pode construí-las a partir de expressões aninhadas. Se você permitir macros nomeadas (ou seja, funções), poderá reutilizar pedaços de uma tabela suspensa em diferentes entidades.
munificent

2
Você acabou de se deparar com o 'problema' do desenvolvimento de jogos. Claro, você pode fazer um jogo em dois dias, mas depois vêm os cinco anos de adição de conteúdo. E adicionar conteúdo é difícil. ESMERILHAMENTO.
Tor Valamo

Respostas:


22

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:

1-10 copper coin

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:

one of
    turquoise stone (50%)
    onyx stone (25%)
    malachite stone (15%)
    jade stone (10%)

Um "um de" seleciona um de seus ramos filhos com base nas probabilidades fornecidas e avalia isso. Gotas podem soltar mais de um item:

any of
    turquoise stone (50%)
    onyx stone (25%)
    malachite stone (15%)
    jade stone (10%)

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 :

:: ancient dragon
    glyph   = D
    groups  = dragon
    drops
        (coins)
        2-3(1:8) one of
            (any-weapon)
            (any-armor)

Aqui, (coins), (any-weapon), e (any-armor)são todas as chamadas de macro:

(any-armor)
    one of
        (shield)
        (helm)
        (boots)
        (gloves)
        (cloak)
        (robe)
        (soft-armor)
        (hard-armor)

que por sua vez chama coisas como:

(cloak)
    one near level
        cloak (10)
        velvet cloak (20)
        fur-lined cloak (50)

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:

  1. Ser capaz de especificar quais coisas são descartadas completamente fora do código.
  2. Simples de implementar o sistema principal em código.
  3. Seja capaz de ajustar o que monstros específicos deixam cair para que o jogador possa fazer uma exploração orientada a objetivos. ("Eu preciso de um colar. Vou procurar anões, pois eles tendem a largá-los.")

O código C # que implementa isso está aqui .


Esta é uma implementação que eu não vi antes. Obrigado!
Extrakun

12

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.


8

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.


3

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%.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.