Juego de Ajedrez Toledo en Javascript

Por enero del 2007 recordé las similitudes entre los lenguajes C y Javascript, me pregunté si sería posible realizar un traslado de mi reciente participación ganadora (19º IOCCC, Most Portable Chess Set), lo hice en una tarde y el resultado es el ajedrez más pequeño del mundo en Javascript, vea también mi ajedrez JS1K.
Juegue en línea:
Se puede seleccionar la pieza de coronación mediante el control. Algunos navegadores pueden mostrar un mensaje de script demasiado lento, solo indique que NO desea interrumpir el script.
Vealo en acción, para jugar haga click en la pieza deseada y luego click en el cuadro destino:
Si usted quiere jugar con las piezas negras, haga click en este para forzar un movimiento, deberá hacer click cada vez después de mover una pieza negra.

El código fuente

La mayor parte del código se parece mucho al original, excepto que los apuntadores fueron trasladados a acceso a matrices. Recientemente actualicé el núcleo con el código de Toledo Nanochess Nov/20/2009.
El nivel de juego está fijo en una profundidad de 3 movimientos, y puede ser modificado (busque /*ply*/ en el código fuente), pero cada nivel extra es un orden de magnitud más lento.
Una breve descripción del funcionamiento de este código puede hallarse en la sección dedicada al Ajedrez Toledo 1, o puede referirse a mi libro de Toledo Nanochess.
<script>//(c)2009 Oscar Toledo G.
var B,i,y,u,b,I=[],G=120,x=10,z=15,M=1e4,l=[5,3,4,6,2,4,3,5,1,1,1,1,1,1,1,1,9,9
,9,9,9,9,9,9,13,11,12,14,10,12,11,13,0,99,0,306,297,495,846,-1,0,1,2,2,1,0,-1,-
1,1,-10,10,-11,-9,9,11,10,20,-9,-11,-10,-20,-21,-19,-12,-8,8,12,19,21];function
X(w,c,h,e,S,s){var t,o,L,E,d,O=e,N=-M*M,K=78-h<<x,p,g,n,m,A,q,r,C,J,a=y?-x:x;
y^=8;G++;d=w||s&&s>=h&&X(0,0,0,21,0,0)>M;do{if(o=I[p=O]){q=o&z^y;if(q<7){A=q--&
2?8:4;C=o-9&z?[53,47,61,51,47,47][q]:57;do{r=I[p+=l[C]];if(!w|p==w){g=q|p+a-S?0
:S;if(!r&(!!q|A<3||!!g)||(r+1&z^y)>9&&q|A>2){if(m=!(r-2&7))return y^=8,I[G--]=
O,K;J=n=o&z;E=I[p-a]&z;t=q|E-7?n:(n+=2,6^y);while(n<=t){L=r?l[r&7|32]-h-q:0;if(
s)L+=(1-q?l[(p-p%x)/x+37]-l[(O-O%x)/x+37]+l[p%x+38]*(q?1:2)-l[O%x+38]+(o&16)/2:
!!m*9)+(!q?!(I[p-1]^n)+!(I[p+1]^n)+l[n&7|32]-99+!!g*99+(A<2):0)+!(E^y^9);if(s>h
||1<s&s==h&&L>z|d){I[p]=n,I[O]=m?(I[g]=I[m],I[m]=0):g?I[g]=0:0;L-=X(s>h|d?0:p,L
-N,h+1,I[G+1],J=q|A>1?0:p,s);if(!(h||s-1|B-O|i-n|p-b|L<-M))return W(),G--,u=J;
J=q-1|A<7||m||!s|d|r|o<z||X(0,0,0,21,0,0)>M;I[O]=o;I[p]=r;m?(I[m]=I[g],I[g]=0):
g?I[g]=9^y:0;}if(L>N||s>1&&L==N&&!h&&Math.random()<.5){I[G]=O;if(s>1){if(h&&c-L
<0)return y^=8,G--,L;if(!h)i=n,B=O,b=p;}N=L;}n+=J||(g=p,m=p<O?g-3:g+2,I[m]<z|I[
m+O-p]||I[p+=p-O])?1:0;}}}}while(!r&q>2||(p=O,q|A>2|o>z&!r&&++C*--A));}}}while(
++O>98?O=20:e-O);return y^=8,G--,N+M*M&&N>-K+1924|d?N:0;}B=i=y=u=0;while(B++<
120)I[B-1]=B%x?B/x%x<2|B%x<2?7:B/x&4?0:l[i++]|16:7;for(a=
"<table cellspacing=0 align=center>",i=18;i<100;a+=++i%10-9?
"<th width=40 height=40 onclick=Y("+i+") style='border:2px solid #aae' id=o"+i+
" bgcolor=#"+(i*.9&1?"9090d0>":"c0c0ff>"):(i++,"<tr>"));
a+="<th colspan=8><select id=t><option>Q<option>R<option>B";
document.write(a+"<option>N</select></table>");
function W(){B=b;for(p=21;p<99;++p)if(q=document.getElementById("o"+p)){q.
innerHTML="<img width=40 src="+(I[p]&z)+".gif>";q.
style.borderColor=p==B?"#ff0":"#aae";}}W();
function Y(s){i=(I[s]^y)&z;if(i>8){b=s;W();}else if(B&&i<9){b=s;i=I[B]&z;if((i&
7)==1&(b<29|b>90))i=14-document.getElementById("t").selectedIndex^y;X(0,0,0,21,
u,1);if(y)setTimeout("X(0,0,0,21,u,2/*ply*/),X(0,0,0,21,u,1)",250);}}
</script>

