/* ------------------------------------------------------ */ /* NGplay_61.c */ /* A Simple Negamax Alpha/Beta Chess Engine */ /* Features : iterative deepening, Null move heuristic */ /* Author: George Georgopoulos (c) 2010 */ /* ------------------------------------------------------ */ #include "propeller2.h" #include #include #include #include //RJA #include #include "time.h" /* -------------------- HEADER -------------------------- */ #define Abs(a) (((a) > 0) ? (a) : -(a)) #define Max(a,b) (((a) > (b)) ? (a) : (b)) #define Min(a,b) (((a) < (b)) ? (a) : (b)) #define SECONDS_PASSED ((GetMillisecs() - start_time)/1000.0) #define _NORMAL_OUTPUT 1 #define _XBOARD_OUTPUT 2 #define MAX_STACK 256 #define MAXMV 100 #define START_DEPTH 3 #define MAX_DEPTH 32 #define PV_CHANGE_THRESH 50 #define MAXSORTEDMOVES 1 #define THREAT_MOVE_THRESH 5 #define MAX_BOOK_MATCHLINES 5500 #define INFINITY 10000 #define CUTOFF 9000 #define NULL_DEPTH 3 #define TERMINAL_NODE -1 #define white 1 #define black 10 #define none 3 /* This is the piece values. Black pieces have the relevant white value + 10(black) Pieces are ordered from lower value to high value so we can use this for move ordering */ enum {WPAWN=2,WKNIGHT,WBISHOP,WROOK,WQUEEN,WKING,BPAWN=12,BKNIGHT,BBISHOP,BROOK,BQUEEN,BKING}; #define PIECEMAX 18 #define LightSq 1 #define DarkSq 2 #define TwoColor 3 #define PAWN_V 100 #define KNIGHT_V 320 #define BISHOP_V 333 #define ROOK_V 510 #define QUEEN_V 880 enum {NORMAL=0,CASTL,PROMOT}; typedef enum { A1=21, B1, C1, D1, E1, F1, G1, H1, A2=31, B2, C2, D2, E2, F2, G2, H2, A3=41, B3, C3, D3, E3, F3, G3, H3, A4=51, B4, C4, D4, E4, F4, G4, H4, A5=61, B5, C5, D5, E5, F5, G5, H5, A6=71, B6, C6, D6, E6, F6, G6, H6, A7=81, B7, C7, D7, E7, F7, G7, H7, A8=91, B8, C8, D8, E8, F8, G8, H8, ENDSQ } squares; struct mvdata { char flag; /*0=NULL,1=Normal >1=promotion piece*/ char from; char to; char dummy; }; typedef union { struct mvdata m; int u; } MOVE; typedef struct LINE { int cmove; /* Number of moves in the line.*/ MOVE argmove[MAXMV]; /* The line. */ /*int scores[MAXMV]; Scores already calculated */ /*int levels[MAXMV]; The depth of previous calc */ } LINE; typedef struct piece_st { int type; int xy; } PIECE; /* -------------------- GLOBALS ------------------------- */ PIECE Wpieces[16], Bpieces[16], empty_p={0,0}, fence_p={-1,-1}; PIECE *board[120] = { &fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p, &fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p, &fence_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&fence_p, &fence_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&fence_p, &fence_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&fence_p, &fence_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&fence_p, &fence_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&fence_p, &fence_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&fence_p, &fence_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&fence_p, &fence_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&empty_p,&fence_p, &fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p, &fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p,&fence_p }; int board64[64] = {A1, B1, C1, D1, E1, F1, G1, H1, A2, B2, C2, D2, E2, F2, G2, H2, A3, B3, C3, D3, E3, F3, G3, H3, A4, B4, C4, D4, E4, F4, G4, H4, A5, B5, C5, D5, E5, F5, G5, H5, A6, B6, C6, D6, E6, F6, G6, H6, A7, B7, C7, D7, E7, F7, G7, H7, A8, B8, C8, D8, E8, F8, G8, H8}; int RowNum[120] ={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,1,1,1,1,1,1,1,1,0, 0,2,2,2,2,2,2,2,2,0, 0,3,3,3,3,3,3,3,3,0, 0,4,4,4,4,4,4,4,4,0, 0,5,5,5,5,5,5,5,5,0, 0,6,6,6,6,6,6,6,6,0, 0,7,7,7,7,7,7,7,7,0, 0,8,8,8,8,8,8,8,8,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0}; int ColNum[120] ={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,1,2,3,4,5,6,7,8,0, 0,1,2,3,4,5,6,7,8,0, 0,1,2,3,4,5,6,7,8,0, 0,1,2,3,4,5,6,7,8,0, 0,1,2,3,4,5,6,7,8,0, 0,1,2,3,4,5,6,7,8,0, 0,1,2,3,4,5,6,7,8,0, 0,1,2,3,4,5,6,7,8,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0}; int Central[120]={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,1,1,0,0,0,0, 0,0,0,0,1,1,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0}; int PartCen[120]={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,1,1,1,1,0,0,0, 0,0,0,1,0,0,1,0,0,0, 0,0,0,1,0,0,1,0,0,0, 0,0,0,1,1,1,1,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0}; int WhiteSq[120]={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,1,0,1,0,1,0,1,0, 0,1,0,1,0,1,0,1,0,0, 0,0,1,0,1,0,1,0,1,0, 0,1,0,1,0,1,0,1,0,0, 0,0,1,0,1,0,1,0,1,0, 0,1,0,1,0,1,0,1,0,0, 0,0,1,0,1,0,1,0,1,0, 0,1,0,1,0,1,0,1,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0}; int PartEdg[120]={0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,1,1,1,1,1,1,0,0, 0,0,1,0,0,0,0,1,0,0, 0,0,1,0,0,0,0,1,0,0, 0,0,1,0,0,0,0,1,0,0, 0,0,1,0,0,0,0,1,0,0, 0,0,1,1,1,1,1,1,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0}; int Edge[120]= {0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,1,1,1,1,1,1,1,1,0, 0,1,0,0,0,0,0,0,1,0, 0,1,0,0,0,0,0,0,1,0, 0,1,0,0,0,0,0,0,1,0, 0,1,0,0,0,0,0,0,1,0, 0,1,0,0,0,0,0,0,1,0, 0,1,0,0,0,0,0,0,1,0, 0,1,1,1,1,1,1,1,1,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0}; int wking=E1, bking=E8; int EnPassantSq=0; int wra1moved=0, wrh1moved=0, wkmoved=0, bra8moved=0, brh8moved=0, bkmoved=0; int hash_board[PIECEMAX][64]; int hash_side; struct cst { int wk; int wra1; int wrh1; int bk; int bra8; int brh8; } cstack[MAX_STACK]; /* kings & rooks status stack */ int cst_p=0; struct mvst { MOVE move; PIECE *captured; int capt; int special; /* values: NORMAL,CASTL,PROMOT */ int PositionHash; } move_stack[MAX_STACK]; /* move stack */ int mv_stack_p=0; MOVE wmoves[MAXMV], bmoves[MAXMV]; int side=white; int max_time = 180*1000; /* default level 3 minutes / move ---> 40 moves in 2 hours */ int start_time; int stop_time; int NotStartingPosition=0; int nodes; int Starting_Mv; FILE* fpDebugOutput = NULL; char DbgBuff[256]; int ComputerSide = black; int HalfMovesPlayed=0, FiftyMoves=0; int Xoutput=0;//RJA; FILE *book_file=NULL; char CurrentLine[2048] = {'\0','\0'}; int MatchingBookMoves[MAX_BOOK_MATCHLINES]; int Pieces=0; int LoneKingReachedEdge=0; unsigned long Rnext = 1; LINE GlobalPV; LINE Ldef; MOVE PlayerMove; int TimeIsUp, ngmax=-INFINITY, PrevNgmax=-INFINITY, danger, CriticalAnswer, WHasCastled, BHasCastled; MOVE Threat; /* -------------------- FUNCTION DEFINITION ------------- */ char ShowPieceIcon(int typ) { switch(typ) { case WROOK : return 'R'; case WKNIGHT: return 'N'; case WBISHOP: return 'B'; case WQUEEN : return 'Q'; case WKING : return 'K'; case WPAWN : return 'P'; case BROOK : return 'r'; case BKNIGHT: return 'n'; case BBISHOP: return 'b'; case BQUEEN : return 'q'; case BKING : return 'k'; case BPAWN : return 'p'; case 0 : return 'E'; default: return '?'; } } /* ------------------------------------------------------ */ char * ShowSquare(int xy) { static char sqb[3]={'\0','\0','\0'}; if (xy==0) { sqb[0]=sqb[1]='.'; } else { sqb[0] = (char)((xy%10-1)+'a'); sqb[1] = (char)((xy/10-2)+'1'); } return sqb; } /* ------------------------------------------------------ */ void ShowPieces(void) {/* for debug */ int i; printf("White:"); for (i=0; i<16; i++) { printf("%c%s ",ShowPieceIcon(Wpieces[i].type),ShowSquare(Wpieces[i].xy)); } printf("\nBlack:"); for (i=0; i<16; i++) { printf("%c%s ",ShowPieceIcon(Bpieces[i].type),ShowSquare(Bpieces[i].xy)); } printf(" Empty(%c%s)",ShowPieceIcon(empty_p.type),ShowSquare(empty_p.xy)); printf("\n\n"); } /* ------------------------------------------------------ */ void InitPieces(void) { int i; Wpieces[0].type = WKING; Wpieces[0].xy = 0; Wpieces[1].type = WQUEEN; Wpieces[1].xy = 0; Wpieces[2].type = WROOK; Wpieces[2].xy = 0; Wpieces[3].type = WROOK; Wpieces[3].xy = 0; Wpieces[4].type = WBISHOP; Wpieces[4].xy = 0; Wpieces[5].type = WBISHOP; Wpieces[5].xy = 0; Wpieces[6].type = WKNIGHT; Wpieces[6].xy = 0; Wpieces[7].type = WKNIGHT; Wpieces[7].xy = 0; for (i=8; i<16; i++) { Wpieces[i].type = WPAWN; Wpieces[i].xy = 0; } Bpieces[0].type = BKING; Bpieces[0].xy = 0; Bpieces[1].type = BQUEEN; Bpieces[1].xy = 0; Bpieces[2].type = BROOK; Bpieces[2].xy = 0; Bpieces[3].type = BROOK; Bpieces[3].xy = 0; Bpieces[4].type = BBISHOP; Bpieces[4].xy = 0; Bpieces[5].type = BBISHOP; Bpieces[5].xy = 0; Bpieces[6].type = BKNIGHT; Bpieces[6].xy = 0; Bpieces[7].type = BKNIGHT; Bpieces[7].xy = 0; for (i=8; i<16; i++) { Bpieces[i].type = BPAWN; Bpieces[i].xy = 0; } } /* ------------------------------------------------------ */ int Myrand(void) { Rnext = Rnext * 1103515245 + 12345; return ((unsigned)(Rnext/65536) % 32768); } /* ------------------------------------------------------ */ void Mysrand(unsigned seed) { Rnext = seed; } /* ------------------------------------------------------ */ int GetMillisecs(void) { //struct time timebuffer; //ftime(&timebuffer); //return (timebuffer.time * 1000) + timebuffer.millitm; return time(NULL)*1000; } /* ------------------------------------------------------ */ int NextSide(int color) { if (color==white) { return black; } else { return white; } } /* ------------------------------------------------------ */ void ExitErrorMesg(char *msg) { fprintf(stderr,"\n\n%s\n\n",msg); exit(1); } /* ------------------------------------------------------ */ void EmptyBoard(void) { register int i; InitPieces(); for (i=0; i<64; i++) { board[board64[i]]=&empty_p; } } /* ------------------------------------------------------ */ void FileDebug(char *str) { if ( (fpDebugOutput = fopen("ggdebug.txt", "a")) ) { fprintf(fpDebugOutput,"%s", str); fclose(fpDebugOutput); } } /* ------------------------------------------------------ */ int HashRand(void ) { int i; int r; for (i = 0; i < 32; ++i) { r ^= Myrand() << i; } return r; } /* ------------------------------------------------------ */ void InitHash(void) { int i, j ; /*printf("\n");*/ Mysrand(17); for (i = 0; i < PIECEMAX; ++i) for (j = 0; j < 64; ++j) { hash_board[i][j] = HashRand(); /*printf("%lld, ",hash_board[i][j]);*/ } hash_side = HashRand(); } /* ------------------------------------------------------ */ int GetPositionHash(void) { register int i, ret; ret = 0; for (i=0; i<64; i++) { ret ^= hash_board[ board[board64[i]]->type ][i]; } if (side==black) ret ^= hash_side; return ret; } /* ------------------------------------------------------ char * PositionString(void) { static char PosStr[100]; int xy, piece, pos, spaces; pos=0; spaces=0; for (xy=21; xy<99; xy++) { if (board[xy]<0) continue; piece=board[xy]; if (piece==0) { spaces++; if (spaces==8) { PosStr[pos] = '8'; pos++; spaces=0; } } else { if (spaces) { PosStr[pos] = spaces + '0'; pos++; spaces=0; } if (piece>black) { piece -= black; switch(piece) { case rook : PosStr[pos] = 'r'; break; case knight: PosStr[pos] = 'n'; break; case bishop: PosStr[pos] = 'b'; break; case queen : PosStr[pos] = 'q'; break; case king : PosStr[pos] = 'k'; break; case pawn : PosStr[pos] = '@'; break; } } else { switch(piece) { case rook : PosStr[pos] = 'R'; break; case knight: PosStr[pos] = 'N'; break; case bishop: PosStr[pos] = 'B'; break; case queen : PosStr[pos] = 'Q'; break; case king : PosStr[pos] = 'K'; break; case pawn : PosStr[pos] = 'o'; break; } } pos++; } } if (spaces) { PosStr[pos] = spaces + '0'; pos++; } PosStr[pos++] = ' '; if (side==black) { PosStr[pos++] = 'b'; } else { PosStr[pos++] = 'w'; } PosStr[pos++] = ' '; if (wkmoved || wrh1moved) { PosStr[pos] = '-'; } else { PosStr[pos] = 'K'; } pos++; if (wkmoved || wra1moved) { PosStr[pos] = '-'; } else { PosStr[pos] = 'Q'; } pos++; if (bkmoved || brh8moved) { PosStr[pos] = '-'; } else { PosStr[pos] = 'k'; } pos++; if (bkmoved || bra8moved) { PosStr[pos] = '-'; } else { PosStr[pos] = 'q'; } pos++; PosStr[pos] = '\0'; return (&PosStr[0]); } ------------------------------------------------------ */ int HashPosAlreadyExamined(void) { int i; int hashP = GetPositionHash(); for (i = 1; i < mv_stack_p; ++i) { if (hashP == move_stack[i].PositionHash) return 1; } return 0; } /* ------------------------------------------------------ */ int HashRepetitions(void) { int i; int ret = 0; int hashP = GetPositionHash(); for (i = 1; i < mv_stack_p; ++i) { if (hashP == move_stack[i].PositionHash) ++ret; } return ret; } /* ------------------------------------------------------ */ void InitTime(void) { start_time = GetMillisecs(); stop_time = start_time + max_time; } /* ------------------------------------------------------ */ int CheckTime(void) { if (GetMillisecs() >= stop_time) { return 1; } return 0; } /* ------------------------------------------------------ */ int ParsePlayerMove(const char* buf, MOVE *mp) { int x1,y1,x2,y2; if (buf[0]>='a' && buf[0]<='h') { x1 = buf[0] - 'a'; if (buf[1]>='1' && buf[1]<='8') { y1 = buf[1] - '1'; if (buf[2]>='a' && buf[2]<='h') { x2 = buf[2] - 'a'; if (buf[3]>='1' && buf[3]<='8') { y2 = buf[3] - '1'; } else {/* not 1-8 */ return 0; } } else {/* not a-h */ return 0; } }else { /* not 1-8 */ return 0; } } else { /* not a-h */ return 0; } mp->m.from = 10*y1+x1+21; mp->m.to = 10*y2+x2+21; if (board[mp->m.from]->type==WPAWN) { if (mp->m.to>=A8) { switch(buf[4]) { case 'r': mp->m.flag=WROOK; break; case 'n': mp->m.flag=WKNIGHT; break; case 'b': mp->m.flag=WBISHOP; break; case 'q': mp->m.flag=WQUEEN; break; default: break; } } else mp->m.flag=WPAWN; } else if (board[mp->m.from]->type==BPAWN) { if (mp->m.to<=H1) { switch(buf[4]) { case 'r': mp->m.flag=BROOK; break; case 'n': mp->m.flag=BKNIGHT; break; case 'b': mp->m.flag=BBISHOP; break; case 'q': mp->m.flag=BQUEEN; break; default: break; } } else mp->m.flag=BPAWN; } else { mp->m.flag=1; } mp->m.dummy=0; return 1; } /* ------------------------------------------------------ */ void PushStatus(void) { cst_p++; cstack[cst_p].wk = wkmoved; cstack[cst_p].wra1=wra1moved; cstack[cst_p].wrh1=wrh1moved; cstack[cst_p].bk = bkmoved; cstack[cst_p].bra8=bra8moved; cstack[cst_p].brh8=brh8moved; } /* ------------------------------------------------------ */ void PopStatus(void) { wkmoved = cstack[cst_p].wk; wra1moved = cstack[cst_p].wra1; wrh1moved = cstack[cst_p].wrh1; bkmoved = cstack[cst_p].bk; bra8moved = cstack[cst_p].bra8; brh8moved = cstack[cst_p].brh8; cst_p--; } /* ------------------------------------------------------ */ int EnPassant(int xy1,int xy2,int *xyc) { if (board[xy1]->type==WPAWN) { if (xy2-xy1==11 || xy2-xy1==9) { if (board[xy2]->type==0) { *xyc = xy2-10; return 1; } } } else if (board[xy1]->type==BPAWN) { if (xy2-xy1==-11 || xy2-xy1==-9) { if (board[xy2]->type==0) { *xyc = xy2+10; return 1; } } } return 0; } /* ------------------------------------------------------ */ void TryMove(MOVE *mp) { int xyc; register int xy1 =mp->m.from; register int xy2 =mp->m.to; register int flag=mp->m.flag; mv_stack_p++; move_stack[mv_stack_p].move.u = mp->u; move_stack[mv_stack_p].special = NORMAL; if (board[xy1]->type==WPAWN) { if (EnPassant(xy1,xy2,&xyc)) { move_stack[mv_stack_p].captured = board[xyc]; move_stack[mv_stack_p].capt = xyc; } else { if (flag>=WKNIGHT && flagtype = flag; move_stack[mv_stack_p].special=PROMOT; } xyc=xy2; move_stack[mv_stack_p].captured = board[xyc]; move_stack[mv_stack_p].capt = xyc; } } else if (board[xy1]->type==BPAWN) { if (EnPassant(xy1,xy2,&xyc)) { move_stack[mv_stack_p].captured = board[xyc]; move_stack[mv_stack_p].capt = xyc; } else { if (flag>=BKNIGHT && flagtype = flag; move_stack[mv_stack_p].special=PROMOT; } xyc=xy2; move_stack[mv_stack_p].captured = board[xyc]; move_stack[mv_stack_p].capt = xyc; } } else { xyc=xy2; move_stack[mv_stack_p].captured = board[xyc]; move_stack[mv_stack_p].capt = xyc; } board[xyc]->xy = 0; /* Captured piece struct modified */ board[xy1]->xy = xy2; /* Moving piece struct modified */ board[xyc] = &empty_p; board[xy2] = board[xy1]; board[xy1] = &empty_p; if (board[xy2]->type==WKING) { wking = xy2; if (xy1==E1) { if (xy2==G1) { /* white short castle */ board[F1] = board[H1]; board[F1]->xy = F1; board[H1] = &empty_p; move_stack[mv_stack_p].special = CASTL; } else if (xy2==C1) { /* white long castle */ board[D1] = board[A1]; board[D1]->xy = D1; board[A1] = &empty_p; move_stack[mv_stack_p].special = CASTL; } } } else if (board[xy2]->type==BKING) { bking = xy2; if (xy1==E8) { if (xy2==G8) { /* black short castle */ board[F8] = board[H8]; board[F8]->xy = F8; board[H8] = &empty_p; move_stack[mv_stack_p].special = CASTL; } else if (xy2==C8) { /* black long castle */ board[D8] = board[A8]; board[D8]->xy = D8; board[A8] = &empty_p; move_stack[mv_stack_p].special = CASTL; } } } } /* ------------------------------------------------------ */ void MakeMove(MOVE *mp) { register int i, xy1, xy2, flag; int xyc; xy1 = mp->m.from; xy2 = mp->m.to; flag = mp->m.flag; mv_stack_p++; move_stack[mv_stack_p].move.u = mp->u; if (xy1==A1) { wra1moved=1; } else if (xy1==A8) { bra8moved=1; } else if (xy1==H1) { wrh1moved=1; } else if (xy1==H8) { brh8moved=1; } if (xy1==E1) { wkmoved=1; if (xy2==G1 || xy2==C1) WHasCastled=1; } else if (xy1==E8) { bkmoved=1; if (xy2==G8 || xy2==C8) BHasCastled=1; } EnPassantSq=0; move_stack[mv_stack_p].special = NORMAL; if (board[xy1]->type==WPAWN) { if (EnPassant(xy1,xy2,&xyc)) { move_stack[mv_stack_p].captured = board[xyc]; move_stack[mv_stack_p].capt = xyc; } else { if (flag>=WKNIGHT && flagtype = flag; move_stack[mv_stack_p].special=PROMOT; } xyc=xy2; move_stack[mv_stack_p].captured = board[xyc]; move_stack[mv_stack_p].capt = xyc; if (xy2-xy1==20) { EnPassantSq=xy1+10; } } } else if (board[xy1]->type==BPAWN) { if (EnPassant(xy1,xy2,&xyc)) { move_stack[mv_stack_p].captured = board[xyc]; move_stack[mv_stack_p].capt = xyc; } else { if (flag>=BKNIGHT && flagtype = flag; move_stack[mv_stack_p].special=PROMOT; } xyc=xy2; move_stack[mv_stack_p].captured = board[xyc]; move_stack[mv_stack_p].capt = xyc; if (xy1-xy2==20) { EnPassantSq=xy1-10; } } } else { xyc=xy2; move_stack[mv_stack_p].captured = board[xyc]; move_stack[mv_stack_p].capt = xyc; } board[xyc]->xy = 0; /* Captured piece struct modified */ board[xy1]->xy = xy2; /* Moving piece struct modified */ board[xyc] = &empty_p; board[xy2] = board[xy1]; board[xy1] = &empty_p; if (board[xy2]->type==WKING) { wking = xy2; if (xy1==E1) { if (xy2==G1) { /* white short castle */ board[F1] = board[H1]; board[F1]->xy = F1; board[H1] = &empty_p; move_stack[mv_stack_p].special = CASTL; } else if (xy2==C1) { /* white long castle */ board[D1] = board[A1]; board[D1]->xy = D1; board[A1] = &empty_p; move_stack[mv_stack_p].special = CASTL; } } } else if (board[xy2]->type==BKING) { bking = xy2; if (xy1==E8) { if (xy2==G8) { /* black short castle */ board[F8] = board[H8]; board[F8]->xy = F8; board[H8] = &empty_p; move_stack[mv_stack_p].special = CASTL; } else if (xy2==C8) { /* black long castle */ board[D8] = board[A8]; board[D8]->xy = D8; board[A8] = &empty_p; move_stack[mv_stack_p].special = CASTL; } } } move_stack[mv_stack_p].PositionHash = GetPositionHash(); } /* ------------------------------------------------------ */ void RetractLastMove(void) { register int xy1=move_stack[mv_stack_p].move.m.from; register int xy2=move_stack[mv_stack_p].move.m.to; register int cpt=move_stack[mv_stack_p].capt; board[xy1] = board[xy2]; board[xy1]->xy = xy1; board[xy2] = &empty_p; board[cpt] = move_stack[mv_stack_p].captured; if (board[cpt] != &empty_p) board[cpt]->xy = cpt; if (move_stack[mv_stack_p].special==PROMOT) { if (xy1>=A7) { /* white pawn promotion */ board[xy1]->type = WPAWN; } else { /* black pawn promotion */ board[xy1]->type = BPAWN; } } else { if (board[xy1]->type==WKING) { wking=xy1; } else if (board[xy1]->type==BKING) { bking=xy1; } if (move_stack[mv_stack_p].special==CASTL) { if (xy1==E1) { /* white castle */ if (xy2==G1) { board[H1] = board[F1]; board[H1]->xy = H1; board[F1] = &empty_p; } else if (xy2==C1) { board[A1] = board[D1]; board[A1]->xy = A1; board[D1] = &empty_p; } else ExitErrorMesg("Internal - error in castle moves "); } else if (xy1==E8) { /* black castle */ if (xy2==G8) { board[H8] = board[F8]; board[H8]->xy = H8; board[F8] = &empty_p; } else if (xy2==C8) { board[A8] = board[D8]; board[A8]->xy = A8; board[D8] = &empty_p; } else ExitErrorMesg("Internal - error in castle moves "); } else ExitErrorMesg("Internal - error in castle moves "); } } move_stack[mv_stack_p].PositionHash = 0; mv_stack_p--; } /* ------------------------------------------------------ */ char *pieceicon(int x, int y) { static char s[3]; int c = (x+y)%2 ? ' ' : '-'; int piece=board[10*y+x+21]->type; s[0]=c; s[1]=c; s[2]='\0'; switch(piece) { case WROOK : s[0] = 'R'; break; case WKNIGHT: s[0] = 'N'; break; case WBISHOP: s[0] = 'B'; break; case WQUEEN : s[0] = 'Q'; break; case WKING : s[0] = 'K'; break; case WPAWN : s[0] = 'o'; break; case BROOK : s[0] = 'r'; break; case BKNIGHT: s[0] = 'n'; break; case BBISHOP: s[0] = 'b'; break; case BQUEEN : s[0] = 'q'; break; case BKING : s[0] = 'k'; break; case BPAWN : s[0] = '@'; break; } return s; } /* ------------------------------------------------------ */ void ShowBoard(void) { int x,y, xy; fprintf(stderr,"\n\n"); fprintf(stderr," +--+--+--+--+--+--+--+--+\n"); for (y=7; y>0; y--) { fprintf(stderr,"%2d ",y+1); for (x=0; x<8; x++) { xy=10*y+x+21; fprintf(stderr,"|%s",pieceicon(x,y)); } fprintf(stderr,"|\n +--+--+--+--+--+--+--+--+\n"); } fprintf(stderr," 1 "); for (x=0; x<8; x++) { xy=10*y+x+21; fprintf(stderr,"|%s",pieceicon(x,y)); } fprintf(stderr,"|\n +--+--+--+--+--+--+--+--+\n"); fprintf(stderr," a b c d e f g h\n\n"); ShowPieces(); } /* ------------------------------------------------------ */ void ReadPosition(char *fname) { FILE *fp; char cbuf[81], *cp, mbuf[60]; int i, color=-1, wkf=0, bkf=0, line=0, Ppos; if ((fp=fopen(fname,"r"))==NULL) { ExitErrorMesg("Cannot Open position file"); } EmptyBoard(); while ( fgets(cbuf,80,fp)!=NULL) { line++; /* if (strstr(cbuf,"Side")!=NULL || strstr(cbuf,"Side")!=NULL) { cp = cbuf; while (*cp && (*cp<'0' || *cp>'9')) { cp++; } SideToMove = atoi(cp); } else */ if (strstr(cbuf,"white")!=NULL || strstr(cbuf,"White")!=NULL) { color=0; } else if (strstr(cbuf,"black")!=NULL || strstr(cbuf,"Black")!=NULL) { color=1; } else if (color==0) { cp = cbuf; while (*cp && *(cp+1) && *(cp+2)) { switch (*cp) { case '\n': case '\t': case ',': case ' ': cp++; break; case 'K': if (*(cp+1)<'a' || *(cp+1)>'h' || *(cp+2)<'1' || *(cp+2)>'8'){ sprintf(mbuf,"Error in Position line %d ->'K%c%c'",line,*(cp+1),*(cp+2)); ExitErrorMesg(mbuf); } if (wkf==1) ExitErrorMesg("Illegal Position. Too many white kings."); Ppos = 10*(cp[2]-'1')+cp[1]-'a'+21; wkf=1; wking = Ppos; board[Ppos] = &Wpieces[0]; Wpieces[0].xy = Ppos; cp+=3; break; case 'Q': if (*(cp+1)<'a' || *(cp+1)>'h' || *(cp+2)<'1' || *(cp+2)>'8') { sprintf(mbuf,"Error in Position line %d ->'Q%c%c'",line,*(cp+1),*(cp+2)); ExitErrorMesg(mbuf); } Ppos = 10*(cp[2]-'1')+cp[1]-'a'+21; if (Wpieces[1].xy==0) { board[Ppos]=&Wpieces[1]; Wpieces[1].xy = Ppos; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Wpieces[i].xy==0) { board[Ppos]=&Wpieces[i]; Wpieces[i].xy = Ppos; Wpieces[i].type = WQUEEN; break; } else if (i==15) { ExitErrorMesg("Illegal Position. Too many white queens."); } } } cp+=3; break; case 'R': if (*(cp+1)<'a' || *(cp+1)>'h' || *(cp+2)<'1' || *(cp+2)>'8') { sprintf(mbuf,"Error in Position line %d ->'R%c%c'",line,*(cp+1),*(cp+2)); ExitErrorMesg(mbuf); } Ppos = 10*(cp[2]-'1')+cp[1]-'a'+21; if (Wpieces[2].xy==0) { board[Ppos]=&Wpieces[2]; Wpieces[2].xy = Ppos; } else if (Wpieces[3].xy==0) { board[Ppos]=&Wpieces[3]; Wpieces[3].xy = Ppos; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Wpieces[i].xy==0) { board[Ppos]=&Wpieces[i]; Wpieces[i].xy = Ppos; Wpieces[i].type = WROOK; break; } else if (i==15) { ExitErrorMesg("Illegal Position. Too many white rooks."); } } } cp+=3; break; case 'B': if (*(cp+1)<'a' || *(cp+1)>'h' || *(cp+2)<'1' || *(cp+2)>'8') { sprintf(mbuf,"Error in Position line %d ->'B%c%c'",line,*(cp+1),*(cp+2)); ExitErrorMesg(mbuf); } Ppos = 10*(cp[2]-'1')+cp[1]-'a'+21; if (Wpieces[4].xy==0) { board[Ppos]=&Wpieces[4]; Wpieces[4].xy = Ppos; } else if (Wpieces[5].xy==0) { board[Ppos]=&Wpieces[5]; Wpieces[5].xy = Ppos; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Wpieces[i].xy==0) { board[Ppos]=&Wpieces[i]; Wpieces[i].xy = Ppos; Wpieces[i].type = WBISHOP; break; } else if (i==15) { ExitErrorMesg("Illegal Position. Too many white bishops."); } } } cp+=3; break; case 'N': if (*(cp+1)<'a' || *(cp+1)>'h' || *(cp+2)<'1' || *(cp+2)>'8') { sprintf(mbuf,"Error in Position line %d ->'N%c%c'",line,*(cp+1),*(cp+2)); ExitErrorMesg(mbuf); } Ppos = 10*(cp[2]-'1')+cp[1]-'a'+21; if (Wpieces[6].xy==0) { board[Ppos]=&Wpieces[6]; Wpieces[6].xy = Ppos; } else if (Wpieces[7].xy==0) { board[Ppos]=&Wpieces[7]; Wpieces[7].xy = Ppos; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Wpieces[i].xy==0) { board[Ppos]=&Wpieces[i]; Wpieces[i].xy = Ppos; Wpieces[i].type = WKNIGHT; break; } else if (i==15) { ExitErrorMesg("Illegal Position. Too many white knights."); } } } cp+=3; break; case 'P': cp++; default: if (*cp<'a' || *cp>'h' || *(cp+1)<'1' || *(cp+1)>'8') { sprintf(mbuf,"Error in Position line %d ->'%c%c'",line,*cp,*(cp+1)); ExitErrorMesg(mbuf); } Ppos = 10*(cp[1]-'1')+cp[0]-'a'+21; if (Ppos <= H1 || Ppos >= A8) { ExitErrorMesg("Illegal White pawn"); } for (i=8; i<16; i++) { if (Wpieces[i].xy==0) { board[Ppos]=&Wpieces[i]; Wpieces[i].xy = Ppos; break; } else if (i==15) { ExitErrorMesg("Illegal Position. Too many white pawns."); } } cp+=2; break; } } } else if (color==1) { cp = cbuf; while (*cp && *(cp+1) && *(cp+2)) { switch (*cp) { case '\n': case '\t': case ',': case ' ': cp++; break; case 'K': if (*(cp+1)<'a' || *(cp+1)>'h' || *(cp+2)<'1' || *(cp+2)>'8') { sprintf(mbuf,"Error in Position line %d ->'K%c%c'",line,*(cp+1),*(cp+2)); ExitErrorMesg(mbuf); } if (bkf==1) ExitErrorMesg("Illegal Position. Too many black kings."); Ppos = 10*(cp[2]-'1')+cp[1]-'a'+21; bkf=1; bking = Ppos; board[Ppos] = &Bpieces[0]; Bpieces[0].xy = Ppos; cp+=3; break; case 'Q': if (*(cp+1)<'a' || *(cp+1)>'h' || *(cp+2)<'1' || *(cp+2)>'8') { sprintf(mbuf,"Error in Position line %d ->'Q%c%c'",line,*(cp+1),*(cp+2)); ExitErrorMesg(mbuf); } Ppos = 10*(cp[2]-'1')+cp[1]-'a'+21; if (Bpieces[1].xy==0) { board[Ppos]=&Bpieces[1]; Bpieces[1].xy = Ppos; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Bpieces[i].xy==0) { board[Ppos]=&Bpieces[i]; Bpieces[i].xy = Ppos; Bpieces[i].type = BQUEEN; break; } else if (i==15) { ExitErrorMesg("Illegal Position. Too many black queens."); } } } cp+=3; break; case 'R': if (*(cp+1)<'a' || *(cp+1)>'h' || *(cp+2)<'1' || *(cp+2)>'8') { sprintf(mbuf,"Error in Position line %d ->'R%c%c'",line,*(cp+1),*(cp+2)); ExitErrorMesg(mbuf); } Ppos = 10*(cp[2]-'1')+cp[1]-'a'+21; if (Bpieces[2].xy==0) { board[Ppos]=&Bpieces[2]; Bpieces[2].xy = Ppos; } else if (Bpieces[3].xy==0) { board[Ppos]=&Bpieces[3]; Bpieces[3].xy = Ppos; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Bpieces[i].xy==0) { board[Ppos]=&Bpieces[i]; Bpieces[i].xy = Ppos; Bpieces[i].type = BROOK; break; } else if (i==15) { ExitErrorMesg("Illegal Position. Too many black rooks."); } } } cp+=3; break; case 'B': if (*(cp+1)<'a' || *(cp+1)>'h' || *(cp+2)<'1' || *(cp+2)>'8') { sprintf(mbuf,"Error in Position line %d ->'B%c%c'",line,*(cp+1),*(cp+2)); ExitErrorMesg(mbuf); } Ppos = 10*(cp[2]-'1')+cp[1]-'a'+21; if (Bpieces[4].xy==0) { board[Ppos]=&Bpieces[4]; Bpieces[4].xy = Ppos; } else if (Bpieces[5].xy==0) { board[Ppos]=&Bpieces[5]; Bpieces[5].xy = Ppos; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Bpieces[i].xy==0) { board[Ppos]=&Bpieces[i]; Bpieces[i].xy = Ppos; Bpieces[i].type = BBISHOP; break; } else if (i==15) { ExitErrorMesg("Illegal Position. Too many black bishops."); } } } cp+=3; break; case 'N': if (*(cp+1)<'a' || *(cp+1)>'h' || *(cp+2)<'1' || *(cp+2)>'8') { sprintf(mbuf,"Error in Position line %d ->'N%c%c'",line,*(cp+1),*(cp+2)); ExitErrorMesg(mbuf); } Ppos = 10*(cp[2]-'1')+cp[1]-'a'+21; if (Bpieces[6].xy==0) { board[Ppos]=&Bpieces[6]; Bpieces[6].xy = Ppos; } else if (Bpieces[7].xy==0) { board[Ppos]=&Bpieces[7]; Bpieces[7].xy = Ppos; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Bpieces[i].xy==0) { board[Ppos]=&Bpieces[i]; Bpieces[i].xy = Ppos; Bpieces[i].type = BKNIGHT; break; } else if (i==15) { ExitErrorMesg("Illegal Position. Too many black knights."); } } } cp+=3; break; case 'P': cp++; default: if (*cp<'a' || *cp>'h' || *(cp+1)<'1' || *(cp+1)>'8') { sprintf(mbuf,"Error in Position line %d ->'%c%c'",line,*cp,*(cp+1)); ExitErrorMesg(mbuf); } Ppos = 10*(cp[1]-'1')+cp[0]-'a'+21; if (Ppos <= H1 || Ppos >= A8) { ExitErrorMesg("Illegal Black pawn"); } for (i=8; i<16; i++) { if (Bpieces[i].xy==0) { board[Ppos]=&Bpieces[i]; Bpieces[i].xy = Ppos; break; } else if (i==15) { ExitErrorMesg("Illegal Position. Too many black pawns."); } } cp+=2; break; } } } } fclose(fp); if (!wkf || !bkf) { ExitErrorMesg("Illegal Position. King(s) missing"); } /* castling flags reset*/ if (wking==E1) { wkmoved=0; WHasCastled=0;} else { wkmoved=1; WHasCastled=1;} if (bking==E8) { bkmoved=0; BHasCastled=0;} else { bkmoved=1; BHasCastled=1;} if (board[A1]->type==WROOK) { wra1moved=0; } else { wra1moved=1; } if (board[H1]->type==WROOK) { wrh1moved=0; } else { wrh1moved=1; } if (board[A8]->type==BROOK) { bra8moved=0; } else { bra8moved=1; } if (board[H8]->type==BROOK) { brh8moved=0; } else { brh8moved=1; } EnPassantSq=0; /* Move Stack Pointers reset */ cst_p=0; mv_stack_p=0; HalfMovesPlayed=0; CurrentLine[0] = '\0'; LoneKingReachedEdge=0; FiftyMoves=0; NotStartingPosition=1; PlayerMove.u=0; } /* ------------------------------------------------------ */ int WhiteKingInCheck(void) { register int xyk=wking, xy; register int test; /* black pawn checks & kings side by side and some knights square */ xy=xyk+8; if (board[xy]->type==BKNIGHT) return 1; xy++; test = board[xy]->type; if (test==BPAWN || test==BKING) /* += 9*/ return 1; xy++; if (board[xy]->type==BKING) /* += 10*/ return 1; xy++; test = board[xy]->type; if (test==BPAWN || test==BKING) /* += 11 */ return 1; xy++; if (board[xy]->type==BKNIGHT) /* += 12*/ return 1; xy=xyk-12; if (board[xy]->type==BKNIGHT) return 1; xy++; if (board[xy]->type==BKING) /* -=11; */ return 1; xy++; if (board[xy]->type==BKING) /* -=10 */ return 1; xy++; if (board[xy]->type==BKING) /* -=9 */ return 1; xy++; if (board[xy]->type==BKNIGHT) /* -=8 */ return 1; if (board[xyk-1]->type==BKING) return 1; if (board[xyk+1]->type==BKING) return 1; /* remaining black knight checks */ if (board[xyk+21]->type==BKNIGHT || board[xyk-21]->type==BKNIGHT) return 1; if (board[xyk+19]->type==BKNIGHT || board[xyk-19]->type==BKNIGHT) return 1; /* black bishop or queen checks */ xy=xyk; for (;;) { xy+=9; test = board[xy]->type; if (testtype; if (testtype; if (testtype; if (testtype; if (testtype; if (testtype; if (testtype; if (testtype; if (test>black) { bmoves++; break; } else if (test==0) { bmoves++; } else { break; } } xy=xy0; for (;;) { xy-=9; test = board[xy]->type; if (test>black) { bmoves++; break; } else if (test==0) { bmoves++; } else { break; } } xy=xy0; for (;;) { xy+=11; test = board[xy]->type; if (test>black) { bmoves++; break; } else if (test==0) { bmoves++; } else { break; } } xy=xy0; for (;;) { xy-=11; test = board[xy]->type; if (test>black) { bmoves++; break; } else if (test==0) { bmoves++; } else { break; } } return (bmoves-6); } /* ------------------------------------------------------ */ void AddWhiteBishopMoves(int xy0, MOVE q[], int *nextf) { register int xy=xy0, test; for (;;) { xy+=9; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy-=9; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy+=11; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy-=11; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } } /* ------------------------------------------------------ */ void AddWhiteBishopNonCaptures(int xy0, MOVE q[], int *nextf) { register int xy=xy0; for (;;) { xy+=9; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy-=9; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy+=11; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy-=11; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } } /* ------------------------------------------------------ */ void AddWhiteBishopCaptures(int xy0, MOVE q[], int *nextf) { register int xy=xy0, test; for (;;) { xy+=9; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test!=0) { break; } } xy=xy0; for (;;) { xy-=9; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test!=0) { break; } } xy=xy0; for (;;) { xy+=11; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test!=0) { break; } } xy=xy0; for (;;) { xy-=11; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test!=0) { break; } } } /* ------------------------------------------------------ */ /* --- White Knight Moves and mobility functions --- */ /* ------------------------------------------------------ */ int WhiteKnightMobility(int xy0) { register int xy, nmoves=0, test; xy = xy0 + 21; test = board[xy]->type; if (test==0 || test>black) { nmoves++; } xy = xy0 - 21; test = board[xy]->type; if (test==0 || test>black) { nmoves++; } xy = xy0 + 19; test = board[xy]->type; if (test==0 || test>black) { nmoves++; } xy = xy0 - 19; test = board[xy]->type; if (test==0 || test>black) { nmoves++; } xy = xy0 + 12; test = board[xy]->type; if (test==0 || test>black) { nmoves++; } xy = xy0 - 12; test = board[xy]->type; if (test==0 || test>black) { nmoves++; } xy = xy0 + 8; test = board[xy]->type; if (test==0 || test>black) { nmoves++; } xy = xy0 - 8; test = board[xy]->type; if (test==0 || test>black) { nmoves++; } return (nmoves-4); } /* ------------------------------------------------------ */ void AddWhiteKnightMoves(int xy0, MOVE q[], int *nextf) { register int xy, test; xy = xy0 + 21; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 21; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 19; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 19; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 12; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 12; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 8; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 8; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } } /* ------------------------------------------------------ */ void AddWhiteKnightNonCaptures(int xy0, MOVE q[], int *nextf) { register int xy; xy = xy0 + 21; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 21; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 19; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 19; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 12; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 12; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 8; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 8; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } } /* ------------------------------------------------------ */ void AddWhiteKnightCaptures(int xy0, MOVE q[], int *nextf) { register int xy; xy = xy0 + 21; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 21; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 19; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 19; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 12; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 12; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 8; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 8; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } } /* ------------------------------------------------------ */ /* --- White Rook Moves and mobility functions --- */ /* ------------------------------------------------------ */ void AddWhiteRookCaptures(int xy0, MOVE q[], int *nextf) { register int xy=xy0, test; for (;;) { xy++; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test!=0) { break; } } xy=xy0; for (;;) { xy--; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test!=0) { break; } } xy=xy0; for (;;) { xy+=10; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test!=0) { break; } } xy=xy0; for (;;) { xy-=10; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test!=0) { break; } } } /* ------------------------------------------------------ */ int WhiteRookMobility(int xy0) { register int xy=xy0, rmoves=0, test; for (;;) { xy++; test = board[xy]->type; if (test>black) { rmoves++; break; } else if (test==0) { rmoves++; } else { break; } } xy=xy0; for (;;) { xy--; test = board[xy]->type; if (test>black) { rmoves++; break; } else if (test==0) { rmoves++; } else { break; } } xy=xy0; for (;;) { xy+=10; test = board[xy]->type; if (test>black) { rmoves++; break; } else if (test==0) { rmoves++; } else { break; } } xy=xy0; for (;;) { xy-=10; test = board[xy]->type; if (test>black) { rmoves++; break; } else if (test==0) { rmoves++; } else { break; } } return (rmoves-7); } /* ------------------------------------------------------ */ void AddWhiteRookNonCaptures(int xy0, MOVE q[], int *nextf) { register int xy=xy0; for (;;) { xy++; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy--; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy+=10; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy-=10; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } } /* ------------------------------------------------------ */ void AddWhiteRookMoves(int xy0, MOVE q[], int *nextf) { register int xy=xy0, test; for (;;) { xy++; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy--; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy+=10; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy-=10; test = board[xy]->type; if (test>black) { AddWhiteMv(xy0,xy,1,q,nextf); break; } else if (test==0) { AddWhiteMv(xy0,xy,1,q,nextf); } else { break; } } } /* ------------------------------------------------------ */ /* ------ White Pawn Moves functions ------ */ /* ------------------------------------------------------ */ void AddWhitePawnMoves(int xy0, MOVE q[], int *nextf) { /* !! Attention. If promotion the promotion piece is saved in q[i]->flag*/ register int xy, xy2; if (xy0>=A7) { /* promotion */ xy = xy0+9; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,WQUEEN,q,nextf); AddWhiteMv(xy0,xy,WKNIGHT,q,nextf); AddWhiteMv(xy0,xy,WROOK,q,nextf); AddWhiteMv(xy0,xy,WBISHOP,q,nextf); } xy++; /* = xy0+10;*/ if (board[xy]->type==0) { AddWhiteMv(xy0,xy,WQUEEN,q,nextf); AddWhiteMv(xy0,xy,WKNIGHT,q,nextf); AddWhiteMv(xy0,xy,WROOK,q,nextf); AddWhiteMv(xy0,xy,WBISHOP,q,nextf); } xy++; /* = xy0+11;*/ if (board[xy]->type>black) { AddWhiteMv(xy0,xy,WQUEEN,q,nextf); AddWhiteMv(xy0,xy,WKNIGHT,q,nextf); AddWhiteMv(xy0,xy,WROOK,q,nextf); AddWhiteMv(xy0,xy,WBISHOP,q,nextf); } } else { xy = xy0 + 9; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); } else if (xy==EnPassantSq) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); /* en passant */ } xy++; /* = xy0 + 10;*/ if (board[xy]->type==0) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); if (xy0<=H2) { /* Two step pawn move*/ xy2 = xy + 10; if (board[xy2]==0) { AddWhiteMv(xy0,xy2,WPAWN,q,nextf); } } } xy++; /* = xy0 + 11;*/ if (board[xy]->type>black) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); } else if (xy==EnPassantSq) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); /* en passant */ } } } /* ------------------------------------------------------ */ void AddWhitePawnNoCapsNoPromMoves(int xy0, MOVE q[], int *nextf) { register int xy=xy0; xy += 10; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); if (xy0<=H2) { /* Two step pawn move*/ xy += 10; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); } } } } /* ------------------------------------------------------ */ void AddWhitePawnCapturesAndPromotions(int xy0, MOVE q[], int *nextf) { /* !! Attention. If promotion the promotion piece is saved in q[i]->flag*/ register int xy; if (xy0>=A7) { /* promotion */ xy = xy0+9; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,WQUEEN,q,nextf); AddWhiteMv(xy0,xy,WKNIGHT,q,nextf); AddWhiteMv(xy0,xy,WROOK,q,nextf); AddWhiteMv(xy0,xy,WBISHOP,q,nextf); } xy++; /* = xy0+10;*/ if (board[xy]->type==0) { AddWhiteMv(xy0,xy,WQUEEN,q,nextf); AddWhiteMv(xy0,xy,WKNIGHT,q,nextf); AddWhiteMv(xy0,xy,WROOK,q,nextf); AddWhiteMv(xy0,xy,WBISHOP,q,nextf); } xy++; /* = xy0+11;*/ if (board[xy]->type>black) { AddWhiteMv(xy0,xy,WQUEEN,q,nextf); AddWhiteMv(xy0,xy,WKNIGHT,q,nextf); AddWhiteMv(xy0,xy,WROOK,q,nextf); AddWhiteMv(xy0,xy,WBISHOP,q,nextf); } } else { xy=xy0+9; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); } else if (xy==EnPassantSq) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); /* en passant */ } xy=xy0+11; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); } else if (xy==EnPassantSq) { AddWhiteMv(xy0,xy,WPAWN,q,nextf); /* en passant */ } } } /* ------------------------------------------------------ */ /* ------ White King Moves functions ------ */ /* ------------------------------------------------------ */ void AddWhiteKingMoves(int xy0, MOVE q[], int *nextf) { register int xy, test; xy = xy0 + 1; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 1; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 11; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 - 10;*/ test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 - 9;*/ test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 9; test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 + 10;*/ test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 + 11;*/ test = board[xy]->type; if (test==0 || test>black) { AddWhiteMv(xy0,xy,1,q,nextf); } if (!wkmoved && xy0==E1) { if (!wrh1moved && board[H1]->type==WROOK) { if (!WhiteKingInCheck() && board[F1]->type==0 && board[G1]->type==0) { wking=F1; if (!WhiteKingInCheck()) { wking=G1; if (!WhiteKingInCheck()) { /* white short castling possible */ AddWhiteMv(E1,G1,1,q,nextf); } } wking=E1; } } if (!wra1moved && board[A1]->type==WROOK) { if (!WhiteKingInCheck()) { if (board[D1]->type==0 && board[C1]->type==0 && board[B1]->type==0) { wking=D1; if (!WhiteKingInCheck()) { wking=C1; if (!WhiteKingInCheck()) { /* white long castling possible */ AddWhiteMv(E1,C1,1,q,nextf); } } wking=E1; } } } } } /* ------------------------------------------------------ */ void AddWhiteKingNonCaptures(int xy0, MOVE q[], int *nextf) { register int xy; xy = xy0 + 1; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 1; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 9; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 + 10;*/ if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 + 11;*/ if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 11; if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 - 10;*/ if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 - 9;*/ if (board[xy]->type==0) { AddWhiteMv(xy0,xy,1,q,nextf); } if (!wkmoved && xy0==E1) { if (!wrh1moved && board[H1]->type==WROOK) { if (!WhiteKingInCheck() && board[F1]->type==0 && board[G1]->type==0) { wking=F1; if (!WhiteKingInCheck()) { wking=G1; if (!WhiteKingInCheck()) { /* white short castling possible */ AddWhiteMv(E1,G1,1,q,nextf); } } wking=E1; } } if (!wra1moved && board[A1]->type==WROOK) { if (!WhiteKingInCheck()) { if (board[D1]->type==0 && board[C1]->type==0 && board[B1]->type==0) { wking=D1; if (!WhiteKingInCheck()) { wking=C1; if (!WhiteKingInCheck()) { /* white long castling possible */ AddWhiteMv(E1,C1,1,q,nextf); } } wking=E1; } } } } } /* ------------------------------------------------------ */ void AddWhiteKingCaptures(int xy0, MOVE q[], int *nextf) { register int xy; xy = xy0 + 1; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 1; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 + 9; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 + 10;*/ if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 + 11;*/ if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy = xy0 - 11; if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 - 10;*/ if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 - 9;*/ if (board[xy]->type>black) { AddWhiteMv(xy0,xy,1,q,nextf); } } /* ------------------------------------------------------------------ */ /* We add Capture moves first because it helps in Alpha-Beta cut-offs */ /* ------------------------------------------------------------------ */ int FindAllWhiteMoves(MOVE q[]) { int nextfree=0; register int i, MaxScore=0, maxi=0, utemp, pf, pt; for (i=0; i<16; i++) { if (Wpieces[i].xy==0) continue; switch (Wpieces[i].type) { case WPAWN : AddWhitePawnCapturesAndPromotions(Wpieces[i].xy,q,&nextfree); break; case WQUEEN : AddWhiteRookCaptures(Wpieces[i].xy,q,&nextfree); AddWhiteBishopCaptures(Wpieces[i].xy,q,&nextfree); break; case WKNIGHT: AddWhiteKnightCaptures(Wpieces[i].xy,q,&nextfree); break; case WROOK : AddWhiteRookCaptures(Wpieces[i].xy,q,&nextfree); break; case WBISHOP: AddWhiteBishopCaptures(Wpieces[i].xy,q,&nextfree); break; case WKING : AddWhiteKingCaptures(Wpieces[i].xy,q,&nextfree); break; } } for (i=0; i<16; i++) { if (Wpieces[i].xy==0) continue; switch (Wpieces[i].type) { case WPAWN : AddWhitePawnNoCapsNoPromMoves(Wpieces[i].xy,q,&nextfree); break; case WQUEEN : AddWhiteRookNonCaptures(Wpieces[i].xy,q,&nextfree); AddWhiteBishopNonCaptures(Wpieces[i].xy,q,&nextfree); break; case WKNIGHT: AddWhiteKnightNonCaptures(Wpieces[i].xy,q,&nextfree); break; case WROOK : AddWhiteRookNonCaptures(Wpieces[i].xy,q,&nextfree); break; case WBISHOP: AddWhiteBishopNonCaptures(Wpieces[i].xy,q,&nextfree); break; case WKING : AddWhiteKingNonCaptures(Wpieces[i].xy,q,&nextfree); break; } } /* Find the capture, using MVV/LVA (Most Valuable Victim/Least Valuable Attacker). Put this move first in order for later processing */ for (i=0; itype != 0) { pf = board[q[i].m.from]->type; pt = board[q[i].m.to]->type - black; utemp = (pt << 4) - pf; /* this is (16*pt) - pf */ if ( utemp > MaxScore ) { MaxScore = utemp; maxi = i; } } } if (maxi) { utemp = q[maxi].u; q[maxi].u = q[0].u; q[0].u = utemp; } return nextfree; } /* ------------------------------------------------------ */ int FindAllWhiteCapturesAndPromotions(MOVE q[]) { int nextfree=0; register int i, MaxScore=0, maxi=0, utemp, pf, pt; for (i=0; i<16; i++) { if (Wpieces[i].xy==0) continue; switch (Wpieces[i].type) { case WQUEEN : AddWhiteRookCaptures(Wpieces[i].xy,q,&nextfree); AddWhiteBishopCaptures(Wpieces[i].xy,q,&nextfree); break; case WROOK : AddWhiteRookCaptures(Wpieces[i].xy,q,&nextfree); break; case WKNIGHT: AddWhiteKnightCaptures(Wpieces[i].xy,q,&nextfree); break; case WPAWN : AddWhitePawnCapturesAndPromotions(Wpieces[i].xy,q,&nextfree); break; case WBISHOP: AddWhiteBishopCaptures(Wpieces[i].xy,q,&nextfree); break; case WKING : AddWhiteKingCaptures(Wpieces[i].xy,q,&nextfree); break; } } /* Find the capture, using MVV/LVA (Most Valuable Victim/Least Valuable Attacker). Put this move first in order fo later processing */ for (i=0; itype != 0) { pf = board[q[i].m.from]->type; pt = board[q[i].m.to]->type - black; utemp = (pt << 4) - pf; /* this is (16*pt) - pf */ if ( utemp > MaxScore ) { MaxScore = utemp; maxi = i; } } } if (maxi) { utemp = q[maxi].u; q[maxi].u = q[0].u; q[0].u = utemp; } return nextfree; } /* ------------------------------------------------------ */ void AddMoveToLine(int from, int to) { static char LineMov[10]={"xxxx "}; int fromx,fromy,tox,toy; HalfMovesPlayed++; if (HalfMovesPlayed > 40) return; fromx = from%10 - 1; tox = to%10 - 1; fromy = from/10 - 2; toy = to/10 - 2; LineMov[0] = (char)fromx + 'a'; LineMov[1] = (char)fromy + '1'; LineMov[2] = (char)tox + 'a'; LineMov[3] = (char)toy + '1'; strcat(CurrentLine, LineMov); } /* ------------------------------------------------------ */ char *TranslateMoves(MOVE *m) { static char mov[10]={"xxxx "}; char fromx,fromy,tox,toy; fromx = m->m.from%10 - 1; tox = m->m.to%10 - 1; fromy = m->m.from/10 - 2; toy = m->m.to/10 - 2; mov[0] = fromx + 'a'; mov[1] = fromy + '1'; mov[2] = tox + 'a'; mov[3] = toy + '1'; mov[4] = '\0'; mov[5] = '\0'; switch(m->m.flag) { case WROOK : case BROOK : mov[4] = 'r'; break; case WKNIGHT: case BKNIGHT: mov[4] = 'n'; break; case WBISHOP: case BBISHOP: mov[4] = 'b'; break; case WQUEEN : case BQUEEN : mov[4] = 'q'; break; } return mov; } /* ------------------------------------------------------ */ char *PV2Str(LINE *aPVp) { static char gPVstr[MAX_DEPTH*10]; /*char Ts[100];*/ int i; gPVstr[0]='\0'; for (i=0; icmove; i++) { /* if (Xoutput==_NORMAL_OUTPUT) { if ((i+1)%2==1) { sprintf(gPVstr,"%s%d.",gPVstr,(i+3)/2); }*/ /*sprintf(Ts,"%d>%s%+6.2lf ", aPV.levels[i],TranslateMoves(&aPV.argmove[i]),0.01*aPV.scores[i]); strcat(gPVstr,Ts); */ /* }*/ strcat(gPVstr, TranslateMoves(&(aPVp->argmove[i]))); strcat(gPVstr," "); } return gPVstr; } /* ------------------------------------------------------ */ int BlackKingInCheck(void) { register int xy=bking, xyk; register int test; /* white pawn checks & kings side by side & some knight squares*/ xyk = xy-12; if (board[xyk]->type==WKNIGHT) return 1; xyk++; test=board[xyk]->type; if (test==WPAWN || test==WKING) /* = xy-11; */ return 1; xyk++; if (board[xyk]->type==WKING) /* = xy-10; */ return 1; xyk++; test=board[xyk]->type; if (test==WPAWN || test==WKING) /* = xy-9; */ return 1; xyk++; if (board[xyk]->type==WKNIGHT) /* = xy-8; */ return 1; xyk=xy+8; if (board[xyk]->type==WKNIGHT) return 1; xyk++; if (board[xyk]->type==WKING) /*=xy+9;*/ return 1; xyk++; if (board[xyk]->type==WKING) /*=xy+10;*/ return 1; xyk++; if (board[xyk]->type==WKING) /*=xy+11;*/ return 1; xyk++; if (board[xyk]->type==WKNIGHT) /*=xy+12;*/ return 1; if (board[xy-1]->type==WKING) return 1; if (board[xy+1]->type==WKING) return 1; /* white knight checks */ if (board[xy+21]->type==WKNIGHT || board[xy-21]->type==WKNIGHT) return 1; if (board[xy+19]->type==WKNIGHT || board[xy-19]->type==WKNIGHT) return 1; /* white bishop or queen checks */ xyk=xy; for (;;) { xyk += 9; test=board[xyk]->type; if (test>black) { break; } else if (test==0) { continue; } else { if (test==WBISHOP || test==WQUEEN) { return 1; } break; } } xyk=xy; for (;;) { xyk -= 9; test=board[xyk]->type; if (test>black) { break; } else if (test==0) { continue; } else { if (test==WBISHOP || test==WQUEEN) { return 1; } break; } } xyk=xy; for (;;) { xyk += 11; test=board[xyk]->type; if (test>black) { break; } else if (test==0) { continue; } else { if (test==WBISHOP || test==WQUEEN) { return 1; } break; } } xyk=xy; for (;;) { xyk -= 11; test=board[xyk]->type; if (test>black) { break; } else if (test==0) { continue; } else { if (test==WBISHOP || test==WQUEEN) { return 1; } break; } } /* white rook or queen checks */ xyk=xy; for (;;) { xyk++; test=board[xyk]->type; if (test>black) { break; } else if (test==0) { continue; } else { if (test==WROOK || test==WQUEEN) { return 1; } break; } } xyk=xy; for (;;) { xyk--; test=board[xyk]->type; if (test>black) { break; } else if (test==0) { continue; } else { if (test==WROOK || test==WQUEEN) { return 1; } break; } } xyk=xy; for (;;) { xyk += 10; test=board[xyk]->type; if (test>black) { break; } else if (test==0) { continue; } else { if (test==WROOK || test==WQUEEN) { return 1; } break; } } xyk=xy; for (;;) { xyk -= 10; test=board[xyk]->type; if (test>black) { break; } else if (test==0) { continue; } else { if (test==WROOK || test==WQUEEN) { return 1; } break; } } return 0; } /* ------------------------------------------------------ */ void AddBlackMv(int xy0, int xy, int flag, MOVE q[], int *nextf) { MOVE mp; mp.m.from=xy0; mp.m.to =xy; mp.m.flag=flag; mp.m.dummy=0; TryMove(&mp); if (BlackKingInCheck()) { RetractLastMove(); return; } RetractLastMove(); q[*nextf].u = mp.u; (*nextf)++; } /* ------------------------------------------------------ */ /* --- Black Bishop moves and Mobility functions --- */ /* ------------------------------------------------------ */ int BlackBishopMobility(int xy0) { register int xy=xy0, bmoves=0, test; for (;;) { xy+=11; test = board[xy]->type; if (test==0) { bmoves++; } else if (test>black || test<0) { break; } else { bmoves++; break; } } xy=xy0; for (;;) { xy-=11; test = board[xy]->type; if (test>black || test<0) { break; } else if (test==0) { bmoves++; } else { bmoves++; break; } } xy=xy0; for (;;) { xy+=9; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { bmoves++; break; } bmoves++; } xy=xy0; for (;;) { xy-=9; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { bmoves++; break; } bmoves++; } return (bmoves-6); } /* ------------------------------------------------------ */ void AddBlackBishopMoves(int xy0, MOVE q[], int *nextf) { register int xy=xy0, test; for (;;) { xy+=11; test = board[xy]->type; if (test==0) { AddBlackMv(xy0,xy,1,q,nextf); } else if (test>black || test<0) { break; } else { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy-=11; test = board[xy]->type; if (test>black || test<0) { break; } else if (test==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy+=9; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { AddBlackMv(xy0,xy,1,q,nextf); break; } AddBlackMv(xy0,xy,1,q,nextf); } xy=xy0; for (;;) { xy-=9; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { AddBlackMv(xy0,xy,1,q,nextf); break; } AddBlackMv(xy0,xy,1,q,nextf); } } /* ------------------------------------------------------ */ void AddBlackBishopNonCaptures(int xy0, MOVE q[], int *nextf) { register int xy=xy0; for (;;) { xy+=11; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy-=11; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy+=9; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy-=9; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { break; } } } /* ------------------------------------------------------ */ void AddBlackBishopCaptures(int xy0, MOVE q[], int *nextf) { register int xy=xy0, test; for (;;) { xy+=11; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy-=11; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy+=9; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy-=9; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { AddBlackMv(xy0,xy,1,q,nextf); break; } } } /* ------------------------------------------------------ */ /* --- Black Knight moves and Mobility functions --- */ /* ------------------------------------------------------ */ int BlackKnightMobility(int xy0) { register int xy, nmoves=0, test; xy = xy0 + 21; test = board[xy]->type; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy = xy0 - 21; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy = xy0 + 19; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy = xy0 - 19; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy = xy0 + 12; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy = xy0 - 12; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy = xy0 + 8; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy = xy0 - 8; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } } /* ------------------------------------------------------ */ void AddBlackKnightCaptures(int xy0, MOVE q[], int *nextf) { register int xy, test; xy = xy0 + 21; test = board[xy]->type; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>black || test<0) { break; } else if (test==0) { rmoves++; } else { rmoves++; break; } } xy=xy0; for (;;) { xy++; test = board[xy]->type; if (test>black || test<0) { break; } else if (test==0) { rmoves++; } else { rmoves++; break; } } xy=xy0; for (;;) { xy-=10; test = board[xy]->type; if (test>black || test<0) { break; } else if (test==0) { rmoves++; } else { rmoves++; break; } } xy=xy0; for (;;) { xy+=10; test = board[xy]->type; if (test>black || test<0) { break; } else if (test==0) { rmoves++; } else { rmoves++; break; } } return (rmoves-7); } /* ------------------------------------------------------ */ void AddBlackRookMoves(int xy0, MOVE q[], int *nextf) { register int xy=xy0, test; for (;;) { xy--; test = board[xy]->type; if (test>black || test<0) { break; } else if (test==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy++; test = board[xy]->type; if (test>black || test<0) { break; } else if (test==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy-=10; test = board[xy]->type; if (test>black || test<0) { break; } else if (test==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy+=10; test = board[xy]->type; if (test>black || test<0) { break; } else if (test==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { AddBlackMv(xy0,xy,1,q,nextf); break; } } } /* ------------------------------------------------------ */ void AddBlackRookNonCaptures(int xy0, MOVE q[], int *nextf) { register int xy=xy0; for (;;) { xy--; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy++; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy-=10; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { break; } } xy=xy0; for (;;) { xy+=10; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } else { break; } } } /* ------------------------------------------------------ */ void AddBlackRookCaptures(int xy0, MOVE q[], int *nextf) { register int xy=xy0, test; for (;;) { xy--; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy++; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy-=10; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { AddBlackMv(xy0,xy,1,q,nextf); break; } } xy=xy0; for (;;) { xy+=10; test = board[xy]->type; if (test>black || test<0) { break; } else if (test!=0) { AddBlackMv(xy0,xy,1,q,nextf); break; } } } /* ------------------------------------------------------ */ /* ------ Black Pawn moves functions ------ */ /* ------------------------------------------------------ */ void AddBlackPawnMoves(int xy0, MOVE q[], int *nextf) { /* !! Attention. If promotion the promotion piece is saved in q[i].flag */ register int xy=xy0, xy2; if (xy<=H2) { /* promotion */ xy-=11; if (board[xy]->type>0 && board[xy]->typetype==0) { AddBlackMv(xy0,xy,BQUEEN,q,nextf); AddBlackMv(xy0,xy,BKNIGHT,q,nextf); AddBlackMv(xy0,xy,BROOK,q,nextf); AddBlackMv(xy0,xy,BBISHOP,q,nextf); } xy++; if (board[xy]->type>0 && board[xy]->typetype>0 && board[xy]->typetype==0) { AddBlackMv(xy0,xy,BPAWN,q,nextf); if (xy0>=A7) { /*two step pawn move*/ xy2 = xy - 10; if (board[xy2]->type==0) { AddBlackMv(xy0,xy2,BPAWN,q,nextf); } } } xy++; /*=xy0-9;*/ if (board[xy]->type>0 && board[xy]->typetype==0) { AddBlackMv(xy0,xy,BPAWN,q,nextf); if (xy0>=A7) { /*two step pawn move*/ xy -= 10; if (board[xy]->type==0) { AddBlackMv(xy0,xy,BPAWN,q,nextf); } } } } /* ------------------------------------------------------ */ void AddBlackPawnCapturesAndPromotions(int xy0, MOVE q[], int *nextf) { /* !! Attention. If promotion the promotion piece is saved in q[i].flag */ register int xy=xy0; if (xy<=H2) { /* promotion */ xy-=11; if (board[xy]->type>0 && board[xy]->typetype==0) { AddBlackMv(xy0,xy,BQUEEN,q,nextf); AddBlackMv(xy0,xy,BKNIGHT,q,nextf); AddBlackMv(xy0,xy,BROOK,q,nextf); AddBlackMv(xy0,xy,BBISHOP,q,nextf); } xy++; if (board[xy]->type>0 && board[xy]->typetype>0 && board[xy]->typetype>0 && board[xy]->typetype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype; if (test>-1 && testtype==BROOK) { if (!BlackKingInCheck() && board[F8]->type==0 && board[G8]->type==0) { bking=F8; if (!BlackKingInCheck()) { bking=G8; if (!BlackKingInCheck()) { /* Black short castling possible */ AddBlackMv(E8,G8,1,q,nextf); } } bking=E8; } } if (!bra8moved && board[A8]->type==BROOK) { if (!BlackKingInCheck()) { if (board[D8]==0 && board[C8]->type==0 && board[B8]->type==0) { bking=D8; if (!BlackKingInCheck()) { bking=C8; if (!BlackKingInCheck()) { /* Black long castling possible */ AddBlackMv(E8,C8,1,q,nextf); } } bking=E8; } } } } } /* ------------------------------------------------------ */ void AddBlackKingNonCaptures(int xy0, MOVE q[], int *nextf) { register int xy; xy = xy0 - 11; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 - 10;*/ if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 - 9;*/ if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy = xy0 + 1; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy = xy0 - 1; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy = xy0 + 9; if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 + 10;*/ if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } xy++; /* = xy0 + 11;*/ if (board[xy]->type==0) { AddBlackMv(xy0,xy,1,q,nextf); } if (!bkmoved && xy0==E8) { if (!brh8moved && board[H8]->type==BROOK) { if (!BlackKingInCheck() && board[F8]->type==0 && board[G8]->type==0) { bking=F8; if (!BlackKingInCheck()) { bking=G8; if (!BlackKingInCheck()) { /* Black short castling possible */ AddBlackMv(E8,G8,1,q,nextf); } } bking=E8; } } if (!bra8moved && board[A8]->type==BROOK) { if (!BlackKingInCheck()) { if (board[D8]->type==0 && board[C8]->type==0 && board[B8]->type==0) { bking=D8; if (!BlackKingInCheck()) { bking=C8; if (!BlackKingInCheck()) { /* Black long castling possible */ AddBlackMv(E8,C8,1,q,nextf); } } bking=E8; } } } } } /* ------------------------------------------------------ */ void AddBlackKingCaptures(int xy0, MOVE q[], int *nextf) { register int xy, test; xy = xy0 + 1; test = board[xy]->type; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype; if (test>0 && testtype != 0) { pf = board[q[i].m.from]->type - black; pt = board[q[i].m.to]->type; utemp = (pt << 4) - pf; /* this is (16*pt) - pf */ if ( utemp > MaxScore ) { MaxScore = utemp; maxi = i; } } } if (maxi) { utemp = q[maxi].u; q[maxi].u = q[0].u; q[0].u = utemp; } return nextfree; } /* ------------------------------------------------------ */ int FindAllBlackCapturesAndPromotions(MOVE q[]) { int nextfree=0; register int i, MaxScore=0, maxi=0, utemp, pf, pt; for (i=0; i<16; i++) { if (Bpieces[i].xy==0) continue; switch (Bpieces[i].type) { case BQUEEN : AddBlackRookCaptures(Bpieces[i].xy,q,&nextfree); AddBlackBishopCaptures(Bpieces[i].xy,q,&nextfree); break; case BPAWN : AddBlackPawnCapturesAndPromotions(Bpieces[i].xy,q,&nextfree); break; case BROOK : AddBlackRookCaptures(Bpieces[i].xy,q,&nextfree); break; case BKNIGHT: AddBlackKnightCaptures(Bpieces[i].xy,q,&nextfree); break; case BBISHOP: AddBlackBishopCaptures(Bpieces[i].xy,q,&nextfree); break; case BKING : AddBlackKingCaptures(Bpieces[i].xy,q,&nextfree); break; } } /* Find the capture, using MVV/LVA (Most Valuable Victim/Least Valuable Attacker). Put this move first in order fo later processing */ for (i=0; itype - black; pt = board[q[i].m.to]->type; utemp = (pt << 4) - pf; /* this is (16*pt) - pf */ if ( utemp > MaxScore ) { MaxScore = utemp; maxi = i; } } } if (maxi) { utemp = q[maxi].u; q[maxi].u = q[0].u; q[0].u = utemp; } return nextfree; } /* ------------------------------------------------------ */ int Eval_KingKnightBishop_vs_King(int xy, int BishopSquaresColor) { if (BishopSquaresColor == DarkSq) { if (xy==A1 || xy==H8 || xy==B1 || xy==A2 || xy==H7 || xy==G8) { /* Small triangle */ return 900; } else if (xy==C1 || xy==B2 || xy==A3 || xy==H6 || xy==G7 || xy==F8) { /* middle triangle inner*/ return 260; } else if (xy==D1 || xy==C2 || xy==B3 || xy==A4 || xy==H5 || xy==G6 || xy==F7 || xy==E8) { /* middle triangle outer */ return 210; } else if (xy==E1 || xy==D2 || xy==C3 || xy==B4 || xy==A5 || xy==H4 || xy==G5 || xy==F6 || xy==E7 || xy==D8) {/* big triangle inner */ return 150; } else if (xy==F1 || xy==E2 || xy==D3 || xy==C4 || xy==B5 || xy==A6 || xy==H3 || xy==G4 || xy==F5 || xy==E6 || xy==D7 || xy==C8) {/* big triangle outer*/ return 100; } else { /* add penalty for other cases (middle board or wrong color corner) */ return -60; } } else if (BishopSquaresColor == LightSq) { if (xy==H1 || xy==A8 || xy==G1 || xy==H2 || xy==A7 || xy==B8) { /* Small triangle */ return 900; } else if (xy==F1 || xy==G2 || xy==H3 || xy==A6 || xy==B7 || xy==C8) { /* middle triangle inner*/ return 260; } else if (xy==E1 || xy==F2 || xy==G3 || xy==H4 || xy==A5 || xy==B6 || xy==C7 || xy==D8) { /* middle triangle outer */ return 210; } else if (xy==D1 || xy==E2 || xy==F3 || xy==G4 || xy==H5 || xy==A4 || xy==B5 || xy==C6 || xy==D7 || xy==E8) {/* big triangle inner */ return 150; } if (xy==C1 || xy==D2 || xy==E3 || xy==F4 || xy==G5 || xy==H6 || xy==A3 || xy==B4 || xy==C5 || xy==D6 || xy==E7 || xy==F8) {/* big triangle outer*/ return 100; } else { return -60; } } else return 0; /* Should never get here*/ } /* ------------------------------------------------------ */ int StaticEval(int * EnoughMaterial) { register int i, test, xy, ret=0, WhitePieces=0, BlackPieces=0, xy0, Passed; register int queens=0, rooks=0, Wbishops=0, Wknights=0, Bbishops=0, Bknights=0, wpawns=0, bpawns=0; register int WBishopColor=0, BBishopColor=0; /*0: No bishop, 1:LightSq, 2:DarkSq, 3:Both */ register int IsAlmostCentered=0, IsBoardEdge=0, IsCentralized=0; int KingHaltsPassed=0; *EnoughMaterial = 1; /* 1st pass*/ for (i=0; i<16; i++) { xy = Wpieces[i].xy; if (xy==0) continue; WhitePieces++; switch (Wpieces[i].type) { case WROOK : ret += ROOK_V; ret += WhiteRookMobility(xy); rooks++; break; case WKNIGHT: ret += KNIGHT_V; if ((xy==B1) || (xy==G1)) { ret -= 8; } ret += WhiteKnightMobility(xy); if (Central[xy]) { ret += 8; } else if (PartCen[xy]) { ret += 4; } Wknights++; break; case WBISHOP: ret += BISHOP_V; if ((xy==C1) || (xy==F1)) ret -= 5; ret += WhiteBishopMobility(xy); Wbishops++; if (WhiteSq[xy]) { WBishopColor += LightSq; } else { WBishopColor += DarkSq; } break; case WQUEEN : ret += QUEEN_V; ret += (WhiteRookMobility(xy)+WhiteBishopMobility(xy)); queens++; break; case WPAWN : ret += PAWN_V; wpawns++; if ((xy==D2) || (xy==E2)) ret -= 8; if ((xy==D4) || (xy==E4)) ret += 1; if (xy >= A5) ret += 2; if (xy >= A6) ret += 5; if (xy >= A7) ret += 20; break; } } for (i=0; i<16; i++) { xy = Bpieces[i].xy; if (xy==0) continue; BlackPieces++; switch (Bpieces[i].type) { case BROOK : ret -= ROOK_V; ret -= BlackRookMobility(xy); rooks++; break; case BKNIGHT: ret -= KNIGHT_V; if ((xy==B8) || (xy==G8)) ret += 8; ret -= BlackKnightMobility(xy); if (Central[xy]) { ret -= 8; } else if (PartCen[xy]) { ret -= 4; } Bknights++; break; case BBISHOP: ret -= BISHOP_V; if ((xy==C8) || (xy==F8)) ret += 5; ret -= BlackBishopMobility(xy); Bbishops++; if (WhiteSq[xy]) { BBishopColor += LightSq; } else { BBishopColor += DarkSq; } break; case BQUEEN : ret -= QUEEN_V; ret -= (BlackRookMobility(xy)+BlackBishopMobility(xy)); queens++; break; case BPAWN : ret -= PAWN_V; bpawns++; if ((xy==D7) || (xy==E7)) ret += 8; if ((xy==D5) || (xy==E5)) ret -= 1; if (xy<=H4) ret -= 2; if (xy<=H3) ret -= 5; if (xy<=H2) ret -= 20; break; } } /* End of 1st pass */ Pieces= WhitePieces + BlackPieces; if ((Pieces<4 || (Pieces==4 && Wbishops==1 && WBishopColor==BBishopColor)) && (wpawns+bpawns==0) && (queens==0) && (rooks==0)) { *EnoughMaterial = 0; return 0; } /* 2nd pass - If Middle game check king safety else do ending evaluation */ if (!(Pieces < 20 && (rooks<4 || Pieces<13) && (queens<2 || Pieces<13 || (Pieces-wpawns-bpawns<7))) ) { /* black king safety*/ if (!WHasCastled) ret -= 30; if (!BHasCastled) ret += 30; xy=bking; if (xy==E8) { ret += 5; } else if (xy==G8 || xy==H8) { ret -= 5; if (board[F7]->type==BPAWN) {ret-=2;} if (board[G7]->type==BPAWN) { ret-=4; } else { if (board[G7]->type==BBISHOP) { ret-=4; } else if (BBishopColor==LightSq || BBishopColor==0) {/* fianceto without bishop*/ ret += 15; if (WBishopColor==DarkSq || WBishopColor==TwoColor) { ret += 35; } } } if (board[H7]->type==BPAWN) {ret-=2;} if (board[H6]->type==BPAWN) {ret-=1;} if (board[G6]->type==BPAWN) {ret-=1;} if (board[F6]->type==BPAWN) {ret-=1;} } else if (xy==C8 || xy==B8 || xy==A8) { ret -= 5; if (xy==B8) ret -=1; if (board[C7]->type==BPAWN) {ret-=2;} if (board[B7]->type==BPAWN) {ret-=3;} if (board[A7]->type==BPAWN) {ret-=2;} if (board[A6]->type==BPAWN) {ret-=1;} } else { test = xy-9; if (board[test]->type==0) ret += 3; test--; if (board[test]->type==0) ret += 3; test--; if (board[test]->type==0) ret += 3; test = xy+9; if (board[test]->type==0) ret += 2; test++; if (board[test]->type==0) ret += 2; test++; if (board[test]->type==0) ret += 2; if (board[xy+1]->type==0) ret += 2; if (board[xy-1]->type==0) ret += 2; } /* white king safety*/ xy=wking; if (xy==E1) { ret -= 5; } else if (xy==G1 || xy==H1) { ret += 5; if (board[F2]->type==WPAWN) {ret+=2;} if (board[G2]->type==WPAWN) { ret+=4; } else { if (board[G2]->type==WBISHOP) { ret+=4; } else if (WBishopColor==DarkSq || WBishopColor==0) {/* fianceto without bishop*/ ret -= 15; if (BBishopColor==LightSq || BBishopColor==TwoColor) { ret -= 35; } } } if (board[H2]->type==WPAWN) {ret+=2;} if (board[H3]->type==WPAWN) {ret+=1;} if (board[G3]->type==WPAWN) {ret+=1;} } else if (xy==C1 || xy==B1 || xy==A1) { ret += 3; if (xy==B1) ret +=1; if (board[C2]->type==WPAWN) {ret+=2;} if (board[B2]->type==WPAWN) {ret+=4;} if (board[A2]->type==WPAWN) {ret+=2;} if (board[A3]->type==WPAWN) {ret+=1;} } else { test = xy-9; if (board[test]->type==0) ret -= 3; test--; if (board[test]->type==0) ret -= 3; test--; if (board[test]->type==0) ret -= 3; test = xy+9; if (board[test]->type==0) ret -= 2; test++; if (board[test]->type==0) ret -= 2; test++; if (board[test]->type==0) ret -= 2; if (board[xy+1]->type==0) ret -= 2; if (board[xy-1]->type==0) ret -= 2; } } else { /* ending */ /* White King special ending evaluation */ int SpecialforBasicEndgames = (LoneKingReachedEdge && (Pieces < 5) && (wpawns+bpawns==0)); xy = wking; if (SpecialforBasicEndgames && (queens==0) && (rooks==0) && (BBishopColor == DarkSq || BBishopColor == LightSq)) { /* K+N+B vs K */ ret -= Eval_KingKnightBishop_vs_King(xy, BBishopColor); } else { int BasicEndGames = ((Pieces < 5) && (wpawns+bpawns==0) && (WhitePieces==1)); if (SpecialforBasicEndgames && BlackPieces==1) { ret -= abs(RowNum[wking] - RowNum[bking]) + abs(ColNum[wking] - ColNum[bking]); } /*IsBoardEdge = Edge[xy];*/ IsCentralized = Central[xy]; IsAlmostCentered = PartCen[xy]; if (Pieces==3 && bpawns==1) {/* special for king+pawn endgames */ Passed = 1; for (xy0=xy+10; xy0<=H7; xy0+=10) { if (board[xy0]->type==BPAWN) { Passed=0; break; } } if (!Passed && xy0-xy<21) { return 0; } } if (Pieces==5 && rooks==2 && bpawns==1 && wpawns==0) {/* special for rook+pawn endgames */ KingHaltsPassed=1; } if (IsCentralized) { /* Centralized King */ if (!KingHaltsPassed) ret += 60; if (BasicEndGames) ret -= 35; } else if (IsAlmostCentered) { /* Partially Centralized King */ if (!KingHaltsPassed) ret += 30; if (BasicEndGames) ret -= 25; } else if (PartEdg[xy]) { /* King almost on edge */ if (!KingHaltsPassed) ret -= 10; if (BasicEndGames) { if (xy==B2 || xy==G2 || xy==B7 || xy==G7) { /* Penalty for almost edge corners */ ret -= 150; } else if (xy==C2 || xy==F2 || xy==B3 || xy==G3 || xy==B6 || xy==C7 || xy==F7 || xy==G6) { /* smaller penalty for closer to center*/ ret -=80; } } } else /*if (IsBoardEdge)*/ { /* king on Edge */ if (KingHaltsPassed) { ret -= 10; } else { ret -= 30; } if (BasicEndGames) { ret -= 300; if ((queens==0) && (rooks==0)) { if ((BBishopColor == 0) || (BBishopColor == TwoColor)) { /* K+B+B vs K or K+N+N vs K*/ if (xy==D1 || xy==E1 || xy==H4 || xy==H5 || xy==A4 || xy==A5 || xy==D8 || xy==E8 ) { /* Away from corner */ ret += 120; } else if (xy==C1 || xy==F1 || xy==H3 || xy==H6 || xy==A3 || xy==A6 || xy==C8 || xy==F8 ) { /* Partially cornered*/ ret -= 10; } else if (xy==A1 || xy==H1 || xy==A8 || xy==H8 || xy==B1 || xy==G1 || xy==H2 || xy==H7 || xy==A2 || xy==A7 || xy==B8 || xy==G8) { /* cornered */ ret -= 120; } } } } } } /* Black King special ending evaluation */ xy = bking; KingHaltsPassed = 0; if (SpecialforBasicEndgames && (queens==0) && (rooks==0) && (WBishopColor == DarkSq || WBishopColor == LightSq)) { /* K+N+B vs K */ ret += Eval_KingKnightBishop_vs_King(xy, WBishopColor); } else { int BasicEndGames = ((Pieces < 5) && (wpawns+bpawns==0) && (BlackPieces==1)); if (SpecialforBasicEndgames && WhitePieces==1) { ret += abs(RowNum[wking] - RowNum[bking]) + abs(ColNum[wking] - ColNum[bking]); } /*IsBoardEdge = Edge[xy];*/ IsCentralized = Central[xy]; IsAlmostCentered = PartCen[xy]; if (Pieces==5 && rooks==2 && wpawns==1 && bpawns==0) {/* special for rook+pawn endgames */ KingHaltsPassed=1; } if (Pieces==3 && wpawns==1) {/* special for king+pawn endgames */ Passed = 1; for (xy0=xy-10; xy0>=A2; xy0-=10) { if (board[xy0]->type==WPAWN) { Passed=0; break; } } if (!Passed && xy-xy0<21) { return 0; } } if (IsCentralized) { if (!KingHaltsPassed) ret -= 60; if (BasicEndGames) ret += 35; } else if (IsAlmostCentered) { if (!KingHaltsPassed) ret -= 30; if (BasicEndGames) ret += 25; } else if (PartEdg[xy]) { /* King almost on edge */ ret += 10; if (BasicEndGames) { if (xy==B2 || xy==G2 || xy==B7 || xy==G7) { /* Penalty for almost edge corners */ ret += 150; } else if (xy==C2 || xy==F2 || xy==B3 || xy==G3 || xy==B6 || xy==C7 || xy==F7 || xy==G6) { /* smaller penalty for closer to center*/ ret +=80; } } } else /*if (IsBoardEdge)*/ { /* king on Edge */ if (KingHaltsPassed) { ret+=10; } else { ret += 30; } if (BasicEndGames) { ret += 300; if ((queens==0) && (rooks==0)) { if ((WBishopColor == 0) || (WBishopColor == TwoColor)) { /* K+B+B vs K or K+N+N vs K*/ if (xy==D1 || xy==E1 || xy==H4 || xy==H5 || xy==A4 || xy==A5 || xy==D8 || xy==E8 ) { /* Away from corner */ ret -= 120; } else if (xy==C1 || xy==F1 || xy==H3 || xy==H6 || xy==A3 || xy==A6 || xy==C8 || xy==F8 ) { /* Partially cornered*/ ret += 10; } else if (xy==A1 || xy==H1 || xy==A8 || xy==H8 || xy==B1 || xy==G1 || xy==H2 || xy==H7 || xy==A2 || xy==A7 || xy==B8 || xy==G8) { /* cornered */ ret += 120; } } } } } } for (i=0; i<16; i++) { /* ending second pass evaluation for white pawns*/ xy = Wpieces[i].xy; if (xy==0) continue; test = Wpieces[i].type; if (test!=WPAWN) continue; Passed = 1; for (xy0=xy+10; xy0<=H7; xy0+=10) { if (board[xy0]->type==BPAWN || board[xy0-1]->type==BPAWN || board[xy0+1]->type==BPAWN) { Passed=0; break; } } if (Passed) { /* Add bonus for passed white pawns */ if (xy >= A4) ret += 35; if (xy >= A5) ret += 15; if (xy >= A6) ret += 25; } if (xy >= A7) ret += 40; } for (i=0; i<16; i++) { /* ending second pass evaluation for black pawns*/ xy = Bpieces[i].xy; if (xy==0) continue; test = Bpieces[i].type; if (test!=BPAWN) continue; Passed = 1; for (xy0=xy-10; xy0>=A2; xy0-=10) { if (board[xy0]->type==WPAWN || board[xy0-1]->type==WPAWN || board[xy0+1]->type==WPAWN) { Passed=0; break; } } if (Passed) { /* Add bonus for passed black pawns */ if (xy<=H5) ret -= 35; if (xy<=H4) ret -= 15; if (xy<=H3) ret -= 25; } if (xy<=H2) ret -= 40; } } return ret; } /* ------------------------------------------------------ */ int IsBookLine(int *BookLineNoP, MOVE movelst[], int moves) { int i, j, matchfound=0; MOVE Am; static char bline[1024]; int matched=0; if (NotStartingPosition) return 0; if (book_file==NULL) return 0; *BookLineNoP=-1; fseek(book_file, 0, SEEK_SET); while (fgets(bline, 1024, book_file)) { matchfound = 1; for (j = 0; j < strlen(CurrentLine); j++) if (bline[j] == '\0' || bline[j] != CurrentLine[j]) matchfound = 0; if (matchfound==1) { /* parse the book move that continues the line */ if (!ParsePlayerMove(&bline[strlen(CurrentLine)], &Am)) { matchfound =0; } else { /* debug printf("\n--Matched--%s--\n",bline);*/ for (i=0; i5 && n>1){ if (ibest>0 && wmovelst[ibest].m.flag) { itemp = wmovelst[0].u; wmovelst[0].u = wmovelst[ibest].u; wmovelst[ibest].u = itemp; } if (igood>1 && wmovelst[igood].m.flag) { itemp = wmovelst[1].u; wmovelst[1].u = wmovelst[igood].u; wmovelst[igood].u = itemp; } if (igood2>2 && wmovelst[igood2].m.flag) { itemp = wmovelst[2].u; wmovelst[2].u = wmovelst[igood2].u; wmovelst[igood2].u = itemp; } } defence_f = 0; for (j=0; j2) { if (BlackMates(1,level+1,b2moves,b2movelst,&InnerLevelKey)) { RetractLastMove(); PopStatus(); continue; } else { if (n>3) { if (BlackMates(2,level+1,b2moves,b2movelst,&InnerLevelKey)) { RetractLastMove(); PopStatus(); continue; } } } } if (BlackMates(n-1,level+1,b2moves,b2movelst,&InnerLevelKey)) { RetractLastMove(); PopStatus(); continue; } else { defence_f = 1; if (n>1) { if (j>2) { if (ibest<0) { ibest = j; } else if (igood<0) { igood = j; } else { igood2 = j; } } } RetractLastMove(); PopStatus(); break; } } /* for every white move */ if (!defence_f) { if (white_moves != 0) { solution_found = 1; if (level==0) { *keyindex = i; } else { RetractLastMove(); PopStatus(); break; } } else if (WhiteKingInCheck()) { solution_found = 1; if (level != 0) { RetractLastMove(); PopStatus(); break; } else { *keyindex = i; } } } RetractLastMove(); PopStatus(); } /* for every black move */ return solution_found; } /* ------------------------------------------------------ */ int WhiteMates(int n, int level, int white_moves, MOVE wmovelst[], int *keyindex) { int i, j, black_moves, w2moves, InnerLevelKey, utemp; int defence_f=0, solution_found=0; int ibest=-1, igood=-1, igood2=-1; MOVE w2movelst[MAXMV], bmovelst[MAXMV];/*, temp;*/ /* debug if (level==0) printf("\nChecking White for mate in %d\n",n); --- */ *keyindex = -1; nodes++; for (i=0; i5 && n>1){ if (ibest>0 && bmovelst[ibest].m.flag) { utemp = bmovelst[0].u; bmovelst[0].u = bmovelst[ibest].u; bmovelst[ibest].u = utemp; } if (igood>1 && bmovelst[igood].m.flag) { utemp = bmovelst[1].u; bmovelst[1].u = bmovelst[igood].u; bmovelst[igood].u = utemp; } if (igood2>2 && bmovelst[igood2].m.flag) { utemp = bmovelst[2].u; bmovelst[2].u = bmovelst[igood2].u; bmovelst[igood2].u = utemp; } } defence_f = 0; for (j=0; j2) { if (WhiteMates(1,level+1,w2moves,w2movelst,&InnerLevelKey)) { RetractLastMove(); PopStatus(); continue; } else { if (n>3) { if (WhiteMates(2,level+1,w2moves,w2movelst,&InnerLevelKey)) { RetractLastMove(); PopStatus(); continue; } } } } if (WhiteMates(n-1,level+1,w2moves,w2movelst,&InnerLevelKey)) { RetractLastMove(); PopStatus(); continue; } else { defence_f = 1; if (n>1) { if (j>2) { if (ibest<0) { ibest = j; } else if (igood<0) { igood = j; } else { igood2 = j; } } } RetractLastMove(); PopStatus(); break; } } /* for every black move */ if (!defence_f) { if (black_moves != 0) { solution_found = 1; if (level==0) { *keyindex = i; } else { RetractLastMove(); PopStatus(); break; } } else if (BlackKingInCheck()) { solution_found = 1; if (level != 0) { RetractLastMove(); PopStatus(); break; } else { *keyindex = i; } } } RetractLastMove(); PopStatus(); } /* for every white move */ return solution_found; } /* ------------------------------------------------------ */ int FindAndUpdateInPlace(MOVE mlp[], int lSize, int uKey, int place) { register int j, f=0, utemp=uKey; if (uKey) { for (j=0; j= beta ) return beta; if( alpha < stand_pat ) alpha = stand_pat; until( every_capture_has_been_examined ) { MakeCapture(); score = -Quiescence( -beta, -alpha ); TakeBackMove(); if( score >= beta ) return beta; if( score > alpha ) alpha = score; } return alpha; } */ int Quiescence(int alpha, int beta, int color, int hasStandpat, int stand_pat) { register int e, score, i, m, NextColor; int IsMaterialEnough; MOVE movelst[MAXMV]; nodes++; if (!hasStandpat) { e = StaticEval(&IsMaterialEnough); if (IsMaterialEnough==0) return 0; } else { e = stand_pat; } /* Return if there are no moves else make stand pat evaluation*/ if (color==black) { NextColor = white; if (!hasStandpat) { e = -e; e += (mv_stack_p - Starting_Mv); } m=FindAllBlackCapturesAndPromotions(movelst); if (m==0) return e; } else { /* white to move */ if (!hasStandpat) { e -= (mv_stack_p - Starting_Mv); } NextColor = black; m=FindAllWhiteCapturesAndPromotions(movelst); if (m==0) return e; } /* Check if we are are too deep in the search tree*/ if (!hasStandpat && (mv_stack_p - Starting_Mv > MAX_DEPTH - 1)) { return e; } /* Main recursive Quiescence algorithm */ if( e >= beta ) return beta; if( alpha < e ) alpha = e; for (i=0; i= beta ) { return beta; } if( score > alpha ) { alpha = score; } } return alpha; } /* ------------------------------------------------------ NEGA MAX ALGORITHM with ALPHA-BETA PRUNING pseudo-code ------------------------------------------------------ //color 1 is white, -1 is black int NegaMax(Board b, int depth, int color, int alpha, int beta) { if ((GameOver(b) or depth>MaxDepth) return color*Analysis(b) int max = -infinity for each legal move m in board b { copy b to c make move m in board c int x= - NegaMax(c, depth+1, -color, -beta, -alpha) if (x>max) max = x if (x>alpha) alpha = x if (alpha>=beta) return alpha } return max } */ /* ------------------------------------------------------------------------------------------ */ /* ---- This is our implementation of Negamax algorithm. Here color is 1=white, 10=black ---- */ /* ------------------------------------------------------------------------------------------ */ int NegaMax(int CanNull, int level, LINE * pline, MOVE mlst[], int n, int depth, int alpha, int beta, int color, int *bestMoveIndex) { register int i, e, x, w2=-1, b2=-1, check, NextDepth, NextColor; int iret=0, IsMaterialEnough, iretNull=-1; MOVE w2movelst[MAXMV], b2movelst[MAXMV]; register int MaxV = -INFINITY; LINE line; MOVE Tbest, NullBest; pline->cmove = 0; *bestMoveIndex = 0; /*start with first move*/ e = StaticEval(&IsMaterialEnough); if (IsMaterialEnough==0) { *bestMoveIndex = TERMINAL_NODE; return 0; } e -= (mv_stack_p - Starting_Mv); /* play good moves as early as possible */ if (color==black) { NextColor = white; e = -e; } else { NextColor = black; } if (mv_stack_p - Starting_Mv > MAX_DEPTH - 1) { /* We are too deep*/ *bestMoveIndex = TERMINAL_NODE; return e; } if (depth==0) { /*node is a terminal node */ *bestMoveIndex = TERMINAL_NODE; return Quiescence(alpha, beta, color, 1, e); } else { nodes++; /* ------------ NULL MOVE HEURISTIC ----------------- * * The side on move "passes" (does nothing) and the * * position is searched to a shallower depth than normal * * (usually 3 plies) This produces a cutoff much quicker * * if our Position is very good. * * ----------------------------------------------------- * * This is skipped for any of the following reasons: * * 1.The side on move is in check. The null move * * results in an illegal position. * * 2.No more than one null move can appear in succession * * or else the search will degenerate into nothing. * * 3.The side on move has little material left making * * zugzwang positions more likely. * * ------------------------------------------------------ */ NullBest.u = 0; if (CanNull && (depth > NULL_DEPTH) && (Pieces > 18) && ( (color==white && !WhiteKingInCheck()) || (color==black && !BlackKingInCheck())) ) { int Null_x; if (color==black) { w2=FindAllWhiteMoves(w2movelst); Null_x = - NegaMax(0, level+1, &line, w2movelst, w2, (depth-1-NULL_DEPTH), -beta, -alpha, NextColor, &iretNull); if (iretNull>=0) { NullBest.u = w2movelst[iretNull].u; } } else { b2=FindAllBlackMoves(b2movelst); Null_x = - NegaMax(0, level+1, &line, b2movelst, b2, (depth-1-NULL_DEPTH), -beta, -alpha, NextColor, &iretNull); if (iretNull>=0) { NullBest.u = b2movelst[iretNull].u; } } if (Null_x>=beta) { *bestMoveIndex = TERMINAL_NODE; return Null_x; } } /* --------- END OF NULL MOVE HEURISTIC -------------- */ #ifdef SHOW_MOVE_ANALYSIS #define DIFPrint if (level==1 && depth>4) DIFPrint printf("\nSearching...depth %d ...\n", depth); #endif for (i=0; i=0) { Tbest.u = w2movelst[iret].u; /* Update Best defense and PV line score vars */ if (level==1 && mlst[i].u==GlobalPV.argmove[0].u && depth>START_DEPTH+1) { if (x < ngmax && ngmax-x>PV_CHANGE_THRESH) { /* Previous PV line failed... */ int Ldsz = line.cmove;/*Max(0,line.cmove-1);*/ danger=1; memcpy(Ldef.argmove, line.argmove, Ldsz * sizeof(MOVE)); Ldef.cmove = Ldsz; /* Previous Global ngmax to change with new deeper evaluation */ ngmax = x; if (Xoutput==_XBOARD_OUTPUT) { printf("%d %d %d %d ", depth, x, (GetMillisecs() - start_time) / 10, nodes); printf("%s? ",TranslateMoves(&GlobalPV.argmove[0])); printf(" %s! %s \n", TranslateMoves(&Tbest),PV2Str(&Ldef)); fflush(stdout); } else if (Xoutput==_NORMAL_OUTPUT) { printf("%7.2lf%7.2lf ",0.01*x, SECONDS_PASSED); printf("%s? ",TranslateMoves(&GlobalPV.argmove[0])); printf(" %s! %s\n", TranslateMoves(&Tbest),PV2Str(&Ldef)); } } } } } } else { check = BlackKingInCheck(); b2=FindAllBlackMoves(b2movelst); if (b2==0) { if (check) {/* Mate */ x = INFINITY - (mv_stack_p - Starting_Mv); } else {/* StaleMate */ x = 0; } } else { /* if we are in check do not reduce depth so we can search deeper */ if (check) { NextDepth = depth; } else { NextDepth = depth-1; } if (level==1) { /* If a threat exists at starting position, put it first in opponent move list*/ if (Threat.u) FindAndUpdateInPlace(b2movelst, b2, Threat.u, 0); } else if (NullBest.u) { /* If null move returned an opponent move put it first in opponent move list */ FindAndUpdateInPlace(b2movelst, w2, NullBest.u, 0); } x = - NegaMax(1, level+1, &line, b2movelst, b2, NextDepth, -beta, -alpha, NextColor, &iret); if (iret>=0) { Tbest.u = b2movelst[iret].u; /* Update Best defense and PV line score vars */ if (level==1 && mlst[i].u==GlobalPV.argmove[0].u && depth>START_DEPTH+1) { if (x < (ngmax - PV_CHANGE_THRESH) ) { int Ldsz = line.cmove;/*Max(0,line.cmove-1);*/ danger=1; memcpy(Ldef.argmove, line.argmove, Ldsz * sizeof(MOVE)); Ldef.cmove = Ldsz; /* Previous Global ngmax to change with new deeper evaluation */ ngmax = x; if (Xoutput==_XBOARD_OUTPUT) { printf("%d %d %d %d ", depth, x, (GetMillisecs() - start_time) / 10, nodes); printf("%s? ",TranslateMoves(&GlobalPV.argmove[0])); printf(" %s! %s \n", TranslateMoves(&Tbest),PV2Str(&Ldef)); fflush(stdout); } else if (Xoutput==_NORMAL_OUTPUT) { printf("%7.2lf%7.2lf ",0.01*x, SECONDS_PASSED); printf("%s? ",TranslateMoves(&GlobalPV.argmove[0])); printf(" %s! %s\n", TranslateMoves(&Tbest),PV2Str(&Ldef)); } } } } } } RetractLastMove(); PopStatus(); #ifdef SHOW_MOVE_ANALYSIS DIFPrint printf("(%d), ",x); #endif if (TimeIsUp) { if (!danger || CriticalAnswer) { return MaxV; } } /*the following constitutes alpha-beta pruning*/ if (x>MaxV) { /* If previously PV line failed try to find answer */ if (danger==1 && level==1 && i>0 && depth>START_DEPTH+1 && x>(MaxV+PV_CHANGE_THRESH)) { CriticalAnswer =1; if (Xoutput==_XBOARD_OUTPUT) { printf("%d %d %d %d %s! \n", depth, x, (GetMillisecs() - start_time) / 10, nodes,TranslateMoves(&mlst[i])); fflush(stdout); } else if (Xoutput==_NORMAL_OUTPUT) { printf("better found %s! (%7.2lf) in %7.2lf secs\n",TranslateMoves(&mlst[i]), 0.01*x, SECONDS_PASSED); } } MaxV = x; *bestMoveIndex = i; /* Update Principal Variation */ if (Tbest.u) { pline->argmove[0].u = Tbest.u; memcpy(pline->argmove + 1, line.argmove, line.cmove * sizeof(MOVE)); pline->cmove = line.cmove + 1; } else { pline->cmove = 0; } } if (x>alpha) { alpha = x; } if (alpha>=beta) { *bestMoveIndex = i; return alpha; } }/* for each node */ return MaxV; } } /* ------------------------------------------------------------------------------------------ */ /* --- A lighter NegaMax algorithm implementation used for Threat move search --- */ /* ------------------------------------------------------------------------------------------ */ int Negalight(int depth, int alpha, int beta, int color) { if (depth==0) { /*node is a terminal node */ return Quiescence(alpha, beta, color, 0, 0); } else { register int i, e, x, n2=-1, NextColor; MOVE m2lst[MAXMV]; register int MaxV = -INFINITY; if (color==white) { n2 = FindAllWhiteMoves(m2lst); if (n2==0) { if (WhiteKingInCheck()) {/* Mate */ return INFINITY - (mv_stack_p - Starting_Mv); } else {/* StaleMate */ return 0; } } NextColor = black; } else { n2 = FindAllBlackMoves(m2lst); if (n2==0) { if (BlackKingInCheck()) {/* Mate */ return INFINITY - (mv_stack_p - Starting_Mv); } else {/* StaleMate */ return 0; } } NextColor = white; } for (i=0; iMaxV) { MaxV = x; } if (x>alpha) { alpha = x; } if (alpha>=beta) { return alpha; } }/* for each node */ return MaxV; } } /* ------------------------------------------------------ */ int PlayAndSortThreatMoves(MOVE q[], int n, int Nextcolor, int depth, int Sorted) { register int i, j, maxscore, maxi, utemp, endL; int scores[MAXMV]; for (i=0; i maxscore) { maxscore = scores[i]; maxi = i; } } utemp = q[maxi].u; q[maxi].u = q[j].u; q[j].u = utemp; utemp = scores[maxi]; scores[maxi] = scores[j]; scores[j] = utemp; } return 1; } /* ------------------------------------------------------ */ void PrintMoveOutput(int depth, int Goodmove, LINE *OpponentLine) { if (Xoutput==_XBOARD_OUTPUT) { printf("%d %d %d %d ", depth, ngmax, (GetMillisecs() - start_time) / 10, nodes); if (Goodmove) { printf("%s! %s\n", TranslateMoves(&GlobalPV.argmove[0]),PV2Str(OpponentLine)); } else { printf("%s %s\n", TranslateMoves(&GlobalPV.argmove[0]),PV2Str(OpponentLine)); } fflush(stdout); } else if (Xoutput==_NORMAL_OUTPUT) { printf("%7.2lf%7.2lf ",0.01*ngmax, SECONDS_PASSED); if (Goodmove) { printf("%s! %s\n", TranslateMoves(&GlobalPV.argmove[0]),PV2Str(OpponentLine)); } else { printf("%s %s\n", TranslateMoves(&GlobalPV.argmove[0]),PV2Str(OpponentLine)); } } } /* ------------------------------------------------------ */ /* --- This initiates the search for white moves --- */ /* ------------------------------------------------------ */ int GetWhiteBestMove(MOVE *mP) { int ret=0, d, w_moves, e, IsMaterialEnough; int tempNG, Alpha, Beta; MOVE wmovelst[MAXMV]; LINE line; InitTime(); nodes = 0; Starting_Mv=mv_stack_p; w_moves=FindAllWhiteMoves(wmovelst); if (w_moves==0) { if (WhiteKingInCheck()) { if (Xoutput==_NORMAL_OUTPUT) { ExitErrorMesg("Black Mates. GAME OVER (0 - 1)"); } else if (Xoutput==_XBOARD_OUTPUT) { printf("0-1 {Black Mates}\n"); } } else { if (Xoutput==_NORMAL_OUTPUT) { ExitErrorMesg("Drawn. Stalemate. GAME OVER (1/2 - 1/2)"); } else if (Xoutput==_XBOARD_OUTPUT) { printf("1/2-1/2 {Draw. Stalemate.}\n"); } } return 0; } if (IsBookLine(&ret,wmovelst,w_moves)) { mP->u = wmovelst[ret].u; return 1; } else { e = StaticEval(&IsMaterialEnough); if (IsMaterialEnough==0) { if (Xoutput==_NORMAL_OUTPUT) { ExitErrorMesg("Drawn. Not enought pieces for mate. GAME OVER (1/2 - 1/2)"); } else if (Xoutput==_XBOARD_OUTPUT) { printf("1/2-1/2 {Draw. Not enough material.}\n"); return 0; } } ret=0; if (w_moves==1) { mP->u = wmovelst[0].u; return 1; } else { if (WhiteKingInCheck()) { Threat.u = 0; } else { /* First Try to find threat for opponent */ MOVE thrlst[MAXMV]; int oppn = FindAllBlackMoves(thrlst); if (oppn>THREAT_MOVE_THRESH) { if (PlayAndSortThreatMoves(thrlst, oppn, white/*Our color*/, START_DEPTH-1, 1/*Sorted moves*/)) { Threat.u = thrlst[0].u; if (Xoutput==_NORMAL_OUTPUT) printf("\n Black's Threat is %s (found in %7.2lf seconds)\n", TranslateMoves(&thrlst[0]), SECONDS_PASSED); } else { Threat.u = 0; } } /* Then Sort Our starting move list using a shallow negamax search */ PlayAndSortThreatMoves(wmovelst, w_moves, black/*next color*/, START_DEPTH-1, w_moves/*sort length*/); } PrevNgmax = ngmax; if (PrevNgmax==-INFINITY && (Abs(e) 3 then put previous PV[0] first in move list */ if (d>START_DEPTH+1) { FindAndUpdateInPlace(wmovelst, w_moves, GlobalPV.argmove[0].u,0); } Alpha = -INFINITY; Beta = INFINITY; tempNG = NegaMax(0, 1, &line, wmovelst, w_moves, d, Alpha, Beta, white, &ret); if (TimeIsUp) { if (danger && (tempNG >= ngmax) && CriticalAnswer) { ngmax = tempNG; GlobalPV.argmove[0].u = wmovelst[ret].u; memcpy(GlobalPV.argmove + 1, line.argmove, line.cmove * sizeof(MOVE)); GlobalPV.cmove = line.cmove + 1; PrintMoveOutput(d, 0, &line); } break; } if (ret>=0 && (!danger || CriticalAnswer)) { int exclamation = (PrevNgmax!=-INFINITY && tempNG > (PrevNgmax + PV_CHANGE_THRESH)); ngmax = tempNG; GlobalPV.argmove[0].u = wmovelst[ret].u; memcpy(GlobalPV.argmove + 1, line.argmove, line.cmove * sizeof(MOVE)); GlobalPV.cmove = line.cmove + 1; PrintMoveOutput(d, exclamation, &line); } if (ngmax > CUTOFF || ngmax < -CUTOFF) break; } } } mP->u = GlobalPV.argmove[0].u; return 1; } /* ------------------------------------------------------ */ /* --- This initiates the search for black moves --- */ /* ------------------------------------------------------ */ int GetBlackBestMove(MOVE *mP) { int ret, d, black_moves, e, IsMaterialEnough; int tempNG, Alpha, Beta; MOVE bmovelst[MAXMV]; LINE line; InitTime(); Starting_Mv=mv_stack_p; nodes = 0; black_moves=FindAllBlackMoves(bmovelst); if (black_moves==0) { if (BlackKingInCheck()) { if (Xoutput==_NORMAL_OUTPUT) { ExitErrorMesg("White Mates. GAME OVER (1 - 0)"); } else if (Xoutput==_XBOARD_OUTPUT) { printf("1-0 {White Mates}\n"); return 0; } } else { if (Xoutput==_NORMAL_OUTPUT) { ExitErrorMesg("Drawn. Stalemate. GAME OVER (1/2 - 1/2)"); } else if (Xoutput==_XBOARD_OUTPUT) { printf("1/2-1/2 {Draw. Stalemate.}\n"); return 0; } } } if (IsBookLine(&ret,bmovelst,black_moves)) { mP->u = bmovelst[ret].u; return 1; } else { e = StaticEval(&IsMaterialEnough); if (IsMaterialEnough==0) { if (Xoutput==_NORMAL_OUTPUT) { ExitErrorMesg("Drawn. Not enought pieces for mate. GAME OVER (1/2 - 1/2)"); } else if (Xoutput==_XBOARD_OUTPUT) { printf("1/2-1/2 {Draw. Not enough material.}\n"); return 0; } } ret=0; if (black_moves==1) { mP->u = bmovelst[0].u; return 1; } else { if (BlackKingInCheck()) { Threat.u = 0; } else { /* First Try to find threat for opponent */ MOVE thrlst[MAXMV]; int oppn = FindAllWhiteMoves(thrlst); if (oppn>THREAT_MOVE_THRESH) { if (PlayAndSortThreatMoves(thrlst, oppn, black/*Our color*/, START_DEPTH-1, 1/*Sorted moves*/)) { Threat.u = thrlst[0].u; if (Xoutput==_NORMAL_OUTPUT) printf("\n White's Threat is %s (found in %7.2lf seconds)\n", TranslateMoves(&thrlst[0]), SECONDS_PASSED); } else { Threat.u = 0; } } /* Then Sort Our starting moves using a shallow negamax search */ PlayAndSortThreatMoves(bmovelst, black_moves, white/*next color*/, START_DEPTH-1, black_moves/*sort length*/); } PrevNgmax = ngmax; if (PrevNgmax==-INFINITY && (Abs(e) 3 then put previous PV[0] first in move list */ if (d>START_DEPTH+1) { FindAndUpdateInPlace(bmovelst, black_moves, GlobalPV.argmove[0].u,0); } Alpha = -INFINITY; Beta = INFINITY; tempNG = NegaMax(0, 1, &line, bmovelst, black_moves, d, -INFINITY, INFINITY, black, &ret); if (TimeIsUp) { if (danger && (tempNG >= ngmax) && CriticalAnswer) { ngmax = tempNG; GlobalPV.argmove[0].u = bmovelst[ret].u; memcpy(GlobalPV.argmove + 1, line.argmove, line.cmove * sizeof(MOVE)); GlobalPV.cmove = line.cmove + 1; PrintMoveOutput(d, 0, &line); } break; } if (ret>=0 && (!danger || CriticalAnswer)) { int exclamation = (PrevNgmax!=-INFINITY && tempNG > (PrevNgmax + PV_CHANGE_THRESH)); ngmax = tempNG; GlobalPV.argmove[0].u = bmovelst[ret].u; memcpy(GlobalPV.argmove + 1, line.argmove, line.cmove * sizeof(MOVE)); GlobalPV.cmove = line.cmove + 1; PrintMoveOutput(d, exclamation, &line); } if (ngmax > CUTOFF || ngmax < -CUTOFF) break; } } } mP->u = GlobalPV.argmove[0].u; return 1; } /* ------------------------------------------------------ */ int GetPlayerMove(int *xy1, int *xy2, int *flag) { char buf[60]; int x1,y1,x2,y2; for (;;) { printf("\b\b\b\b\b\b\b\b\b\b\b\bGive move : "); gets(buf); if (!strcmp(buf,"retract")) { return 2; } if (buf[0]>='a' && buf[0]<='h') { x1 = buf[0] - 'a'; if (buf[1]>='1' && buf[1]<='8') { y1 = buf[1] - '1'; if (buf[2]>='a' && buf[2]<='h') { x2 = buf[2] - 'a'; if (buf[3]>='1' && buf[3]<='8') { y2 = buf[3] - '1'; break; } } } } } *xy1 = 10*y1+x1+21; *xy2 = 10*y2+x2+21; if (board[*xy1]->type==WPAWN) { if (*xy2>=A8) { switch(buf[4]) { case 'r': *flag=WROOK; break; case 'n': *flag=WKNIGHT; break; case 'b': *flag=WBISHOP; break; case 'q': *flag=WQUEEN; break; default: fprintf(stderr,"Give promotion piece number(knight=1,bishop=2,rook=3,queen=4), :"); scanf("%d",flag); *flag = (*flag) + 2; break; } } else *flag=WPAWN; } else if (board[*xy1]->type==BPAWN) { if (*xy2<=H1) { switch(buf[4]) { case 'r': *flag=BROOK; break; case 'n': *flag=BKNIGHT; break; case 'b': *flag=BBISHOP; break; case 'q': *flag=BQUEEN; break; default: fprintf(stderr,"Give promotion piece number(knight=1,bishop=2,rook=3,queen=4), :"); scanf("%d",flag); *flag = (*flag) + 2; *flag = black + (*flag); break; } } else *flag=BPAWN; } else { *flag=1; } return 0; } /* ------------------------------------------------------ */ int MoveExistsInList(int xy1, int xy2, int flag, MOVE q[]) { /* This returns -1 if not found else returns the index found*/ int i; for (i=0; q[i].m.flag && im.from]->type == WPAWN) || (board[amovep->m.from]->type == BPAWN)) { /* pawn move */ FiftyMoves = 0; } if (board[amovep->m.to]->type > 0) { /* capture */ FiftyMoves = 0; } for (i=0; i<16; i++) { if (Bpieces[i].xy>0) { bl_pieces++; } if (Wpieces[i].xy>0) { wh_pieces++; } } if (bl_pieces==1 && Edge[bking]) { LoneKingReachedEdge = 1; } if (wh_pieces==1 && Edge[wking]) { LoneKingReachedEdge = 1; } } /* ---------------------------------------------------------------------------- */ /* ------------- This is the Custom Console Play interface function ----------- */ /* ---------------------------------------------------------------------------- */ void Play(void) { int n, from, to, fl; MOVE amove; int e, IsMaterialEnough; for (;;) { side=white; e = StaticEval(&IsMaterialEnough); if (IsMaterialEnough==0) { ExitErrorMesg("Draw. Not enough Material. (1/2 - 1/2)"); } n=FindAllWhiteMoves(wmoves); if (n==0) { if (WhiteKingInCheck()) { ExitErrorMesg("Black Checkmates !! GAME OVER (0-1)"); } else { ExitErrorMesg("Stalemate. GAME OVER (1/2 - 1/2)"); } } if ( ComputerSide == white) { if (!GetWhiteBestMove(&amove)) continue; UpdateSpecialConditions(&amove); printf("\n Computer Played : %s in %7.2lf secs",TranslateMoves(&amove), SECONDS_PASSED); } else { int comm; do { ShowBoard(); comm = GetPlayerMove(&from, &to, &fl); if (comm==2) { RetractLastMove(); PopStatus(); continue; } amove.m.flag = fl; amove.m.from = from; amove.m.to = to; amove.m.dummy=0; PlayerMove.u = amove.u; UpdateSpecialConditions(&amove); } while(MoveExistsInList(from,to,fl, wmoves)<0); } PushStatus(); MakeMove(&amove); AddMoveToLine(amove.m.from,amove.m.to); if (HashRepetitions() == 3) { ExitErrorMesg("1/2-1/2 {Draw by repetition}\n"); } if (FiftyMoves>=100) { ExitErrorMesg("1/2-1/2 {Draw by fifty moves rule}\n"); } side=black; e = StaticEval(&IsMaterialEnough); if (IsMaterialEnough==0) { ExitErrorMesg("Draw. Not enough Material. (1/2 - 1/2)"); } n=FindAllBlackMoves(bmoves); if (n==0) { if (BlackKingInCheck()) { ExitErrorMesg("White Checkmates !! GAME OVER (1-0)"); } else { ExitErrorMesg("Stalemate. GAME OVER (1/2 - 1/2)"); } } if (ComputerSide == black) { if (!GetBlackBestMove(&amove)) continue; UpdateSpecialConditions(&amove); printf("\n Computer Played : %s in %7.2lf secs",TranslateMoves(&amove), SECONDS_PASSED); } else { int comm; do { ShowBoard(); comm = GetPlayerMove(&from, &to,&fl); if (comm==2) { RetractLastMove(); PopStatus(); continue; } amove.m.flag = fl; amove.m.from = from; amove.m.to = to; amove.m.dummy=0; PlayerMove.u = amove.u; UpdateSpecialConditions(&amove); } while(MoveExistsInList(from,to,fl, bmoves)<0); } PushStatus(); MakeMove(&amove); AddMoveToLine(amove.m.from,amove.m.to); if (HashRepetitions() == 3) { ExitErrorMesg("1/2-1/2 {Draw by repetition}\n"); } if (FiftyMoves>=100) { ExitErrorMesg("1/2-1/2 {Draw by fifty moves rule}\n"); } } } /* ------------------------------------------------------ */ void ReadXboardPosition(void) { char cbuf[256], command[256]; int i, Xcolor=0; while (fgets(cbuf, 256, stdin) != NULL) { /*FileDebug(cbuf);*/ if (cbuf[0] == '\n') break; sscanf(cbuf, "%s", command); if (!strcmp(command, "#")) { EmptyBoard(); } if (!strcmp(command, "c")) { Xcolor=black; } if (!strcmp(command, ".")) { break; } if (cbuf[0] && cbuf[1] && cbuf[2]) { switch (cbuf[0]) { case '\n': case '\t': case ',': case ' ': break; case 'K': if (Xcolor==black) { bking = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; Bpieces[0].xy = bking; board[bking] = &Bpieces[0]; } else { wking = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; Wpieces[0].xy = wking; board[wking] = &Wpieces[0]; } break; case 'Q': if (Xcolor==black) { if (Bpieces[1].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[1]; Bpieces[1].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Bpieces[i].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[i]; Bpieces[i].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; Bpieces[i].type = BQUEEN; break; } } } } else { if (Wpieces[1].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[1]; Wpieces[1].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Wpieces[i].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[i]; Wpieces[i].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; Wpieces[i].type = WQUEEN; break; } } } } break; case 'R': if (Xcolor==black) { if (Bpieces[2].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[2]; Bpieces[2].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else if (Bpieces[3].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[3]; Bpieces[3].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Bpieces[i].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[i]; Bpieces[i].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; Bpieces[i].type = BROOK; break; } } } } else { if (Wpieces[2].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[2]; Wpieces[2].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else if (Wpieces[3].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[3]; Wpieces[3].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Wpieces[i].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[i]; Wpieces[i].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; Wpieces[i].type = WROOK; break; } } } } break; case 'B': if (Xcolor==black) { if (Bpieces[4].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[4]; Bpieces[4].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else if (Bpieces[5].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[5]; Bpieces[5].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Bpieces[i].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[i]; Bpieces[i].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; Bpieces[i].type = BBISHOP; break; } } } } else { if (Wpieces[4].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[4]; Wpieces[4].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else if (Wpieces[5].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[5]; Wpieces[5].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Wpieces[i].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[i]; Wpieces[i].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; Wpieces[i].type = WBISHOP; break; } } } } break; case 'N': if (Xcolor==black) { if (Bpieces[6].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[6]; Bpieces[6].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else if (Bpieces[7].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[7]; Bpieces[7].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Bpieces[i].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[i]; Bpieces[i].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; Bpieces[i].type = BKNIGHT; break; } } } } else { if (Wpieces[6].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[6]; Wpieces[6].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else if (Wpieces[7].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[7]; Wpieces[7].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; } else { /* promoted piece */ for (i=8; i<16; i++) { if (Wpieces[i].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[i]; Wpieces[i].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; Wpieces[i].type = WKNIGHT; break; } } } } break; case 'P': if (Xcolor==black) { for (i=8; i<16; i++) { if (Bpieces[i].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Bpieces[i]; Bpieces[i].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; break; } } } else { for (i=8; i<16; i++) { if (Wpieces[i].xy==0) { board[10*(cbuf[2]-'1')+cbuf[1]-'a'+21] = &Wpieces[i]; Wpieces[i].xy = 10*(cbuf[2]-'1')+cbuf[1]-'a'+21; break; } } } break; default: break; } } } /* castling flags reset*/ if (wking==E1) { wkmoved=0; WHasCastled=0;} else { wkmoved=1; WHasCastled=1;} if (bking==E8) { bkmoved=0; BHasCastled=0;} else { bkmoved=1; BHasCastled=1;} if (board[A1]->type==WROOK) { wra1moved=0; } else { wra1moved=1; } if (board[H1]->type==WROOK) { wrh1moved=0; } else { wrh1moved=1; } if (board[A8]->type==BROOK) { bra8moved=0; } else { bra8moved=1; } if (board[H8]->type==BROOK) { brh8moved=0; } else { brh8moved=1; } EnPassantSq=0; /* Move Stack Pointers reset */ cst_p=0; mv_stack_p=0; HalfMovesPlayed=0; CurrentLine[0] = '\0'; LoneKingReachedEdge=0; FiftyMoves=0; NotStartingPosition=1; PlayerMove.u=0; } /* ----------------- Checks draw by repetition or 50 moves rule --------------- */ void CheckSpecialDrawRules(void) { int e, IsMaterialEnough; e = StaticEval(&IsMaterialEnough); if (IsMaterialEnough==0) { printf("1/2-1/2 {Draw. Not enough material.}\n"); } else if (HashRepetitions() == 3) { printf("1/2-1/2 {Draw by repetition}\n"); } else if (FiftyMoves>=100) { printf("1/2-1/2 {Draw by fifty moves rule}\n"); } } /* ----------------- Checks for Mate or Stalemate under Xboard interface --------------- */ void CheckForMate(void) { MOVE xmoves[MAXMV]; int n; if (side==white) { n=FindAllWhiteMoves(xmoves); if (n==0) { if (WhiteKingInCheck()) { printf("0-1 {Black Checkmates}\n"); } else { printf("1/2-1/2 {Stalemate}\n"); } } } else { n=FindAllBlackMoves(xmoves); if (n==0) { if (BlackKingInCheck()) { printf("1-0 {White Checkmates}\n"); } else { printf("1/2-1/2 {Stalemate}\n"); } } } } /* ---------------------------------------------------------------------------- */ /* ----------------- This is the main Xboard interface function --------------- */ /* ---------------------------------------------------------------------------- */ void xboard(void) { char line[256], command[256]; int moveNo=40, TimeMins, Incr;/*, from, to, fl;*/ MOVE amove; side=white; ComputerSide=none; /* no engine at start */ max_time = 15000; /* by default 15 seconds/move */ signal(SIGINT, SIG_IGN); printf("\n"); for (;;) { fflush(stdout); if (side == ComputerSide) { if (side==white) { if (!GetWhiteBestMove(&amove)) { ComputerSide=none; continue; } } else { if (!GetBlackBestMove(&amove)) { ComputerSide=none; continue; } } printf("move %s\n",TranslateMoves(&amove)); UpdateSpecialConditions(&amove); PushStatus(); MakeMove(&amove); AddMoveToLine(amove.m.from,amove.m.to); CheckSpecialDrawRules(); side = NextSide(side); CheckForMate(); continue; } if (!fgets(line, 256, stdin)) { return; } if (line[0] == '\n') { continue; } /*FileDebug(line);*/ sscanf(line, "%s", command); if (!strcmp(command, "new")) { StartingPosition(); side=white; ComputerSide=black; continue; } if (!strcmp(command, "quit")){ return; } if (!strcmp(command, "force")) { ComputerSide = none; continue; } if (!strcmp(command, "white")) { side = white; ComputerSide = black; continue; } if (!strcmp(command, "black")) { side = black; ComputerSide = white; continue; } if (!strcmp(command, "time")) { if ((moveNo - mv_stack_p/2)>0) { sscanf(line, "time %d", &max_time); max_time *= 10; max_time /= (moveNo - mv_stack_p/2); } continue; } if (!strcmp(command, "post")) { Xoutput = _XBOARD_OUTPUT; continue; } if (!strcmp(command, "nopost")) { Xoutput = 0; continue; } if (!strcmp(command, "level")) { sscanf(line, "level %d %d %d", &moveNo, &TimeMins, &Incr); if (moveNo!=0) { max_time = TimeMins*60000/moveNo; } else { max_time = TimeMins*60000/30; } continue; } if (!strcmp(command, "hint")) { MOVE amove; if (side==white) { if (!GetWhiteBestMove(&amove)) continue; } else { if (!GetBlackBestMove(&amove)) continue; } printf("Hint: %s\n",TranslateMoves(&amove)); continue; } if (!strcmp(command, "undo")) { RetractLastMove(); PopStatus(); side = NextSide(side); continue; } if (!strcmp(command, "remove")) { RetractLastMove(); PopStatus(); RetractLastMove(); PopStatus(); continue; } if (!strcmp(command, "go")) { ComputerSide = side; continue; } if (!strcmp(command, "edit")) { ReadXboardPosition(); continue; } if (!ParsePlayerMove(line,&amove)) { printf("Error (unknown command): %s\n", command); } else { PlayerMove.u = amove.u; UpdateSpecialConditions(&amove); PushStatus(); MakeMove(&amove); AddMoveToLine(amove.m.from,amove.m.to); CheckSpecialDrawRules(); side = NextSide(side); CheckForMate(); } } } /* ------------------------------------------------------- */ /* --- This searches for Mate in Custom play console ----- */ /* ------------------------------------------------------- */ void mate(void) { int i, matelevel, WmovNo, key=-1; MOVE Wmovelst[MAXMV]; system("cls"); ShowBoard(); fprintf(stderr,"\nGive matelevel: "); scanf("%d",&matelevel); start_time = GetMillisecs(); WmovNo=FindAllWhiteMoves(Wmovelst); fprintf(stderr,"\n"); for (i=1; i<=matelevel; i++) { if (WhiteMates(i, 0, WmovNo, Wmovelst, &key)) { fprintf(stderr,"\n\nMate in %d moves found! \n\n1.%s !\n\nTime used=%lf secs\n\n", i, TranslateMoves(&Wmovelst[key]), SECONDS_PASSED); return; } fprintf(stderr,"\nNo Mate in %d moves. Time used=%lf secs", i, SECONDS_PASSED); } fprintf(stderr,"\n\n"); } /* ------------------------------------------------------- */ /* ------- Main Function for NGplay Chess Engine -------- */ /* ------------------------------------------------------- */ int main(int argc, char **argv) { char s[256], book_s[20]; InitHash(); strcpy(book_s,"NG2book.txt"); StartingPosition(); printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"); printf("%s Chess Engine\n", argv[0]); printf("Optional Run Time Usage: %s -p -b \n", argv[0]); printf("Commands available:\n"); printf("\n"); printf("xboard - switch to XBoard mode\n"); printf("play - Play using Native console\n"); printf("mate - Find mate for white side\n"); printf("help - displays a list of commands.\n"); printf("bye - exit the program\n"); printf("\n"); /* for debug getch(); ----- */ if (argc>1) { int i; for (i=0; i "); if (scanf("%s", s) == EOF) return 0; if (!strcmp(s, "bye")) { printf("Share and enjoy!\n"); break; } if (!strcmp(s, "xboard")) { xboard(); break; } if (!strcmp(s, "play")) { Xoutput = _NORMAL_OUTPUT; ShowBoard(); do { fprintf(stderr,"Give Computer Side (White = 1, Black = 2, None = 3) : "); scanf("%d",&ComputerSide); } while ((ComputerSide!=1) && (ComputerSide!=2) && (ComputerSide!=3)); if (ComputerSide==2) ComputerSide=black; fprintf(stderr,"Give Computer Time (seconds per move) : "); scanf("%d", &max_time); max_time *= 1000; fprintf(stderr,"Game begins!\n"); Play(); break; } if (!strcmp(s, "mate")) { mate(); break; } if (!strcmp(s, "help")) { printf("xboard - switch to XBoard mode\n"); printf("play - Play using Native console\n"); printf("mate - Find mate for white side\n"); printf("help - displays a list of commands.\n"); printf("bye - exit the program\n"); continue; } } if (book_file) fclose(book_file); return 0; }