Three days later and I am ready to release Yoda version 0.1. This version is simply a foundation with no serious attempt made to save characters or improve strength. It has the following features:
* 1788 bytes in size (no comments or white space)
* Alpha-beta full width search
* Static evaluation consisting of material and centre bonus for pawns, knights and bishops.
* Partial UCI support, understanding 'uci', 'isready', 'position', 'quit' and 'go'. This is enough to play a game under Arena, at least.
* Time management - Using the infomation in the 'go' command and node counts.
* All rules of chess except underpromotion (it will neither play nor accept these).
Below is the source code:
Code: Select all
#include <stdio.h>
#define V break;
#define v return
#define X strtok(0," ")
#define Q 9999
#define Z ;if(!strncmp(g,
int B[Q],z[]={205,199,200,217,196,200,199,205},M,l=1<<24,N,E,C,d,f,G,H,
L[]={10,8,21,0,8,18,0,13,1,16,15,17,0,14,18,31,33,0,1,16,0,15,16,17,0},q=Q*2;
char g[Q], *i;
int R(int D, int a, int b, int P, int n, int O, int o, int p, int r){
++N;
if (!--D)
v E;
int c=0, F=0, J, K, T, A, U, S, h, e, I, j, k;
for(;F<128;F=F+9&~8)
for(K=L[J=L[(A=B[F])&7]];K && A&M;
K=(K>0 & B[F]%8!=2) ? -K : L[++J])
for(T=F+K;1;T+=K) {
if (A%128==34 & F+K==T) /* Adjust black pawns to move downwards */
T+=2*(K=-K);
if ((T&136) || ((U=B[T])&M) || (A%8==2 && abs(K)==16 && U) ||
(A%8==2 & K*K!=256 & !U & T!=n) ||
(A%8==4 & abs(F-T)==2 & (U || !(A & B[T>F ? T+1 : T-2]&128)))) V
if (T==O | T==o | U%8==4) v q; /* Illegal previous move? */
h=(A%8==2 & abs(T-F)==32) ? T+F>>1 : q; /* Find current ep square */
/* Make move */
I=j=k=q;if (A%8==4 & abs(T-F)==2) { if (B[T-1]) V /* Castling stuff */
B[j=(I=F)+T>>1]=B[k=T>F ? T+1 : T-2];B[k]=0; }
B[T]=A&127;B[F]=0;e=(U%32)*50; /* Move pieces and calculate eval change */
if (A%32<9) e+=B[T+8]-B[F+8]; /* Positional eval update */
if (A%8==2 && ((T+K+1)&128)) { B[T]^=27;e+=1150; } /* Promotion */
if (A%8==2 & T==n) { B[n^16]=0;e+=100; } /* En-passent capture */
M^=96;E=-E-e; /* Swap side to move and update eval */
if (F==p & T==r) { C=h;d=I;f=j;v q; } /* Exit early to make move */
S=-R(D, -b, -a, P+1, h, I, j, q, q);c|=S>-q; /* Recursive search */
B[F]=A;B[T]=U; /* Undo move */
if (A%8==2 & T==n) B[n^16]=A^96; /* Undo promotion */
if (A%8==4 & abs(T-F)==2) { B[k]=B[j];B[j]=0; } /* Undo castling */
E=-E-e;M^=96; /* Reset eval and side to move */
if (N>l) v q; /* Time to end search? */
if (S>a) { /* New best move? */
a=S; /* New best score */
if (!P) { G=F;H=T; } /* If root set global to/from */
if (S>=b) v b; } /* Beta cutoff */
if (((A&135)==130 & abs(F-T)==16) || /* Double pawn moves and castling */
(A%8==4 & abs(F-T)==1) & !U) ; /* need extra iteration */
else if (U | !(A&8)) V /* Capture or not slider, exit loop */
}
/* No legal moves - checkmate/stalemate */
if (!c) { M^=96;a=(R(3, -Q, Q, 1, q, q, q, q, q)==q) ? P-Q/2 : 0;M^=96; }
v a; } /* Return score for this node */
main() {
int s, F, t, u;
N=0; /* Reset node counter */
strtok(gets(g), " ") /* Wait for commands */
Z"uci",4)) puts("id name Y\nid author D\nuciok")
Z"i",1)) puts("readyok")
Z"q",1)) exit(0)
Z"p",1)) {
C=d=f=q; /* Reset board */
for(s=E=0;s<8;++s) {
B[s+16]=194;B[s+96]=162;B[s+112]=(B[s]=z[s])-32;
B[s+32]=B[s+48]=B[s+(M=64)]=B[s+80]=F=0;
for(;F<8;++F)B[s*16+F+8]=(s&4?s^7:s)+(F&4?F^7:F); }
X; /* Make moves given by the GUI */
for(X;i=X;) R(2,-Q,Q,1,C,d,f,*i-97+(i[1]-49)*16,i[2]-97+(i[3]-49)*16); }
Z"go", 2)) {
for(;i=X;) /* Parse time left */
if (!strcmp(i+1, "time") & *i==(M&64?119:98)) l=atoi(X)<<9;
/* Search and print best move */
for(s=2;N<l;++s) if(R(s,-Q,Q,0,C,d,f,q,q)-q) { t=G;u=H; }
printf("bestmove %c%i%c%i%c\n", t%16+97, t/16+1, u%16+97, u/16+1,
((B[t]%8==2 && (u/16==0 || u/16==7)) ? 'q' : 0)); }
fflush(stdout); /* Ensure our data reaches the GUI */
main(); } /* 'Loop' back to start */
[moderation]
I updated the thread name to Iota instead of Yoda.
/Julien
[/moderation]