Graphical Chess Game. 19th IOCCC. Most Portable Chess Set
This program is an evolution of my
previous IOCCC chess, the engine was reduced,
gameplay was enhanced and I managed to squeeze in a graphical interface that
works both for X/Window and Windows. Not an easy thing, in fact this program
actually is unique on Internet.
Remarks
There are so many text-based chess programs, what is that of
A1, H5, C4, D5? The queen is really pointing to the king?
So I managed to do a graphical X11 chess program (WYSIAIE,
or What You See Is An IOCCC Entry), point'n'click to move pieces is the only
required action,
Here is the source code, written in C language:
#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; }
How to compile it
First, download the source code from
here.
Because it is resource-hungry, I suggest strongly to
compile it using maximum optimization, on GCC you can use:
gcc -O3 -fexpensive-optimizations toledo3.c -o prog -lX11
As this chess program is portable, you can also download a
complete pack, source code and executable for Windows.
How to use it
These are the command-line options for the X11 version:
prog Two-players mode (useful if you don't have a board at hand)
prog 1 Human white - Computer black, level 1 (fast)
prog 2 Human white - Computer black, level 2 (medium)
prog 3 Human white - Computer black, level 3 (very slow)
prog 1 b Human black - Computer white, level 1 (fast)
prog 2 b Human black - Computer white, level 2 (medium)
prog 3 b Human black - Computer white, level 3 (very slow)
The computer will check that your moves are legal, full
legal chess moves are allowed, except minor promotions on human side.
The game will continue up to its logical conclusion, you
make a mistake and the computer surpasses you. ;)
What about the engine
Uses an alpha-beta search up to a depth of 3+level plies,
extended with quiescence search, that helps playing strength, something
around 1400 (level 1) to 1600 ELO (level 3).
It searches the board and generates moves for each piece
located, a lot of comparisons are used for en passant, castling and
promotion. Would be faster with optimizations, but that
optimizations use valuable IOCCC characters.
It plays a different game every time, using the C library
random number generator.
Known "features"
- Because this is my second X11 program (the first was
point'n'click happy face), I added sentences everywhere
until it worked. :)
- It is portable to Wind*ws (using the supplied layer.c file)
Change #include <X11/Xlib.h> to #include "layer.c" and
use a Wind*ws compiler (only tested with Dev C/C++ 4.9.9.2)
The play level is fixed, though you can change it easily (also see Extras
section below).
Of course, this is an example of an obfuscated Wind*ws
program (there exists another way of writing them?)
- It will give warnings on compilation, so you can be sure
that your compiler works.
- It will not update the window while it is "thinking"
- The space character has many useful applications, specially
when it comes about the character limit. 8)
- I still don't understand what to do after semicolons. :P
Programming challenges
- It is possible to convert this code into a
Javascript script with graphical interface.
Can you do it? (you can work on it, but I've already done it, see
Toledo Javascript Chess)
- Can you enhance the evaluation function so
it plays stronger? (I did it in Toledo Nanochess)
- Can you add better graphics? (child's play for any good programmer)
Update (Oct/07/2007)
Here is a little add-on to give status about gameplay
status on the window title bar, change v } } } } to:
v Y=y,XStoreName(d,w,- 1e6>a u,1,1)?y=~y,a u,1,
0)>1e6?y?"Black's wins": "White's wins":"Stalemate"
:"Chess"),y=Y,z=0;} } } }
For Wind*ws, Add the following line to layer.c:
void XStoreName(int a,HWND b,char *c) { SetWindowText(b,c); }
Note for the purists: this extra code exceeds the
IOCCC entry size limit.
Yet another interface
On the spirit of portability, I've worked out a
minimal text interface, that can serve as an obfuscated
reference for developing new obfuscated interfaces,
just replace all code before X(w,c,h,e,S,s) with:
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?"KQRBNP .pnbrqk"
[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 ) ; } }
Download from
here, it sizes up
to 1357 non-blank characters, but I did it still smaller, faster, and stronger,
check
Toledo Nanochess.
Extras
- Optional layer_df.c file contributed by
David Forgeas from France to support command line in Windows,
I've improved it further to allow two-players mode
(same options as X11), use with Windows' cmd.
Related links
Last modified: Apr/26/2021