<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: FelipeRes</title>
    <description>The latest articles on DEV Community by FelipeRes (@feliperes).</description>
    <link>https://dev.to/feliperes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F509654%2F8c9d8bd0-0923-4fb5-ab42-e60678f9220c.png</url>
      <title>DEV Community: FelipeRes</title>
      <link>https://dev.to/feliperes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/feliperes"/>
    <language>en</language>
    <item>
      <title>Hermética TCG - Manual de Regras
</title>
      <dc:creator>FelipeRes</dc:creator>
      <pubDate>Sun, 06 Dec 2020 20:31:13 +0000</pubDate>
      <link>https://dev.to/hermetica/hermetica-tcg-manual-de-regras-168i</link>
      <guid>https://dev.to/hermetica/hermetica-tcg-manual-de-regras-168i</guid>
      <description>&lt;h1&gt;
  
  
  Hermética TCG - Manual de Regras
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Contexto
&lt;/h2&gt;

&lt;p&gt;Jogos de cartas colecionáveis existem a mais de um século, com o formato e estética de jogo sendo reformulado "recentemente" por Magic: The Gathering. A ideia de ter cartas com figuras de heróis ou criaturas e artefatos com os quais os jogadores possam se identificar é bem lucrativa e quase toda franquia famosa em algum momento lança o se próprio jogo de carta. Hearthstone trouxe em 2014 o conceito para o mundo digital logo no momento em que os jogos como serviço começaram a crescer e se expandir no mundo mobile. A ideia é a mesma: Ao invés de pacotes de cartas aleatórias físicas, os jogadores compram pacotes de cartas digitais, com a diferença de que é possível comprar o mesmo sem dinheiro, apenas dedicando horas e horas de gameplay. Logo esse formato foi adaptado até mesmo para outros generos de jogos com as mal faladas loot boxes e até mesmo em jogos de futebol como literalmente pacotes de figurinha no Fifa com a imagem de jogadores faamosos.&lt;/p&gt;

&lt;p&gt;No geral, jogos de carta são uma simulação bem abstrata de um combate, esporte e evento. Apesar de puxaram muitos conceitos de jogos de RPG, no geral eles tem regras bem definidas e um game design que favorece a estratégia e criativdidade, sem apelar para a interpretação. Magic mesmo é um jogo quase que puramente matemático, a não ser que você esteja jogando commander, né? Como simulações de eventos quase absurdos, normalmente os enredos que explicam o jogo são bem permissivos. Muitas vezes, nem explicação tem para o que está acontecendo, você ja consegue entender somente por causa do nome da franquia, como acontece com Yu-Gi-Oh! ou mesmo com Legends of Runeterra. Para esse último, eu nem precisei jogar ou conhecer League of Legends para me divertir com o jogo uma vez que apenas as regras, estratégia e desenhos das cartas eram suficientes para tal.&lt;/p&gt;

&lt;p&gt;Esse contexto nos leva a Hermética: Jogo que eu decidi criar tanto como um exercício de arquitetura de software como algo que talvez me renda algum dinheiro e também uma forma de contar histórias que não consigo porque tenho que trabalhar em outras coisas. Hermetica é um Trading Card Game assim como vários outros no mercado. Suas regras não são inovadoras e ele é bem simular a outros jogos digitais famosos. Claro, apesar de não precisar, eu criei um conceito de história para o jogo. &lt;/p&gt;

&lt;h2&gt;
  
  
  2. Conceito
&lt;/h2&gt;

&lt;p&gt;Em Hermética, as cartas são representações de ideias. O objetivo do jogador é manifestar essas ideias e tentar superar adversidades, e claro, tudo acontece no mundo das ideias. O processo de manifestação de ideias se dá em 4 estágios: &lt;/p&gt;

&lt;p&gt;1 - &lt;strong&gt;Mundo da Emanação&lt;/strong&gt;: Onde o jogador inicialmente sente vontade de jogar o jogo, começa a conhecer e entender as cartas e por fim aprende sobre as regras do jogo.&lt;/p&gt;

&lt;p&gt;2 - &lt;strong&gt;Mundo da Criação&lt;/strong&gt;: Nesse mundo, o jogador começa a se apropriar das cartas e compreender a sinergia que existe entre as mesmas. Assim ele irá construir os seu baralhos conforme suas próprias ideias e preferências do que ele quer manifestar.&lt;/p&gt;

&lt;p&gt;3 - &lt;strong&gt;Mundo da Formação&lt;/strong&gt;: O jogo de fato começa nesse mundo. Aqui o jogador já se encontra com seu baralho formado e com as cartas em mãos. As cartas em mãos são apenas uma pequena parte do que realmente está no baralho e chegam de forma aletória. Cabe ao jogador tomar as decisões corretas e decidir o que irá manifestar e quando.&lt;/p&gt;

&lt;p&gt;4 - &lt;strong&gt;Mundo da Manifestação&lt;/strong&gt;: Esse é o mundo ou literalmente o espaço físico onde as cartas são jogadas. Existem regras para que um jogador possa manifestar uma carta e todos o processo do mundo da criação até a manifestação é pensado nessas regras. Após manifestar suas ideias dentro desse mundo, o jogador deve argumentar com seu adversário(batalhar através das regras) para vencer o jogo. &lt;/p&gt;

&lt;h2&gt;
  
  
  3. Elementos do jogo
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 Cartas
&lt;/h3&gt;

