Wednesday, March 29, 2017

Bosquejo de un lenguaje de patrones de ajedrez



Ya antes en este blog (busquen por "patrones de ajedrez") he hablado sobre un lenguaje para describir posiciones de ajedrez, el cual es lo suficientemente genérico para establecer patrones del juego. Después de varios meses de trabajar en esto, creo haber hallado un lenguaje de patrones que bien puede ser útil para expresar posiciones de ajedrez de forma que puedan usarse para cambiar incluso el paradigma de cómo los programas de ajedrez funcionan, quitando el cálculo bestial que hoy en día hacen por un enfoque más humano, basándose en que el ajedrez es un juego en donde intervienen patrones, sin lugar a dudas. De esta manera podrían construirse programas "más humanos".

Introducción al lenguaje de patrones

Definimos el ataque de una pieza a otra como:

Pi(P2)

donde P1 es la pieza del atacante y P2 es la pieza atacada. Si las piezas son del mismo color, hablamos de que P1 defiende a P2, pero si son de diferente color, P1 ataca a P2. Por ejemplo, A(ph7), lo cual significa que un alfil ataca a un peón negro en h7. Por convención las piezas blancas se ponen con su iniciales mayúsculas y las piezas negras con sus iniciales en minúscula.

También podemos decir: A(h7), lo que indica que el alfil blanco ataca la casilla h7. Cabe decir que no es necesario decir en qué casilla está el alfil del blanco. De hecho, en el ejemplo, el alfil podría estar en b1, c2, d3, e4, f5 o g6.

Podemos definir una pieza en una casilla en particular con la notación: Ad3, lo que indica que el alfil blanco está en la casilla d3. Nótese que en este caso no sabemos qué casillas ataca/defiende. Solamente sabemos su posición.

Se ha definido una instrucción: taboo(casilla), indicando que para el defensor, la "casilla" mencionada no está disponible. Por ejemplo, en la partida Carlsen - Karjakin, del Campeonato Mundial 2016 llevado a cabo en Nueva York a fines del año pasado, se llegó a esta posición:


Carlsen - Karjakin
Nueva York 2016
Juegan las blancas

El patrón de esta posición es D(h6), Tc8, T(f7), Ph5, rh7, pg7, taboo(g6). 1. Dh6+

El patrón no sólo describe la posición, sino que también se define al menos la primera jugada que debe hacerse (1. Dh6+). Esto podría ser una manera para hacer un programa en donde los patrones orientaran sobre cuáles son las mejores jugadas en lugar de hacer un cálculo de fuerza bruta.

Pero como ya indicamos antes en este mismo blog, tenemos que en la partida Popov - Novopashin, URSS 1979, se dio la siguiente posición:


Popov - Novopashin
URSS 1979
Juegan las blancas

Cuyo patrón es: D(h6), Tf8, Tb1, Ph4, rh7, pg7, taboo(g6). 1. Dh6+

Nótese que la instrucción taboo(g6) hace que la casilla g6 no esté disponible a las negras. Es intereante cómo los dos patrones se ven muy similares.

Otra idea interesante es la de los conectores lógicos. Un patrón en ajedrez consiste en definir las piezas en ciertas casillas o definiendo qué ataca o qué defiende. El patrón puede considerarse como un conjunto de instrucciones separadas por comas. Definimos a la "," como el AND lógico e introducimos el otro conector lógico, el OR, cuyo símbolo será ";" como en la mejor tradición del lenguaje Prolog. Sin embargo, en lugar de usar los símbolos, quien defina un patrón puede usar indistintamente "AND" o "," y "OR" o ";".

Por ejemplo, en la partida Pestalozzi - Duhm, Berna 1990, se llegó a  la siguiente posición:


Pestalozzi - Duhm, 
Berna 1990
Juegan la blancas

Aquí tenemos el sacrificio griego, el cual podría definirse como: A(h7), Cf3, Pe5, ph7, pg7, pf7, pe6, rg8 y añadiendo Dd1 OR Dg4. La primera jugada es 1. Axh7+.

Definiéndolo de esta manera, tenemos que el patrón buscado será:

A(h7), Cf3, Pe5, ph7, pg7, pf7, pe6, rg8, Dd1
o
A(h7), Cf3, Pe5, ph7, pg7, pf7, pe6, rg8, Dg4


Patrones posicionales

Un lenguaje de patrones debe poder no solamente lidiar con elementos tácticos. Debería tener la capacidad de definir patrones posicionales. Definimos estos a partir de su estructura de peones. Así, creamos dos instrucciones: structw(lista de peones) y structb(lista de peones). Por ejemplo, en Botvinnik - Donner, tenemos la siguiente posición:


Botvinnik - Donner
Amsterdam, 1963
Juegan las blancas

Su patrón puede expresarse como:

structw(a3, b4, e2, f2, g3, h2)
structb(a7, b6, e6, f7, g7, h7)
obtener el punto débil c6 (para las blancas)

Botvinnik logró la ventaja después de 14. Cd4, Axg2 15. Rxg2 Dc7 16. Db3 Tfc8 17. Tfc1 Db7+ 18. Df3 Cd5 19. e4 C5f6 20. b5! a6 21. Cc6, logrando quedarse con la casilla c6 y posteriormente llevándose el triunfo.