Derivaciones del código fuente

Este juego de ajedrez en Javascript tiene actualmente varias derivaciones, mismo núcleo pero diferentes interfaces gráficas:

Miniajedrez para el concurso JS1K

El concurso JS1K dio inicio el domingo 1º de agosto del 2010, organizado por Peter van der Zee y teniendo como jurados a Thomas Fuchs (autor de Scriptaculous), Remy Sharp, Patrick H. Lauke y Christopher Williams, todos ellos expertos programadores de Javascript. El objetivo del concurso fue simple, los participantes debían crear un programa en Javascript lo más impresionante posible en 1024 bytes, o sea un kilobyte, sin depender de archivos externos. El periodo para participaciones se cerró el 10 de septiembre.
Yo me enteré el 8 de agosto de este concurso y me pareció un buen desafío escribir un ajedrez en 1K de Javascript, así que usando como base mi ajedrez Javascript de 2.2K en 6 horas logré compactarlo en 1K, tuve que quitar enroque, captura al paso y limitar la coronación solo a dama, dejando un tablero sencillo con letras para representar las piezas, click en cuadro origen y destino para mover las piezas.
Lo envié al día siguiente al concurso y aún puede jugarlo en línea como la participación 226. Observe que mi código Javascript de 1018 octetos además de incluir una inteligencia artificial, también contiene la interface con el usuario y la visualización del tablero. No fue fácil como lo notaron varias personas.
La primera versión del miniajedrez
La primera versión del miniajedrez.
Dos horas después de ser publicado, el entusiasta Laxminarayan Kamath me envió un correo sugiriéndome ponerle gráficas Unicode y un tip de optimización que utilicé posteriormente. El miércoles 11 en otras 6 horas de trabajo recorté más de 50 bytes, haciendo suficiente espacio para poner gráficas Unicode para las piezas de ajedrez, agrandé el tablero para que fueran cómodamente visibles y también iluminé el cuadro donde el usuario hace click. El mismo día envié esta actualización al concurso (obtuvo el número 298), y las gráficas sorprendieron al público.
Unos días después el español Román Cortés me compartió amablemente tips de optimización para ahorrar bytes, en ese tiempo también reescribí la inteligencia artificial para ahorrar espacio, con los bytes sobrantes le introduje variedad en las jugadas (Math.random), y actualización inmediata del tablero al hacer el click final. Esta fue la tercera revisión (participación 435) y recibió excelentes y multitudinarios comentarios, cientos de menciones en Twitter y miles de visitas desde blogs y foros de Estados Unidos, España, China, Japón, Rusia, Francia y Alemania. Estimo que esta versión fue jugada por al menos 25,000 personas alrededor del mundo, esta cifra fue ampliamente superada por la última versión que estimo fue jugada por 100,000 personas.
La tercera versión del miniajedrez
La tercera versión del miniajedrez en acción.
Un alemán anónimo reportó que era fácil forzar el mate del loco a mi programa, me di cuenta de que con un extra de «inteligencia» se solucionaba ese detalle y además hice que se iluminara la última pieza movida. Esta fue la cuarta actualización (participación 699).
Por casualidad justamente el mismo día que hice la actualización recibí un correo del inglés Matt Round, donde me informaba de su artículo sobre una partida de mi ajedrez contra el legendario ajedrez ZX-81 de 1K, y mi ajedrez empataba en vez de dar mate. Supe que podía mejorarlo y me puse a la tarea otra vez, fue bastante difícil «apretar» esos últimos bytes (aquí aproveché finalmente el tip de optimización de Kamath), lo logré y fue mi última actualización (participación 750) antes del cierre de participaciones de JS1K.
¡Y ganó!, el 25 de septiembre del 2010, Thomas Fuchs y Remy Sharp demostraron las participaciones ganadoras del JS1K en Berlín, Alemania, durante la conferencia jsConf.eu, mi ajedrez conquistó el segundo lugar, iniciando una ola de menciones.
He aquí la versión definitiva del Ajedrez Javascript en 1023 bytes, note que la versión original está escrita en una sola línea que tuvo que ser dividida en varias para ponerla aquí, además esto es Javascript puro, debe ser invocado por marcadores HTML tales como <body> <script src="miniajedrez.js"> </body>
// Tiny Chess (c)2010 Óscar Toledo G.
for(B=i=y=u=b=i=5-5,x=10,I=[],l=[];B++<304;
I[B-1]=B%x?B/x%x<2|B%x<2?7:B/x&4?0:l[i++]=("ECDFBDCEAAAAAAAA"+
"IIIIIIIIMKLNJLKM@G@TSb~?A6J57IKJT576,+-48HLSUmgukgg OJNMLK  IDHGFE")
.charCodeAt(y++)-64:7);function X(c,h,e,s){c^=8;for(var o,S,C,A,R,T,G,d=e&&X(c,0
)>1e4,n,N=-1e8,O=20,K=78-h<<9;++O<99;)if((o=I[T=O])&&(G=o^c)<7){A=G--&2?8:4;C=
o-9?l[61+G]:49;do if(!(R=I[T+=l[C]])&&!!G|A<3||(R+1^c)>9&&G|A>2){if(!(R-2&7)
)return K;n=G|(c?T>29:T<91)?o:6^c;S=(R&&l[R&7|32]*2-h-G)+(n-o?110:!G&&(A<2)+1);
if(e>h||1<e&e==h&&S>2|d){I[T]=n;I[O]=0;S-=X(c,h+1,e,S-N);if(!(h||e-1|B-O|T-b|S<
-1e4))return W(),c&&setTimeout("X(8,0,2),X(8,0,1)",75);I[O]=o;I[T]=R}if(S>N||!h
&S==N&&Math.random()<.5)if(N=S,e>1)if(h?s-S<0:(B=O,b=T,0))break}while(!R&G>2||(
T=O,(G||A>2|(c?O>78:O<41)&!R)&&++C*--A))}return-K+768<N|d&&N}function W(){i=
"<table>";for(u=18;u<99;document.body.innerHTML=i+=++u%x-9?
"<th width=60 height=60 onclick='I[b="+u+
"]>8?W():X(0,0,1)'style='font-size:50px'bgcolor=#"+(u-B?u*.9&1||9:"d")+
"0f0e0>&#"+(I[u]?9808+l[67+I[u]]:160):u++&&"<tr>")B=b}W()
Por último, logré una versión con enroque y captura al paso en 1024 bytes (¡si es posible!), pero la visualización quedó en blanco y negro, mientras que la calidad de juego no resultó de mi gusto, funciona como prueba de concepto, pero no daba el ancho para el concurso. Fue archivada (aunque publicable aquí si hay ofertas interesantes :)), en favor de una versión expandida de mi participación final con enroque y captura al paso, aquí está esa versión de 1251 bytes.
// Chess (c)2010 Óscar Toledo G.
for(B=i=y=u=b=i=5-5,x=10,z=15,I=[],l=[];l[B]=("ustvrtsuqqqqqqqq"+
"yyyyyyyy}{|~z|{}@G@TSb~?A6J57IKJT576,+-48HLSUmgukgg OJNMLK  IDHGFE")
.charCodeAt(B)-64,B++<120;I[B-1]=B%x?B/x%x<2|B%x<2?7:B/x&4?0:l[u++]:7);
function X(c,h,e,S,s){c^=8;for(var T,o,L,E,D,O=20,G,N=-1e8,n,g,d=S&&X(c,0)>1e4,
C,R,A,K=78-h<<9,a=c?x:-x;++O<99;)if((o=I[T=O])&&(G=o&z^c)<7){A=G--&2?8:4;C=9-o&
z?l[61+G]:49;do{R=I[T+=l[C]];g=D=G|T+a-e?0:e;if(!R&&(G||A<3||g)||(1+R&z^c)>9&&G
|A>2){if(!(2-R&7))return K;for(E=n=G|I[T-a]-7?o&z:6^c;E;E=!E&&!d&&!(g=T,D=T<O?g
-3:g+2,I[D]<z|I[D+O-T]|I[T+=T-O])){L=(R&&l[R&7|32]*2-h-G)+(G?0:n-o&z?110:(D&&14
)+(A<2)+1);if(S>h||1<S&S==h&&L>2|d){I[T]=n,I[g]=I[D],I[O]=D?I[D]=0:0;L-=X(c,h+1
,E=G|A>1?0:T,S,L-N);if(!(h||S-1|B-O|T-b|L<-1e4))return W(y=E),c&&setTimeout(
"X(8,0,y,2),X(8,0,y,1)",75);E=1-G|A<7|D|!S|R|o<z||X(c,0)>1e4;I[O]=o;I[T]=R;I[D
]=I[g];D?I[g]=G?0:9^c:0}if(L>N||!h&L==N&&Math.random()<.5)if(N=L,S>1)if(h?s-L<0
:(B=O,b=T,0))return N}}}while(!R&G>2||(T=O,G|A>2|z<o&!R&&++C*--A))}return-K+
768<N|d&&N}function W(){i="<table>";for(u=18;u<98;document.body.innerHTML=i+=++
u%x-9?"<th width=60 height=60 onclick='I[b="+u+
"]&8?W():X(0,0,y,1)'style='font-size:50px'bgcolor=#"+(u-B?u*.9&1||9:"d")+
"0f0e0>&#"+(I[u]&15?9808+l[67+(I[u]&15)]:160)+";":u++&&"<tr>")B=b}W()
En la parte de arriba de esta página usted puede descargar el archivo ZIP con los códigos fuente.

Otros programas pequeños de ajedrez en Javascript

Douglas Bagnall de Nueva Zelanda escribió el primer juego de ajedrez en 5K de Javascript, con motivo del ya desaparecido concurso de Javascript de 5K. Los programas más pequeños basados en su código fuente exceden 4 kilobytes. Estos programas y otros están disponibles en http://p4wn.sourceforge.net/
El matemático John A. Moody de la Universidad de Warwick en el Reino Unido también ha escrito su propio ajedrez pequeño en Javascript en 2.7 kilobytes, actualmente no detecta movimientos ilegales y no maneja enroque ni captura al paso.

Ligas relacionadas

Última modificación: 03-ago-2016