&lt;p&gt;São obviamente o principal elemento do jogo. As cartas modificam o jogo pois possuem efeitos que se sobrepõem as mesmas descritas na propria carta. Diferente de outros jogos, em Hermética as cartas não possuem tipos. São apenas cartas. Elas possuem características que as diferenciam umas das outras, mas essas características podem ou não existir. Ou seja, existem cartas que tem descrição, outras que não. Existem cartas que possuem poder e vida, e cartas que não possuem. Durante o jogo, as cartas cartas podem ter todas suas características alteradas por algum efeito de carta. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fLhkbJHv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lu312u4ivq1k0z534g1n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fLhkbJHv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/lu312u4ivq1k0z534g1n.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caracterísitcas obrigratórias&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Nome&lt;/strong&gt;: Palavra ou frase que identifica a carta. Esse valor não pode ser nulo e não representa o nome original da carta. Se esse valor for alterado, cartas que possuem efeitos que apontam nomes de carta devem especificar se requisitam o &lt;em&gt;nome&lt;/em&gt; ou o &lt;em&gt;nome original&lt;/em&gt;. O &lt;em&gt;nome original&lt;/em&gt; é absolutamente fisico e não pode ser mudado por nenhum efeito de carta. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cor&lt;/strong&gt;: É a cor que fica ao redor da carta. Toda carta tem uma cor e não existem cartas transparentes. Qualquer cor pode existir, mas as cores básicas de se identificar serão as do espectro RGB: Preto, Cinza, Branco, Vermelho, Azul, Verde, Ciano, Magenta, Amarelo e mais algumas cores secundárias: Roxo, Lilás, Laranja.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Imagem&lt;/strong&gt;: A imagem da carta ocupa quase toda a área de visualização da carta e é unica para cada &lt;em&gt;nome original&lt;/em&gt; de carta. Assim como o nome original da mesma, ele não pode ser alterado.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Caracterísitcas opicionais&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Poder&lt;/strong&gt;: As cartas podem ter um número inteiro negativo ou positivo diferente de 0 que representa o seu poder e é usado em parâmetros de combate.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Vida&lt;/strong&gt;: As cartas podem ter um número inteiro negativo ou positivo diferente de 0 que representa o sua vida durante os combates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Tipo&lt;/strong&gt;: Essa característica é ambígua pois eu falei que as cartas não possuem tipo. O tipo aqui pode ser entendido apenas como uma tag que não afeta as regras do uso da carta, mas caracteriza a carta. As cartas podem ter até cinco tipos que podem ser qualquer coisa e são representados por um ícone e uma palavra. A palavra não é mostrada na carta, apenas o ícone. Haverá tabelas de ícones onde os jogadores possam identificar. Uma carta com o desenho de uma abelha, pode por exemplo, possuir o tipo &lt;em&gt;inseto&lt;/em&gt; e &lt;em&gt;abelha&lt;/em&gt;. Uma carta de um artesão pode por exemplo possuir os tipos &lt;em&gt;humano&lt;/em&gt; e &lt;em&gt;artesão&lt;/em&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Recurso Gerado&lt;/strong&gt;: Texto que explica os efeitos e recursos que a carta gera. Esse texto pode ser alterado por efeitos, mas o efeito real da carta não é alterado. O texto amarelo explica quantos recursos a carta gera por turno e o outro texto explica qual o seu efeito. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Requisitos de Invocação&lt;/strong&gt;: Cartas que possuem esse elemento não podem ser jogadas ao menos que o jogador consuma em campo os recursos ou outras cartas com características especificas que são descritos nesse campo. Esse campo não pode ter seu texto ou valor alterado por efeito de carta. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3.2 Campo
&lt;/h3&gt;

&lt;p&gt;É no campo onde o jogo acontece e é onde as cartas são jogadas e os recursos ficam alocados. O campo é dividido em duas partes, uma para cada jogador e elas ficam contrapostas uma a outra. Um jogador só pode jogar cartas em seu campo. As cartas jogadas devem ser posicionadas horizontalmente uma ao lado da outra. O baralho de cada jogador fica no lado mais esquerdo do campo. Os recuros ficam posicionados verticalmente abaixo das cartas. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OpOs9cwg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8yj9my8212mfpb6h4gim.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OpOs9cwg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/8yj9my8212mfpb6h4gim.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3.3 Recursos
&lt;/h3&gt;

&lt;p&gt;Recursos são elementos que ficam em campo e são representados por um ícone, genérico ou especifico e uma palavra. Recurso podem ter um valor inteiro, não negativo, não nulo, que representa a sua quantidade. Recursos são gerados apenas por cartas ou efeitos de carta e normalmente são usados como objeto de consumo para efeitos de carta ou manifestação das mesmas. Recursos podem ser por exemplo: &lt;em&gt;amor&lt;/em&gt;, &lt;em&gt;temperança&lt;/em&gt;, &lt;em&gt;dinheiro&lt;/em&gt;, &lt;em&gt;tinta&lt;/em&gt;, &lt;em&gt;poder&lt;/em&gt;, &lt;em&gt;água&lt;/em&gt;, &lt;em&gt;silicio&lt;/em&gt;... ou qualquer coisa  que é possível medir ou contar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jo3w_B2n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z1b0ylvhww86jt82p69q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jo3w_B2n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/z1b0ylvhww86jt82p69q.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Como jogar?
&lt;/h2&gt;

&lt;p&gt;Hermética é um jogo para dois jogadores que se alternam em turnos. Um jogador não pode interferir no turno do outro jogador. Um jogador deve declrar quando o seu turno começa para que o outro jogador possa começar. O jogador que irá começar o jogo é sorteado por qualquer algoritimo de sorteio ou mesmo jogos como como dados, moeda, jankenpon ou "impar ou par".&lt;/p&gt;

&lt;h3&gt;
  
  
  Durante seu turno, um jogador pode:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Jogar apenas uma carta sem requistos de manifestação cartas em seu campo&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Jogar quantas cartas com requisitos de manifestação ele puder jogar em seu campo&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ativar o efeito de uma carta em seu campo que não esteja dormindo&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gerar recursos com uma carta em seu campo que não esteja dormundo&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Declarar ataque a uma carta do oponente com uma carta sua que não esteja dormindo&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Declarar ataque a um recurso do oponente com uma carta que não esteja dormindo&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encerrar seu turno&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sequencia de ações:
&lt;/h3&gt;

&lt;p&gt;1 - Decide-se quem quem será o primeiro a jogar.&lt;br&gt;
2 - Os dois jogadores embaralham e posicionam seus baralhos no canto esquerdo de seu campo.&lt;br&gt;
2 - Cada jogador puxa de seu baralho 4 cartas.&lt;br&gt;
3 - Se o jogador estiver começando a sua vez, ele deve puxar uma carta de seu baralho.&lt;br&gt;
4 - O jogador pode realizar qualquer uma das ações descritas antes.&lt;br&gt;
5 - O jogador em algum momento deve encerrar seu turno.&lt;br&gt;
6 - Inicia a ação do proximo jogador voltando para a ação 3.&lt;/p&gt;

&lt;h3&gt;
  
  
  Condições de vitória e derrota
&lt;/h3&gt;

