AI con JavaScript para jugar al Ajedrez

  Gonzalo Ruiz de Villa

  @gruizdevilla

  CTO @gft_es

  GDE Web technologies

 Octubre 2018

https://goo.gl/ZwfBjZ

Setup de proyecto

Una pequeña configuración de inicio

  • chess.js 
  • chessboard.js
  • jquery (ouch!)
  • algún estilo mínimo

Pintemos el tablero

Creamos la partida

Agregamos interacción

let config = {
    draggable: true,
    position: 'start',
    onMouseoverSquare,
    onMouseoutSquare,
    onDragStart,
    onDrop,
    onSnapEnd
}

onMouseoverSquare(square, piece)

 

  • marquemos las celdas a las que se puede mover (y la actual)

onMouseoutSquare()

 

  • desmarcar

onDragStart(square, piece)

 

  • ¿checkmate?
  • ¿draw?
  • ¿fichas negras? vamos a jugar con blancas

onDrop(from, to)

 

  • desmarcar 
  • ¿movimiento válido?
             NO -> 'snapback'
             SI ->  ¿ha terminado?
                       movimiento "aleatorio" de negras

makeBestMove

 

  • seleccionar movimiento
    • de los posibles uno al azar
  • aplicarlo
    • al juego
    • actualizar tablero
    • ¿ha terminado?

onSnapEnd

 

  • actualizamos el tablero con la configuración del juego (por si, por ejemplo,  hay un enroque o promoción de un peón) 

 

 


 

Funcionando pero poco inteligente

Algoritmo del Museo Británico

Nodos en el árbol: 10

120

Estimación de Claude Shannon (https://en.wikipedia.org/wiki/Claude_Shannon)

Átomos: 10

80

Segundos en un año:  PI * 10

7

Nanosegundos/segundo:  10

9

Años universo:  10

10

Total: 10

106

Nodos en el árbol: 10

120

VS

Evaluando el tablero

(desde la perspectiva de negras)

-900 900
-90 90
-50 50
-30 30
-30 30
-10 10
{
    k:900,
    q: 90,
    r: 50,
    b: 30,
    n: 30,
    p: 10
}

Pasos

  • Para cada movimiento
  • Simula y calcula valor de posición
  • Si mejora, guárdala

Minimax




        function minimax(node, depth, maximizingPlayer) is
            if depth = 0 or node is a terminal node then
                return the heuristic value of node
            if maximizingPlayer then
                value := −∞
                for each child of node do
                    value := max(value, minimax(child, depth − 1, FALSE))
                return value
            else (* minimizing player *)
                value := +∞
                for each child of node do
                    value := min(value, minimax(child, depth − 1, TRUE))
                return value

Minimax

-1

0

0

1

0

1

0

-1

-2

-1

-1

-1

2

1

2

-1

-1

-1

-1

0

Configuración del minimax

Podar el árbol: ⍺β

6

4

6

9

7

6

1

2

2

8

1

1

8

9

2

8

⍺: mejor valor visto xa maximizador

β: mejor valor visto xa minimizador

 

⍺: -∞

β: 6

⍺: 4
β:

X

0

X

⍺: 6

β:

⍺: 6

β: 8

⍺: 6

β:

⍺: 6

β:

⍺: 8

β:

8

⍺:-∞
β:∞

Deep Blue consistía en:

  • Minimax
  • ⍺β
  • Profundización progresiva
  • Computación paralela (a saco)
  • Libro de aperturas
  • Cosas específicas para terminar la partida
  • Profundización desigual

Deep Blue vs Kasparov

One more thing

-1<Fichas con pesos <1

vacio ? 1 : 0

blanca ? 1 : 0

juega blanca ? 1 : 0

negra ? 1 : 0

movs sin comer/50

movs/100

0 (pdte de usar)

Hidden 512

Output 6100 labels

Maxpooling

8 x 8 x 8

Kernel 5

8 x 8 x 8

Kernel 5

8 x 8 x 8

Kernel 3

Red neuronal para imitar partidas

¿Cual es la predicción?

Pesos para todos los movimientos posibles en el ajedrez (no solo los válidos para una posición dada)

Pasos:

  1. Adaptar FEN para entrada de DNN
  2. Predecir
  3. Cambiar pesos de movimientos no legítimos a 0
  4. Sacar indice con argMax sobre pesos > 0
  5. Buscar en label por índice obtenido

GRACIAS

Referencias

Repos