Ajedrez por computadora


CH v0.5 ß















CH v0.5 ß

CH Es un programa en el que un jugador humano se enfrenta a la máquina, estando esta en clara ventaja. El reto es para la máquina, que debe dar jaque mate al jugador.


La inteligencia artificial de la máquina utiliza el siguiente algoritmo:

   - Generar todos los movimientos posibles.

   - Para cada movimiento, generar todos los movimientos posibles
     del jugador humano.

   - Para cada movimiento, generar de nuevo todos los movimientos
     posibles.

Esto se repite tantas veces como jugadas queremos que anticipe la máquina.
Pero en última instancia habrá que decidir si una situación del tablero es buena o mala. Para ello, en lugar de realizar los dos últimos pasos, el programa da una puntuación a la situación del tablero para decidir si ese movimiento sería bueno o malo. Para esto, toma en consideración algunos parámetros:

   - DISTANCIA A LOS BORDES
     Para hacer un jaque mate hay que llevar al rey a un borde 
     del tablero.  Por eso se asigna mejor puntuación a las jugadas
     donde los movimientos  posibles del rey le dejan más cerca de
     algún borde.

   - DISTANCIA AL REY
     Por otro lado, puesto que para hacer jaque mate también es
     necesario que el rey de la máquina esté próximo al rey del
     jugador, ya que la reina le necesita, se da mejor puntuación
     a aquellas jugadas en las que los dos reyes están más cerca.

   - SITUACIONES A EVITAR
     Se le da muy mala puntuación a las jugadas en las que la
     máquina pierde a la reina o el jugador humano hace tablas
     (no puede mover, o sólo puede volver a la casilla de la que vino).

   - SITUACIONES A CONSEGUIR
     Se da muy buena puntuación a las jugadas que son jaque mate.


El programa se controla con el cursor del teclado numérico.
Bloq Num debe estar desactivada.





CAPTURAS


Una jugada de jaque.



El rey acorralado.



La máquina ganádome otra vez.



CÓDIGO


int jaque (char **);
int mueve (char **, int, int, int, int, int);
int mover_jugador (char **);
int mover_maquina (char **, int);
int mate (char **);