&lt;p&gt;Cada jogador começa com um recurso inicial chamado &lt;strong&gt;potencial&lt;/strong&gt; de quantidade 20. Esse recurso é o principal recurso do jogador. Se esse recurso acabar ou chegar a zero, ele perde o jogo imediatamente e o outro jogador ganha. Se os dois jogadores zerarem esse recurso ao mesmo tempo, é considerado um empate. &lt;/p&gt;

&lt;h3&gt;
  
  
  Sistema de combate
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hat33y83--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/65mi6vsoz5oq5ojdf5x9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hat33y83--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/65mi6vsoz5oq5ojdf5x9.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Qualquer carta pode entrar em combate, independete se ela tem ou não características de combate. O combate é realizado quando uma carta declara ataque a uma outra carta. Após o ataque, os pontos de poder e vida das cartas são alterados da seguinte forma:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;vida do atacante = vida do atacante - poder do atacado.&lt;/li&gt;
&lt;li&gt;vida do atacado = vida do atacado - poder do atacante. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O seja, quando uma carta declara ataque, ela é atacada de volta. A vida de uma carta é deduzida de seu atacando. Após declarar um ataque, tanto a carta atacante quanto a carta alvo começam a dormir. Quando a vida de uma carta se torna menor ou igual a zero e a carta está dormindo, a carta é removida do campo, recolocada no baralho e o mesmo é reembaralhado.&lt;/p&gt;

&lt;p&gt;Um jogador pode declarar ataque a um recurso e a quantidade do recurso será deduzida pelo ataque da carta. O recurso não ataca de volta a carta atacante, mas ela ainda dorme após o ataque.&lt;/p&gt;

&lt;h3&gt;
  
  
  O que significa dormir?
&lt;/h3&gt;

&lt;p&gt;As cartas possuem dois estados: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Acordada&lt;/strong&gt;: A carta está livre para declarar ataque, gerar recursos ou ativar efeitos. Se a carta realizar qualquer uma dessas ações, ela dorme logo após a conclusão da ação. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dormindo&lt;/strong&gt;: A carta não pode realizar qualquer ação, mas ainda pode ser alvo de efeito de carta, alvo de ataques e alvo de manifestação. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;obs: Como o jogo é digital, então a representação da carta dormindo mostra uma sombra escura sobre a mesma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SE UMA CARTA DORMINDO TEM SUA VIDA MENOR OU IGUAL A 0, ELA É REMOVIDA DO CAMPO, RECOLOCADA NO BARALHO E O BARALHO É REEMBARALHADO&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A regra acima tem vários desdobramentos, uma vez que nem toda carta tem vida. Se uma carta sem vida ativa seu efeito, ela é removida do campo após a conclusão do efeito. O mesmo vale para cartas com vida negativa. Se uma carta com vida é alvo de um efeito que zera a sua vida, ela não é removida do campo, mas se ela for alvo de ataque ou realziar qualquer ação que à faça dormir, ela será removida do campo. &lt;/p&gt;

&lt;p&gt;Quando um jogador declara o seu final de turno, todas suas cartas e as de seu oponente são acordadas imediatamente. &lt;/p&gt;

&lt;h3&gt;
  
  
  Regras automáticas e limitações
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Se uma carta é enviada do campo para o baralho, seja por qualquer motivo. Todas as suas caracterísiticas são resetadas para o seu estado original. &lt;/li&gt;
&lt;li&gt;Um jogador não pode declarar qualquer ataque em seu primeiro turno.&lt;/li&gt;
&lt;li&gt;Todo jogador deve puxar uma carta de seu baralho no começo do seu turno. Se ele não tiver cartas no baralho, ele deve seguir o jogo normalmente. &lt;/li&gt;
&lt;li&gt;Um baralho deve ter no mínimo 15 cartas que podem se repetir indefinidamente. &lt;/li&gt;
&lt;li&gt;O baralho é reembaralhado sempre que uma carta é adicionada ao mesmo ou quando uma carta é deliberadamente escolhida por algum efeito de carta.&lt;/li&gt;
&lt;li&gt;Efeitos de carta não são prolongados e são ativados imediatamente. Eles não presistem ao longo de turno e não podem ser ativados automaticamente. Eles somente são ativados pela decisão do jogador ou por outro efeito de carta. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Glossário de ações
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Manifestar&lt;/strong&gt;: Ato de colcoar uma carta de sua mão no campo. Esse ato só é considerado manifestar quando é feito pelas regras naturais do jogo e não por efeitos de carta.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Campo&lt;/strong&gt;: Local físico onde as cartas são posicionadas e onde há os marcadores de recurso.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dormir&lt;/strong&gt;: Estado da carta onde ela fica incapacitada de realziar qualquer ação.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apontar alvo&lt;/strong&gt;: Quando o jogador precisa de outras cartas para ativar efeitos, realizar manifestações ou declarar ataques, ele deve apontar quais cartas serão utilizadas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remover do campo&lt;/strong&gt;: Uma carta é removida do campo quando sua vida é menor ou igual a zero e ela está dormindo. Não confundir com enviar para o baralho. Toda carta removida do campo é automaticamente colocada no baralho.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Card Games Programming 1 - Game Core</title>
      <dc:creator>FelipeRes</dc:creator>
      <pubDate>Fri, 04 Dec 2020 23:42:28 +0000</pubDate>
      <link>https://dev.to/feliperes/card-games-programming-1-game-core-4e8h</link>
      <guid>https://dev.to/feliperes/card-games-programming-1-game-core-4e8h</guid>
      <description>&lt;p&gt;Develop a digital card game can be an interesting exercise for architecture software. You don't need to think about complex math algorithms and frame-accurate precision like action games unless you are creating a peculiar card game. I am talking about simple card games like UNO, Blackjack, or games with a complex game design like Magic and Yu-Gi-Oh! You can create a simple mechanic with some rules and have so much fun with a lot of tools, variations, and game modes that can be easily introduced procedurally during the game development. But it will work only if you create good software architecture.&lt;/p&gt;

&lt;p&gt;In this series of posts, I will explore a bit of how to create, improve, and maintain a complex card game like Magic, Hearthstone, and other digital games. I am creating my own card game called Hermetica and in the next posts, I will talk more about it. For while, let's get started with some fundamentals. &lt;/p&gt;

