Dagaz: una historia de persistencia

Cualquier tecnología suficientemente avanzada es indistinguible de la magia.
Arthur Clark
 
- Ya no quiero ser una comparación ... Hazme una metáfora.
China Mieville


Trabajar en un gran proyecto es similar al buceo en el metro . Resolviendo problemas particulares, abrimos nuevas oportunidades. Con el tiempo, estas oportunidades se fortalecen, se conectan con otras oportunidades y esto nos permite resolver problemas antiguos, mucho más importantes y complejos de una manera nueva y completamente inesperada. Tengo un buen ejemplo sobre este tema. Y quiero hablar de él.

El módulo de configuración común se concibió como una simple herramienta de depuración. A menudo, es muy útil poder volver a una posición específica para localizar el problema. Pero este arreglo de figuras surge fugazmente en el juego, y su restauración merece un trabajo considerable. Necesitaba una herramienta para automatizar este proceso, y lo hice. De hecho, puedo codificar fácilmente cualquier posición describiendo la ubicación de las piezas en el tablero:

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

Luego, puedo agregar estos parámetros a la url para reproducir la posición. Esto es lo que hace la configuración común. El módulo guarda la descripción de todas las posiciones intermedias en el registro y permite reproducirlas. Este no es un mecanismo muy perfecto. Por ejemplo, tal descripción no nos da nada si no sabemos a qué juego pertenece. Hay otras deficiencias, que discutiré más adelante. Ahora, es hora de conocer al próximo participante en nuestra historia.


La opción de niveles progresivos vino de Zillions of Games y durante mucho tiempo no entendí por qué era necesaria. Intenta apagar todas las bombillas (es simple) y entenderás de lo que estoy hablando. Después de que el jugador gana, los niveles progresivos miran la url actual, y si encuentra un número en ella, la aumenta en uno. De hecho, esta es una excelente manera de involucrar al jugador, pero sus capacidades no se limitan a esto. Hay juegos que consisten en varias rondas. Una vez terminado, los jugadores, de acuerdo con ciertas reglas, redistribuyen las piezas y comienzan a jugar nuevamente.


Este enfoque a menudo se practica en mankali africano . En Ovalhu , por ejemplo, el juego no solo comienza de nuevo. Los jugadores usan granos capturados en la ronda anterior para llenar inicialmente sus agujeros. Los agujeros que no se completaron se consideran eliminados del juego; no se pueden usar. De hecho, en cada ronda se juega un nuevo juego, en un nuevo tablero. Solo cuando el perdedor en la siguiente ronda, el jugador no puede llenar al menos un hoyo, se reconoce su derrota final.

Esta oportunidad se puede entender mucho más amplia.

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


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


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


, , . . "", , , , .

El siguiente paso fue dado casi por accidente. Hay sonido en mis juegos. Realmente me gusta, pero probablemente hay personas en el mundo a las que molesta. Fue para ellos que fue posible apagarlo. Parece que esto funcionó bien, pero la configuración no se guardó en ningún lugar y después de cada actualización de la página, el sonido tuvo que apagarse nuevamente (y esto molestó aún más). Me pidieron que solucionara este problema de alguna manera y la primera solución que me vino a la mente fue una cookie (la primera solución no siempre es exitosa).

Así es como se veía
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";
    }
}

No quería tirar basura, por lo que las cookies duraron poco hasta que se cerró la ventana del navegador. Y luego pensé: "¿por qué no enseñar también la configuración común para que se almacene en cookies?" Tuve que establecer el parámetro max-age , pero valió la pena. En primer lugar, el estado del juego ahora se guardaba cuando la ventana se cerraba accidentalmente. Como beneficio adicional, cambiar el modo de juego con el bot AI / no AI tampoco restableció el juego. ¡Eso fue genial!

Por supuesto, tuve que prever algo más
, , , , 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, , , , .

Desafortunadamente, hay juegos para los que el método de guardar el estado mediante el módulo de configuración común no es adecuado. En el Kamisado mencionado anteriormente , la capacidad de completar un movimiento (para todos los movimientos excepto el primero) depende de en qué campo se completó el movimiento anterior. Hay juegos con mecánicas aún más complejas:


En el molino , además de los movimientos habituales, hay otros bonos: si un jugador ha dispuesto sus tres piezas en una fila, tiene derecho a eliminar la pieza de un oponente del tablero. Además, las reglas prohíben construir el mismo triplete dos veces seguidas. Todo esto significa que para que el juego funcione correctamente, debes guardar el historial de movimientos anteriores. Afortunadamente, existe esa oportunidad.

El módulo de administrador de sesión guarda el historial del juego, permitiendo al jugador retroceder uno o más movimientos, posiblemente realizando otro movimiento. Además, la opción de asesor está asociada con este mecanismo, que le dice al jugador un posible movimiento al jugar con el bot. En retrospectiva, la idea de guardar la historia del juego en cookies parece obvia, pero no lo hice de inmediato.

El juego por correspondencia apareció por primera 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 .

El siguiente paso fue bastante obvio: comencé a guardar la descripción SGF de las partes en una cookie, y luego me dijeron que no era muy moderno y moví todo a localStorage (esto simplificó el código y resolvió algunos problemas de depuración en Google Chrome). En este punto, el lector puede tener una pregunta. Tengo dos mecanismos para el mismo propósito, y uno de ellos es más perfecto que el otro. ¿Por qué no cambiar todos los juegos a la persistencia de sesión? Lamentablemente, esto no es tan simple.

Hay familias enteras de juegos para las que guardar sesiones no es aplicable:

  1. (Shatranj, Sittuyin, Janggi, Stratego, Luzhanqi, Banqi )
  2. , session-manager (Ur, Puluc, Shen, Backgammon, Chaturaji )
  3. (Kamisado, Washington, Ohvalhu)
  4. Finalmente, hay juegos en los que la persistencia del administrador de sesión no se puede usar, por razones de rendimiento (curiosamente, en Fanorona , a pesar de su aparente simplicidad, al comienzo del juego, hay un gran número de posibles debuts relacionados con los detalles específicos de la toma). en este juego)

En general, tengo dos mecanismos diseñados, en general, para lo mismo. Y esto es genial, porque puedo elegir cuál aplicar.

All Articles