Dagaz: Uma História de Persistência

Qualquer tecnologia suficientemente avançada é indistinguível da mágica.
Arthur Clark
 
- Eu não quero mais ser uma comparação ... Faça de mim uma metáfora.
China Mieville


Trabalhar em um grande projeto é semelhante ao metrô . Resolvendo problemas específicos, abrimos novas oportunidades. Com o tempo, essas oportunidades se fortalecem, se conectam com outras e isso nos permite resolver problemas antigos, muito mais importantes e complexos de uma maneira nova e completamente inesperada. Eu tenho um bom exemplo sobre este assunto. E eu quero falar sobre ele.

O módulo de instalação comum foi concebido como uma ferramenta simples de depuração. Freqüentemente, é muito útil poder retornar a uma posição específica para localizar o problema. Mas esse arranjo de figuras surge rapidamente no jogo, e sua restauração merece um trabalho considerável. Eu precisava de uma ferramenta para automatizar esse processo e o fiz. Na verdade, posso facilmente codificar qualquer posição descrevendo a localização das peças no quadro:

? setup = 0c3; 0a2; 0c2; 0d2; 1a1; 4b1; 5c1; 1d1; -1a4; 4b4; 5c4; 1d4; 0a3; 0d3; 0b2 ;; & turn = 0

Em seguida, posso adicionar esses parâmetros ao URL para reproduzir a posição. É isso que a instalação comum faz. O módulo salva a descrição de todas as posições intermediárias no log e torna possível reproduzi-las. Este não é um mecanismo muito perfeito. Por exemplo, essa descrição não nos fornece nada se não soubermos a que jogo pertence. Existem outras deficiências, que discutirei mais adiante. Agora, é hora de conhecer o próximo participante da nossa história.


A opção de níveis progressivos veio do Zillions of Games e, por um longo tempo, não entendi por que era necessária. Tente desligar todas as lâmpadas (é simples) e você entenderá do que estou falando. Depois que o jogador vence, os níveis progressivos examinam o URL atual e, se ele encontrar um número, aumenta em um. De fato, esta é uma ótima maneira de envolver o jogador, mas suas capacidades não se limitam a isso. Existem jogos que consistem em várias rodadas. Depois de terminar um, os jogadores, de acordo com certas regras, redistribuem as peças e começam a jogar novamente.


Essa abordagem é frequentemente praticada no mankali africano . Em Ovalhu , por exemplo, o jogo não começa novamente. Os jogadores usam grãos capturados na rodada anterior para preencher inicialmente seus buracos. Os buracos que não foram preenchidos são considerados eliminados do jogo e não podem ser usados. De fato, a cada rodada, um novo jogo é jogado, em um novo tabuleiro. Somente quando o perdedor na próxima rodada, o jogador não puder preencher pelo menos um buraco, sua derrota final será reconhecida.

Esta oportunidade pode ser entendida muito mais ampla.

, . common-setup . , , , . , .


, . «» , . , "Magyar Dama" ( , «»), Hive, , . , , , , , .


( , roguelike-). «», seed, . , ( ). (, ), .


, , . . "", , , , .

O próximo passo foi dado quase por acidente. Há som nos meus jogos. Eu realmente gosto dele, mas provavelmente há pessoas no mundo que ele irrita. Foi para eles que foi possível desligá-lo. Parece que isso funcionou bem, mas as configurações não foram salvas em nenhum lugar e, após cada atualização da página, o som teve que ser desativado novamente (e isso incomodou ainda mais). Foi-me pedido que, de alguma forma, resolvesse esse problema e a primeira solução que me veio à mente foi um cookie (a primeira solução nem sempre é bem-sucedida).

Aqui está como ficou
Dagaz.Controller.sound = function() {
    if (Dagaz.Controller.soundOff) {
        sound.innerHTML = "no Sound";
        Dagaz.Controller.soundOff = false;
        document.cookie = "dagaz.sound=on";
    } else {
        sound.innerHTML = "Sound";
        Dagaz.Controller.soundOff = true;
        document.cookie = "dagaz.sound=off";
    }
}

Como eu não queria jogar lixo, os cookies tiveram vida curta até a janela do navegador ser fechada. E então pensei: "por que não ensinar a configuração comum a ser armazenada em cookies também?" Eu tive que definir o parâmetro max-age , mas valeu a pena. Primeiro, o estado do jogo foi salvo agora quando a janela foi fechada acidentalmente. Como bônus, alternar o modo de jogo com o bot AI / no AI também não redefiniu o jogo. Isso foi ótimo!

Claro, eu tive que prever outra coisa
, , , , cookie ( ). «New game», . . , common-setup , ? cookie ( , ).