&lt;p&gt;A card game is essentially a turn-based game with the entities represented by cards. The most that I will show in this post is valid for other turn based games. By overview, we can split the game architecture in theses parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Game Core: The main API that control the game rules and players.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Action Request: The "input" of the game that can be queued and processed by the Game Core. It can be made by a player, a lot of players or IA system or automatically created by the game.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Log: The register of each event that happened in the game until the end.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Visual representation: Is about the graphics of the game and UI interaction. The application will run around the Game Core.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this post, let's get started with the concept of the &lt;strong&gt;Game Core.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Game Core is the main part of the card game software. It represents the main entities and the rules of the game. Imagine a game like chess: You have pieces with a moveset, a table with tiles zones, and the rules. The Game Core, in a software approach, doesn't know how the game will be shown to the player. It only offers an application interface to interaction and can represent the entities with poco class.&lt;/p&gt;

&lt;p&gt;The core needs to work without any dependency if possible. This is important to maintain portability if your game will be an online or multiplatform game and create unit tests can be easy too. &lt;/p&gt;

&lt;p&gt;Game Core API responsibilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Receive the player movement input by a request.&lt;/li&gt;
&lt;li&gt;Check if each movement request is valid.&lt;/li&gt;
&lt;li&gt;Apply the consequences of movement.&lt;/li&gt;
&lt;li&gt;Determinate when a plyers ends the turn and when the game ends.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's thinking in a simple card game like UNO and for while, let's forget the special cards. In this game, we have up to 10 players around a deck on a table with cards in their hands. One card is drawn from the deck and positioned on the table. The first player needs to play a card with the same color or the same number and finish your turn to the next player. You probably know the other rules, I am only listing the important information to modeling the game.&lt;/p&gt;