Los patrones posicionales son más difíciles de definir porque no hay un mecanismo directo para obtener la ventaja por métodos tácticos, pero a través de structw/b podemos definirlos. Esto es lo que en la literatura de ajesrez se denomina como "priyomes", que es una palabra rusa que se usa para representar algún tipo de maniobra o técnica típica. Por ejemplo, una técnica de un priyome defensivo es usar el rey, en los finales de torres, para atacar los peones enemigos. Sin embargo, los priyomes normalmente se usan para referirse a posiciones con cierta estructura de peones.


Un resumen de las instrucciones de este lenguaje de patrones

Las instrucciones del lenguaje son:

P1(P2) - La pieza 1 ataca/defiende a la pieza 2.
P(casilla) - La pieza ataca la casilla.
P casilla - La pieza está en esa casilla
taboo(casilla) - hace esa casilla como no disponible al bando defensor.
structw(lista de peones) - define la estructura de los peones blancos en el tablero.
structb(lista de peones) - define la estructura de los peones negros en el tablero.
Conectores lógicos - "," = AND y ";" = OR. Pueden usarse indistintamente (",",";") o (AND,OR).
Comentarios (por línea) - "//", por ejemplo //esto es un comentario.

Por el momento lo dejo aquí. Hay cosas que definir, por ejemplo, ¿cómo es que dos patrones son similares? ¿cómo definir la similitud en dos patrones para considerarlos que son el mismo? ¿se puede crear una métrica de la similitud? Hay que trabajar sobre esto.

3 comments:

Antonio Gude said...

Muy interesante. Felicitaciones.

Guillermo Sovero said...

Estimado Manuel. Aquí te saludo de mucho tiempo. Leo de vez en cuando tu blog y esta entrada me resultó muy interesante. Esta idea sobre patrones la has tenido desde hace mucho y es magnífico el progreso que llevas. Lo que te comentaré lo hago como simple aficionado al juego y sin ser experto en algoritmos. Cuando se tiene A(h7), entonces el alfil blanco en "cualquier" posición ataca h7. Aquí en mi humilde opinión creo que ya se perdió generalidad pues h7 es una posición absoluta. Creo que más información proporciona A(p); es decir que alfil blanco ataca peón negro en cualquier parte del tablero. Pero, ¿cuál peon negro? Pues no se sabe por el momento pero sería interesante enlistar no una ni dos, sino todas las constantes del tipo P1(P2) y obtener el "conjunto mínimo necesario" para que exista el patrón que se está estudiando. Pienso que no es un problema nada sencillo pero seguiré al tanto de tu avance. Lo que quise sugerir en este comentaro es un enfoque más "cualitativo" para no perder generalidad. Saludos. Guillermo.

Morsa said...

Guillermo,
Gracias por tu mensaje. No lo he puesto aquí pero el programa en el que he trabajado, a cualquier posición legal, el sistema me dice todos los ataques y defensas posibles, tanto de blancas como de negras. Voy a hacer un video del mismo para que lo observes trabajando.

Lo que mencionas de por ejemplo, A(h7), tiene sentido y ya lo había pensado pero no como tú lo ves. Fíjate en la posición de popov-Novopashin, de URSS 1979, en donde la combinación que hace el blanco es idéntica a la que ejecuta Carlsen contra Karjakin. En la posición de Popov vs Novopashin, el patrón es D(h6), Tf8, Tb1, Ph4, rh7, pg7, taboo(g6). 1. Dh6+, pero pienso que debería incluir una instrucción como T*1, en donde indicara que en principio, la torre de b1 podría estar no necesariamente en b1. Curiosamente solamente podría estar en b1 o en f1 para ganar, por lo cual no sé aún cómo generalizar la idea.

La intención es que si pones T*1 esto debería ser equivalente a Ta1, Tb1,, Tc1, ..., Th1, pero no sé si esto tiene sentido. En mi programa tendría que sustituir el patrón T*1 por la torre en cada columna. Estoy en eso aún.

Por otra parte, al respecto de las posiciones absolutas o no, el patrón del regalo griego, por ejemplo: A(h7), Dd1, Cf3, Pe5, pe6, pf7, pg7, ph7, rg8, podría ponerse por ejemplo, dos filas adelante (recorriendo todo para mantener el ataque a h7, por ejemplo poniendo el alfil atacando h5, pero no habría mate, a menos que hubiese una torre blanca que le impidiese al negro ir a la 7a fila. Dicho de otra manera, hay muchas posicione que son específicas y que sí, dejan de ser generales para ser, como dices tú, absolutas, pero esto es un problema que quiero entender es de la naturaleza del ajedrez.

Para intentar ser más claros, hay posiciones en donde el patrón puede cambiar sin perder generalidad y hay otros que solamente se pueden dar en ciertas situaciones, por ejemplo, el mate de Greco, por mencionar uno que se me ocurre en estos momentos.

En fin, hay que seguir elaborando. Creo tener una base firme para los patrones y ahora mi preocupación es la parte de la similitud y del cómo crearuna métrica. El Dr. Rafael Fernández me dio una idea interesante pero no la anoté y se me olvidó. Le hablaré para que me la repita, a ver si por ahí se puede hacer algo. Por el momento estoy pensando que la métrica puede ser directamente proporcional a la cantidad de "items" que se encuentren en el patrón y que se cumplan.

Sigo escribiendo nomás se me ocurra el siguiente paso. Agradezco el interés. De verdad.
saludos
Manuel