/* * init.c - C source for GNU CHESS * * Copyright (c) 1988,1989,1990 John Stanback * Copyright (c) 1992 Free Software Foundation * * This file is part of GNU CHESS. * * GNU Chess is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GNU Chess is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Chess; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "gnuchess.h" #ifdef CACHE extern struct etable __far __aligned etab[2][ETABLE]; #endif extern int __aligned ThinkInARow; extern int __aligned bookflag; extern int __aligned Sdepth2; #ifdef AMIGA #define __USE_SYSBASE #define MOVENOWMENUNUM 0x42 #define THINKMENUNUM 0x82 #define SHOWMENUNUM 0xa2 #define BOOKMENUNUM 0xc2 #define SUPERMENUNUM 0xe2 #define ADVANCEDMENUNUM 0x102 #define INTERMEDIATEMENUNUM 0x122 #define EASYMENUNUM 0x142 #include #include #include extern int __aligned cmptr_sec,cmptr_min,hum_sec,hum_min; extern int procpri; extern struct Process *myproc; extern int __far ResignOffered; #endif extern struct Menu Menu1; #define MenuList1 Menu1 extern int MenuStripSet; extern struct MenuItem MenuItem8ab; extern struct Window __aligned *wG; unsigned int urand (void); /* .... MOVE GENERATION VARIABLES AND INITIALIZATIONS .... */ void InitHashCode(unsigned int); short __aligned PCRASH,PCENTER; extern int PlayMode; extern unsigned int TTadd; #if defined NULLMOVE || defined DEEPNULL extern short int __aligned no_null; extern short int __aligned null; /* Null-move already made or not */ extern short int __aligned PVari; /* Is this the PV */ #endif extern short __aligned Threat[MAXDEPTH]; extern unsigned short int __aligned PrVar[MAXDEPTH]; extern short __aligned PawnStorm; extern short __aligned start_stage; extern short __aligned thrashing_tt; /* must we recycle slots at random. TomV */ extern short int ISZERO; extern int __aligned global_tmp_score; extern int __aligned previous_score; int __aligned FirstTime=1; extern int SupervisorMode; extern int IllegalMove; extern int CheckIllegal; #ifdef LONGINTS2 INTSIZE __far distdata[64][64]; INTSIZE __far taxidata[64][64]; #else INTSIZE __aligned distdata[64][64]; INTSIZE __aligned taxidata[64][64]; #endif #ifdef KILLT /* put moves to the center first */ void Initialize_killt (void) { REG unsigned INTSIZE f, t, s; REG INTSIZE d; for (f = 64; f--;) for (t = 64; t--;) { d = taxidata[f][0x1b]; if (taxidata[f][0x1c] < d) d = taxidata[f][0x1c]; if (taxidata[f][0x23] < d) d = taxidata[f][0x23]; if (taxidata[f][0x24] < d) d = taxidata[f][0x24]; s = d; d = taxidata[t][0x1b]; if (taxidata[t][0x1c] < d) d = taxidata[t][0x1c]; if (taxidata[t][0x23] < d) d = taxidata[t][0x23]; if (taxidata[t][0x24] < d) d = taxidata[t][0x24]; s -= d; killt[(f << 8) | t] = s; killt[(f << 8) | t | 0x80] = s; } } #endif void Initialize_dist (void) { REG INTSIZE a, b, d, di; for (a = 0; a < 64; a++) for (b = 0; b < 64; b++) { d = abs (column (a) - column (b)); di = abs (row (a) - row (b)); taxidata[a][b] = d + di; distdata[a][b] = (d > di ? d : di); } #ifdef KILLT Initialize_killt (); #endif } const INTSIZE __aligned Stboard[64] = {rook, knight, bishop, queen, king, bishop, knight, rook, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, 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, pawn, pawn, pawn, pawn, pawn, pawn, pawn, pawn, rook, knight, bishop, queen, king, bishop, knight, rook}; const INTSIZE __aligned Stcolor[64] = {white, white, white, white, white, white, white, white, white, white, white, white, white, white, white, white, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, neutral, black, black, black, black, black, black, black, black, black, black, black, black, black, black, black, black}; INTSIZE __aligned board[64], color[64]; INTSIZE __aligned amigaboard[64],amigacolor[64]; /* given epsquare, from where can a pawn be taken? */ const INTSIZE __aligned epmove1[64] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 24, 25, 26, 27, 28, 29, 30, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 32, 33, 34, 35, 36, 37, 38, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}; const INTSIZE __aligned epmove2[64] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 25, 26, 27, 28, 29, 30, 31, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 33, 34, 35, 36, 37, 38, 39, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63}; /* * nextpos[piece][from-square] , nextdir[piece][from-square] gives vector of * positions reachable from from-square in ppos with piece such that the * sequence ppos = nextpos[piece][from-square]; pdir = * nextdir[piece][from-square]; u = ppos[sq]; do { u = ppos[u]; if(color[u] * != neutral) u = pdir[u]; } while (sq != u); will generate the sequence of * all squares reachable from sq. * * If the path is blocked u = pdir[sq] will generate the continuation of the * sequence in other directions. */ unsigned char __far __aligned nextpos[8][64][64]; unsigned char __far __aligned nextdir[8][64][64]; /* * ptype is used to separate white and black pawns, like this; ptyp = * ptype[side][piece] piece can be used directly in nextpos/nextdir when * generating moves for pieces that are not black pawns. */ const INTSIZE __aligned ptype[2][8] = { no_piece, pawn, knight, bishop, rook, queen, king, no_piece, no_piece, bpawn, knight, bishop, rook, queen, king, no_piece}; /* data used to generate nextpos/nextdir */ static const INTSIZE __aligned direc[8][8] = { 0, 0, 0, 0, 0, 0, 0, 0, 10, 9, 11, 0, 0, 0, 0, 0, 8, -8, 12, -12, 19, -19, 21, -21, 9, 11, -9, -11, 0, 0, 0, 0, 1, 10, -1, -10, 0, 0, 0, 0, 1, 10, -1, -10, 9, 11, -9, -11, 1, 10, -1, -10, 9, 11, -9, -11, -10, -9, -11, 0, 0, 0, 0, 0}; static const INTSIZE __aligned max_steps[8] = {0, 2, 1, 7, 7, 7, 1, 2}; static const INTSIZE __aligned nunmap[120] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, -1, -1, 8, 9, 10, 11, 12, 13, 14, 15, -1, -1, 16, 17, 18, 19, 20, 21, 22, 23, -1, -1, 24, 25, 26, 27, 28, 29, 30, 31, -1, -1, 32, 33, 34, 35, 36, 37, 38, 39, -1, -1, 40, 41, 42, 43, 44, 45, 46, 47, -1, -1, 48, 49, 50, 51, 52, 53, 54, 55, -1, -1, 56, 57, 58, 59, 60, 61, 62, 63, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; int __aligned InitFlag = false; void Initialize_moves (void) /* * This procedure pre-calculates all moves for every piece from every square. * This data is stored in nextpos/nextdir and used later in the move * generation routines. */ { INTSIZE ptyp, po, p0, d, di, s, delta; unsigned char *ppos, *pdir; INTSIZE dest[8][8]; INTSIZE steps[8]; INTSIZE sorted[8]; for (ptyp = 0; ptyp < 8; ptyp++) for (po = 0; po < 64; po++) for (p0 = 0; p0 < 64; p0++) { nextpos[ptyp][po][p0] = (unsigned char) po; nextdir[ptyp][po][p0] = (unsigned char) po; } for (ptyp = 1; ptyp < 8; ptyp++) for (po = 21; po < 99; po++) if (nunmap[po] >= 0) { ppos = nextpos[ptyp][nunmap[po]]; pdir = nextdir[ptyp][nunmap[po]]; /* dest is a function of direction and steps */ for (d = 0; d < 8; d++) { dest[d][0] = nunmap[po]; delta = direc[ptyp][d]; if (delta != 0) { p0 = po; for (s = 0; s < max_steps[ptyp]; s++) { p0 = p0 + delta; /* * break if (off board) or (pawns only move two * steps from home square) */ if ((nunmap[p0] < 0) || (((ptyp == pawn) || (ptyp == bpawn)) && ((s > 0) && ((d > 0) || (Stboard[nunmap[po]] != pawn))))) break; else dest[d][s] = nunmap[p0]; } } else s = 0; /* * sort dest in number of steps order currently no sort * is done due to compability with the move generation * order in old gnu chess */ steps[d] = s; for (di = d; s > 0 && di > 0; di--) if (steps[sorted[di - 1]] == 0) /* should be: < s */ sorted[di] = sorted[di - 1]; else break; sorted[di] = d; } /* * update nextpos/nextdir, pawns have two threads (capture * and no capture) */ p0 = nunmap[po]; if (ptyp == pawn || ptyp == bpawn) { for (s = 0; s < steps[0]; s++) { ppos[p0] = (unsigned char) dest[0][s]; p0 = dest[0][s]; } p0 = nunmap[po]; for (d = 1; d < 3; d++) { pdir[p0] = (unsigned char) dest[d][0]; p0 = dest[d][0]; } } else { pdir[p0] = (unsigned char) dest[sorted[0]][0]; for (d = 0; d < 8; d++) for (s = 0; s < steps[sorted[d]]; s++) { ppos[p0] = (unsigned char) dest[sorted[d]][s]; p0 = dest[sorted[d]][s]; if (d < 7) pdir[p0] = (unsigned char) dest[sorted[d + 1]][0]; /* * else is already initialized */ } } } } void NewGame (void) /* * Reset the board and other variables to start a new game. */ { INTSIZE l; int tmp; char tstr[32]; INTSIZE a, r, c, sq, i, found; int tmpcolor; char s[16]; TTadd = ISZERO = 1; cmptr_min = hum_min = cmptr_sec = hum_sec = -1; if (AmigaStarted) { if (FirstTime) { FirstTime = 0; } else { if (!LoadFullBitMap()) { ExitChess(); } (void)SetTaskPri((struct Task *)myproc,procpri); } } /* SupervisorMode = 0;*/ bookflag = previous_score = 0; global_tmp_score = 0; CheckIllegal = IllegalMove = 0; Mate = 0; ResignOffered = 0; ThinkInARow = ThinkAheadDepth = ThinkAheadWorked = 0; DrawnGame = 0; MateString[0] = '\0'; compptr = oppptr = 0; // was -1 in 2.35 stage = stage2 = -1; /* the game is not yet started */ flag.illegal = flag.mate = flag.quit = flag.reverse = flag.bothsides = flag.onemove = flag.force = false; flag.material = flag.coords = flag.hash = flag.beep = flag.rcptr = true; flag.threat = true; flag.stars = flag.shade = flag.back = flag.musttimeout = false; #ifdef CLIENT flag.gamein = true; #else flag.gamein = false; #endif #if defined(MSDOS) && !defined(SEVENBIT) flag.rv = false; #else flag.rv = true; #endif /* MSDOS && !SEVENBIT */ ClearPointer(wG); mycnt1 = mycnt2 = 0; GenCnt = NodeCnt = et0 = epsquare = XCmore = 0; dither = 0; WAwindow = WAWNDW; WBwindow = WBWNDW; BAwindow = BAWNDW; BBwindow = BBWNDW; xwndw = BXWNDW; if (!MaxSearchDepth) MaxSearchDepth = MAXDEPTH - 1; contempt = 0; GameCnt = 0; Game50 = 1; hint = 0x0C14; ISZERO = 1; ZeroRPT (); Developed[white] = Developed[black] = false; MouseDropped = 0; Castled[white] = Castled[black] = 0; myEnPassant[white] = myEnPassant[black] = 0; castld[white] = castld[black] = false; #if defined NULLMOVE || defined DEEPNULL no_null=0; null = 0; /* Null-move already made or not */ PVari = 0; /* Is this the PV */ #endif PawnStorm = start_stage = 0; thrashing_tt = 0; /* must we recycle slots at random. TomV */ ClearMem(QueenCheck,MAXDEPTH*sizeof(short)); ClearMem(PrVar,MAXDEPTH*sizeof(short)); ClearMem(Threat,MAXDEPTH*sizeof(short)); ClearMem(ThreatSave,MAXDEPTH*sizeof(short)); ClearMem(Pscore,MAXDEPTH*sizeof(short)); ClearMem(Tscore,MAXDEPTH*sizeof(short)); ClearMem(ChkFlag,MAXDEPTH*sizeof(short)); ClearMem(CptrFlag,MAXDEPTH*sizeof(short)); ClearMem(PawnThreat,MAXDEPTH*sizeof(short)); PawnThreat[0] = CptrFlag[0] = false; Pscore[0] = 12000; Tscore[0] = 12000; opponent = white; computer = black; for (l = 0; l < TREE; l++) Tree[l].f = Tree[l].t = 0; #ifdef OLD_TTABLE gsrand ((unsigned int) 1); if (!InitFlag) { for (c = white; c <= black; c++) for (p = pawn; p <= king; p++) for (l = 0; l < 64; l++) { hashcode[c][p][l].key = (((unsigned long) urand ())); hashcode[c][p][l].key += (((unsigned long) urand ()) << 16); hashcode[c][p][l].bd = (((unsigned long) urand ())); hashcode[c][p][l].bd += (((unsigned long) urand ()) << 16); #ifdef LONG64 hashcode[c][p][l].key += (((unsigned long) urand ()) << 32); hashcode[c][p][l].key += (((unsigned long) urand ()) << 48); hashcode[c][p][l].bd += (((unsigned long) urand ()) << 32); hashcode[c][p][l].bd += (((unsigned long) urand ()) << 48); #endif } } #else //new ttable stuff from pl70 if (!InitFlag) InitHashCode((unsigned int)1); #endif // oldttable for (l = 0; l < 64; l++) { amigaboard[l] = board[l] = Stboard[l]; amigacolor[l] = color[l] = Stcolor[l]; Mvboard[l] = 0; } InitializeStats (); time0 = time ((long *) 0); ElapsedTime (1); flag.regularstart = true; if (MenuStripSet) { MenuItem8ab.Flags |= CHECKED; SetMenuStrip(wG,&MenuList1); /* attach any Menu */ } Book = BOOKFAIL; if (!InitFlag) { if (TCflag) { strcpy(tstr,"60 10"); SelectLevel (tstr); SetTimeControl (); } else if (MaxResponseTime == 0) { strcpy(tstr,"60 10"); SelectLevel (tstr); SetTimeControl (); } UpdateDisplay (0, 0, 1, 0); /* GetOpenings(black);*/ #ifdef CACHE Initialize_ttable(); #endif InitFlag = true; } else { if (TCflag) { sprintf(tstr,"%d %d",TCmoves,TCminutes); SelectLevel (tstr); SetTimeControl (); } } GetOpenings(black); hashbd = hashkey = 0; #ifdef AMIGA tmp = player; player = white; UpdateClocks(); player = black; UpdateClocks(); player = tmp; #endif #ifdef CACHE #if ttblsz ZeroTTable (0); TTadd = 0; #endif /* ttblsz */ #ifndef AMIGA memset ((signed char *) etab, 0, sizeof (etab)); #else ClearMem(etab,sizeof(etab)); #endif #endif if (PlayMode == 1) { flag.regularstart = false; Book = 0; strcpy(s," g8"); a = tmpcolor = black; c = s[1] - 'a'; r = s[2] - '1'; if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8)) { sq = locn (r, c); color[sq] = a; board[sq] = no_piece; for (i = no_piece; i <= king; i++) if ((s[0] == pxx[i]) || (s[0] == qxx[i])) { board[sq] = i; found=1; break; } if ((found==0)||(board[sq] == no_piece)) color[sq] = neutral; } strcpy(s," b8"); a = tmpcolor = black; c = s[1] - 'a'; r = s[2] - '1'; if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8)) { sq = locn (r, c); color[sq] = a; board[sq] = no_piece; for (i = no_piece; i <= king; i++) if ((s[0] == pxx[i]) || (s[0] == qxx[i])) { board[sq] = i; found=1; break; } if ((found==0)||(board[sq] == no_piece)) color[sq] = neutral; } if (MenuStripSet) { OnMenu(wG,ADVANCEDMENUNUM); OffMenu(wG,BOOKMENUNUM); OffMenu(wG,INTERMEDIATEMENUNUM); OnMenu(wG,EASYMENUNUM); } GameCnt = 0; Game50 = 1; ISZERO = 1; ZeroRPT (); Sdepth2 = Sdepth = 0; InitializeStats (); DrawAmigaBoard(); } else if (PlayMode == 0) { flag.regularstart = false; Book = 0; strcpy(s," d8"); a = tmpcolor = black; c = s[1] - 'a'; r = s[2] - '1'; if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8)) { sq = locn (r, c); color[sq] = a; board[sq] = no_piece; for (i = no_piece; i <= king; i++) if ((s[0] == pxx[i]) || (s[0] == qxx[i])) { board[sq] = i; found=1; break; } if ((found==0)||(board[sq] == no_piece)) color[sq] = neutral; } strcpy(s," g8"); a = tmpcolor = black; c = s[1] - 'a'; r = s[2] - '1'; if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8)) { sq = locn (r, c); color[sq] = a; board[sq] = no_piece; for (i = no_piece; i <= king; i++) if ((s[0] == pxx[i]) || (s[0] == qxx[i])) { board[sq] = i; found=1; break; } if ((found==0)||(board[sq] == no_piece)) color[sq] = neutral; } strcpy(s," b8"); a = tmpcolor = black; c = s[1] - 'a'; r = s[2] - '1'; if ((c >= 0) && (c < 8) && (r >= 0) && (r < 8)) { sq = locn (r, c); color[sq] = a; board[sq] = no_piece; for (i = no_piece; i <= king; i++) if ((s[0] == pxx[i]) || (s[0] == qxx[i])) { board[sq] = i; found=1; break; } if ((found==0)||(board[sq] == no_piece)) color[sq] = neutral; } if (MenuStripSet) { OnMenu(wG,ADVANCEDMENUNUM); OnMenu(wG,INTERMEDIATEMENUNUM); OffMenu(wG,EASYMENUNUM); OffMenu(wG,BOOKMENUNUM); } GameCnt = 0; Game50 = 1; ISZERO = 1; ZeroRPT (); Sdepth2 = Sdepth = 0; InitializeStats (); DrawAmigaBoard(); } else if (PlayMode == 2) { if (MenuStripSet) { OnMenu(wG,BOOKMENUNUM); OffMenu(wG,ADVANCEDMENUNUM); OnMenu(wG,INTERMEDIATEMENUNUM); OnMenu(wG,EASYMENUNUM); } } #ifdef KILLT ClearMem(killt,sizeof(killt)); Initialize_dist (); #endif #ifdef HISTORY #ifdef AMIGA ClearMem(history,sizeof(history)); #else memset(history,0,sizeof(history)); #endif #endif #ifdef NODITHER PCRASH = PCRASHS; PCENTER = PCENTERS; #else PCRASH = PCRASHS + (dither?(rand() % PCRASHV):0); PCENTER = PCENTERS + (dither?(rand() % PCENTERV):0); #endif MoveMem128(board,amigaboard); MoveMem128(color,amigacolor); } void InitConst (char *lang) { FILE *constfile; char s[256]; char sl[5]; int len, entry; char *p, *q; constfile = fopen (LANGFILE, "r"); if (!constfile) { /* printf ("NO LANGFILE\n");*/ exit (1); } while (fgets (s, sizeof (s), constfile)) { if (s[0] == '!') continue; len = strlen (s); for (q = &s[len]; q > &s[8]; q--) if (*q == '}') break; if (q == &s[8]) { /* printf ("{ error in cinstfile\n");*/ exit (1); } *q = '\0'; if (s[3] != ':' || s[7] != ':' || s[8] != '{') { /* printf ("Langfile format error %s\n", s);*/ exit (1); } s[3] = s[7] = '\0'; if (lang == NULL) { lang = sl; strcpy (sl, &s[4]); } if (strcmp (&s[4], lang)) continue; entry = atoi (s); if (entry < 0 || entry >= CPSIZE) { /* printf ("Langfile number error\n");*/ exit (1); } for (q = p = &s[9]; *p; p++) { if (*p != '\\') { *q++ = *p; } else if (*(p + 1) == 'n') { *q++ = '\n'; p++; } } *q = '\0'; if (entry < 0 || entry > 255) { /* printf ("Langfile error %d\n", entry);*/ exit (0); } CP[entry] = (char *) malloc ((unsigned) strlen (&s[9]) + 1); if (CP[entry] == NULL) { ShowMessage("malloc"); exit (0); } strcpy (CP[entry], &s[9]); } fclose (constfile); } #ifdef OLDTTABLE #ifndef CACHE #ifdef ttblsz void Initialize_ttable () { if (rehash < 0) rehash = MAXrehash - 1; } #endif /* ttblsz */ #else #ifdef ttblsz void Initialize_ttable () { char astr[32]; int doit = true; if (rehash < 0) rehash = MAXrehash; while(doit && ttblsize >= (1<<13)){ ttable[0] = (struct hashentry *)malloc((unsigned)(sizeof(struct hashentry))*(ttblsize+rehash)); ttable[1] = (struct hashentry *)malloc((unsigned)(sizeof(struct hashentry))*(ttblsize+rehash)); if(ttable[0] == NULL || ttable[1] == NULL){ if(ttable[0] != NULL)free(ttable[0]); ttblsize = ttblsize>>1; } else doit = false; } if(ttable[0] == NULL || ttable[1] == NULL) { ShowMessage("Critical Mem Failure"); Delay(100L); AmigaShutDown(); exit(1); } sprintf(astr,"transposition tbl is %d\n",ttblsize); ShowMessage(astr); } #endif /* ttblsz */ #endif #endif // oldttable