&lt;p&gt;Here is the code of poco classes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Card&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;hand&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;players&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="n"&gt;currentPlayer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your turn, the player automatically draws a card and can do only one movement in your turn that is to put one card face up in the top of a stack of cards. We can give him/her a function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Player&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;//...&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Drawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)){&lt;/span&gt;
            &lt;span class="n"&gt;hand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)){&lt;/span&gt;
            &lt;span class="n"&gt;hand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Game Core needs to know who is the current player and it can avoid the movement. But before, it needs to know how to change the player's turn and which one is the card on top of the stack. Let's write some functions to support the Game Core API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;//...&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;NextPlayer&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;

        &lt;span class="c1"&gt;//Tip to circular list&lt;/span&gt;
        &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddLast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;players&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RemoveFirst&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt; 

        &lt;span class="c1"&gt;//Assign the current player&lt;/span&gt;
        &lt;span class="n"&gt;currentPlayer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;players&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;First&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="c1"&gt;//Current player drawn the card automatically the &lt;/span&gt;
        &lt;span class="n"&gt;currentPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;deck&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RemoveFirst&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;//The game needs a easy way to get the card in top of stack&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="nf"&gt;StackCard&lt;/span&gt;&lt;span class="p"&gt;(){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Count&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;//The game needs to know if a card is valid to play&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;CorrectCard&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;StackCard&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; 
                  &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="nf"&gt;StackCard&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The function NextPlayer will runaways after a valid player movement request. And the functions StackCard and CorrectCard are helpers to clean the code and e easy setup. The function that the API uses to expose to application needs to know who is playing, witch card, the current player turn, and the current card on top of the stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;//...&lt;/span&gt;

    &lt;span class="c1"&gt;//This is the public API function to receive a player movement&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Card&lt;/span&gt; &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="c1"&gt;//Check if is the expected player turn&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;player&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;currentPlayer&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;

            &lt;span class="c1"&gt;//Check too if the card is valid to play&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;CorrectCard&lt;/span&gt;&lt;span class="p"&gt;()){&lt;/span&gt;

                &lt;span class="c1"&gt;//Do the drawn movement&lt;/span&gt;
                &lt;span class="n"&gt;currentPlayer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Play&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="c1"&gt;//stack receives the card&lt;/span&gt;
                &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="c1"&gt;//wait for the next player movement&lt;/span&gt;
                &lt;span class="nf"&gt;NextPlayer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Game Core needs to be clean and simple and needs to work in itself universe without dependencies. All other setups need to work around it  &lt;/p&gt;

&lt;p&gt;But it's just the beginning of the journey! Our game core can have a lot of other functionalities like throw exceptions to invalid movements, factory objects to set up the game cards, functions to check game design problems like when the cards over. All these ideas will be worked on in future posts.&lt;/p&gt;

&lt;p&gt;Thanks to read!&lt;/p&gt;

</description>
      <category>unity3d</category>
      <category>gamedev</category>
    </item>
    <item>
      <title>Card Games e Data-Driven</title>
      <dc:creator>FelipeRes</dc:creator>
      <pubDate>Sun, 08 Nov 2020 17:24:38 +0000</pubDate>
      <link>https://dev.to/feliperes/card-games-e-data-driven-48mb</link>
      <guid>https://dev.to/feliperes/card-games-e-data-driven-48mb</guid>
      <description>&lt;p&gt;&lt;strong&gt;Data-Driven&lt;/strong&gt; é uma abordagem muito comum no mundo do desenvolvimento de jogos. Ela permite que programadores e criadores de conteudo possam trabalhar de forma paralela e com bastante autonomia, contanto que respeitem os protocolos estabelecidos para os dois lados. A ideia aqui é simples: ao invés de compilar todo o projeto e solicitar uma atualização para seu jogador porque você precisa adicionar uma roupinha nova, o update pode ser apenas um novo arquivo baixado pelo jogo e guardado em algum lugar. &lt;/p&gt;

&lt;p&gt;Eu penso que a maior parte da graça dos jogos de carta em si são as cartas de fato e não exatamente suas regras. Jogos como &lt;strong&gt;Magic: The Gathering&lt;/strong&gt;, por exemplo, tiveram as regras refinadas por anos, mas o jogo só é interessante de se jogar se o projeto de design das cartas promover boas dinâmicas entre os jogadores, atendendo a suas espectativas e estilos pessoais. &lt;strong&gt;A Wizards of the Coast&lt;/strong&gt; atualmente mantém uma equipe de 20 pessoas que são responsáveis só pelo desenvolvimento e teste do jogo e as coleções são projetadas com 2 anos de antecedência. Para o jogador, isso evita as temidas Banned List e assegura uma melhor qualidade e saude para o jogo além de manter estável a economia da compra, venda e troca de cartas avulsas. &lt;/p&gt;

&lt;p&gt;Mas &lt;strong&gt;Magic: The Gathering&lt;/strong&gt; é essencialmente um jogo de cartas físico e apesar de possuir uma versão digital com &lt;strong&gt;Magic: The Gathering Arena&lt;/strong&gt;, existem propiedades e possibildades que somente um jogo físico pode promover. Uma das primeiras regras de Magic é que se a descrição de uma carta for contraditória as regras do jogo, os jogadores devem literalmente fazer o que está escrito na carta. Por exemplo, Goblin Game:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7tflgpyb2q6jezja5xwe.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7tflgpyb2q6jezja5xwe.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Resumidamente, os jogadores devem esconder o máximo de objetos que conseguirem e ao revelar os objetos simultaneamente, além de perderem vida igual a quantidade de objetos, o jogador que revelar menos irá perder metade da vida. Agora explica pro programador como ele vai implementar isso? Dá para abstrarir para uma versão resumida em computador, mas não é a mesma coisa da vida real. Além disso, existem cartas como Shahrazad:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffz7dzd82tjiszmdh3lyy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffz7dzd82tjiszmdh3lyy.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A não ser que a sua engine ou arquitetura dê suporte a multiplas instancias de jogo, este tipo de efeito é uma tremenda dor de cabeça não só para programadores como jogadores. Em &lt;strong&gt;Yu-Gi-Oh!&lt;/strong&gt;, há casos mais extremos como Yu-Jo Friendship:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi8ecso8f312kotuoxng5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi8ecso8f312kotuoxng5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Você deve oferecer um aperto de mão para seu oponente e se ele aceitar, os pontos de vida dos dois jogadores se tornam a média da soma dos dois?&lt;/p&gt;

&lt;p&gt;Esses são casos extremos e essas cartas normalmente são banidas do competitivo, mas a discursão que quero trazer aqui é como podemos computacionalmente implementar tanta variedade de efeitos de carta dentro de uma abordagem &lt;strong&gt;Data-Driven&lt;/strong&gt;. Vamos começar com o básico que é como representar as cartas em arquivos que poderão ser lidos pelo seu jogo.&lt;/p&gt;

&lt;p&gt;Os dois formatos de arquivo mais populares para representar dados são XML e JSON, muito utilizados em projetos web e para configurações de frameworks, cada um com suas vantagens e desvantagens, embora o JSON tenha ficado bem mais popular devido a popularização do javascript como liguagen de front-end, back-end e até desktop. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs7rwtfmaeasgq8ej7kvq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fs7rwtfmaeasgq8ej7kvq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;a href="https://xkcd.com/2327/" rel="noopener noreferrer"&gt;xkcd.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Outra abordagem é utilizar bancos de dado SQL e dependendo dos tipos de jogos, os dados ficam armazenados em bancos locais como SQLite e assim é possivel aproveitar as diversas ferramentas de consulta que é possivel fazer com SQL. Dentro dessa abordagem, basta uma atualização no banco para que novos conteúdos estejam disponíveis no banco.&lt;/p&gt;

&lt;p&gt;Ainda há uma terceira opção bem conhecida que é o uso de scripts em Lua. Se provavelmente você já ouviu que Lua é muito utilizada em jogos mas nunca viu uma aplicação prática, aguarde um momento que você entenderá porque Lua é uma das melhores opções e porque eu decidi não utilizá-la. &lt;/p&gt;

&lt;p&gt;Por fim, além de outros formatos mais obscuros, e é possivel criar seus próprios formatos de arquivo ou recorrer ao bom e velho txt. A desvantagem de se fazer isso seria ter que escrever seus próprios interpretadores e gerenciadores de arquivo o que pode ser custoso e difícil de se manter.&lt;/p&gt;

&lt;p&gt;Digamos que tenhamos um jogo de carta bem simples onde as cartas tem um id, nome, poder, descrição, tipo e uma imagem. Vamos agora representar cartas dentro dos diferentes formatos já citados e analisar cada uma das vantagens e desvantagens das implementações.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"The mighty cat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"power"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"This is the strongest cat in the multiverse"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Cat"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"2.png"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O JSON é de longe o formato mais legível e um dos mais compactos para se armazenar dados na forma de chave e valor. A maioria das linguagens dão suporte para conversão de JSON em objetos de alguma forma, e outras como javascript já o tem incorporado em sua própria sintaxe. Para jogos feitos em javascript, jogos online com servidor autoritativo ou que atualizam dados com um padrão REST este formato se torna ótimo para serialização. Além disso, ele é rápido para fazer consultas e ocupa pouco espaço de armazenamento se comparado com a maioria dos proximos exemplos. Porém nem todas as liguagens são amigaveis para esse padrão e pode não ser tão trivial realizar buscas, as vezes necessitando realizar muitos forloops para encontrar dados mais específicos.&lt;/p&gt;

&lt;h2&gt;
  
  
  XML
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;card&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;id&amp;gt;&lt;/span&gt;   2 &lt;span class="nt"&gt;&amp;lt;/id&amp;gt;&lt;/span&gt;  
    &lt;span class="nt"&gt;&amp;lt;name&amp;gt;&lt;/span&gt; The mighty cat &lt;span class="nt"&gt;&amp;lt;/name&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;power&amp;gt;&lt;/span&gt;10 &lt;span class="nt"&gt;&amp;lt;/power&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;description&amp;gt;&lt;/span&gt; This is the strongest cat in the multiverse &lt;span class="nt"&gt;&amp;lt;/description&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;type&amp;gt;&lt;/span&gt; Cat &lt;span class="nt"&gt;&amp;lt;/type&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;image&amp;gt;&lt;/span&gt;2.png&lt;span class="nt"&gt;&amp;lt;/image&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/card&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como primo mais velho do JSON, o XML era um formato muito popular antes da ascensão do javascript e por conta disso exitem muitas ferramentas consolidadas para utilizar. Seu formato é facilmente legível e ele é facilmente integrável com bancos de dados SQL além de ter ótimas ferramentas de busca como o XQuery que podem ser importante se seu jogo de cartas tiver mais de 1000 cartas únicas. Porém o XML gera um grande volume de texto e costuma ter buscas mais lentas o que pode impactar na performance uma vez que toda a estrutura de texto será convertida em uma arvore que fica armazenada em memória.&lt;/p&gt;

&lt;h2&gt;
  
  
  CSV
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;id,name,power,description,type,image
2,The mighty cat,10,This is the strongest cat in the multiverse,Cat,2.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Isso aqui é basicamente uma planilha exel, apesar de ser o formato mais compacto e fácil de se ler pois toda linguagem tem uma biblioteca para ler CSV(na maioria das vezes nativa), o ruim aqui é transformar esses dados em uma instância de objeto e o pior de tudo é fazer consultas. Você também precisaria criar suas próprias ferramentas de insersão, leitura e deleção de dados. &lt;/p&gt;

&lt;h2&gt;
  
  
  SQL
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="n"&gt;TALBE&lt;/span&gt; &lt;span class="s1"&gt;'cards'&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nb"&gt;UNSIGNED&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;power&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;image&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id)
);
INSERT INTO '&lt;/span&gt;&lt;span class="n"&gt;cards&lt;/span&gt;&lt;span class="s1"&gt;' VALUES("The mighty cat",10,"This is the strongest cat in the multiverse","Cat","2.png");
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bancos SQL e suas implementações mais simples como sqlite3 possui todo o arsenal necessário para criar, manter e gerenciar dados com padrões consolidados na indústria. Mas como você pode ver no exemplo acima, não é a coisa mais simples do mundo. Os dados em SQL são bem estruturados em arquivos binários então você não poderia aleterá-los apenas editando um arquivo de texto, embora inserir novos dados pode ser feito com uma simples linha de comando. Além disso, SQL pode guardar os registros de id de forma mais inteligente e tem de longe as melhores ferramentas de busca. Um possivel problema é que os dados em bancos SQL é sua rigidez com relação a mudança em comparação a exemplos anteriores. No exemplo acima, foi definido que o tipo "Cat" era apenas um texto, mas e se o jogo tiver uma quantidade de tipos bem definidos? Seria interessante ter uma tabela para tipo e até mesmo uma para image caso haja mais metadados. Caso seja necessário alterar estruturas de dados chaves estrangeiras, seria necessário um bom conhecimento e experiência em SQL para conseguir alterar tudo sem destruir os dados das cartas. &lt;/p&gt;