-
var getName = function() {
  var str = window.location.pathname.toString();
  var result = str.match(/\/([^.\/]+)\./);
  if (result) {
      return result[1].replace("-board", "").replace("-ai", "");
  } else {
      return str;
  }
}

var badName = function(str) {
  var result = str.match(/[?&]game=([^&*]*)/);
  if (result) {
      return result[1] != getName();
  } else {
      return true;
  }
}

var getCookie = function() {
  var str = document.cookie;
  var result = str.match(/dagaz\.(setup=[^*]*)/);
  if (result) {
      var r = decodeURIComponent(result[1]);
      if (badName(r)) return "";
      return "?" + r;
  } else {
      return "";
  }
}

var getSetup = function() {
  var str = window.location.search.toString();
  var result = str.match(/[?&]setup=([^&]*)/);
  if (result) {
      return result[1];
  } else {
      str = getCookie();
      result = str.match(/[?&]setup=([^&]*)/);
      if (result) {
          return result[1];
      } else {
          return "";
      }
  }
}

Dagaz.Model.getSetup = function(design, board) {
  var str = "";
  ...
  str = str + ";&turn=" + board.turn;
  if (Dagaz.Controller.persistense == "setup") {
      var s = str + "&game=" + getName() + "*";
      var maxage = getMaxage();
      if (maxage) {
        document.cookie = "dagaz.setup=" + encodeURIComponent(s) + "; max-age=" + maxage;
      } else {
        document.cookie = "dagaz.setup=" + encodeURIComponent(s);
      }
  }
  return "?setup=" + str;
}

, . , ( Pasang Chaturanji) , , , (Morris, Bolotoudou) common-setup , . , !


. ( , ). , Stratego Luzhanqi, ( ). (common-setup, , ), …


, , , common-setup , . ( Mana, , ), , .

, , . , random, c seed , , , - . , seed cookie, , , , .

Infelizmente, existem jogos para os quais o método de salvar o estado pelo módulo de configuração comum não é adequado. No Kamisado mencionado acima , a capacidade de concluir uma jogada (para todas as jogadas, exceto a primeira) depende de qual campo a jogada anterior foi concluída. Existem jogos com mecânica ainda mais complexa:


No Moinho , além dos movimentos usuais, existem bônus - se um jogador organizou suas três peças seguidas, ele tem o direito de remover a peça de um oponente do tabuleiro. Além disso, as regras proíbem a construção do mesmo trigêmeo duas vezes seguidas. Tudo isso significa que, para que o jogo funcione corretamente, você deve salvar o histórico dos movimentos anteriores. Felizmente, existe essa oportunidade.

O módulo gerenciador de sessões salva o histórico do jogo, permitindo ao jogador retroceder um ou mais lances, possivelmente realizando outro lance. Além disso, a opção de orientador está associada a esse mecanismo, que informa ao jogador uma possível jogada ao jogar com o bot. Em retrospecto, a idéia de salvar a história do jogo em cookies parece óbvia, mas não cheguei a ela imediatamente.

Jogo de correspondência apareceu pela primeira vez
Dagaz . - , "Zillions of Games", 1998 . 2003 Zillions , , . Ed van Zon . "MindSports", .


MindSports Dagaz . Ed , Java-, , , . , Ed Dagaz, .

, , , , . , Dagaz, , - backend-, JavaScript- . Ed session-manager, . , , , , , , ( , ), , .

SGF , , session-manager , SGF . , , , , SGF ( , ). , MindSports, , 80 Dagaz .

O próximo passo foi bastante óbvio - comecei a salvar a descrição SGF das partes em um cookie e, em seguida, eles me disseram que não era muito moderno e mudei tudo para o localStorage (isso simplificou o código e resolveu alguns problemas de depuração no Google Chrome). Neste ponto, o leitor pode ter uma pergunta. Eu tenho dois mecanismos para o mesmo objetivo, e um deles é mais perfeito que o outro. Por que não mudar todos os jogos para persistência de sessão? Infelizmente, isso não é tão simples.

Existem famílias inteiras de jogos para as quais as sessões de salvamento não são aplicáveis:

  1. (Shatranj, Sittuyin, Janggi, Stratego, Luzhanqi, Banqi )
  2. , session-manager (Ur, Puluc, Shen, Backgammon, Chaturaji )
  3. (Kamisado, Washington, Ohvalhu)
  4. Finalmente, existem jogos em que a persistência do gerenciador de sessões não pode ser usada, por razões de desempenho (por incrível que pareça, em Fanorona , por toda a sua aparente simplicidade, no início do jogo, há um grande número de possíveis estreias relacionadas às especificidades de neste jogo)

Em geral, tenho dois mecanismos projetados, em geral, para o mesmo. E isso é ótimo, porque eu posso escolher qual aplicar.

All Articles