Juego gráfico de ajedrez. 19º IOCCC. Most Portable Chess Set
Este programa es una evolución de mi
ajedrez IOCCC previo,
reduje el núcleo, lo hice jugar mejor y me las arreglé para poner una interfaz
gráfica que funciona en X/Window y en Windows. No fue algo sencillo, de hecho
en la actualidad este programa es único en Internet.
Comentarios
Existen tantos programas de ajedrez basados en texto, ¿qué
es eso de A1, H5, C4, D5?. ¿La reina realmente ataca al rey?
Así que me las ingenié para realizar un programa gráfico de
ajedrez X11 (LQVUPI, o Lo Que Ves es Una Participación del IOCCC), apuntar y
click para mover piezas es la única acción requerida.
Aquí está el código fuente, escrito en lenguaje C:
#include <X11/Xlib.h>
char *l="dbcefcbddabcddcba~WAB+ +BAW~ +-84HLSU?A6J57IKJT576,",
*F=" ,>>,> xl~w/? ,>>>,s m_>>__ mm2>>> >uk>>> ",*f;y,u;
#define v for (i=b=0;b>511?b=0,i+=64:0,i<512;b+=64) A=i/64*10+b/64+21,XCopy\
Plane(d, r[I[A]+7+14*(i+b>>6&1)+28*(A==z)],w,C,0,0,64,64,b,i,1); XFlush(d);
#define _(a) *f++=a&*F?-(z%14<7):"U\252U\0DDDD"[z/14*2|u&1],
#define G(p) p##Pixel(d,DefaultScreen(d))
#define R(a) |(a==O|p==a)*
#define P return y=~y,
#define a X(0,0,0,
#define H while(
#define D ;if(
I[304],b,i,z;main(x,W) char**W; { Display *d =
XOpenDisplay(""); Window w = XCreateSimpleWindow
(d, DefaultRootWindow(d), 64,64,512,512,2,G(Black)
,G(Black)); XGCValues g; XButtonEvent e; int A,r
[56],Z,* m = I , C ,Y; XSelectInput(d,w,32772);
XMapWindow( d, w); g. foreground = G(White);
C=XCreateGC(d,w,4,&g); F+=48; H f=I,i=0,z<56){
H u=0,i++<8){ H _(0)_( 64)_(16)_(8)_(4)_(2)_(1
)_(0)++u<8); F++; } F-= z%7-6?z%14<6?16:0:8; r[
z++]=XCreateBitmapFromData(d,w,I,64,64); } srand(
time(z=u=0)); H I[z]=-( z>98|z<21|(z+1)%10<2),
++z<120); H ++m<9+I) 80 [m]=-2,90[m]=~(20[m]=7&*
l++),30[m]=1; D 1<x) Z= *W[1]-45; D 2<x){ a u,1
,Z); a u,0,1); z=0; } H 1){ XNextEvent(d,&e); D
e.type==12){ v } D e. type==4){ b=e.y/64*10+e
.x/64+21; D(b[I]^y)<-1) { z=b; v} else{ i=(b<29
|b>90)&((z[I]^y)==-2)?- 6^y:z[I]; Y=y; a u,0,1);
z=0; v D 1<x&&Y-y){ a u ,1,Z); a u,0,1); } z=0;
v } } } }
X(w,c,h,e,S,s)
{ int p,O= *l,t,d,o,C ,*g,E,n,*m =I,N=-1e8,
A,L,r,x = 10,q; y=~y ; H--O>20)
{ o=I[p=O] D q=o^y,q> 0){ q+=(q< 2)*y,C=q
["51#/+++"], A=q["95+3/33"]; do { m=0,
r=I[p+=C[l ]-64] D !w |p==w&&q>1 |C+2<A|!r)
{ d=abs(O- p) D g=q<2 &e>>6==p+(
y?x:-x)?I+ (e>>6):0, !r&(q>1|d% x<1||g)|(r
^y)<-1){ n =o,t=q<2&( 89<p|30>p)
?n+=y|1,6^ y:o+(y|1) D (r^y)<-6 ) P 1e7-811
*h; H n-t) { O[I]=0,p [I]=n,m?*g
=*m,*m=0:g ?*g=0:0; E=e&63 R( 91)16 R(28)
4 R(21)2 R (98)32; L= (q>1?6-q?l
[p/x-1]-l[ O/x-1]-q+2 :(E|=y?8:1 ,!!m)*9:(E
|=20-d?0: 64*p,n-o?( l[15+n]-' '
)*9:d/8+!! g*99))+(l[ r+15]-' ') *9+l[p%x]-
h-l[O%x]; L-=s>h||s== h&L>49&1<s
?X(s>h?0:p ,L,h+1,E,N ,s):0 D !( z-O|i-n|h|
p-b|S|L<- 1e6))return u=E; O[I]=
o,p[I]=r,m ?*m=*g,*g= 0:g?*g=-2^ y:0 D S|h&&
(L>N||!h&N ==L&&rand( )&4)){ N=L
D !h&&s) i =n,z=O,b=p D h&&c-L<S ) P L; } q
>5&d<2&C+6 <A&&(g=I+p ,r=I[p+=p-
O],m=p<O?g -3:g+2,!(e &(p<O?3:5) <<3*-y|*g|
r|m[p<O?1: -1])&&L>- 1e6&&1e6>a
63,1,0))?d ++:(n+=y|1 );} } } C +=q<2&C+3>
A&((y?O<80 :39<O)||r) ; } H!r&q>
2&q<6||(p= O,++C<A)) ; } } P N+ 1e8?N:0; }
Como compilarlo
Primero descargue el código fuente desde
aquí.
Ya que es hambriento de recursos, sugiero francamente que
se compile con optimización máxima, en GCC puede utilizar:
gcc -O3 -fexpensive-optimizations toledo3.c -o prog -lX11
Como este ajedrez es transportable, está disponible un paquete
completo con código fuente y ejecutable para Windows.
Como utilizarlo
Estas son las opciones de línea de órdenes para la versión
X11:
prog Modo de dos jugadores (útil si no hay un tablero a mano)
prog 1 Humano con blancas - Computadora negras, nivel 1 (rápido)
prog 2 Humano con blancas - Computadora negras, nivel 2 (medio)
prog 3 Humano con blancas - Computadora negras, nivel 3 (muy lento)
prog 1 b Humano con negras - Computadora blancas, nivel 1 (rápido)
prog 2 b Humano con negras - Computadora blancas, nivel 2 (medio)
prog 3 b Humano con negras - Computadora blancas, nivel 3 (muy lento)
La computadora revisará que los movimientos sean legales,
se admiten todos los movimientos legales del ajedrez, excepto coronación a
piezas menores del lado humano.
El juego continúa hasta su conclusión lógica: cometes un
error y la computadora te gana. ;)
Acerca del núcleo
Utiliza una búsqueda alfa-beta hasta una profundidad de
nivel+3 movimientos, extendida con búsqueda de tranquilidad, eso ayuda a la
fuerza de juego, aproximadamente entre 1400 (nivel 1) y 1600 ELO (nivel
3).
Analiza el tablero y genera movimientos para cada pieza
localizada, un montón de comparaciones son usadas para al paso, enroque y
coronación. Sería más rápido con optimizaciones, pero esas optimizaciones
ocuparían valiosos caracteres IOCCC.
Siempre juega diferente cada vez, ya que utiliza el
generador de números aleatorios de la librería C.
«Características» conocidas
- Como es mi segundo programa X11 (el primero fue apunta y click en cara
feliz), agregué sentencias en todas partes hasta que funcionó. :)
- Es transportable a Wind*ws (utilice el archivo anexo layer.c)
Cambie #include <X11/Xlib.h> a #include "layer.c"
y utilice un compilador Wind*ws (solo probado con Dev C/C++ 4.9.9.2)
El nivel de juego está fijo, aunque puede cambiarse fácilmente (vea además
debajo la sección de extras).
Por supuesto, este es un ejemplo de un programa Wind*ws confuso (¿existe
otra forma de escribirlos?)
- Dará advertencias al compilarse, solo para asegurarse de que su compilador
funciona.
- No actualizará la ventana mientras está «pensando»
- El caracter de espacio tiene muchas aplicaciones útiles, especialmente
cuando tiene que ver con el límite de caracteres. 8)
- Todavía no entiendo que hacer después de los punto y coma. :P
Desafíos de programación
- Es posible convertir este código a un script Javascript con interfaz
gráfica. ¿Puede hacerlo? (puede trabajarlo, pero ya lo hice, vea
Ajedrez Toledo Javascript)
- ¿Puede mejorar la función de evaluación para que juegue mejor? (lo hice
en Toledo Nanochess)
- ¿Puede añadir mejores gráficas? (un juego de niños para cualquier buen
programador)
Actualización (7-oct-2007)
Aquí hay un pequeño aditamento para informar acerca del
estado del juego en la barra de título de la ventana, cambie
v } } } } por:
v Y=y,XStoreName(d,w,- 1e6>a u,1,1)?y=~y,a u,1,
0)>1e6?y?"Negras ganan": "Blancas ganan": "Ahogado"
:"Ajedrez"),y=Y,z=0;} } } }
Para Wind*ws, agregue la siguente línea a layer.c:
void XStoreName(int a,HWND b,char *c) { SetWindowText(b,c); }
Nota para los puristas: este código extra excede el límite
de tamaño para participaciones del IOCCC.
Otra interfaz
Siguiendo el espíritu de la transportabilidad, trabajé una
interfaz mínima de texto, que puede servir como una referencia confusa para
desarrollar nuevas interfaces confusas,
solo reemplace todo el código antes de X(w,c,h,e,S,s) con:
char *l="dbcefcbddabcddcba~WAB+ +BAW~ +-84HLSU?A6J57IKJT576,";
#define F (getchar()&15)
#define R(a) |(a==O|p==a)*
#define P return y=~y,
#define a X(0,0,0,
#define H while(
#define D ;if(
I [
304]
,b,i,z,*m=I,
u,p,x =10,y;
main( W ) {
srand( time(
0)) ; H I
[z] =-(z>
98 |z<
21| (z+
1) %x<2
) , ++z <
120 ); H ++m
<9+ I)80 [m]
=- 2 ,
90[ m]=
~( m [20
]= 7 & *l
++ ) , 30[ m]=
1; H z=19){ H++ z<
100 ) putchar(z %x- 9?"RDTACP .pcatdr"
[7 +z [I]] :x ) D
x - ( z = F ) ) {
i = I [ z+= 100
-F* x] ; b =F;
b+= 100
-F* x ;
H x -(p
=F) ) i
=-p ^y
; } else a u, 1, 3+W); a
u , 0 , 1 ) ; } }
Descargue de
aquí, mide
1357 caracteres (sin contar espacios), aún así lo he hecho más pequeño, rápido
y fuerte, vea
Toledo Nanochess.
Extras
- Archivo opcional layer_df.c contribuido
por David Forgeas de Francia para soportar línea de órdenes en
Windows. Lo he mejorado más para permitir el modo de dos jugadores (mismas
opciones que en X11), utilice con cmd de Windows.
Ligas relacionadas
Última modificación: 26-abr-2021