&lt;p&gt;Esse formato pode ser o mais custoso de se implementar em um primeiro momento, mas depois de feito, pode ser muito bem aproveitado embora sua portabilidade para plataformas como mobile e consoles possa ser problemática uma vez que implementações como postgresql e mysql costumam ser um servidor e muitas plataformas não permitiram a instalação de um banco de dados. Apesar de ser possivel implementar em arquivo local como sqlite3 ou via stream de dados, o sucesso do uso de bancos SQL irá depender muito do ambiente onde o jogo será disponibilzado.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lua Language
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;setId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;setName&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"The mighty cat"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;setPower&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;setDescription&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"This is the strongest cat in the multiverse"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;setType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Cat"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;card&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;setImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"2.png"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Como eu amo essa linguagem. Lua é uma linda pérola no mundo da programação pois ela permite exetender funcionalidades através arquivos de script externo, sem a necessidade de recompilar o projeto inteiro. Lembra que muitos sabem que ela é bastante usada em jogos, mas muitos não sabem como? Bom, imagine que você cria um RPG com diversos itens com efeitos buffs e nerfs varidos. &lt;/p&gt;

&lt;p&gt;Toda vez que você precisar criar um item novo como uma espada que aumenta seu ataque em 5%, você irá implementar um método novo para o item e recompilar todo o projeto? Não com Lua! Os scripts de Lua podem acompanhar o jogo externamente e se o jogo externaliza uma API para modificação, tudo pode ser feito em tempo de execução. O jogo carrega o script, interpreta a linguagem e roda as instruções nelas contidas. Ainda é possível usar condicionais, forloops e todas ferramentas que uma linguagem de programação normal teria, tudo de forma externa. &lt;/p&gt;

&lt;p&gt;Isso é ótimo para designers poderem testar o jogo sem a necessidade de acesso ao código fonte ou de compilar o jogo em si. Se você jogou jogos mais antigos de RPG no PC e fuçou seus arquivos ou mesmo já fez mods para jogos como &lt;strong&gt;Ragnarok&lt;/strong&gt; e &lt;strong&gt;Warcraft 3&lt;/strong&gt;, provavelmente já deve ter visto ou mexido em diversos scripts Lua nas pastas do jogo. &lt;/p&gt;

&lt;p&gt;Porém, apesar de ser compativel com diversas linguagens de programação, não é tão assegurado sua portabilidade para plataformas propietárias como IOS ou para consoles pois as vezes existem políticas para a leitura de arquivos locais que possam de alguma forma prejudicar o uso do jogo via hacking.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Real Problema
&lt;/h2&gt;

&lt;p&gt;A escolha da tecnologia usada para seu modelo &lt;strong&gt;Data-Driven&lt;/strong&gt; de jogo irá depender muito da plataforma que você deseja usar e da experiência que você e sua equipe possui com a tecnologia. Mas se seu card game utilizar do mesmo conceito de Magic, Yu-Gi-Oh!, Hearthstone, Pokemon TCG e tantos outros jogos similares, você irá cair no problema do efeito de carta.&lt;/p&gt;

&lt;p&gt;Como eu citei no começo do artigo, em card games físicos, as regras das cartas se sobrepoem as regras do jogo e com a adição a longo prazo de mais cartas ao jogo, não é possivel prever o que pode acontecer. Você pode tentar implementar cada efeito de carta como um método a ser chamado no jogo, mas isso necessitaría recompilar o jogo inteiro a cada nova carta adicionada além de nem toda linguagem facilitar a busca por nome de métodos implementados, sejam eles estáticos ou orientado a objetos. &lt;/p&gt;

&lt;p&gt;Eu não sei como grandes empresas realizam a implementação de seus card games, portanto irei citar como exemplo aqui o EDOPro, uma simulador de Yu-Gi-Oh! bem completo e atualizado e Forge, um simulador para Magic The Gathering. Ambos possuem seu código fonte no  GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  EDOPro
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff9yi0g5b7zjw0a0spd2z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ff9yi0g5b7zjw0a0spd2z.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Esse é a nova versão do ygopro, escrita em C++ e que é mantida por uma comunidade bem engajada, dando suporte até mesmo a partidas online e fugindo de possíveis processos da Konami. A ferramenta costuma ser utilizada por jogadores profissionais para montar e testar diferentes tipos de decks e estratégias antes de comprar as cartas de fato. &lt;/p&gt;

