Author: Uri Blass
Date: 10:51:02 02/09/06
Go up one level in this thread
On February 09, 2006 at 13:42:58, Tony Thomas Karippa wrote:
>On February 09, 2006 at 03:42:52, Uri Blass wrote:
>
>>On February 09, 2006 at 01:29:20, Roger D Davis wrote:
>>
>>>On February 08, 2006 at 21:23:24, Joshua Shriver wrote:
>>>
>>>>I came across this page while reading the winboard forum.
>>>>Amazing engine for being so small. Full engine in ~2000 lines of code.
>>>>
>>>>http://home.hccnet.nl/h.g.muller/max-src2.html
>>>>
>>>>Josh
>>>
>>>Anyone tested this? Would be remarkable if it plays Master strength or better in
>>>so few lines.
>>>
>>>Roger
>>
>>I read about it and asked ab out it's level.
>>It does not play well and it is even losing against weak tscp that is clearly
>>weaker than master level.
>>
>>Uri
>Do you think you can write a better engine with fewer characters??
I believe that it is possible to do it but first I need to understand the code.
I do not waste a lot of effort about it but I already replaced some names of
varaibles and replaced some defines by code that is more clear to me to get the
following code.
Note that names of one letter are not good for understanding the code and I
think that it is better to replace all names by longer names for explaining the
code.
/***************************************************************************/
/* micro-Max, */
/* A chess program smaller than 2KB (of non-blank source), by H.G. Muller */
/***************************************************************************/
/* version 3.2 (2000 characters) features: */
/* - recursive negamax search */
/* - quiescence search with recaptures */
/* - recapture extensions */
/* - (internal) iterative deepening */
/* - best-move-first 'sorting' */
/* - a hash table storing score and best move */
/* - full FIDE rules (expt minor ptomotion) and move-legality checking */
#include "stdlib.h"
#include "stdio.h"
#define K(A,B) *(int*)(T+A+(B&8)+S*(B&7))
#define J(A) K(y+A,board[y])-K(x+A,u)-K(H+A,t)
#define U 16777224
struct _ {int K,V;char X,Y,D;} A[U]; /* hash table, 16M+8 entries*/
int V=112,M=136,S=128,I=8e3,C=799,Q,N,i; /* V=0x70=rank mask, M=0x88 */
char O,K,L,
w[]={0,1,1,3,-1,3,5,9}, /* relative piece values */
o[]={-16,-15,-17,0,1,16,0,1,16,15,17,0,14,18,31,33,0, /* step-vector lists */
7,-1,11,6,8,3,6, /* 1st dir. in o[] per piece*/
6,3,5,7,4,5,3,6}, /* initial piece setup */
board[129], /* board: half of
16x8+dummy*/
T[1035], /* hash translation table */
piece_symbol[]=".?+nkbrq?*?NKBRQ"; /* piece symbols on
printout*/
D(int side,int q,int l,int e,int J,int Z,int E,int z,int depth) /* recursive
minimax search, k=moving side was replaced by side,n was replaced by depth*/
//int k,q,l,e,J,Z,E,z,n; /* (q,l)=window, e=current eval. score, E=e.p. sqr.*/
{ /* e=score, z=prev.dest; J,Z=hashkeys; return score*/
int j,r,m,v,d,h,i=9,F,G;
char t,p,u,x,y,X,Y,H,B;
struct _*a=A;
/* lookup pos. in hash table*/
j=(side*E^J)&U-9; /* try 8 consec. locations */
while ((h=A[++j].K)&&h-Z&&--i); /* first empty or match
*/
a+=i?j:0; /* dummy A[0] if miss & full*/
if(a->K) /* hit: pos. is in hash tab */
{d=a->D;v=a->V;X=a->X; /* examine stored data */
if(d>=depth) /* if depth sufficient:
*/
{if(v>=l|X&S&&v<=q|X&8)return v; /* use if window compatible */
d=depth-1; /* or use as iter. start
*/
}X&=~M;Y=a->Y; /* with best-move hint */
Y=d?Y:0; /* don't try best at d=0 */
}else d=X=Y=0; /* start iter., no best yet */
N++; /* node count (for timing) */
while (d++<depth|z==8&N<1e6&d<98) /* iterative deepening
loop */
{x=B=X; /* start scan at prev. best */
Y|=8&Y>>4; /* request try noncastl. 1st*/
m=d>1?-I:e; /* unconsidered:static eval */
do{u=board[x]; /* scan board looking for
*/
if(u&side) /* own piece (inefficient!)*/
{r=p=u&7; /* p = piece type (set r>0) */
j=o[p+16]; /* first step vector f.piece*/
while (r=p>2&r<0?-r:-o[++j]) /* loop over directions o[]
*/
{A: /* resume normal after best */
y=x;F=G=S; /* (x,y)=move, (F,G)=castl.R*/
do{H=y+=r; /* y traverses ray */
if(Y&8)H=y=Y&~M; /* sneak in prev. best move */
if(y&M)break; /* board edge hit */
if(p<3&y==E)H=y^16; /* shift capt.sqr. H if e.p.*/
t=board[H];if(t&side|p<3&!(r&7)!=!t)break; /* capt. own, bad pawn
mode */
i=99*w[t&7]; /* value of capt. piece t */
if(i<0||E-S&&board[E]&&y-E<2&E-y<2)m=I; /* K capt. or bad castling
*/
if(m>=l)goto C; /* abort on fail high */
if(h=d-(y!=z)) /* remaining depth(-recapt.)*/
{v=p<6?board[x+8]-board[y+8]:0; /* center positional pts.
*/
board[G]=board[H]=board[x]=0;board[y]=u&31; /* do move, strip
virgin-bit*/
if(!(G&M)){board[F]=side+6;v+=30;} /* castling: put R & score
*/
if(p<3) /* pawns: */
{v-=9*(((x-2)&M||board[x-2]!=u)+ /* structure, undefended
*/
((x+2)&M||board[x+2]!=u)-1); /* squares plus bias
*/
if(y+r+1&S){board[y]|=7;i+=C;} /* promote p to Q, add
score*/
}
v=-D(24-side,-l-(l>e),m>q?-m:-q,-e-v-i, /* recursive eval. of reply */
J+J(0),Z+J(8)+G-S,F,y,h); /* J,Z: hash keys */
v-=v>e; /* delayed-gain penalty */
if(z==9) /* called as move-legality */
{if(v!=-I&x==K&y==L) /* checker: if move found */
{Q=-e-i;O=F;return l;} /* & not in check, signal */
v=m; /* (prevent fail-lows on */
} /* K-capt. replies) */
board[G]=side+38;board[F]=board[y]=0;board[x]=u;board[H]=t; /* undo
move,G can be dummy */
if(Y&8){m=v;Y&=~8;goto A;} /* best=1st done,redo normal*/
if(v>m){m=v;X=x;Y=y|S&G;} /* update max, mark with S */
} /* if non castling */
t+=p<5; /* fake capt. for nonsliding*/
if(p<3&6*side+(y&V)==S /* pawn on 3rd/6th, or */
||(u&~24)==36&j==7&& /* virgin K moving sideways,*/
G&M&&board[G=(x|7)-(r>>1&7)]&32 /* 1st, virgin R in corner
G*/
&&!(board[G^1]|board[G^2]) /* 2 empty sqrs. next to
R */
){F=y;t--;} /* unfake capt., enable e.p.*/
}while(!t); /* if not capt. continue
ray*/
}}}while ((x=x+9&~M)-B); /* next sqr. of board, wrap
*/
C:if(m>I/4|m<-I/4)d=99; /* mate is indep. of depth */
m=m+I?m:-D(24-side,-I,I,0,J,Z,S,z,1)/2; /* best loses K: (stale)mate*/
if(!a->K|(a->X&M)!=M|a->D<=d) /* if new/better type/depth:*/
{a->K=Z;a->V=m;a->D=d;A->K=0; /* store in hash,dummy stays*/
a->X=X|8*(m>q)|S*(m<l);a->Y=Y; /* empty, type (limit/exact)*/
} /* encoded in X S,8 bits */
/*if(z==8)printf("%2d ply, %9d searched, %6d by
(%2x,%2x)\n",d-1,N,m,X,Y&0x77);*/
}
if(z&8){K=X;L=Y&~M;}
return m;
}
int main()
{
int j,side=8,*p,c[9];
for (i=0;i<8;i++)
{board[i]=(board[i+V]=o[i+24]+40)+8;board[i+16]=18;board[i+96]=9; /* initial
board setup*/
for (j=0;j<8;j++) board[16*j+i+8]=(i-4)*(i-4)+(j-3.5)*(j-3.5); /* center-pts
table */
} /*(in unused half
board[])*/
for (i=M;i<1035;i++) T[i]=rand()>>9;
while (1) /* play loop
*/
{for (i=0;i<121;i++) printf(" %c",i&8&&(i+=7)?10:piece_symbol[board[i]&15]); /*
print board */
p=c;while ((*p++=getchar())>10); /* read input line
*/
N=0;
if(*c-10){K=c[0]-16*c[1]+C;L=c[2]-16*c[3]+C;}else /* parse entered move */
D(side,-I,I,Q,1,1,O,8,0); /* or think up one */
for (i=0;i<U;i++) A[i].K=0; /* clear hash
table */
if(D(side,-I,I,Q,1,1,O,9,2)==I)
side^=24; /* check legality & do*/
}
return 0;
}
Uri
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.