Toledo Nanochess
I've improved the
Toledo Chess 1
engine to squeeze out every character possible, this reduced version was used
as the basis for
Toledo Chess 2, a chess program with
graphical interface that can be printed on a single sheet of paper!.
This latter engine brought two branches, one devoted to
create the most small chess program possible, without en passant, castling and
promotion only to queen, this is Toledo Picochess.
The other branch objective was to create the most small
full-chess program, with an enhanced evaluation function, this is
Toledo Nanochess.
With only 1258 non-blank characters, Toledo Nanochess is
the current world's smallest chess program in C, at this date (Feb/13/2009)
I'm not aware of smaller programs with this playing-strength.
The closest competitor is H.G. Muller with
Micromax v1.6 in
1433 non-blank characters. Although Toledo Nanochess is smaller, it manages to
beat gracefully Micromax v1.6, see
game 1 and
game 2, as both are deterministic programs, these are
the only possible games, also I did a
Nunn match (PGN
format), a way to test chess programs with ten predeterminated start positions
and alternating colors, so you can be sure of the real strength, the result was
+5 =11 -4 with advantage for Toledo Nanochess.
/**************************************************************************\
| Toledo Nanochess (c) Copyright 2009 Oscar Toledo G. All rights reserved |
| 1258 non-blank characters. Evolution from my winning IOCCC 2005 entry. |
| o Use D2D4 algebraic style for movements. biyubi@gmail.com Aug/10/2009 |
| o On promotion add a number for final piece (3=N, 4=B, 5=R, 6=Q) |
| o Press Enter alone for computer to play. |
| o Full legal chess moves. http://nanochess.110mb.com |
| o Remove these comments to get 1326 bytes source code (*NIX end-of-line) |
\**************************************************************************/
char*l="ustvrtsuqqqqqqqqyyyyyyyy}{|~z|{}"
" 76Lsabcddcba .pknbrq PKNBRQ ?A6J57IKJT576,+-48HLSU";
#define F getchar()&z
#define v X(0,0,0,21,
#define Z while(
#define _ ;if(
#define P return--G,y^=8,
B,i,y,u,b,I[411],*G=I,x=10,z=15,M=1e4;X(w,c,h,e,S,s){int 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&&v 0,0)>M;do{_ o=I[
p=O]){q=o&z^y _ q<7){A=q--&2?8:4;C=o-9&z?q["& .$ "]:42;do{r=I[p+=C[l]-64]_!w|p
==w){g=q|p+a-S?0:I+S _!r&(q|A<3||g)||(r+1&z^y)>9&&q|A>2){_ m=!(r-2&7))P G[1]=O,
K;J=n=o&z;E=I[p-a]&z;t=q|E-7?n:(n+=2,6^y);Z n<=t){L=r?l[r&7]*9-189-h-q:0 _ s)L
+=(1-q?l[p/x+5]-l[O/x+5]+l[p%x+6]*-~!q-l[O%x+6]+o/16*8:!!m*9)+(q?0:!(I[p-1]^n)+
!(I[p+1]^n)+l[n&7]*9-386+!!g*99+(A<2))+!(E^y^9)_ s>h||1<s&s==h&&L>z|d){p[I]=n,O
[I]=m?*g=*m,*m=0:g?*g=0:0;L-=X(s>h|d?0:p,L-N,h+1,G[1],J=q|A>1?0:p,s)_!(h||s-1|B
-O|i-n|p-b|L<-M))P y^=8,u=J;J=q-1|A<7||m||!s|d|r|o<z||v 0,0)>M;O[I]=o;p[I]=r;m?
*m=*g,*g=0:g?*g=9^y:0;}_ L>N){*G=O _ h&&c-L<0)P L;N=L _!h&s>1)i=n,B=O,b=p;}n+=J
||(g=I+p,m=p<O?g-3:g+2,*m<z|I[p+=p-O]|m[p<O?1:-1]);}}}}Z!r&q>2||(p=O,q|A>2|o>z&
!r&&++C*--A));}}}Z++O>98?O=20:e-O);P N+M*M&&N>-K+1924|d?N:0;}main(){Z++B<121)*G
++=B/x%x<2|B%x<2?7:B/x&4?0:*l++&31;Z B=19){Z B++<99)putchar(B%x?l[B[I]|16]:x)_
x-(B=F)){i=I[B+=(x-F)*x]&z;b=F;b+=(x-F)*x;Z x-(*G=F))i=*G^8^y;}else v u,5);v u,
1);}}
How to compile it
First, download the source code from
here, you can also download previous versions:
I suggest strongly to compile this chess program with the maximum
optimization allowed by your compiler, on GCC you can use:
gcc -O3 -fexpensive-optimizations toledo_nanochess.c -o toledo
How to run it
Run it without arguments. Enter movements as D2D4 and Enter
(computer will reject illegal moves), press Enter alone for computer to play
(6-ply depth analysis). Enjoy it!
WinBoard interface
I've developed a version of Toledo Nanochess with my own
integrated Winboard interface, and its source code sizes up at 2 KB!, currently
the world's smallest chess engine.
It is now available as a complete pack with source code,
logo and optimized executables for Windows.
Previously H.G. Muller has developed Max2WB, an ingenious
adaptor for using the first version of Toledo Nanochess with Winboard, and
Jim Ablett has published it kindly:
You will need a program that speaks "WinBoard", showing a
graphical board while calling Toledo Nanochess, also them can show PGN game
files, some known Winboard interfaces are:
/**************************************************************************\
| Toledo Nanochess (c) Copyright 2009 Oscar Toledo G. All rights reserved |
| 1258 non-blank characters. biyubi@gmail.com Aug/10/2009 |
| o This version includes a minimal Winboard adapter (697 extra bytes) |
| o Full legal chess moves. http://nanochess.110mb.com |
| o Remove these comments to get 2023 bytes source code (*NIX end-of-line) |
\**************************************************************************/
#include <stdio.h>
#include <time.h>
char*l="ustvrtsuqqqqqqqqyyyyyyyy}{|~z|{}"
" 76Lsabcddcba .pknbrqmove %s\n\0?A6J57IKJT576,+-48HLSU";
#define v X(0,0,0,21,
#define Z while(
#define _ ;if(
#define P return--G,y^=8,
B,i,y,u,b,I[411],*G=I,x=10,z=15,M=1e4,f,j,m,n,t,o,L,E,D,O=100;X(w,c,h,e,S,s){
int 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;D++;y^=8;G++;d=
w||s&&s>=h&&v 0,0)>M;do{_ o=I[p=O]){q=o&z^y _ q<7){A=q--&2?8:4;C=o-9&z?q[
"& .$ "]:42;do{r=I[p+=C[l]-64]_!w|p==w){g=q|p+a-S?0:I+S _!r&(q|A<3||g)||(r+1&z
^y)>9&&q|A>2){_ m=!(r-2&7))P G[1]=O,K;J=n=o&z;E=I[p-a]&z;t=q|E-7?n:(n+=2,6^y);Z
n<=t){L=r?l[r&7]*9-189-h-q:0 _ s)L+=(1-q?l[p/x+5]-l[O/x+5]+l[p%x+6]*-~!q-l[O%x+
6]+o/16*8:!!m*9)+(q?0:!(I[p-1]^n)+!(I[p+1]^n)+l[n&7]*9-386+!!g*99+(A<2))+!(E^y^
9)_ s>h||1<s&s==h&&L>z|d){p[I]=n,O[I]=m?*g=*m,*m=0:g?*g=0:0;L-=X(s>h|d?0:p,L-N,
h+1,G[1],J=q|A>1?0:p,s)_!(h||s-1|B-O|i-n|p-b|L<-M))P y^=8,u=J;J=q-1|A<7||m||!s|
d|r|o<z||v 0,0)>M;O[I]=o;p[I]=r;m?*m=*g,*g=0:g?*g=9^y:0;}_ L>N){*G=O _ h&&c-L<0
)P L;N=L _!h&s>1)i=n,B=O,b=p;}n+=J||(g=I+p,m=p<O?g-3:g+2,*m<z|I[p+=p-O]|m[p<O?1
:-1]);}}}}Z!r&q>2||(p=O,q|A>2|o>z&!r&&++C*--A));}}}Z++O>98?O=20:e-O);P N+M*M&&N
>-K+1924|d?N:0;}
#define D(z)_!strcmp(g,#z))
main(){char*a,g[80];clock_t k;setbuf(stdout,0);Z fgets(g+x,69,stdin)){sscanf(g+
x,"%9s%d%d",g,&n,&D)D(quit)break D(force)f=1 D(post)j=1 D(nopost)j=0 D(level)o=
n,E=n?n:20,O=D*6e3/E D(time)O=n/(E-L%E)D(new){_*l-'u')l-=32;G=I;B=y=u=f=L=0;Z++
B<121)*G++=B/x%x<2|B%x<2?7:B/x&4?0:*l++&31;}D(go)f=0 D(protover)puts(
"feature myname=\"Toledo Nanochess Aug/10/2009\" done=1")_ isalpha(*g)&&isdigit
(g[1])){a=g;B=*a++&z;B+=100-(*a++&z)*x;b=*a++&z;b+=100-(*a++&z)*x;i=(*a-'q'?*a-
'r'?*a-98?*a-'n'?I[B]&z^y:11:12:13:14)^y;v u,1)_!f)strcpy(g,"go");}D(go){k=
clock();D=0;n=O<50?4:5;B=21;do{m=X(0,0,0,B,u,n);t=(clock()-k)*1e2/
CLOCKS_PER_SEC;*g=B%x+96;g[1]=58-B/x;g[2]=b%x+96;g[3]=58-b/x;g[4]=I[B]-i&z?l[i&
7|16]:0;g[5]=0;n++;_ j)printf("%d %d %d %d %s\n",n,m,t,D,g);}Z m>-M&m<M&t*x<O);
_ o)L++;v u,1);printf(l+23,g);}}}
Toledo Picochess. A chess program in 1K of C
This version of the code is similar,
except that there is no en passant nor castling, and only is allowed promotion
to queen. At 944 non-blank characters or 1009 bytes (removing the comments)
is probably the smallest-ever C program that plays chess.
/**************************************************************************\
| Toledo Picochess (c) Copyright 2007 Oscar Toledo G. All rights reserved |
| 944 non-blank characters. Evolution from my winning IOCCC 2005 entry. |
| o Use D2D4 algebraic style for movements. biyubi@gmail.com Jan/21/2007 |
| o Only promotion to queen, no en passant or castling. nanochess.110mb.com|
| o Press Enter alone for computer to play (num.args+5 == depth of search) |
| o Remove these comments to get 1009-bytes source code (*NIX end-of-line) |
\**************************************************************************/
#define F (getchar()&15)
#define v main(0,0,0,0,
#define Z while(
#define P return y=~y,
#define _ ;if(
char*l="dbcefcbddabcddcba~WAB+ +BAW~ +-48HLSU?A6J57IKJT576,";B,y,
b,I[149];main(w,c,h,e,S,s){int t,o,L,E,d,O=*l,N=-1e9,p,*m=I,q,r,x=10 _*I){y=~y;
Z--O>20){o=I[p=O]_ q=o^y,q>0){q+=(q<2)*y,t=q["51#/+++"],E=q["95+3/33"];do{r=I[p
+=t[l]-64]_!w|p==w&&q>1|t+2<E|!r){d=abs(O-p)_!r&(q>1|d%x<1)|(r^y)<-1){_(r^y)<-6
)P 1e5-443*h;O[I]=0,p[I]=q<2&(89<p|30>p)?5^y:o;L=(q>1?6-q?l[p/x-1]-l[O/x-1]-q+2
:0:(p[I]-o?846:d/8))+l[r+15]*9-288+l[p%x]-h-l[O%x];L-=s>h||s==h&L>49&1<s?main(s
>h?0:p,L,h+1,e,N,s):0 _!(B-O|h|p-b|S|L<-1e4))return 0;O[I]=o,p[I]=r _ S|h&&(L>N
||!h&L==N&&1&rand())){N=L _!h&&s)B=O,b=p _ h&&c-L<S)P N;}}}t+=q<2&t+3>E&((y?O<
80:39<O)||r);}Z!r&q>2&q<6||(p=O,++t<E));}}P N+1e9?N:0;}Z I[B]=-(21>B|98<B|2>(B+
1)%x),++B<120);Z++m<9+I)30[m]=1,90[m]=~(20[m]=*l++&7),80[m]=-2;Z p=19){Z++p<O)
putchar(p%x-9?"KQRBNP .pnbrqk"[7+p[I]]:x)_ x-(B=F)){B+=O-F*x;b=F;b+=O-F*x;Z x-F
);}else v 1,3+w);v 0,1);}}
How to compile it
First, download the source code from
here.
I suggest strongly to compile this chess program with the maximum
optimization allowed by your compiler, on GCC you can use:
gcc -O3 -fexpensive-optimizations toledo_picochess.c -o toledo
How to run it
Run it without arguments to get 5-ply analysis, with one
argument to get 6-ply analysis.
Enter movements as D2D4 and Enter (computer will reject
illegal moves), press Enter alone for computer to play. Enjoy it!
Table of program sizes
A little table of program sizes.
Note: all sizes without comments.
| Program | Source bytes | Non-blank characters | IOCCC characters
|
| Toledo Picochess | 1009 | 944 | 942
|
| Toledo Nanochess | 1326 | 1258 | 1256
|
| Toledo Nanochess Winboard | 2023 | 1930 | 1925
|
| Toledo Chess 2 | 3473 | 2122 | 2039
|
| Toledo Chess 1 | 3004 | 2187 | 2045
|
Last modified: Oct/16/2009