&lt;p&gt;EDOPro utiliza um banco de dados SQLite para guardar os dados das cartas que recebem um ID de seu criador e as cartas normalmente são criadas e atualizadas pela comunidade. Associados ao banco, há uma pasta no projeto do jogo com todas as imagens das cartas que recebem no nome, o mesmo ID das cartas no banco. Para os efeitos de carta, ainda há uma segunda pasta que contém todos os scripts em Lua para cada efeito de carta único dentro do jogo. &lt;/p&gt;

&lt;p&gt;O core do jogo em C++ disponibiliza para scripts Lua diversas funções genéricas para buscar, modificar e realizar jogadas. Dependendo da carta, o código em Lua pode ou não ficar complicado. Veja o exemplo do Pot of Greed, carta mágica que permite o jogador comprar duas cartas de seu deck:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight lua"&gt;&lt;code&gt;&lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;GetID&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nc"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;initial_effect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;--Activate&lt;/span&gt;
    &lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Effect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CreateEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SetCategory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;CATEGORY_DRAW&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SetType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EFFECT_TYPE_ACTIVATE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SetProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EFFECT_FLAG_PLAYER_TARGET&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SetCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EVENT_FREE_CHAIN&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SetTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;SetOperation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;RegisterEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nc"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;target&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;chk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chk&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Duel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsPlayerCanDraw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;Duel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetTargetPlayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;Duel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetTargetParam&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;Duel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetOperationInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;CATEGORY_DRAW&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="nc"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;activate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;tp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;eg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;ev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;re&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;rp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;local&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;Duel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetChainInfo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;CHAININFO_TARGET_PLAYER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;CHAININFO_TARGET_PARAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;Duel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Draw&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;REASON_EFFECT&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assim como Magic e outros card games, Yu-Gi-Oh! tem o conceito de pilha que o mesmo chama de corrente onde um efeito de carta pode ser disparado em resposta ao outro, normalmente neutralizando-o. A primeira função em lua aqui tem como objetivo configurar o jogo e prepará-lo para caso aconteça alguma efeito em resposta. A segunda função configura os parâmetros da ativação do efeito e caso seja necessário o jogador apontar os alvos do efeito, isso pode gerar ativar outros efeitos de corrente no jogo. Por fim, a ultima função é a ativação do efeito de fato. &lt;/p&gt;

&lt;p&gt;Como você pode imaginar, portar toda essa arquitetura para plataformas como Android pode ser quase que totalmente inviável. Houve ainda uma versão intitulada Yu-Gi-Oh! Pro 2 que era feita com Unity e usava C# em sua base de código base e teoricamente permitiria o port para Android, reaproveitando o mesmo banco de dados de carta, mas aparentemente essa versão foi descontinuada por conter muitos bugs e ser bem mais pesada e lenta que a original.&lt;/p&gt;

&lt;h2&gt;
  
  
  Forge
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8tkdp3tzf417u5z0y0hn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8tkdp3tzf417u5z0y0hn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Esse é um entre vários simuladores de Magic, mas eu não sei porque não há tanto engajamento da comunidade para sua manutenção igual há na comunidade de Yu-Gi-Oh. Esse é escrito em Java e suas cartas são representadas em arquivos de texto similares a txt.&lt;/p&gt;

&lt;p&gt;O interessante desse simulador é que os efeitos de carta são interpretados a partir de um texto com uma sintaxe única, o que permite ser facilmente legível mostrando que ter tipos customizados podem ser uma vantagem para quem sabe escrever bons interpretadores. Veja o exemplo da carta Black Lotus:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name:Black Lotus
ManaCost:0
Types:Artifact
A:AB$ Mana | Cost$ T Sac&amp;lt;1/CARDNAME&amp;gt; | Produced$ Any | Amount$ 3 | AILogic$ BlackLotus | SpellDescription$ Add three mana of any one color.
SVar:Picture:http://www.wizards.com/global/images/magic/general/black_lotus.jpg
Oracle:{T}, Sacrifice Black Lotus: Add three mana of any one color.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não vou mentir que a interface desse jogo é horrorosa e sei que exite diversas skins para mesma, mas eles ainda conseguiram portar para Android uma versão a pouco tempo atrás, mostrando outra vantagem de ter tipos de arquivo de dados customizados. O jogo ainda utiliza diversos outros arquivos de configuração, coleção de cartas, decks pré feitos e outras cosias com arquvivos muito similares a CSV.&lt;/p&gt;

&lt;h2&gt;
  
  
  Minha Solução
&lt;/h2&gt;

&lt;p&gt;Recentemente decidir criar o meu próprio card game baseado em Magic (que original...) e tive que enfrentar todos os desafios que citei acima e cheguei particularmente em uma solução diferente dos demais que me concedeu algumas vantagens e desvantagens. O jogo que desenvolvi também possui cartas com efeitos únicos e a plaraforma que escolhi como princiapis foi PC e Android. Comecei desenvolvimento utilziando Unity pois já sou experiente com essa engine e obviamente todo o meu código seria escrito em C#.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fywbcssdevlf2ccu7jcsi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fywbcssdevlf2ccu7jcsi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;De início, a minha ideia era criar um servidor autoritativo onde o jogo em si funcionaria no servidor e através de requisições http na Unity, o jogador poderia visualizar e interagir com o servidor. Dessa forma, escolhi python como linguagem de servidor, flask como framework web e JSON para guardar os dados das cartas.Por ser uma linguagem interpretada, python permite a execução de statements ou expressões em temo de excução e dessa forma eu poderia adicionar efeitos nas cartas, escevendo o corpo da função do efeito no arquivo de JSON:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;#método que cria e adiciona a carta
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;AddEffect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;newEffect&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;newEffect&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pass&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;def fun(player,targets):&lt;/span&gt;&lt;span class="se"&gt;\n\t&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;newEffect&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;self.effect = fun&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="nf"&gt;locals&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
            &lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;del fun&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"uniqueName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"zangao1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"Zangão 1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"power"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"life"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"types"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="s2"&gt;"inseto"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s2"&gt;"abelha"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"color"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"YELLOW"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"card = player.getCardHand(targets[0])&lt;/span&gt;&lt;span class="se"&gt;\n\t&lt;/span&gt;&lt;span class="s2"&gt;player.discard(card)&lt;/span&gt;&lt;span class="se"&gt;\n\t&lt;/span&gt;&lt;span class="s2"&gt;player.pullCards(1)"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OBS: As cartas originalmente tem bem mais atributes do que eu mostrei acima.&lt;/p&gt;

