Como implementar os “cartões de efeitos especiais” do jogo de cartas colecionáveis?

16

Estou tentando escrever uma espécie de jogo de cartas colecionáveis ​​aqui, de alguma forma, é semelhante ao Magic The Gathering , ou ao Yu-Gi-Oh! jogo de cartas.

Para aqueles que não estão familiarizados com isso, basicamente, no jogo, existe um tipo especial de carta (cartas de feitiço / armadilha / etc.), que têm efeitos especiais que podem alterar as regras do jogo. O que eu totalmente não tenho idéia é como implementar a lógica desses cartões. Eu tenho uma idéia de armazenar os dados do cartão com alguns sinalizadores que podem sinalizar que tipo de habilidade ele possui, mas isso seria muito limitado no que ele pode fazer (apenas algumas modificações simples nas estatísticas, talvez).

Para ter uma idéia de que tipo de efeito essas cartas podem ter, aqui está um exemplo dos efeitos da carta de feitiço que estão presentes no Yu-Gi-Oh! jogo de cartas:

  • Reviva uma criatura que foi destruída
  • Assuma o controle da criatura do oponente
  • Modifique as estatísticas da criatura com base em algumas condições (por exemplo, número de criaturas com certos nomes que foram destruídos)
  • Convoque especial certas criaturas se algumas condições forem cumpridas.
  • Funda duas ou mais criaturas em uma criatura mais forte.
  • Imunidade a alguns dos efeitos das cartas especiais.

A Konami criou vários videogames, completos com a variedade de IA e milhares de cartas. Eu não acho que é realmente possível codificar todo o banco de dados, é?

Agora, é claro que o que estou tentando fazer não é tão complexo quanto esses jogos, mas estou curioso, como eles os implementam?

hndr
fonte

Respostas:

17

Existem vários projetos de código aberto dessa natureza, com diferentes abordagens para implementar as regras. Aqui está uma entrada de blog do criador de uma das implementações mais conhecidas do MtG, o CardForge. Pode não ser uma lista completa, mas contém vários projetos de código aberto onde você pode simplesmente navegar pelo código ou visitar os fóruns para perguntas específicas.

Como resposta real: sua melhor aposta para uma estrutura robusta é empregar estritamente a programação orientada a objetos. Toda ação, todo gatilho, toda habilidade é um objeto. Zonas como Mão, Biblioteca também são objetos, escusado será dizer. No mecanismo de regras, nunca passe objetos burros, como cadeias ou números inteiros, para descrever objetos de jogos, mas apenas seus objetos.

Toda ação coloca um número de gatilhos em uma pilha, onde todas as outras habilidades podem verificar se eles se importam ou não com esse gatilho em particular e, se o fazem, eles disparam suas próprias ações, potencialmente criando novos gatilhos e assim por diante.

Então você trabalha essas pilhas de acordo com as regras do jogo, até que a pilha esteja vazia, momento em que novas ações podem ser tomadas etc.

Idealmente, se você implementar perfeitamente as regras do jogo, seu código de regras não conterá uma única placa codificada. Os cartões codificados permanentemente podem criar atalhos convenientes, mas, a longo prazo, isso inchará seu código e criará armadilhas potenciais, como quando novos cartões são lançados que interagem com esses cartões de uma maneira nova. Em um jogo como o MtG, com mais de 12.000 cards únicos e sem fim à vista, existem MUITAS interações.

Hackworth
fonte
1
Boa resposta. No mundo da programação funcional, eu gostaria que cada cartão fosse um fechamento sobre o ambiente do jogo, para ser ainda mais ridiculamente genérico. Por exemplo, um cartão pode criar de forma aceitável uma nova "Área" adicionando uma lista de cartões à lista de áreas. Concretamente: Zombie Monster Mayhem: Todas as criaturas derrotadas são revividas no novo "Cemitério Comunitário" sem suas habilidades especiais e atacam aleatoriamente um jogador com base no lançamento de dados.
Br26
Link adicional: github.com/Fluorohydride/ygopro-core para uma famosa implementação de YGO de código aberto, uma vez que o YGO também foi mencionado na pergunta.
SK19
2

É uma tarefa bastante fútil tentar incorporar tudo isso apenas com opções e variáveis. Você precisaria ter funções de código rígido ou, mais provavelmente, um script que você interpreta durante o tempo de execução. Você exporia as funções necessárias para verificar o status do quadro e dos decks e cemitérios ao script e às funções para executar ações e assim por diante. O script é então apenas uma string simples para armazenar junto com as outras variáveis ​​associadas ao cartão.

Toni
fonte
Ou, como sugeriu o hackworth, ter algum tipo de bloco comum que é combinado para obter o comportamento necessário. Isso exigiria alguns blocos lógicos, além do que ele sugeriu, eu acho. Ter blocos de comportamento compartilhados pode facilitar a filtragem de cards que tenham algum tipo de qualidades compartilhadas.
Toni
1

Também estou planejando jogos de cartas usando linguagens da web com o mysql db. Atualmente, estou optando por uma configuração muito genérica, para que ela seja muito flexível para novos cartões exclusivos. Por exemplo, em vez de:

reduceHitPoints() { } 
reduceMana() { }
reduceSpeed() { }

poderia ser facilmente:

reduce($attacker, $target, $reduceWhat, $amount) { }
massReduce($attacker, Array $targets, $reduceWhat, $amount) { }

A aplicação desse conceito a todas as ações simplificará as classes, permitindo a criação de novos cartões simplesmente adicionando uma única linha à sua tabela de cartões.

Todas as opções e habilidades serão definidas no banco de dados nessa única linha.

appthat
fonte