int jaque (char **tablero) { int i, x, y, pos, jaque; jaque=0; x=0; y=0; while (y<8) { if (tablero[x][y]) { switch (tablero[x][y]) { case 0x11: for (i=0;i<8;i++) { if (pieza(tablero,x,y,i,1)==JUGADOR) jaque |= 0x03; } break; case 0x12: for (i=0;i<8;i++) { if (pieza(tablero,x,y,i,8)==JUGADOR) jaque |=0x01; } break; } } x++; y+=x/8; x%=8; } return (jaque); }
int mueve (char **tablero, int ox, int oy, int dx, int dy, int fake) { int tmpx, tmpy, movim, fin, dist; char pact, pant; //piezas actual y anterior if (dx<0 || dx>7 || dy<0 || dx>7) return 0; pact=tablero[ox][oy]; dist= (abs(dx-ox)>abs(dy-oy)) ? abs(dx-ox) : abs(dy-oy); movim=direccion(ox, oy, dx, dy); if (movim!=-1) { tmpx=ox; tmpy=oy; fin=0; while (!fin) { tmpx+=desp[movim][0]; tmpy+=desp[movim][1]; if (tmpx>7 || tmpx<0 || tmpy>7 || tmpy<0) fin=1; else if (((pact & 0x10)==(tablero[tmpx][tmpy] & 0x10)) && tablero[tmpx][tmpy]) fin=1; else if (tmpx==dx && tmpy==dy) fin=2; } if (fin==2) { switch (pact & 0x0F) { case 0x01: if (dist==1) fin=0; break; case 0x02: fin=0; break; } if (!fin) { pant=tablero[dx][dy]; tablero[dx][dy]=pact; tablero[ox][oy]=0; if (jaque(tablero) > ((pact & 0x10) >>4 )) { tablero[dx][dy]=pant; tablero[ox][oy]=pact; return 0; } if (fake) { tablero[dx][dy]=pant; tablero[ox][oy]=pact; } return 1; } } else return 0; // choque o fuera de tablero } printf ("Invalid"); return 0; // movimiento invalido }
int mover_jugador(char **tablero) { int x,y,nx,ny,fin,movim; char car, bkppieza; fin=0; x=0; y=0; while (tablero[x][y]!=JUGADOR) { x++; y+=x/8; x%=8; } ultima[2]=x; ultima[3]=y; while (!fin) { car=getch(); movim=-1; if (car==27) fin=1; else if (car==0) { car=getch(); if (car=='H') movim=0; else if (car=='I') movim=1; else if (car=='M') movim=2; else if (car=='Q') movim=3; else if (car=='P') movim=4; else if (car=='O') movim=5; else if (car=='K') movim=6; else if (car=='G') movim=7; } if (movim>-1) { if (mueve (tablero,x,y,x+desp[movim][0],y+desp[movim][1],0)) { if (x+desp[movim][0]==ultima[0] && y+desp[movim][1]==ultima[1]) ultima[4]++; else ultima[4]=0; ultima[0]=ultima[2]; ultima[1]=ultima[3]; return 1; } } } return 0; }
int mover_maquina(char **tablero, int depth) { int i, j, x,y,nx,ny,fin,movim; int kx ,ky, nkx, nky, r, bkprpieza; int ox, oy, dx, dy, punt, mejorpunt, localpunt, dir; char car, bkppieza; kx=0; ky=0; while (tablero[kx][ky]!=JUGADOR) { kx++; ky+=kx/8; kx%=8; } x=0; y=0; mejorpunt=10000; while (y<8) { if (tablero[x][y] & 0x10) { switch (tablero[x][y]) { case REY: for (i=0;i<8;i++) { nx=x+desp[i][0]; ny=y+desp[i][1]; if (mueve(tablero,x,y,nx,ny,1)) { tablero[x][y]=0; bkppieza=tablero[nx][ny]; tablero[nx][ny]=REY; if (depth & 0x7F) { deb++; if (!(jaque(tablero) & 0x02)) { punt=puntua(tablero); if (punt<-500) punt*=((depth & 0x7F)+1); if (puntlocalpunt) localpunt=punt; } tablero[kx][ky]=JUGADOR; tablero[nkx][nky]=bkprpieza; } if (localpunt< mejorpunt) { mejorpunt=localpunt; ox=x;oy=y;dx=nx;dy=ny; } } } } else { if (!(jaque(tablero) & 0x02)) punt=puntua(tablero); deb++; if (punt< mejorpunt) { mejorpunt=punt; ox=x; oy=y; dx=nx; dy=ny; } } tablero[x][y]=REY; tablero[nx][ny]=bkppieza; } } break; case REINA: for (j=0;j<8;j++) { for (i=0;i<8;i++) { nx=x+desp[i][0]*j; ny=y+desp[i][1]*j; if (mueve(tablero,x,y,nx,ny,1)) { tablero[x][y]=0; bkppieza=tablero[nx][ny]; tablero[nx][ny]=REINA; if (depth & 0x7F) { deb++; if (!(jaque(tablero) & 0x02)) { punt=puntua(tablero); if (punt<-500) punt*=((depth & 0x7F)+1); if (puntlocalpunt) localpunt=punt; } tablero[kx][ky]=JUGADOR; tablero[nkx][nky]=bkprpieza; } if (localpunt< mejorpunt) { mejorpunt=localpunt; ox=x;oy=y;dx=nx;dy=ny; } } } } else { if (!(jaque(tablero) & 0x02)) punt=puntua(tablero); deb++; if (punt< mejorpunt) { mejorpunt=punt; ox=x; oy=y; dx=nx; dy=ny; } } tablero[x][y]=REINA; tablero[nx][ny]=bkppieza; } } } break; } } x++; y+=x/8; x%=8; } if (depth & 0x80) { mueve (tablero, ox,oy,dx,dy,0); gotoxy (5,22); return 1; } else return mejorpunt; }
int mate (char **tablero) { int i, x, y, nx, ny, bkpieza; if (jaque(tablero)==1) { x=0; y=0; while (tablero[x][y]!=JUGADOR) { x++; y+=x/8; x%=8; } tablero[x][y]=0; for (i=0;i<8;i++) { nx=x+desp[i][0]; ny=y+desp[i][1]; if (nx>=0 && nx<8 && ny>=0 && ny<8) { bkpieza=tablero[nx][ny]; tablero[nx][ny]=JUGADOR; if (!(jaque(tablero) & 0x01)) { tablero[nx][ny]=bkpieza; tablero[x][y]=JUGADOR; return 0; } tablero[nx][ny]=bkpieza; } } tablero[x][y]=JUGADOR; return 1; } return 0; }

Para dudas, consultas, sugerencias, bugs, etc...
rzr00@yahoo.es

"If you can't beat your computer at chess, try kickboxing." -- Anon.

Copyright © Arturo Granell (RzR) 2004
Todos los derechos reservados.