&lt;p&gt;Quando o arquivo JSON era lido e objeto da carta criado, o campo "effect" no JSON era interpretado e encapsulado dentro de um método que por sua vez era associado ao campo "effect" do objeto python. O metodo ainda passava através do parâmetro "targets" uma lista de possiveis alvos que aquele efeito poderia fazer.&lt;/p&gt;

&lt;p&gt;Tudo ia muito bem até eu ver que haveria a necessidade de jogar localmente contra uma IA, e bem... não tinha como eu rodar o que eu tinha feito em python localmente. Eu pensei em algumas soluções:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Utilizar Lua para escrever o core do game&lt;/strong&gt;. Com o jogo todo implementado em Lua, eu utilizaria uma API para interagir com o jogo e toda a regra de negócio estaria implementado em scripts externos que eu poderia utilizar tanto localmente como em servidor remoto. O problema seria a compatilibade para exportar isso para outras plataformas e todo o trabalho reescrever e manter o jogo em Lua que não é a melhor linguagem para implementar um jogo desse tipo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Utilizar um interpretador python dentro da Unity&lt;/strong&gt;. Além disso me fornecer uma péssima performance, os intepretadores não eram perfeitamentes compatíveis e poderiam ocasionar bugs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reescrever o jogo em C# e usar o mesmo código do servidor no cliente&lt;/strong&gt;. Isso até me daria a vantagem de reaproveitar muito código que já estava implementado, mas C# é uma linguagem compilada e eu teria que repensar como algumas coisas iriam funcionar.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Eu escolhi a 3º opção entao depois de umas duas semanas fazendo essa conversão, a arquitetura ficou mais ou menos assim:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnuji9nrovwz2iscyqxi5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnuji9nrovwz2iscyqxi5.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Chegou a hora da verdade: Como eu iria implementar os efeitos de carta em arquivos externos ao JSON? &lt;/p&gt;

&lt;p&gt;Primeiramente pensei em fazer uma abordagem parecida com o que ocorre no EDOPro, utilizando scripts em Lua ou até mesmo tags especificas em JSON e uma API para efeitos genéricos com parâmetros externos, mas isso atrapalha muito quando você precisa comparar valores ou realizar qualquer operação matemática no efeito da carta.&lt;/p&gt;

&lt;p&gt;Então eu pensei: &lt;strong&gt;Será que dá para eu interpretar C# em tempo de execução, compilar e adiconar o efeito a carta?&lt;/strong&gt; E depois de várias pesquisas, descobri que sim! A Microsoft disponibiliza um conjunto de funcionalidades de interpretação e depuração da linguagem no namespace Microsoft.CSharp para que as pessoas possam construir seus proprios interpretadores costumizados e o namespace System.CodeDom.Compiler contém um compilador que pode retornar objetos e classes instanciadas em tempo de execução. &lt;/p&gt;

&lt;p&gt;Veja abaixo o método que converte uma string no corpo de uma função em C#:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;effect&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="n"&gt;MethodInfo&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;PerformInjection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;newBody&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;CompilerParameters&lt;/span&gt; &lt;span class="n"&gt;parameters&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CompilerParameters&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GenerateInMemory&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReferencedAssemblies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"System.dll"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReferencedAssemblies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Hermetica&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReferencedAssemblies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Hermetica&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ReferencedAssemblies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UnityEngine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MonoBehaviour&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;codeProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CSharpCodeProvider&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;codeProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CompileAssemblyFromSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"using Hermetica; using System; public class Effect { public void Active(Hermetica.Player player, Hermetica.Card[] targets) { "&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;newBody&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" }}"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CompiledAssembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Activator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;GetMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Active"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;//instance method who active the effect &lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Active&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Hermetica&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Player&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Hermetica&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Card&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
        &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;player&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;targets&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Não é a coisa mais bonita do mundo e não é tão seguro ainda, mas funciona muito bem. É o mesmo conceito aplicado em python onde eu posso escrever o corpo de uma função em C# dentro de um arquivo JSON e na hora de desserializar a carta, o código é compilado e o objeto gerado tem o seu método copiado e embutido no campo &lt;strong&gt;MethodInfo&lt;/strong&gt; da carta.&lt;/p&gt;

&lt;p&gt;A desvantagem aqui é apenas o tempo de carregamento e desserialização das cartas uma vez que ao mesmo tempo que o jogo irá ler um arquivo de texto para desserializar ele vai compilar um código em tempo de execução. Esses arquivos JSON ficam dentro da pasta &lt;strong&gt;Resources&lt;/strong&gt; do Unity que é compilada junto com toda a aplicação e eu tenho assim a vantagem de usar somente uma linguagem para desenvolver todo o jogo.&lt;/p&gt;

&lt;p&gt;Há um detalhe que devo mencionar: o código não rodava em um servidor linux pois os namespaces citados só estavam disponíveis para .NET 4 em diante, e a versão de linux possui até pouco tempo .NET 3. Então tive que escrever o servidor com &lt;strong&gt;.NET Core 5&lt;/strong&gt; que foi recentemente lançado e além de ser multiplataforma, é a promessa da Microsfot para unificar toda o ambiente .NET. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcn3ex5fjyns8pd8onwer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcn3ex5fjyns8pd8onwer.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O jogo ainda não está completo pois falta muitas cartas para desenhar e testar, mas todas a build para PC já funciona muito bem, incluindo o modo online. Caso queiram me acompanhar em mais artigos e pesquisas, podem me seguir aqui mesmo no Dev.to, em breve o jogo terá uma página só para ele. Em breve pretendo escrever mais sobre a arquitetura de um card game, game design, implementações de card games na unity, sistemas de busca de cartas e a importancia das exceptions. Caso eu tenha errado alguma coisa, por favor, comentem para que eu atualize o artigo e muito obrigado por ler até aqui!&lt;/p&gt;

</description>
      <category>gamedev</category>
      <category>unity3d</category>
    </item>
  </channel>
</rss>
