1*41194Sbostic /*
2*41194Sbostic C source for CHESS
3*41194Sbostic
4*41194Sbostic Revision: 4-25-88
5*41194Sbostic
6*41194Sbostic Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
7*41194Sbostic Copyright (c) 1988 John Stanback
8*41194Sbostic
9*41194Sbostic This file is part of CHESS.
10*41194Sbostic
11*41194Sbostic CHESS is distributed in the hope that it will be useful,
12*41194Sbostic but WITHOUT ANY WARRANTY. No author or distributor
13*41194Sbostic accepts responsibility to anyone for the consequences of using it
14*41194Sbostic or for whether it serves any particular purpose or works at all,
15*41194Sbostic unless he says so in writing. Refer to the CHESS General Public
16*41194Sbostic License for full details.
17*41194Sbostic
18*41194Sbostic Everyone is granted permission to copy, modify and redistribute
19*41194Sbostic CHESS, but only under the conditions described in the
20*41194Sbostic CHESS General Public License. A copy of this license is
21*41194Sbostic supposed to have been given to you along with CHESS so you
22*41194Sbostic can know your rights and responsibilities. It should be in a
23*41194Sbostic file named COPYING. Among other things, the copyright notice
24*41194Sbostic and this notice must be preserved on all copies.
25*41194Sbostic */
26*41194Sbostic
27*41194Sbostic
28*41194Sbostic #include <stdio.h>
29*41194Sbostic #include <ctype.h>
30*41194Sbostic
31*41194Sbostic #ifdef MSDOS
32*41194Sbostic #include <stdlib.h>
33*41194Sbostic #include <time.h>
34*41194Sbostic #include <alloc.h>
35*41194Sbostic #define ttblsz 4096
36*41194Sbostic #else
37*41194Sbostic #include <sys/param.h>
38*41194Sbostic #include <sys/times.h>
39*41194Sbostic #define ttblsz 16384
40*41194Sbostic #define huge
41*41194Sbostic #endif MSDOS
42*41194Sbostic
43*41194Sbostic #include "move.h"
44*41194Sbostic
45*41194Sbostic #define neutral 2
46*41194Sbostic #define white 0
47*41194Sbostic #define black 1
48*41194Sbostic #define no_piece 0
49*41194Sbostic #define pawn 1
50*41194Sbostic #define knight 2
51*41194Sbostic #define bishop 3
52*41194Sbostic #define rook 4
53*41194Sbostic #define queen 5
54*41194Sbostic #define king 6
55*41194Sbostic #define valueP 100
56*41194Sbostic #define valueN 350
57*41194Sbostic #define valueB 355
58*41194Sbostic #define valueR 550
59*41194Sbostic #define valueQ 1100
60*41194Sbostic #define valueK 1200
61*41194Sbostic #define ctlP 0x4000
62*41194Sbostic #define ctlN 0x2800
63*41194Sbostic #define ctlB 0x1800
64*41194Sbostic #define ctlR 0x0400
65*41194Sbostic #define ctlQ 0x0200
66*41194Sbostic #define ctlK 0x0100
67*41194Sbostic #define ctlBQ 0x1200
68*41194Sbostic #define ctlRQ 0x0600
69*41194Sbostic #define ctlNN 0x2000
70*41194Sbostic #define pxx " PNBRQK"
71*41194Sbostic #define qxx " pnbrqk"
72*41194Sbostic #define rxx "12345678"
73*41194Sbostic #define cxx "abcdefgh"
74*41194Sbostic #define check 0x0001
75*41194Sbostic #define capture 0x0002
76*41194Sbostic #define draw 0x0004
77*41194Sbostic #define promote 0x0008
78*41194Sbostic #define cstlmask 0x0010
79*41194Sbostic #define epmask 0x0020
80*41194Sbostic #define exact 0x0040
81*41194Sbostic #define pwnthrt 0x0080
82*41194Sbostic #define truescore 0x0001
83*41194Sbostic #define lowerbound 0x0002
84*41194Sbostic #define upperbound 0x0004
85*41194Sbostic #define maxdepth 30
86*41194Sbostic #define true 1
87*41194Sbostic #define false 0
88*41194Sbostic #define absv(x) ((x) < 0 ? -(x) : (x))
89*41194Sbostic #if (NEWMOVE < 1)
90*41194Sbostic #define taxicab(a,b) (abs(column[a]-column[b]) + abs(row[a]-row[b]))
91*41194Sbostic #endif
92*41194Sbostic struct leaf
93*41194Sbostic {
94*41194Sbostic short f,t,score,reply;
95*41194Sbostic unsigned short flags;
96*41194Sbostic };
97*41194Sbostic struct GameRec
98*41194Sbostic {
99*41194Sbostic unsigned short gmove;
100*41194Sbostic short score,depth,time,piece,color;
101*41194Sbostic long nodes;
102*41194Sbostic };
103*41194Sbostic struct TimeControlRec
104*41194Sbostic {
105*41194Sbostic short moves[2];
106*41194Sbostic long clock[2];
107*41194Sbostic };
108*41194Sbostic struct BookEntry
109*41194Sbostic {
110*41194Sbostic struct BookEntry *next;
111*41194Sbostic unsigned short *mv;
112*41194Sbostic };
113*41194Sbostic struct hashval
114*41194Sbostic {
115*41194Sbostic unsigned long bd;
116*41194Sbostic unsigned short key;
117*41194Sbostic };
118*41194Sbostic struct hashentry
119*41194Sbostic {
120*41194Sbostic unsigned long hashbd;
121*41194Sbostic unsigned short mv,flags;
122*41194Sbostic short score,depth;
123*41194Sbostic };
124*41194Sbostic
125*41194Sbostic char mvstr1[5],mvstr2[5];
126*41194Sbostic struct leaf Tree[2000],*root;
127*41194Sbostic short TrPnt[maxdepth],board[64],color[64];
128*41194Sbostic short row[64],column[64],locn[8][8],Pindex[64],svalue[64];
129*41194Sbostic short PieceList[2][16],PieceCnt[2],atak[2][64],PawnCnt[2][8];
130*41194Sbostic short castld[2],kingmoved[2],mtl[2],pmtl[2],emtl[2],hung[2];
131*41194Sbostic short c1,c2,*atk1,*atk2,*PC1,*PC2,EnemyKing;
132*41194Sbostic short mate,post,opponent,computer,Sdepth,Awindow,Bwindow,dither;
133*41194Sbostic long ResponseTime,ExtraTime,Level,et,et0,time0,cputimer,ft;
134*41194Sbostic long NodeCnt,evrate,ETnodes,EvalNodes,HashCnt;
135*41194Sbostic short quit,reverse,bothsides,hashflag,InChk,player,force,easy,beep;
136*41194Sbostic short wking,bking,FROMsquare,TOsquare,timeout,Zscore,zwndw,xwndw,slk;
137*41194Sbostic short INCscore;
138*41194Sbostic short HasPawn[2],HasKnight[2],HasBishop[2],HasRook[2],HasQueen[2];
139*41194Sbostic short ChkFlag[maxdepth],CptrFlag[maxdepth],PawnThreat[maxdepth];
140*41194Sbostic short Pscore[maxdepth],Tscore[maxdepth],Threat[maxdepth];
141*41194Sbostic struct GameRec GameList[240];
142*41194Sbostic short GameCnt,Game50,epsquare,lpost,rcptr,contempt;
143*41194Sbostic short MaxSearchDepth;
144*41194Sbostic struct BookEntry *Book;
145*41194Sbostic struct TimeControlRec TimeControl;
146*41194Sbostic short TCflag,TCmoves,TCminutes,OperatorTime;
147*41194Sbostic short otherside[3]={1,0,2};
148*41194Sbostic short rank7[3]={6,1,0};
149*41194Sbostic short map[64]=
150*41194Sbostic {0,1,2,3,4,5,6,7,
151*41194Sbostic 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
152*41194Sbostic 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,
153*41194Sbostic 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,
154*41194Sbostic 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,
155*41194Sbostic 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,
156*41194Sbostic 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,
157*41194Sbostic 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77};
158*41194Sbostic short unmap[120]=
159*41194Sbostic {0,1,2,3,4,5,6,7,-1,-1,-1,-1,-1,-1,-1,-1,
160*41194Sbostic 8,9,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,
161*41194Sbostic 16,17,18,19,20,21,22,23,-1,-1,-1,-1,-1,-1,-1,-1,
162*41194Sbostic 24,25,26,27,28,29,30,31,-1,-1,-1,-1,-1,-1,-1,-1,
163*41194Sbostic 32,33,34,35,36,37,38,39,-1,-1,-1,-1,-1,-1,-1,-1,
164*41194Sbostic 40,41,42,43,44,45,46,47,-1,-1,-1,-1,-1,-1,-1,-1,
165*41194Sbostic 48,49,50,51,52,53,54,55,-1,-1,-1,-1,-1,-1,-1,-1,
166*41194Sbostic 56,57,58,59,60,61,62,63};
167*41194Sbostic short Dcode[120]=
168*41194Sbostic {0,1,1,1,1,1,1,1,0,0,0,0,0,0,0x0E,0x0F,
169*41194Sbostic 0x10,0x11,0x12,0,0,0,0,0,0,0,0,0,0,0,0x0F,0x1F,
170*41194Sbostic 0x10,0x21,0x11,0,0,0,0,0,0,0,0,0,0,0x0F,0,0,
171*41194Sbostic 0x10,0,0,0x11,0,0,0,0,0,0,0,0,0x0F,0,0,0,
172*41194Sbostic 0x10,0,0,0,0x11,0,0,0,0,0,0,0x0F,0,0,0,0,
173*41194Sbostic 0x10,0,0,0,0,0x11,0,0,0,0,0x0F,0,0,0,0,0,
174*41194Sbostic 0x10,0,0,0,0,0,0x11,0,0,0x0F,0,0,0,0,0,0,
175*41194Sbostic 0x10,0,0,0,0,0,0,0x11};
176*41194Sbostic short Stboard[64]=
177*41194Sbostic {rook,knight,bishop,queen,king,bishop,knight,rook,
178*41194Sbostic pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
179*41194Sbostic 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,
180*41194Sbostic pawn,pawn,pawn,pawn,pawn,pawn,pawn,pawn,
181*41194Sbostic rook,knight,bishop,queen,king,bishop,knight,rook};
182*41194Sbostic short Stcolor[64]=
183*41194Sbostic {white,white,white,white,white,white,white,white,
184*41194Sbostic white,white,white,white,white,white,white,white,
185*41194Sbostic 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
186*41194Sbostic black,black,black,black,black,black,black,black,
187*41194Sbostic black,black,black,black,black,black,black,black};
188*41194Sbostic short sweep[7]= {false,false,false,true,true,true,false};
189*41194Sbostic short Dpwn[3]={4,6,0};
190*41194Sbostic short Dstart[7]={6,4,8,4,0,0,0};
191*41194Sbostic short Dstop[7]={7,5,15,7,3,7,7};
192*41194Sbostic short Dir[16]={1,0x10,-1,-0x10,0x0F,0x11,-0x0F,-0x11,
193*41194Sbostic 0x0E,-0x0E,0x12,-0x12,0x1F,-0x1F,0x21,-0x21};
194*41194Sbostic short Pdir[34]={0,0x38,0,0,0,0,0,0,0,0,0,0,0,0,0x02,0x35,
195*41194Sbostic 0x38,0x35,0x02,0,0,0,0,0,0,0,0,0,0,0,0,0x02,
196*41194Sbostic 0,0x02};
197*41194Sbostic short pbit[7]={0,0x01,0x02,0x04,0x08,0x10,0x20};
198*41194Sbostic unsigned short killr0[maxdepth],killr1[maxdepth],killr2[maxdepth];
199*41194Sbostic unsigned short killr3[maxdepth],PrVar[maxdepth];
200*41194Sbostic unsigned short PV,hint,Swag0,Swag1,Swag2,Swag3,Swag4;
201*41194Sbostic unsigned short hashkey;
202*41194Sbostic unsigned long hashbd;
203*41194Sbostic struct hashval hashcode[2][7][64];
204*41194Sbostic struct hashentry huge *ttable,*ptbl;
205*41194Sbostic unsigned char history[8192];
206*41194Sbostic
207*41194Sbostic short Mwpawn[64],Mbpawn[64],Mknight[2][64],Mbishop[2][64];
208*41194Sbostic short Mking[2][64],Kfield[2][64];
209*41194Sbostic short value[7]={0,valueP,valueN,valueB,valueR,valueQ,valueK};
210*41194Sbostic short control[7]={0,ctlP,ctlN,ctlB,ctlR,ctlQ,ctlK};
211*41194Sbostic short PassedPawn0[8]={0,60,80,120,200,360,600,800};
212*41194Sbostic short PassedPawn1[8]={0,30,40,60,100,180,300,800};
213*41194Sbostic short PassedPawn2[8]={0,15,25,35,50,90,140,800};
214*41194Sbostic short PassedPawn3[8]={0,5,10,15,20,30,140,800};
215*41194Sbostic short ISOLANI[8] = {-12,-16,-20,-24,-24,-20,-16,-12};
216*41194Sbostic short BACKWARD[8] = {-6,-10,-15,-21,-28,-28,-28,-28};
217*41194Sbostic short BMBLTY[14] = {-2,0,2,4,6,8,10,12,13,14,15,16,16,16};
218*41194Sbostic short RMBLTY[14] = {0,2,4,6,8,10,11,12,13,14,14,14,14,14};
219*41194Sbostic short Kthreat[16] = {0,-8,-20,-36,-52,-68,-80,-80,-80,-80,-80,-80,
220*41194Sbostic -80,-80,-80,-80};
221*41194Sbostic short KNIGHTPOST,KNIGHTSTRONG,BISHOPSTRONG,KATAK,KBNKsq;
222*41194Sbostic short PEDRNK2B,PWEAKH,PADVNCM,PADVNCI,PAWNSHIELD,PDOUBLED,PBLOK;
223*41194Sbostic short RHOPN,RHOPNX,KHOPN,KHOPNX,KSFTY;
224*41194Sbostic short ATAKD,HUNGP,HUNGX,KCASTLD,KMOVD,XRAY,PINVAL;
225*41194Sbostic short stage,stage2,Zwmtl,Zbmtl,Developed[2],PawnStorm;
226*41194Sbostic short PawnBonus,BishopBonus,RookBonus;
227*41194Sbostic short KingOpening[64]=
228*41194Sbostic { 0, 0, -4,-10,-10, -4, 0, 0,
229*41194Sbostic -4, -4, -8,-12,-12, -8, -4, -4,
230*41194Sbostic -12,-16,-20,-20,-20,-20,-16,-12,
231*41194Sbostic -16,-20,-24,-24,-24,-24,-20,-16,
232*41194Sbostic -16,-20,-24,-24,-24,-24,-20,-16,
233*41194Sbostic -12,-16,-20,-20,-20,-20,-16,-12,
234*41194Sbostic -4, -4, -8,-12,-12, -8, -4, -4,
235*41194Sbostic 0, 0, -4,-10,-10, -4, 0, 0};
236*41194Sbostic short KingEnding[64]=
237*41194Sbostic { 0, 6,12,18,18,12, 6, 0,
238*41194Sbostic 6,12,18,24,24,18,12, 6,
239*41194Sbostic 12,18,24,30,30,24,18,12,
240*41194Sbostic 18,24,30,36,36,30,24,18,
241*41194Sbostic 18,24,30,36,36,30,24,18,
242*41194Sbostic 12,18,24,30,30,24,18,12,
243*41194Sbostic 6,12,18,24,24,18,12, 6,
244*41194Sbostic 0, 6,12,18,18,12, 6, 0};
245*41194Sbostic short DyingKing[64]=
246*41194Sbostic { 0, 8,16,24,24,16, 8, 0,
247*41194Sbostic 8,32,40,48,48,40,32, 8,
248*41194Sbostic 16,40,56,64,64,56,40,16,
249*41194Sbostic 24,48,64,72,72,64,48,24,
250*41194Sbostic 24,48,64,72,72,64,48,24,
251*41194Sbostic 16,40,56,64,64,56,40,16,
252*41194Sbostic 8,32,40,48,48,40,32, 8,
253*41194Sbostic 0, 8,16,24,24,16, 8, 0};
254*41194Sbostic short KBNK[64]=
255*41194Sbostic {99,90,80,70,60,50,40,40,
256*41194Sbostic 90,80,60,50,40,30,20,40,
257*41194Sbostic 80,60,40,30,20,10,30,50,
258*41194Sbostic 70,50,30,10, 0,20,40,60,
259*41194Sbostic 60,40,20, 0,10,30,50,70,
260*41194Sbostic 50,30,10,20,30,40,60,80,
261*41194Sbostic 40,20,30,40,50,60,80,90,
262*41194Sbostic 40,40,50,60,70,80,90,99};
263*41194Sbostic short pknight[64]=
264*41194Sbostic { 0, 4, 8,10,10, 8, 4, 0,
265*41194Sbostic 4, 8,16,20,20,16, 8, 4,
266*41194Sbostic 8,16,24,28,28,24,16, 8,
267*41194Sbostic 10,20,28,32,32,28,20,10,
268*41194Sbostic 10,20,28,32,32,28,20,10,
269*41194Sbostic 8,16,24,28,28,24,16, 8,
270*41194Sbostic 4, 8,16,20,20,16, 8, 4,
271*41194Sbostic 0, 4, 8,10,10, 8, 4, 0};
272*41194Sbostic short pbishop[64]=
273*41194Sbostic {14,14,14,14,14,14,14,14,
274*41194Sbostic 14,22,18,18,18,18,22,14,
275*41194Sbostic 14,18,22,22,22,22,18,14,
276*41194Sbostic 14,18,22,22,22,22,18,14,
277*41194Sbostic 14,18,22,22,22,22,18,14,
278*41194Sbostic 14,18,22,22,22,22,18,14,
279*41194Sbostic 14,22,18,18,18,18,22,14,
280*41194Sbostic 14,14,14,14,14,14,14,14};
281*41194Sbostic short PawnAdvance[64]=
282*41194Sbostic { 0, 0, 0, 0, 0, 0, 0, 0,
283*41194Sbostic 4, 4, 4, 0, 0, 4, 4, 4,
284*41194Sbostic 6, 8, 2,10,10, 2, 8, 6,
285*41194Sbostic 6, 8,12,16,16,12, 8, 6,
286*41194Sbostic 8,12,16,24,24,16,12, 8,
287*41194Sbostic 12,16,24,32,32,24,16,12,
288*41194Sbostic 12,16,24,32,32,24,16,12,
289*41194Sbostic 0, 0, 0, 0, 0, 0, 0, 0};
290*41194Sbostic
291*41194Sbostic
main(argc,argv)292*41194Sbostic main(argc,argv)
293*41194Sbostic int argc; char *argv[];
294*41194Sbostic {
295*41194Sbostic #ifdef MSDOS
296*41194Sbostic ttable = (struct hashentry huge *)farmalloc(ttblsz *
297*41194Sbostic (unsigned long)sizeof(struct hashentry));
298*41194Sbostic #else
299*41194Sbostic ttable = (struct hashentry *)malloc(ttblsz *
300*41194Sbostic (unsigned long)sizeof(struct hashentry));
301*41194Sbostic #endif
302*41194Sbostic Level = 0; TCflag = false; OperatorTime = 0;
303*41194Sbostic if (argc == 2) Level = atoi(argv[1]);
304*41194Sbostic if (argc == 3)
305*41194Sbostic {
306*41194Sbostic TCmoves = atoi(argv[1]); TCminutes = atoi(argv[2]); TCflag = true;
307*41194Sbostic }
308*41194Sbostic Initialize();
309*41194Sbostic NewGame();
310*41194Sbostic #if (NEWMOVE > 0)
311*41194Sbostic Initialize_dist();
312*41194Sbostic #if (NEWMOVE > 1)
313*41194Sbostic Initialize_moves();
314*41194Sbostic #endif
315*41194Sbostic #endif
316*41194Sbostic while (!(quit))
317*41194Sbostic {
318*41194Sbostic if (bothsides && !mate) SelectMove(opponent,1); else InputCommand();
319*41194Sbostic if (!(quit || mate || force)) SelectMove(computer,1);
320*41194Sbostic }
321*41194Sbostic ExitChess();
322*41194Sbostic }
323*41194Sbostic
324*41194Sbostic
325*41194Sbostic
326*41194Sbostic /* ............ INTERFACE ROUTINES ........................... */
327*41194Sbostic
VerifyMove(s,iop,mv)328*41194Sbostic int VerifyMove(s,iop,mv)
329*41194Sbostic char s[];
330*41194Sbostic short iop;
331*41194Sbostic unsigned short *mv;
332*41194Sbostic
333*41194Sbostic /*
334*41194Sbostic Compare the string 's' to the list of legal moves available for the
335*41194Sbostic opponent. If a match is found, make the move on the board.
336*41194Sbostic */
337*41194Sbostic
338*41194Sbostic {
339*41194Sbostic static short pnt,tempb,tempc,tempsf,tempst,cnt;
340*41194Sbostic static struct leaf xnode;
341*41194Sbostic struct leaf *node;
342*41194Sbostic
343*41194Sbostic *mv = 0;
344*41194Sbostic if (iop == 2)
345*41194Sbostic {
346*41194Sbostic UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst);
347*41194Sbostic return(false);
348*41194Sbostic }
349*41194Sbostic cnt = 0;
350*41194Sbostic MoveList(opponent,2);
351*41194Sbostic pnt = TrPnt[2];
352*41194Sbostic while (pnt < TrPnt[3])
353*41194Sbostic {
354*41194Sbostic node = &Tree[pnt++];
355*41194Sbostic algbr(node->f,node->t,(short) node->flags & cstlmask);
356*41194Sbostic if (strcmp(s,mvstr1) == 0 || strcmp(s,mvstr2) == 0)
357*41194Sbostic {
358*41194Sbostic cnt++; xnode = *node;
359*41194Sbostic }
360*41194Sbostic }
361*41194Sbostic if (cnt == 1)
362*41194Sbostic {
363*41194Sbostic MakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst);
364*41194Sbostic if (SqAtakd(PieceList[opponent][0],computer))
365*41194Sbostic {
366*41194Sbostic UnmakeMove(opponent,&xnode,&tempb,&tempc,&tempsf,&tempst);
367*41194Sbostic ShowMessage("Illegal Move!!");
368*41194Sbostic return(false);
369*41194Sbostic }
370*41194Sbostic else
371*41194Sbostic {
372*41194Sbostic if (iop == 1) return(true);
373*41194Sbostic if (xnode.flags & epmask) UpdateDisplay(0,0,1,0);
374*41194Sbostic else UpdateDisplay(xnode.f,xnode.t,0,xnode.flags & cstlmask);
375*41194Sbostic if (xnode.flags & cstlmask) Game50 = GameCnt;
376*41194Sbostic else if (board[xnode.t] == pawn || (xnode.flags & capture))
377*41194Sbostic Game50 = GameCnt;
378*41194Sbostic GameList[GameCnt].depth = GameList[GameCnt].score = 0;
379*41194Sbostic GameList[GameCnt].nodes = 0;
380*41194Sbostic ElapsedTime(1);
381*41194Sbostic GameList[GameCnt].time = (short)et;
382*41194Sbostic TimeControl.clock[opponent] -= et;
383*41194Sbostic --TimeControl.moves[opponent];
384*41194Sbostic *mv = (xnode.f << 8) + xnode.t;
385*41194Sbostic algbr(xnode.f,xnode.t,false);
386*41194Sbostic return(true);
387*41194Sbostic }
388*41194Sbostic }
389*41194Sbostic if (cnt > 1) ShowMessage("Ambiguous Move!");
390*41194Sbostic return(false);
391*41194Sbostic }
392*41194Sbostic
393*41194Sbostic
NewGame()394*41194Sbostic NewGame()
395*41194Sbostic
396*41194Sbostic /*
397*41194Sbostic Reset the board and other variables to start a new game.
398*41194Sbostic */
399*41194Sbostic
400*41194Sbostic {
401*41194Sbostic short l,r,c,p;
402*41194Sbostic
403*41194Sbostic mate = quit = reverse = bothsides = post = false;
404*41194Sbostic hashflag = force = PawnStorm = false;
405*41194Sbostic beep = rcptr = easy = true;
406*41194Sbostic lpost = NodeCnt = epsquare = et0 = 0;
407*41194Sbostic dither = 0;
408*41194Sbostic Awindow = 90;
409*41194Sbostic Bwindow = 90;
410*41194Sbostic xwndw = 90;
411*41194Sbostic MaxSearchDepth = 29;
412*41194Sbostic contempt = 0;
413*41194Sbostic GameCnt = -1; Game50 = 0;
414*41194Sbostic Zwmtl = Zbmtl = 0;
415*41194Sbostic Developed[white] = Developed[black] = false;
416*41194Sbostic castld[white] = castld[black] = false;
417*41194Sbostic kingmoved[white] = kingmoved[black] = 0;
418*41194Sbostic PawnThreat[0] = CptrFlag[0] = Threat[0] = false;
419*41194Sbostic Pscore[0] = 12000; Tscore[0] = 12000;
420*41194Sbostic opponent = white; computer = black;
421*41194Sbostic for (r = 0; r < 8; r++)
422*41194Sbostic for (c = 0; c < 8; c++)
423*41194Sbostic {
424*41194Sbostic l = 8*r+c; locn[r][c] = l;
425*41194Sbostic row[l] = r; column[l] = c;
426*41194Sbostic board[l] = Stboard[l]; color[l] = Stcolor[l];
427*41194Sbostic }
428*41194Sbostic for (c = white; c <= black; c++)
429*41194Sbostic for (p = pawn; p <= king; p++)
430*41194Sbostic for (l = 0; l < 64; l++)
431*41194Sbostic {
432*41194Sbostic hashcode[c][p][l].key = (unsigned short)rand();
433*41194Sbostic hashcode[c][p][l].bd = ((unsigned long)rand() << 16) +
434*41194Sbostic (unsigned long)rand();
435*41194Sbostic }
436*41194Sbostic ClrScreen();
437*41194Sbostic if (TCflag) SetTimeControl();
438*41194Sbostic else if (Level == 0) SelectLevel();
439*41194Sbostic UpdateDisplay(0,0,1,0);
440*41194Sbostic InitializeStats();
441*41194Sbostic time0 = time((long *)0);
442*41194Sbostic ElapsedTime(1);
443*41194Sbostic GetOpenings();
444*41194Sbostic }
445*41194Sbostic
446*41194Sbostic
algbr(f,t,iscastle)447*41194Sbostic algbr(f,t,iscastle)
448*41194Sbostic short f,t,iscastle;
449*41194Sbostic {
450*41194Sbostic mvstr1[0] = cxx[column[f]]; mvstr1[1] = rxx[row[f]];
451*41194Sbostic mvstr1[2] = cxx[column[t]]; mvstr1[3] = rxx[row[t]];
452*41194Sbostic mvstr2[0] = qxx[board[f]];
453*41194Sbostic mvstr2[1] = mvstr1[2]; mvstr2[2] = mvstr1[3];
454*41194Sbostic mvstr1[4] = '\0'; mvstr2[3] = '\0';
455*41194Sbostic if (iscastle)
456*41194Sbostic if (t > f) strcpy(mvstr2,"o-o");
457*41194Sbostic else strcpy(mvstr2,"o-o-o");
458*41194Sbostic }
459*41194Sbostic
460*41194Sbostic
461*41194Sbostic /* ............ MOVE GENERATION & SEARCH ROUTINES .............. */
462*41194Sbostic
SelectMove(side,iop)463*41194Sbostic SelectMove(side,iop)
464*41194Sbostic short side,iop;
465*41194Sbostic
466*41194Sbostic /*
467*41194Sbostic Select a move by calling function search() at progressively deeper
468*41194Sbostic ply until time is up or a mate or draw is reached. An alpha-beta
469*41194Sbostic window of -90 to +90 points is set around the score returned from the
470*41194Sbostic previous iteration. If Sdepth != 0 then the program has correctly
471*41194Sbostic predicted the opponents move and the search will start at a depth of
472*41194Sbostic Sdepth+1 rather than a depth of 1.
473*41194Sbostic */
474*41194Sbostic
475*41194Sbostic {
476*41194Sbostic static short i,alpha,beta,score,tempb,tempc,tempsf,tempst,xside,rpt;
477*41194Sbostic
478*41194Sbostic timeout = false;
479*41194Sbostic xside = otherside[side];
480*41194Sbostic if (iop != 2) player = side;
481*41194Sbostic if (TCflag)
482*41194Sbostic {
483*41194Sbostic if (((TimeControl.moves[side] + 3) - OperatorTime) != 0)
484*41194Sbostic ResponseTime = (TimeControl.clock[side]) /
485*41194Sbostic (TimeControl.moves[side] + 3) -
486*41194Sbostic OperatorTime;
487*41194Sbostic else ResponseTime = 0;
488*41194Sbostic ResponseTime += (ResponseTime*TimeControl.moves[side])/(2*TCmoves+1);
489*41194Sbostic }
490*41194Sbostic else ResponseTime = Level;
491*41194Sbostic if (iop == 2) ResponseTime = 999;
492*41194Sbostic if (Sdepth > 0 && root->score > Zscore-zwndw) ResponseTime -= ft;
493*41194Sbostic else if (ResponseTime < 1) ResponseTime = 1;
494*41194Sbostic ExtraTime = 0;
495*41194Sbostic ExaminePosition();
496*41194Sbostic ScorePosition(side,&score);
497*41194Sbostic ShowSidetomove();
498*41194Sbostic
499*41194Sbostic if (Sdepth == 0)
500*41194Sbostic {
501*41194Sbostic ZeroTTable();
502*41194Sbostic SearchStartStuff(side);
503*41194Sbostic for (i = 0; i < 8192; i++) history[i] = 0;
504*41194Sbostic FROMsquare = TOsquare = -1;
505*41194Sbostic PV = 0;
506*41194Sbostic if (iop != 2) hint = 0;
507*41194Sbostic for (i = 0; i < maxdepth; i++)
508*41194Sbostic PrVar[i] = killr0[i] = killr1[i] = killr2[i] = killr3[i] = 0;
509*41194Sbostic alpha = score-90; beta = score+90;
510*41194Sbostic rpt = 0;
511*41194Sbostic TrPnt[1] = 0; root = &Tree[0];
512*41194Sbostic MoveList(side,1);
513*41194Sbostic for (i = TrPnt[1]; i < TrPnt[2]; i++) pick(i,TrPnt[2]-1);
514*41194Sbostic if (Book != NULL) OpeningBook();
515*41194Sbostic if (Book != NULL) timeout = true;
516*41194Sbostic NodeCnt = ETnodes = EvalNodes = HashCnt = 0;
517*41194Sbostic Zscore = 0; zwndw = 20;
518*41194Sbostic }
519*41194Sbostic
520*41194Sbostic while (!timeout && Sdepth < MaxSearchDepth)
521*41194Sbostic {
522*41194Sbostic Sdepth++;
523*41194Sbostic ShowDepth(' ');
524*41194Sbostic score = search(side,1,Sdepth,alpha,beta,PrVar,&rpt);
525*41194Sbostic for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
526*41194Sbostic if (score < alpha)
527*41194Sbostic {
528*41194Sbostic ShowDepth('-');
529*41194Sbostic ExtraTime = 10*ResponseTime;
530*41194Sbostic ZeroTTable();
531*41194Sbostic score = search(side,1,Sdepth,-9000,beta,PrVar,&rpt);
532*41194Sbostic }
533*41194Sbostic if (score > beta && !(root->flags & exact))
534*41194Sbostic {
535*41194Sbostic ShowDepth('+');
536*41194Sbostic ExtraTime = 0;
537*41194Sbostic ZeroTTable();
538*41194Sbostic score = search(side,1,Sdepth,alpha,9000,PrVar,&rpt);
539*41194Sbostic }
540*41194Sbostic score = root->score;
541*41194Sbostic if (!timeout)
542*41194Sbostic for (i = TrPnt[1]+1; i < TrPnt[2]; i++) pick(i,TrPnt[2]-1);
543*41194Sbostic ShowResults(score,PrVar,'.');
544*41194Sbostic for (i = 1; i <= Sdepth; i++) killr0[i] = PrVar[i];
545*41194Sbostic if (score > Zscore-zwndw && score > Tree[1].score+250) ExtraTime = 0;
546*41194Sbostic else if (score > Zscore-3*zwndw) ExtraTime = ResponseTime;
547*41194Sbostic else ExtraTime = 3*ResponseTime;
548*41194Sbostic if (root->flags & exact) timeout = true;
549*41194Sbostic if (Tree[1].score < -9000) timeout = true;
550*41194Sbostic if (4*et > 2*ResponseTime + ExtraTime) timeout = true;
551*41194Sbostic if (!timeout)
552*41194Sbostic {
553*41194Sbostic Tscore[0] = score;
554*41194Sbostic if (Zscore == 0) Zscore = score;
555*41194Sbostic else Zscore = (Zscore+score)/2;
556*41194Sbostic }
557*41194Sbostic zwndw = 20+abs(Zscore/12);
558*41194Sbostic beta = score + Bwindow;
559*41194Sbostic if (Zscore < score) alpha = Zscore - Awindow - zwndw;
560*41194Sbostic else alpha = score - Awindow - zwndw;
561*41194Sbostic }
562*41194Sbostic
563*41194Sbostic score = root->score;
564*41194Sbostic if (rpt >= 2 || score < -12000) root->flags |= draw;
565*41194Sbostic if (iop == 2) return(0);
566*41194Sbostic if (Book == NULL) hint = PrVar[2];
567*41194Sbostic ElapsedTime(1);
568*41194Sbostic
569*41194Sbostic if (score > -9999 && rpt <= 2)
570*41194Sbostic {
571*41194Sbostic MakeMove(side,root,&tempb,&tempc,&tempsf,&tempst);
572*41194Sbostic algbr(root->f,root->t,(short) root->flags & cstlmask);
573*41194Sbostic }
574*41194Sbostic else mvstr1[0] = '\0';
575*41194Sbostic OutputMove();
576*41194Sbostic if (score == -9999 || score == 9998) mate = true;
577*41194Sbostic if (mate) hint = 0;
578*41194Sbostic if (root->flags & cstlmask) Game50 = GameCnt;
579*41194Sbostic else if (board[root->t] == pawn || (root->flags & capture))
580*41194Sbostic Game50 = GameCnt;
581*41194Sbostic GameList[GameCnt].score = score;
582*41194Sbostic GameList[GameCnt].nodes = NodeCnt;
583*41194Sbostic GameList[GameCnt].time = (short)et;
584*41194Sbostic GameList[GameCnt].depth = Sdepth;
585*41194Sbostic if (TCflag)
586*41194Sbostic {
587*41194Sbostic TimeControl.clock[side] -= (et + OperatorTime);
588*41194Sbostic if (--TimeControl.moves[side] == 0) SetTimeControl();
589*41194Sbostic }
590*41194Sbostic if ((root->flags & draw) && bothsides) quit = true;
591*41194Sbostic if (GameCnt > 238) quit = true;
592*41194Sbostic player = xside;
593*41194Sbostic Sdepth = 0;
594*41194Sbostic fflush(stdin);
595*41194Sbostic return(0);
596*41194Sbostic }
597*41194Sbostic
598*41194Sbostic
OpeningBook()599*41194Sbostic OpeningBook()
600*41194Sbostic
601*41194Sbostic /*
602*41194Sbostic Go thru each of the opening lines of play and check for a match with
603*41194Sbostic the current game listing. If a match occurs, generate a random number.
604*41194Sbostic If this number is the largest generated so far then the next move in
605*41194Sbostic this line becomes the current "candidate". After all lines are
606*41194Sbostic checked, the candidate move is put at the top of the Tree[] array and
607*41194Sbostic will be played by the program. Note that the program does not handle
608*41194Sbostic book transpositions.
609*41194Sbostic */
610*41194Sbostic
611*41194Sbostic {
612*41194Sbostic short j,pnt;
613*41194Sbostic unsigned short m,*mp;
614*41194Sbostic unsigned r,r0;
615*41194Sbostic struct BookEntry *p;
616*41194Sbostic
617*41194Sbostic srand((unsigned)time0);
618*41194Sbostic r0 = m = 0;
619*41194Sbostic p = Book;
620*41194Sbostic while (p != NULL)
621*41194Sbostic {
622*41194Sbostic mp = p->mv;
623*41194Sbostic for (j = 0; j <= GameCnt; j++)
624*41194Sbostic if (GameList[j].gmove != *(mp++)) break;
625*41194Sbostic if (j > GameCnt)
626*41194Sbostic if ((r=rand()) > r0)
627*41194Sbostic {
628*41194Sbostic r0 = r; m = *mp;
629*41194Sbostic hint = *(++mp);
630*41194Sbostic }
631*41194Sbostic p = p->next;
632*41194Sbostic }
633*41194Sbostic
634*41194Sbostic for (pnt = TrPnt[1]; pnt < TrPnt[2]; pnt++)
635*41194Sbostic if ((Tree[pnt].f<<8) + Tree[pnt].t == m) Tree[pnt].score = 0;
636*41194Sbostic pick(TrPnt[1],TrPnt[2]-1);
637*41194Sbostic if (Tree[TrPnt[1]].score < 0) Book = NULL;
638*41194Sbostic }
639*41194Sbostic
640*41194Sbostic
641*41194Sbostic #define UpdateSearchStatus\
642*41194Sbostic {\
643*41194Sbostic if (post) ShowCurrentMove(pnt,node->f,node->t);\
644*41194Sbostic if (pnt > TrPnt[1])\
645*41194Sbostic {\
646*41194Sbostic d = best-Zscore; e = best-node->score;\
647*41194Sbostic if (best < alpha) ExtraTime = 10*ResponseTime;\
648*41194Sbostic else if (d > -zwndw && e > 4*zwndw) ExtraTime = -ResponseTime/3;\
649*41194Sbostic else if (d > -zwndw) ExtraTime = 0;\
650*41194Sbostic else if (d > -3*zwndw) ExtraTime = ResponseTime;\
651*41194Sbostic else if (d > -9*zwndw) ExtraTime = 3*ResponseTime;\
652*41194Sbostic else ExtraTime = 5*ResponseTime;\
653*41194Sbostic }\
654*41194Sbostic }
655*41194Sbostic
search(side,ply,depth,alpha,beta,bstline,rpt)656*41194Sbostic int search(side,ply,depth,alpha,beta,bstline,rpt)
657*41194Sbostic short side,ply,depth,alpha,beta,*rpt;
658*41194Sbostic unsigned short bstline[];
659*41194Sbostic
660*41194Sbostic /*
661*41194Sbostic Perform an alpha-beta search to determine the score for the current
662*41194Sbostic board position. If depth <= 0 only capturing moves, pawn promotions
663*41194Sbostic and responses to check are generated and searched, otherwise all
664*41194Sbostic moves are processed. The search depth is modified for check evasions,
665*41194Sbostic certain re-captures and threats. Extensions may continue for up to 11
666*41194Sbostic ply beyond the nominal search depth.
667*41194Sbostic */
668*41194Sbostic
669*41194Sbostic #define prune (cf && score+node->score < alpha)
670*41194Sbostic #define ReCapture (rcptr && score > alpha && score < beta &&\
671*41194Sbostic ply > 2 && CptrFlag[ply-1] && CptrFlag[ply-2])
672*41194Sbostic #define MateThreat (ply < Sdepth+4 && ply > 4 &&\
673*41194Sbostic ChkFlag[ply-2] && ChkFlag[ply-4] &&\
674*41194Sbostic ChkFlag[ply-2] != ChkFlag[ply-4])
675*41194Sbostic
676*41194Sbostic {
677*41194Sbostic register short j,pnt;
678*41194Sbostic short best,tempb,tempc,tempsf,tempst;
679*41194Sbostic short xside,pbst,d,e,cf,score,rcnt;
680*41194Sbostic unsigned short mv,nxtline[maxdepth];
681*41194Sbostic struct leaf *node,tmp;
682*41194Sbostic
683*41194Sbostic NodeCnt++;
684*41194Sbostic xside = otherside[side];
685*41194Sbostic if (depth < 0) depth = 0;
686*41194Sbostic
687*41194Sbostic if (ply <= Sdepth+3) repetition(rpt); else *rpt = 0;
688*41194Sbostic if (*rpt >= 2) return(0);
689*41194Sbostic
690*41194Sbostic score = evaluate(side,xside,ply,alpha,beta);
691*41194Sbostic if (score > 9000)
692*41194Sbostic {
693*41194Sbostic bstline[ply] = 0;
694*41194Sbostic return(score);
695*41194Sbostic }
696*41194Sbostic
697*41194Sbostic if (depth > 0)
698*41194Sbostic {
699*41194Sbostic if (InChk || PawnThreat[ply-1] || ReCapture) ++depth;
700*41194Sbostic }
701*41194Sbostic else
702*41194Sbostic {
703*41194Sbostic if (score >= alpha &&
704*41194Sbostic (InChk || PawnThreat[ply-1] || Threat[ply-1])) ++depth;
705*41194Sbostic else if (score <= beta && MateThreat) ++depth;
706*41194Sbostic }
707*41194Sbostic
708*41194Sbostic if (depth > 0 && hashflag && ply > 1)
709*41194Sbostic {
710*41194Sbostic ProbeTTable(side,depth,&alpha,&beta,&score);
711*41194Sbostic bstline[ply] = PV;
712*41194Sbostic bstline[ply+1] = 0;
713*41194Sbostic if (beta == -20000) return(score);
714*41194Sbostic if (alpha > beta) return(alpha);
715*41194Sbostic }
716*41194Sbostic
717*41194Sbostic if (Sdepth == 1) d = 7; else d = 11;
718*41194Sbostic if (ply > Sdepth+d || (depth < 1 && score > beta)) return(score);
719*41194Sbostic
720*41194Sbostic if (ply > 1)
721*41194Sbostic if (depth > 0) MoveList(side,ply);
722*41194Sbostic else CaptureList(side,xside,ply);
723*41194Sbostic
724*41194Sbostic if (TrPnt[ply] == TrPnt[ply+1]) return(score);
725*41194Sbostic
726*41194Sbostic cf = (depth < 1 && ply > Sdepth+1 && !ChkFlag[ply-2] && !slk);
727*41194Sbostic
728*41194Sbostic if (depth > 0) best = -12000; else best = score;
729*41194Sbostic if (best > alpha) alpha = best;
730*41194Sbostic
731*41194Sbostic for (pnt = pbst = TrPnt[ply];
732*41194Sbostic pnt < TrPnt[ply+1] && best <= beta;
733*41194Sbostic pnt++)
734*41194Sbostic {
735*41194Sbostic if (ply > 1) pick(pnt,TrPnt[ply+1]-1);
736*41194Sbostic node = &Tree[pnt];
737*41194Sbostic mv = (node->f << 8) + node->t;
738*41194Sbostic nxtline[ply+1] = 0;
739*41194Sbostic
740*41194Sbostic if (prune) break;
741*41194Sbostic if (ply == 1) UpdateSearchStatus;
742*41194Sbostic
743*41194Sbostic if (!(node->flags & exact))
744*41194Sbostic {
745*41194Sbostic MakeMove(side,node,&tempb,&tempc,&tempsf,&tempst);
746*41194Sbostic CptrFlag[ply] = (node->flags & capture);
747*41194Sbostic PawnThreat[ply] = (node->flags & pwnthrt);
748*41194Sbostic Tscore[ply] = node->score;
749*41194Sbostic PV = node->reply;
750*41194Sbostic node->score = -search(xside,ply+1,depth-1,-beta,-alpha,
751*41194Sbostic nxtline,&rcnt);
752*41194Sbostic if (abs(node->score) > 9000) node->flags |= exact;
753*41194Sbostic else if (rcnt == 1) node->score /= 2;
754*41194Sbostic if (rcnt >= 2 || GameCnt-Game50 > 99 ||
755*41194Sbostic (node->score == 9999-ply && !ChkFlag[ply]))
756*41194Sbostic {
757*41194Sbostic node->flags |= draw; node->flags |= exact;
758*41194Sbostic if (side == computer) node->score = contempt;
759*41194Sbostic else node->score = -contempt;
760*41194Sbostic }
761*41194Sbostic node->reply = nxtline[ply+1];
762*41194Sbostic UnmakeMove(side,node,&tempb,&tempc,&tempsf,&tempst);
763*41194Sbostic }
764*41194Sbostic if (node->score > best && !timeout)
765*41194Sbostic {
766*41194Sbostic if (depth > 0)
767*41194Sbostic if (node->score > alpha && !(node->flags & exact))
768*41194Sbostic node->score += depth;
769*41194Sbostic best = node->score; pbst = pnt;
770*41194Sbostic if (best > alpha) alpha = best;
771*41194Sbostic for (j = ply+1; nxtline[j] > 0; j++) bstline[j] = nxtline[j];
772*41194Sbostic bstline[j] = 0;
773*41194Sbostic bstline[ply] = mv;
774*41194Sbostic if (ply == 1)
775*41194Sbostic {
776*41194Sbostic if (best == alpha)
777*41194Sbostic {
778*41194Sbostic tmp = Tree[pnt];
779*41194Sbostic for (j = pnt-1; j >= 0; j--) Tree[j+1] = Tree[j];
780*41194Sbostic Tree[0] = tmp;
781*41194Sbostic pbst = 0;
782*41194Sbostic }
783*41194Sbostic if (Sdepth > 2)
784*41194Sbostic if (best > beta) ShowResults(best,bstline,'+');
785*41194Sbostic else if (best < alpha) ShowResults(best,bstline,'-');
786*41194Sbostic else ShowResults(best,bstline,'&');
787*41194Sbostic }
788*41194Sbostic }
789*41194Sbostic if (NodeCnt > ETnodes) ElapsedTime(0);
790*41194Sbostic if (timeout) return(-Tscore[ply-1]);
791*41194Sbostic }
792*41194Sbostic
793*41194Sbostic node = &Tree[pbst];
794*41194Sbostic mv = (node->f<<8) + node->t;
795*41194Sbostic if (hashflag && ply <= Sdepth && *rpt == 0 && best == alpha)
796*41194Sbostic PutInTTable(side,best,depth,alpha,beta,mv);
797*41194Sbostic if (depth > 0)
798*41194Sbostic {
799*41194Sbostic j = (node->f<<6) + node->t; if (side == black) j |= 0x1000;
800*41194Sbostic if (history[j] < 150) history[j] += 2*depth;
801*41194Sbostic if (node->t != (GameList[GameCnt].gmove & 0xFF))
802*41194Sbostic if (best <= beta) killr3[ply] = mv;
803*41194Sbostic else if (mv != killr1[ply])
804*41194Sbostic {
805*41194Sbostic killr2[ply] = killr1[ply];
806*41194Sbostic killr1[ply] = mv;
807*41194Sbostic }
808*41194Sbostic if (best > 9000) killr0[ply] = mv; else killr0[ply] = 0;
809*41194Sbostic }
810*41194Sbostic return(best);
811*41194Sbostic }
812*41194Sbostic
813*41194Sbostic
evaluate(side,xside,ply,alpha,beta)814*41194Sbostic evaluate(side,xside,ply,alpha,beta)
815*41194Sbostic short side,xside,ply,alpha,beta;
816*41194Sbostic
817*41194Sbostic /*
818*41194Sbostic Compute an estimate of the score by adding the positional score from
819*41194Sbostic the previous ply to the material difference. If this score falls
820*41194Sbostic inside a window which is 180 points wider than the alpha-beta window
821*41194Sbostic (or within a 50 point window during quiescence search) call
822*41194Sbostic ScorePosition() to determine a score, otherwise return the estimated
823*41194Sbostic score. If one side has only a king and the other either has no pawns
824*41194Sbostic or no pieces then the function ScoreLoneKing() is called.
825*41194Sbostic */
826*41194Sbostic
827*41194Sbostic {
828*41194Sbostic short s,evflag;
829*41194Sbostic
830*41194Sbostic hung[white] = hung[black] = 0;
831*41194Sbostic slk = ((mtl[white] == valueK && (pmtl[black] == 0 || emtl[black] == 0)) ||
832*41194Sbostic (mtl[black] == valueK && (pmtl[white] == 0 || emtl[white] == 0)));
833*41194Sbostic s = -Pscore[ply-1] + mtl[side] - mtl[xside];
834*41194Sbostic s -= INCscore;
835*41194Sbostic
836*41194Sbostic if (slk) evflag = false;
837*41194Sbostic else evflag =
838*41194Sbostic (ply == 1 || ply < Sdepth ||
839*41194Sbostic ((ply == Sdepth+1 || ply == Sdepth+2) &&
840*41194Sbostic (s > alpha-xwndw && s < beta+xwndw)) ||
841*41194Sbostic (ply > Sdepth+2 && s >= alpha-25 && s <= beta+25));
842*41194Sbostic
843*41194Sbostic if (evflag)
844*41194Sbostic {
845*41194Sbostic EvalNodes++;
846*41194Sbostic ataks(side,atak[side]);
847*41194Sbostic if (atak[side][PieceList[xside][0]] > 0) return(10001-ply);
848*41194Sbostic ataks(xside,atak[xside]);
849*41194Sbostic InChk = (atak[xside][PieceList[side][0]] > 0);
850*41194Sbostic ScorePosition(side,&s);
851*41194Sbostic }
852*41194Sbostic else
853*41194Sbostic {
854*41194Sbostic if (SqAtakd(PieceList[xside][0],side)) return(10001-ply);
855*41194Sbostic InChk = SqAtakd(PieceList[side][0],xside);
856*41194Sbostic if (slk) ScoreLoneKing(side,&s);
857*41194Sbostic }
858*41194Sbostic
859*41194Sbostic Pscore[ply] = s - mtl[side] + mtl[xside];
860*41194Sbostic if (InChk) ChkFlag[ply-1] = Pindex[TOsquare];
861*41194Sbostic else ChkFlag[ply-1] = 0;
862*41194Sbostic Threat[ply-1] = (hung[side] > 1 && ply == Sdepth+1);
863*41194Sbostic return(s);
864*41194Sbostic }
865*41194Sbostic
866*41194Sbostic
ProbeTTable(side,depth,alpha,beta,score)867*41194Sbostic ProbeTTable(side,depth,alpha,beta,score)
868*41194Sbostic short side,depth,*alpha,*beta,*score;
869*41194Sbostic
870*41194Sbostic /*
871*41194Sbostic Look for the current board position in the transposition table.
872*41194Sbostic */
873*41194Sbostic
874*41194Sbostic {
875*41194Sbostic short hindx;
876*41194Sbostic if (side == white) hashkey |= 1; else hashkey &= 0xFFFE;
877*41194Sbostic hindx = (hashkey & (ttblsz-1));
878*41194Sbostic ptbl = (ttable + hindx);
879*41194Sbostic if (ptbl->depth >= depth && ptbl->hashbd == hashbd)
880*41194Sbostic {
881*41194Sbostic HashCnt++;
882*41194Sbostic PV = ptbl->mv;
883*41194Sbostic if (ptbl->flags & truescore)
884*41194Sbostic {
885*41194Sbostic *score = ptbl->score;
886*41194Sbostic *beta = -20000;
887*41194Sbostic return(true);
888*41194Sbostic }
889*41194Sbostic /*
890*41194Sbostic else if (ptbl->flags & upperbound)
891*41194Sbostic {
892*41194Sbostic if (ptbl->score < *beta) *beta = ptbl->score+1;
893*41194Sbostic }
894*41194Sbostic */
895*41194Sbostic else if (ptbl->flags & lowerbound)
896*41194Sbostic {
897*41194Sbostic if (ptbl->score > *alpha) *alpha = ptbl->score-1;
898*41194Sbostic }
899*41194Sbostic }
900*41194Sbostic return(false);
901*41194Sbostic }
902*41194Sbostic
903*41194Sbostic
PutInTTable(side,score,depth,alpha,beta,mv)904*41194Sbostic PutInTTable(side,score,depth,alpha,beta,mv)
905*41194Sbostic short side,score,depth,alpha,beta;
906*41194Sbostic unsigned short mv;
907*41194Sbostic
908*41194Sbostic /*
909*41194Sbostic Store the current board position in the transposition table.
910*41194Sbostic */
911*41194Sbostic
912*41194Sbostic {
913*41194Sbostic short hindx;
914*41194Sbostic if (side == white) hashkey |= 1; else hashkey &= 0xFFFE;
915*41194Sbostic hindx = (hashkey & (ttblsz-1));
916*41194Sbostic ptbl = (ttable + hindx);
917*41194Sbostic ptbl->hashbd = hashbd;
918*41194Sbostic ptbl->depth = depth;
919*41194Sbostic ptbl->score = score;
920*41194Sbostic ptbl->mv = mv;
921*41194Sbostic ptbl->flags = 0;
922*41194Sbostic if (score < alpha) ptbl->flags |= upperbound;
923*41194Sbostic else if (score > beta) ptbl->flags |= lowerbound;
924*41194Sbostic else ptbl->flags |= truescore;
925*41194Sbostic }
926*41194Sbostic
927*41194Sbostic
ZeroTTable()928*41194Sbostic ZeroTTable()
929*41194Sbostic {
930*41194Sbostic int i;
931*41194Sbostic if (hashflag)
932*41194Sbostic for (i = 0; i < ttblsz; i++)
933*41194Sbostic {
934*41194Sbostic ptbl = (ttable + i);
935*41194Sbostic ptbl->depth = 0;
936*41194Sbostic }
937*41194Sbostic }
938*41194Sbostic
939*41194Sbostic
MoveList(side,ply)940*41194Sbostic MoveList(side,ply)
941*41194Sbostic short side,ply;
942*41194Sbostic
943*41194Sbostic /*
944*41194Sbostic Fill the array Tree[] with all available moves for side to play. Array
945*41194Sbostic TrPnt[ply] contains the index into Tree[] of the first move at a ply.
946*41194Sbostic */
947*41194Sbostic
948*41194Sbostic {
949*41194Sbostic register short i;
950*41194Sbostic short xside,f;
951*41194Sbostic
952*41194Sbostic xside = otherside[side];
953*41194Sbostic if (PV == 0) Swag0 = killr0[ply]; else Swag0 = PV;
954*41194Sbostic Swag1 = killr1[ply]; Swag2 = killr2[ply];
955*41194Sbostic Swag3 = killr3[ply]; Swag4 = 0;
956*41194Sbostic if (ply > 2) Swag4 = killr1[ply-2];
957*41194Sbostic TrPnt[ply+1] = TrPnt[ply];
958*41194Sbostic Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
959*41194Sbostic for (i = PieceCnt[side]; i >= 0; i--)
960*41194Sbostic GenMoves(ply,PieceList[side][i],side,xside);
961*41194Sbostic if (kingmoved[side] == 0 && !castld[side])
962*41194Sbostic {
963*41194Sbostic f = PieceList[side][0];
964*41194Sbostic if (castle(side,f,f+2,0))
965*41194Sbostic {
966*41194Sbostic LinkMove(ply,f,f+2,xside);
967*41194Sbostic Tree[TrPnt[ply+1]-1].flags |= cstlmask;
968*41194Sbostic }
969*41194Sbostic if (castle(side,f,f-2,0))
970*41194Sbostic {
971*41194Sbostic LinkMove(ply,f,f-2,xside);
972*41194Sbostic Tree[TrPnt[ply+1]-1].flags |= cstlmask;
973*41194Sbostic }
974*41194Sbostic }
975*41194Sbostic }
976*41194Sbostic
977*41194Sbostic #if (NEWMOVE < 11)
GenMoves(ply,sq,side,xside)978*41194Sbostic GenMoves(ply,sq,side,xside)
979*41194Sbostic short ply,sq,side,xside;
980*41194Sbostic
981*41194Sbostic /*
982*41194Sbostic Generate moves for a piece. The from square is mapped onto a special
983*41194Sbostic board and offsets (taken from array Dir[]) are added to the mapped
984*41194Sbostic location. The newly generated square is tested to see if it falls off
985*41194Sbostic the board by ANDing the square with 88 HEX. Legal moves are linked
986*41194Sbostic into the tree.
987*41194Sbostic */
988*41194Sbostic
989*41194Sbostic {
990*41194Sbostic register short m,u,d;
991*41194Sbostic short i,m0,piece;
992*41194Sbostic
993*41194Sbostic piece = board[sq]; m0 = map[sq];
994*41194Sbostic if (sweep[piece])
995*41194Sbostic for (i = Dstart[piece]; i <= Dstop[piece]; i++)
996*41194Sbostic {
997*41194Sbostic d = Dir[i]; m = m0+d;
998*41194Sbostic while (!(m & 0x88))
999*41194Sbostic {
1000*41194Sbostic u = unmap[m];
1001*41194Sbostic if (color[u] == neutral)
1002*41194Sbostic {
1003*41194Sbostic LinkMove(ply,sq,u,xside);
1004*41194Sbostic m += d;
1005*41194Sbostic }
1006*41194Sbostic else if (color[u] == xside)
1007*41194Sbostic {
1008*41194Sbostic LinkMove(ply,sq,u,xside);
1009*41194Sbostic break;
1010*41194Sbostic }
1011*41194Sbostic else break;
1012*41194Sbostic }
1013*41194Sbostic }
1014*41194Sbostic else if (piece == pawn)
1015*41194Sbostic {
1016*41194Sbostic if (side == white && color[sq+8] == neutral)
1017*41194Sbostic {
1018*41194Sbostic LinkMove(ply,sq,sq+8,xside);
1019*41194Sbostic if (row[sq] == 1)
1020*41194Sbostic if (color[sq+16] == neutral)
1021*41194Sbostic LinkMove(ply,sq,sq+16,xside);
1022*41194Sbostic }
1023*41194Sbostic else if (side == black && color[sq-8] == neutral)
1024*41194Sbostic {
1025*41194Sbostic LinkMove(ply,sq,sq-8,xside);
1026*41194Sbostic if (row[sq] == 6)
1027*41194Sbostic if (color[sq-16] == neutral)
1028*41194Sbostic LinkMove(ply,sq,sq-16,xside);
1029*41194Sbostic }
1030*41194Sbostic for (i = Dstart[piece]; i <= Dstop[piece]; i++)
1031*41194Sbostic if (!((m = m0+Dir[i]) & 0x88))
1032*41194Sbostic {
1033*41194Sbostic u = unmap[m];
1034*41194Sbostic if (color[u] == xside || u == epsquare)
1035*41194Sbostic LinkMove(ply,sq,u,xside);
1036*41194Sbostic }
1037*41194Sbostic }
1038*41194Sbostic else
1039*41194Sbostic {
1040*41194Sbostic for (i = Dstart[piece]; i <= Dstop[piece]; i++)
1041*41194Sbostic if (!((m = m0+Dir[i]) & 0x88))
1042*41194Sbostic {
1043*41194Sbostic u = unmap[m];
1044*41194Sbostic if (color[u] != side) LinkMove(ply,sq,u,xside);
1045*41194Sbostic }
1046*41194Sbostic }
1047*41194Sbostic }
1048*41194Sbostic #endif
1049*41194Sbostic
LinkMove(ply,f,t,xside)1050*41194Sbostic LinkMove(ply,f,t,xside)
1051*41194Sbostic short ply,f,t,xside;
1052*41194Sbostic
1053*41194Sbostic /*
1054*41194Sbostic Add a move to the tree. Assign a bonus to order the moves
1055*41194Sbostic as follows:
1056*41194Sbostic 1. Principle variation
1057*41194Sbostic 2. Capture of last moved piece
1058*41194Sbostic 3. Other captures (major pieces first)
1059*41194Sbostic 4. Killer moves
1060*41194Sbostic 5. "history" killers
1061*41194Sbostic */
1062*41194Sbostic
1063*41194Sbostic {
1064*41194Sbostic register short s,z;
1065*41194Sbostic unsigned short mv;
1066*41194Sbostic struct leaf *node;
1067*41194Sbostic
1068*41194Sbostic node = &Tree[TrPnt[ply+1]];
1069*41194Sbostic ++TrPnt[ply+1];
1070*41194Sbostic node->flags = node->reply = 0;
1071*41194Sbostic node->f = f; node->t = t;
1072*41194Sbostic mv = (f<<8) + t;
1073*41194Sbostic s = 0;
1074*41194Sbostic if (mv == Swag0) s = 2000;
1075*41194Sbostic else if (mv == Swag1) s = 60;
1076*41194Sbostic else if (mv == Swag2) s = 50;
1077*41194Sbostic else if (mv == Swag3) s = 40;
1078*41194Sbostic else if (mv == Swag4) s = 30;
1079*41194Sbostic if (color[t] != neutral)
1080*41194Sbostic {
1081*41194Sbostic node->flags |= capture;
1082*41194Sbostic if (t == TOsquare) s += 500;
1083*41194Sbostic s += value[board[t]] - board[f];
1084*41194Sbostic }
1085*41194Sbostic if (board[f] == pawn)
1086*41194Sbostic if (row[t] == 0 || row[t] == 7)
1087*41194Sbostic {
1088*41194Sbostic node->flags |= promote;
1089*41194Sbostic s += 800;
1090*41194Sbostic }
1091*41194Sbostic else if (row[t] == 1 || row[t] == 6)
1092*41194Sbostic {
1093*41194Sbostic node->flags |= pwnthrt;
1094*41194Sbostic s += 600;
1095*41194Sbostic }
1096*41194Sbostic else if (t == epsquare) node->flags |= epmask;
1097*41194Sbostic z = (f<<6) + t; if (xside == white) z |= 0x1000;
1098*41194Sbostic s += history[z];
1099*41194Sbostic node->score = s - 20000;
1100*41194Sbostic }
1101*41194Sbostic
1102*41194Sbostic #if (NEWMOVE < 10)
CaptureList(side,xside,ply)1103*41194Sbostic CaptureList(side,xside,ply)
1104*41194Sbostic short side,xside,ply;
1105*41194Sbostic
1106*41194Sbostic /*
1107*41194Sbostic Generate captures and Pawn promotions only.
1108*41194Sbostic */
1109*41194Sbostic
1110*41194Sbostic #define LinkCapture\
1111*41194Sbostic {\
1112*41194Sbostic node->f = sq; node->t = u;\
1113*41194Sbostic node->reply = 0;\
1114*41194Sbostic node->flags = capture;\
1115*41194Sbostic node->score = value[board[u]] + svalue[board[u]] - piece;\
1116*41194Sbostic if (piece == pawn && (u < 8 || u > 55))\
1117*41194Sbostic {\
1118*41194Sbostic node->flags |= promote;\
1119*41194Sbostic node->score = valueQ;\
1120*41194Sbostic }\
1121*41194Sbostic ++node;\
1122*41194Sbostic ++TrPnt[ply+1];\
1123*41194Sbostic }
1124*41194Sbostic
1125*41194Sbostic {
1126*41194Sbostic register short m,u;
1127*41194Sbostic short d,sq,i,j,j1,j2,m0,r7,d0,piece,*PL;
1128*41194Sbostic struct leaf *node;
1129*41194Sbostic
1130*41194Sbostic TrPnt[ply+1] = TrPnt[ply];
1131*41194Sbostic node = &Tree[TrPnt[ply]];
1132*41194Sbostic Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
1133*41194Sbostic if (side == white)
1134*41194Sbostic {
1135*41194Sbostic r7 = 6; d0 = 8;
1136*41194Sbostic }
1137*41194Sbostic else
1138*41194Sbostic {
1139*41194Sbostic r7 = 1; d0 = -8;
1140*41194Sbostic }
1141*41194Sbostic PL = PieceList[side];
1142*41194Sbostic for (i = 0; i <= PieceCnt[side]; i++)
1143*41194Sbostic {
1144*41194Sbostic sq = PL[i];
1145*41194Sbostic m0 = map[sq]; piece = board[sq];
1146*41194Sbostic j1 = Dstart[piece]; j2 = Dstop[piece];
1147*41194Sbostic if (sweep[piece])
1148*41194Sbostic for (j = j1; j <= j2; j++)
1149*41194Sbostic {
1150*41194Sbostic d = Dir[j]; m = m0+d;
1151*41194Sbostic while (!(m & 0x88))
1152*41194Sbostic {
1153*41194Sbostic u = unmap[m];
1154*41194Sbostic if (color[u] == neutral) m += d;
1155*41194Sbostic else
1156*41194Sbostic {
1157*41194Sbostic if (color[u] == xside) LinkCapture;
1158*41194Sbostic break;
1159*41194Sbostic }
1160*41194Sbostic }
1161*41194Sbostic }
1162*41194Sbostic else
1163*41194Sbostic {
1164*41194Sbostic for (j = j1; j <= j2; j++)
1165*41194Sbostic if (!((m = m0+Dir[j]) & 0x88))
1166*41194Sbostic {
1167*41194Sbostic u = unmap[m];
1168*41194Sbostic if (color[u] == xside) LinkCapture;
1169*41194Sbostic }
1170*41194Sbostic if (piece == pawn && row[sq] == r7)
1171*41194Sbostic {
1172*41194Sbostic u = sq+d0;
1173*41194Sbostic if (color[u] == neutral) LinkCapture;
1174*41194Sbostic }
1175*41194Sbostic }
1176*41194Sbostic }
1177*41194Sbostic }
1178*41194Sbostic #endif
1179*41194Sbostic
castle(side,kf,kt,iop)1180*41194Sbostic int castle(side,kf,kt,iop)
1181*41194Sbostic short side,kf,kt,iop;
1182*41194Sbostic
1183*41194Sbostic /*
1184*41194Sbostic Make or Unmake a castling move.
1185*41194Sbostic */
1186*41194Sbostic
1187*41194Sbostic {
1188*41194Sbostic short rf,rt,d,t0,xside;
1189*41194Sbostic
1190*41194Sbostic xside = otherside[side];
1191*41194Sbostic if (kt > kf)
1192*41194Sbostic {
1193*41194Sbostic rf = kf+3; rt = kt-1; d = 1;
1194*41194Sbostic }
1195*41194Sbostic else
1196*41194Sbostic {
1197*41194Sbostic rf = kf-4; rt = kt+1; d = -1;
1198*41194Sbostic }
1199*41194Sbostic if (iop == 0)
1200*41194Sbostic {
1201*41194Sbostic if (board[kf] != king || board[rf] != rook || color[rf] != side)
1202*41194Sbostic return(false);
1203*41194Sbostic if (color[kt] != neutral || color[rt] != neutral) return(false);
1204*41194Sbostic if (d == -1 && color[kt+d] != neutral) return(false);
1205*41194Sbostic if (SqAtakd(kf,xside)) return(false);
1206*41194Sbostic if (SqAtakd(kt,xside)) return(false);
1207*41194Sbostic if (SqAtakd(kf+d,xside)) return(false);
1208*41194Sbostic }
1209*41194Sbostic else
1210*41194Sbostic {
1211*41194Sbostic if (iop == 1) castld[side] = true; else castld[side] = false;
1212*41194Sbostic if (iop == 2)
1213*41194Sbostic {
1214*41194Sbostic t0 = kt; kt = kf; kf = t0;
1215*41194Sbostic t0 = rt; rt = rf; rf = t0;
1216*41194Sbostic }
1217*41194Sbostic board[kt] = king; color[kt] = side; Pindex[kt] = 0;
1218*41194Sbostic board[kf] = no_piece; color[kf] = neutral;
1219*41194Sbostic board[rt] = rook; color[rt] = side; Pindex[rt] = Pindex[rf];
1220*41194Sbostic board[rf] = no_piece; color[rf] = neutral;
1221*41194Sbostic PieceList[side][Pindex[kt]] = kt;
1222*41194Sbostic PieceList[side][Pindex[rt]] = rt;
1223*41194Sbostic if (hashflag)
1224*41194Sbostic {
1225*41194Sbostic UpdateHashbd(side,king,kf,kt);
1226*41194Sbostic UpdateHashbd(side,rook,rf,rt);
1227*41194Sbostic }
1228*41194Sbostic }
1229*41194Sbostic return(true);
1230*41194Sbostic }
1231*41194Sbostic
1232*41194Sbostic
EnPassant(xside,f,t,iop)1233*41194Sbostic EnPassant(xside,f,t,iop)
1234*41194Sbostic short xside,f,t,iop;
1235*41194Sbostic
1236*41194Sbostic /*
1237*41194Sbostic Make or unmake an en passant move.
1238*41194Sbostic */
1239*41194Sbostic
1240*41194Sbostic {
1241*41194Sbostic short l;
1242*41194Sbostic if (t > f) l = t-8; else l = t+8;
1243*41194Sbostic if (iop == 1)
1244*41194Sbostic {
1245*41194Sbostic board[l] = no_piece; color[l] = neutral;
1246*41194Sbostic }
1247*41194Sbostic else
1248*41194Sbostic {
1249*41194Sbostic board[l] = pawn; color[l] = xside;
1250*41194Sbostic }
1251*41194Sbostic InitializeStats();
1252*41194Sbostic }
1253*41194Sbostic
1254*41194Sbostic
MakeMove(side,node,tempb,tempc,tempsf,tempst)1255*41194Sbostic MakeMove(side,node,tempb,tempc,tempsf,tempst)
1256*41194Sbostic short side,*tempc,*tempb,*tempsf,*tempst;
1257*41194Sbostic struct leaf *node;
1258*41194Sbostic
1259*41194Sbostic /*
1260*41194Sbostic Update Arrays board[], color[], and Pindex[] to reflect the new board
1261*41194Sbostic position obtained after making the move pointed to by node. Also
1262*41194Sbostic update miscellaneous stuff that changes when a move is made.
1263*41194Sbostic */
1264*41194Sbostic
1265*41194Sbostic {
1266*41194Sbostic register short f,t;
1267*41194Sbostic short xside,ct,cf;
1268*41194Sbostic
1269*41194Sbostic xside = otherside[side];
1270*41194Sbostic f = node->f; t = node->t; epsquare = -1;
1271*41194Sbostic FROMsquare = f; TOsquare = t;
1272*41194Sbostic INCscore = 0;
1273*41194Sbostic GameList[++GameCnt].gmove = (f<<8) + t;
1274*41194Sbostic if (node->flags & cstlmask)
1275*41194Sbostic {
1276*41194Sbostic GameList[GameCnt].piece = no_piece;
1277*41194Sbostic GameList[GameCnt].color = side;
1278*41194Sbostic castle(side,f,t,1);
1279*41194Sbostic }
1280*41194Sbostic else
1281*41194Sbostic {
1282*41194Sbostic *tempc = color[t]; *tempb = board[t];
1283*41194Sbostic *tempsf = svalue[f]; *tempst = svalue[t];
1284*41194Sbostic GameList[GameCnt].piece = *tempb;
1285*41194Sbostic GameList[GameCnt].color = *tempc;
1286*41194Sbostic if (*tempc != neutral)
1287*41194Sbostic {
1288*41194Sbostic UpdatePieceList(*tempc,t,1);
1289*41194Sbostic if (*tempb == pawn) --PawnCnt[*tempc][column[t]];
1290*41194Sbostic if (board[f] == pawn)
1291*41194Sbostic {
1292*41194Sbostic --PawnCnt[side][column[f]];
1293*41194Sbostic ++PawnCnt[side][column[t]];
1294*41194Sbostic cf = column[f]; ct = column[t];
1295*41194Sbostic if (PawnCnt[side][ct] > 1+PawnCnt[side][cf])
1296*41194Sbostic INCscore -= 15;
1297*41194Sbostic else if (PawnCnt[side][ct] < 1+PawnCnt[side][cf])
1298*41194Sbostic INCscore += 15;
1299*41194Sbostic else if (ct == 0 || ct == 7 || PawnCnt[side][ct+ct-cf] == 0)
1300*41194Sbostic INCscore -= 15;
1301*41194Sbostic }
1302*41194Sbostic mtl[xside] -= value[*tempb];
1303*41194Sbostic if (*tempb == pawn) pmtl[xside] -= valueP;
1304*41194Sbostic if (hashflag) UpdateHashbd(xside,*tempb,-1,t);
1305*41194Sbostic INCscore += *tempst;
1306*41194Sbostic }
1307*41194Sbostic color[t] = color[f]; board[t] = board[f]; svalue[t] = svalue[f];
1308*41194Sbostic Pindex[t] = Pindex[f]; PieceList[side][Pindex[t]] = t;
1309*41194Sbostic color[f] = neutral; board[f] = no_piece;
1310*41194Sbostic if (board[t] == pawn)
1311*41194Sbostic if (t-f == 16) epsquare = f+8;
1312*41194Sbostic else if (f-t == 16) epsquare = f-8;
1313*41194Sbostic if (node->flags & promote)
1314*41194Sbostic {
1315*41194Sbostic board[t] = queen;
1316*41194Sbostic --PawnCnt[side][column[t]];
1317*41194Sbostic mtl[side] += valueQ - valueP;
1318*41194Sbostic pmtl[side] -= valueP;
1319*41194Sbostic HasQueen[side] = true;
1320*41194Sbostic if (hashflag)
1321*41194Sbostic {
1322*41194Sbostic UpdateHashbd(side,pawn,f,-1);
1323*41194Sbostic UpdateHashbd(side,queen,f,-1);
1324*41194Sbostic }
1325*41194Sbostic INCscore -= *tempsf;
1326*41194Sbostic }
1327*41194Sbostic if (board[t] == king) ++kingmoved[side];
1328*41194Sbostic if (node->flags & epmask) EnPassant(xside,f,t,1);
1329*41194Sbostic else if (hashflag) UpdateHashbd(side,board[t],f,t);
1330*41194Sbostic }
1331*41194Sbostic }
1332*41194Sbostic
1333*41194Sbostic
UnmakeMove(side,node,tempb,tempc,tempsf,tempst)1334*41194Sbostic UnmakeMove(side,node,tempb,tempc,tempsf,tempst)
1335*41194Sbostic short side,*tempc,*tempb,*tempsf,*tempst;
1336*41194Sbostic struct leaf *node;
1337*41194Sbostic
1338*41194Sbostic /*
1339*41194Sbostic Take back a move.
1340*41194Sbostic */
1341*41194Sbostic
1342*41194Sbostic {
1343*41194Sbostic register short f,t;
1344*41194Sbostic short xside;
1345*41194Sbostic
1346*41194Sbostic xside = otherside[side];
1347*41194Sbostic f = node->f; t = node->t; epsquare = -1;
1348*41194Sbostic GameCnt--;
1349*41194Sbostic if (node->flags & cstlmask) castle(side,f,t,2);
1350*41194Sbostic else
1351*41194Sbostic {
1352*41194Sbostic color[f] = color[t]; board[f] = board[t]; svalue[f] = *tempsf;
1353*41194Sbostic Pindex[f] = Pindex[t]; PieceList[side][Pindex[f]] = f;
1354*41194Sbostic color[t] = *tempc; board[t] = *tempb; svalue[t] = *tempst;
1355*41194Sbostic if (node->flags & promote)
1356*41194Sbostic {
1357*41194Sbostic board[f] = pawn;
1358*41194Sbostic ++PawnCnt[side][column[t]];
1359*41194Sbostic mtl[side] += valueP - valueQ;
1360*41194Sbostic pmtl[side] += valueP;
1361*41194Sbostic if (hashflag)
1362*41194Sbostic {
1363*41194Sbostic UpdateHashbd(side,queen,-1,t);
1364*41194Sbostic UpdateHashbd(side,pawn,-1,t);
1365*41194Sbostic }
1366*41194Sbostic }
1367*41194Sbostic if (*tempc != neutral)
1368*41194Sbostic {
1369*41194Sbostic UpdatePieceList(*tempc,t,2);
1370*41194Sbostic if (*tempb == pawn) ++PawnCnt[*tempc][column[t]];
1371*41194Sbostic if (board[f] == pawn)
1372*41194Sbostic {
1373*41194Sbostic --PawnCnt[side][column[t]];
1374*41194Sbostic ++PawnCnt[side][column[f]];
1375*41194Sbostic }
1376*41194Sbostic mtl[xside] += value[*tempb];
1377*41194Sbostic if (*tempb == pawn) pmtl[xside] += valueP;
1378*41194Sbostic if (hashflag) UpdateHashbd(xside,*tempb,-1,t);
1379*41194Sbostic }
1380*41194Sbostic if (board[f] == king) --kingmoved[side];
1381*41194Sbostic if (node->flags & epmask) EnPassant(xside,f,t,2);
1382*41194Sbostic else if (hashflag) UpdateHashbd(side,board[f],f,t);
1383*41194Sbostic }
1384*41194Sbostic }
1385*41194Sbostic
1386*41194Sbostic
UpdateHashbd(side,piece,f,t)1387*41194Sbostic UpdateHashbd(side,piece,f,t)
1388*41194Sbostic short side,piece,f,t;
1389*41194Sbostic
1390*41194Sbostic /*
1391*41194Sbostic hashbd contains a 32 bit "signature" of the board position. hashkey
1392*41194Sbostic contains a 16 bit code used to address the hash table. When a move is
1393*41194Sbostic made, XOR'ing the hashcode of moved piece on the from and to squares
1394*41194Sbostic with the hashbd and hashkey values keeps things current.
1395*41194Sbostic */
1396*41194Sbostic
1397*41194Sbostic {
1398*41194Sbostic if (f >= 0)
1399*41194Sbostic {
1400*41194Sbostic hashbd ^= hashcode[side][piece][f].bd;
1401*41194Sbostic hashkey ^= hashcode[side][piece][f].key;
1402*41194Sbostic }
1403*41194Sbostic if (t >= 0)
1404*41194Sbostic {
1405*41194Sbostic hashbd ^= hashcode[side][piece][t].bd;
1406*41194Sbostic hashkey ^= hashcode[side][piece][t].key;
1407*41194Sbostic }
1408*41194Sbostic }
1409*41194Sbostic
1410*41194Sbostic
UpdatePieceList(side,sq,iop)1411*41194Sbostic UpdatePieceList(side,sq,iop)
1412*41194Sbostic short side,sq,iop;
1413*41194Sbostic
1414*41194Sbostic /*
1415*41194Sbostic Update the PieceList and Pindex arrays when a piece is captured or
1416*41194Sbostic when a capture is unmade.
1417*41194Sbostic */
1418*41194Sbostic
1419*41194Sbostic {
1420*41194Sbostic register short i;
1421*41194Sbostic if (iop == 1)
1422*41194Sbostic {
1423*41194Sbostic PieceCnt[side]--;
1424*41194Sbostic for (i = Pindex[sq]; i <= PieceCnt[side]; i++)
1425*41194Sbostic {
1426*41194Sbostic PieceList[side][i] = PieceList[side][i+1];
1427*41194Sbostic Pindex[PieceList[side][i]] = i;
1428*41194Sbostic }
1429*41194Sbostic }
1430*41194Sbostic else
1431*41194Sbostic {
1432*41194Sbostic PieceCnt[side]++;
1433*41194Sbostic PieceList[side][PieceCnt[side]] = sq;
1434*41194Sbostic Pindex[sq] = PieceCnt[side];
1435*41194Sbostic }
1436*41194Sbostic }
1437*41194Sbostic
1438*41194Sbostic
InitializeStats()1439*41194Sbostic InitializeStats()
1440*41194Sbostic
1441*41194Sbostic /*
1442*41194Sbostic Scan thru the board seeing what's on each square. If a piece is found,
1443*41194Sbostic update the variables PieceCnt, PawnCnt, Pindex and PieceList. Also
1444*41194Sbostic determine the material for each side and set the hashkey and hashbd
1445*41194Sbostic variables to represent the current board position. Array
1446*41194Sbostic PieceList[side][indx] contains the location of all the pieces of
1447*41194Sbostic either side. Array Pindex[sq] contains the indx into PieceList for a
1448*41194Sbostic given square.
1449*41194Sbostic */
1450*41194Sbostic
1451*41194Sbostic {
1452*41194Sbostic register short i,sq;
1453*41194Sbostic epsquare = -1;
1454*41194Sbostic for (i = 0; i < 8; i++)
1455*41194Sbostic PawnCnt[white][i] = PawnCnt[black][i] = 0;
1456*41194Sbostic mtl[white] = mtl[black] = pmtl[white] = pmtl[black] = 0;
1457*41194Sbostic PieceCnt[white] = PieceCnt[black] = 0;
1458*41194Sbostic hashbd = hashkey = 0;
1459*41194Sbostic for (sq = 0; sq < 64; sq++)
1460*41194Sbostic if (color[sq] != neutral)
1461*41194Sbostic {
1462*41194Sbostic mtl[color[sq]] += value[board[sq]];
1463*41194Sbostic if (board[sq] == pawn)
1464*41194Sbostic {
1465*41194Sbostic pmtl[color[sq]] += valueP;
1466*41194Sbostic ++PawnCnt[color[sq]][column[sq]];
1467*41194Sbostic }
1468*41194Sbostic if (board[sq] == king) Pindex[sq] = 0;
1469*41194Sbostic else Pindex[sq] = ++PieceCnt[color[sq]];
1470*41194Sbostic PieceList[color[sq]][Pindex[sq]] = sq;
1471*41194Sbostic hashbd ^= hashcode[color[sq]][board[sq]][sq].bd;
1472*41194Sbostic hashkey ^= hashcode[color[sq]][board[sq]][sq].key;
1473*41194Sbostic }
1474*41194Sbostic }
1475*41194Sbostic
1476*41194Sbostic
pick(p1,p2)1477*41194Sbostic pick(p1,p2)
1478*41194Sbostic short p1,p2;
1479*41194Sbostic
1480*41194Sbostic /*
1481*41194Sbostic Find the best move in the tree between indexes p1 and p2. Swap the
1482*41194Sbostic best move into the p1 element.
1483*41194Sbostic */
1484*41194Sbostic
1485*41194Sbostic {
1486*41194Sbostic register short p,s;
1487*41194Sbostic short p0,s0;
1488*41194Sbostic struct leaf temp;
1489*41194Sbostic
1490*41194Sbostic s0 = Tree[p1].score; p0 = p1;
1491*41194Sbostic for (p = p1+1; p <= p2; p++)
1492*41194Sbostic if ((s = Tree[p].score) > s0)
1493*41194Sbostic {
1494*41194Sbostic s0 = s; p0 = p;
1495*41194Sbostic }
1496*41194Sbostic if (p0 != p1)
1497*41194Sbostic {
1498*41194Sbostic temp = Tree[p1]; Tree[p1] = Tree[p0]; Tree[p0] = temp;
1499*41194Sbostic }
1500*41194Sbostic }
1501*41194Sbostic
1502*41194Sbostic
repetition(cnt)1503*41194Sbostic repetition(cnt)
1504*41194Sbostic short *cnt;
1505*41194Sbostic
1506*41194Sbostic /*
1507*41194Sbostic Check for draw by threefold repetition.
1508*41194Sbostic */
1509*41194Sbostic
1510*41194Sbostic {
1511*41194Sbostic register short i,c;
1512*41194Sbostic short f,t,b[64];
1513*41194Sbostic unsigned short m;
1514*41194Sbostic *cnt = c = 0;
1515*41194Sbostic if (GameCnt > Game50+3)
1516*41194Sbostic {
1517*41194Sbostic /*
1518*41194Sbostic memset((char *)b,0,64*sizeof(short));
1519*41194Sbostic */
1520*41194Sbostic for (i = 0; i < 64; b[i++] = 0);
1521*41194Sbostic for (i = GameCnt; i > Game50; i--)
1522*41194Sbostic {
1523*41194Sbostic m = GameList[i].gmove; f = m>>8; t = m & 0xFF;
1524*41194Sbostic if (++b[f] == 0) c--; else c++;
1525*41194Sbostic if (--b[t] == 0) c--; else c++;
1526*41194Sbostic if (c == 0) (*cnt)++;
1527*41194Sbostic }
1528*41194Sbostic }
1529*41194Sbostic }
1530*41194Sbostic
1531*41194Sbostic #if (NEWMOVE < 3)
SqAtakd(sq,side)1532*41194Sbostic int SqAtakd(sq,side)
1533*41194Sbostic short sq,side;
1534*41194Sbostic
1535*41194Sbostic /*
1536*41194Sbostic See if any piece with color 'side' ataks sq. First check for pawns
1537*41194Sbostic or king, then try other pieces. Array Dcode is used to check for
1538*41194Sbostic knight attacks or R,B,Q co-linearity.
1539*41194Sbostic */
1540*41194Sbostic
1541*41194Sbostic {
1542*41194Sbostic register short m,d;
1543*41194Sbostic short i,m0,m1,loc,piece,*PL;
1544*41194Sbostic
1545*41194Sbostic m1 = map[sq];
1546*41194Sbostic if (side == white) m = m1-0x0F; else m = m1+0x0F;
1547*41194Sbostic if (!(m & 0x88))
1548*41194Sbostic if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true);
1549*41194Sbostic if (side == white) m = m1-0x11; else m = m1+0x11;
1550*41194Sbostic if (!(m & 0x88))
1551*41194Sbostic if (board[unmap[m]] == pawn && color[unmap[m]] == side) return(true);
1552*41194Sbostic if (distance(sq,PieceList[side][0]) == 1) return(true);
1553*41194Sbostic
1554*41194Sbostic PL = PieceList[side];
1555*41194Sbostic for (i = 1; i <= PieceCnt[side]; i++)
1556*41194Sbostic {
1557*41194Sbostic loc = PL[i]; piece = board[loc];
1558*41194Sbostic if (piece == pawn) continue;
1559*41194Sbostic m0 = map[loc]; d = Dcode[abs(m1-m0)];
1560*41194Sbostic if (d == 0 || (Pdir[d] & pbit[piece]) == 0) continue;
1561*41194Sbostic if (piece == knight) return(true);
1562*41194Sbostic else
1563*41194Sbostic {
1564*41194Sbostic if (m1 < m0) d = -d;
1565*41194Sbostic for (m = m0+d; m != m1; m += d)
1566*41194Sbostic if (color[unmap[m]] != neutral) break;
1567*41194Sbostic if (m == m1) return(true);
1568*41194Sbostic }
1569*41194Sbostic }
1570*41194Sbostic return(false);
1571*41194Sbostic }
1572*41194Sbostic #endif
1573*41194Sbostic
1574*41194Sbostic #if (NEWMOVE < 2)
ataks(side,a)1575*41194Sbostic ataks(side,a)
1576*41194Sbostic short side,*a;
1577*41194Sbostic
1578*41194Sbostic /*
1579*41194Sbostic Fill array atak[][] with info about ataks to a square. Bits 8-15
1580*41194Sbostic are set if the piece (king..pawn) ataks the square. Bits 0-7
1581*41194Sbostic contain a count of total ataks to the square.
1582*41194Sbostic */
1583*41194Sbostic
1584*41194Sbostic {
1585*41194Sbostic register short u,m;
1586*41194Sbostic short d,c,j,j1,j2,piece,i,m0,sq,*PL;
1587*41194Sbostic
1588*41194Sbostic /*
1589*41194Sbostic memset((char *)a,0,64*sizeof(short));
1590*41194Sbostic */
1591*41194Sbostic for (u = 0; u < 64; a[u++] = 0);
1592*41194Sbostic Dstart[pawn] = Dpwn[side]; Dstop[pawn] = Dstart[pawn] + 1;
1593*41194Sbostic PL = PieceList[side];
1594*41194Sbostic for (i = 0; i <= PieceCnt[side]; i++)
1595*41194Sbostic {
1596*41194Sbostic sq = PL[i];
1597*41194Sbostic m0 = map[sq];
1598*41194Sbostic piece = board[sq];
1599*41194Sbostic c = control[piece]; j1 = Dstart[piece]; j2 = Dstop[piece];
1600*41194Sbostic if (sweep[piece])
1601*41194Sbostic for (j = j1; j <= j2; j++)
1602*41194Sbostic {
1603*41194Sbostic d = Dir[j]; m = m0+d;
1604*41194Sbostic while (!(m & 0x88))
1605*41194Sbostic {
1606*41194Sbostic u = unmap[m];
1607*41194Sbostic a[u] = ++a[u] | c;
1608*41194Sbostic if (color[u] == neutral) m += d;
1609*41194Sbostic else break;
1610*41194Sbostic }
1611*41194Sbostic }
1612*41194Sbostic else
1613*41194Sbostic for (j = j1; j <= j2; j++)
1614*41194Sbostic if (!((m = m0+Dir[j]) & 0x88))
1615*41194Sbostic {
1616*41194Sbostic u = unmap[m];
1617*41194Sbostic a[u] = ++a[u] | c;
1618*41194Sbostic }
1619*41194Sbostic }
1620*41194Sbostic }
1621*41194Sbostic #endif
1622*41194Sbostic
1623*41194Sbostic /* ............ POSITIONAL EVALUATION ROUTINES ............ */
1624*41194Sbostic
ScorePosition(side,score)1625*41194Sbostic ScorePosition(side,score)
1626*41194Sbostic short side,*score;
1627*41194Sbostic
1628*41194Sbostic /*
1629*41194Sbostic Perform normal static evaluation of board position. A score is
1630*41194Sbostic generated for each piece and these are summed to get a score for each
1631*41194Sbostic side.
1632*41194Sbostic */
1633*41194Sbostic
1634*41194Sbostic {
1635*41194Sbostic register short sq,s;
1636*41194Sbostic short i,xside,pscore[3];
1637*41194Sbostic
1638*41194Sbostic wking = PieceList[white][0]; bking = PieceList[black][0];
1639*41194Sbostic UpdateWeights();
1640*41194Sbostic xside = otherside[side];
1641*41194Sbostic pscore[white] = pscore[black] = 0;
1642*41194Sbostic
1643*41194Sbostic for (c1 = white; c1 <= black; c1++)
1644*41194Sbostic {
1645*41194Sbostic c2 = otherside[c1];
1646*41194Sbostic if (c1 == white) EnemyKing = bking; else EnemyKing = wking;
1647*41194Sbostic atk1 = atak[c1]; atk2 = atak[c2];
1648*41194Sbostic PC1 = PawnCnt[c1]; PC2 = PawnCnt[c2];
1649*41194Sbostic for (i = 0; i <= PieceCnt[c1]; i++)
1650*41194Sbostic {
1651*41194Sbostic sq = PieceList[c1][i];
1652*41194Sbostic s = SqValue(sq,side);
1653*41194Sbostic pscore[c1] += s;
1654*41194Sbostic svalue[sq] = s;
1655*41194Sbostic }
1656*41194Sbostic }
1657*41194Sbostic if (hung[side] > 1) pscore[side] += HUNGX;
1658*41194Sbostic if (hung[xside] > 1) pscore[xside] += HUNGX;
1659*41194Sbostic
1660*41194Sbostic *score = mtl[side] - mtl[xside] + pscore[side] - pscore[xside] + 10;
1661*41194Sbostic if (dither) *score += rand() % dither;
1662*41194Sbostic
1663*41194Sbostic if (*score > 0 && pmtl[side] == 0)
1664*41194Sbostic if (emtl[side] < valueR) *score = 0;
1665*41194Sbostic else if (*score < valueR) *score /= 2;
1666*41194Sbostic if (*score < 0 && pmtl[xside] == 0)
1667*41194Sbostic if (emtl[xside] < valueR) *score = 0;
1668*41194Sbostic else if (-*score < valueR) *score /= 2;
1669*41194Sbostic
1670*41194Sbostic if (mtl[xside] == valueK && emtl[side] > valueB) *score += 200;
1671*41194Sbostic if (mtl[side] == valueK && emtl[xside] > valueB) *score -= 200;
1672*41194Sbostic }
1673*41194Sbostic
1674*41194Sbostic
ScoreLoneKing(side,score)1675*41194Sbostic ScoreLoneKing(side,score)
1676*41194Sbostic short side,*score;
1677*41194Sbostic
1678*41194Sbostic /*
1679*41194Sbostic Static evaluation when loser has only a king and winner has no pawns
1680*41194Sbostic or no pieces.
1681*41194Sbostic */
1682*41194Sbostic
1683*41194Sbostic {
1684*41194Sbostic short winner,loser,king1,king2,s,i;
1685*41194Sbostic
1686*41194Sbostic UpdateWeights();
1687*41194Sbostic if (mtl[white] > mtl[black]) winner = white; else winner = black;
1688*41194Sbostic loser = otherside[winner];
1689*41194Sbostic king1 = PieceList[winner][0]; king2 = PieceList[loser][0];
1690*41194Sbostic
1691*41194Sbostic s = 0;
1692*41194Sbostic
1693*41194Sbostic if (pmtl[winner] > 0)
1694*41194Sbostic for (i = 1; i <= PieceCnt[winner]; i++)
1695*41194Sbostic s += ScoreKPK(side,winner,loser,king1,king2,PieceList[winner][i]);
1696*41194Sbostic
1697*41194Sbostic else if (emtl[winner] == valueB+valueN)
1698*41194Sbostic s = ScoreKBNK(winner,king1,king2);
1699*41194Sbostic
1700*41194Sbostic else if (emtl[winner] > valueB)
1701*41194Sbostic s = 500 + emtl[winner] - DyingKing[king2] - 2*distance(king1,king2);
1702*41194Sbostic
1703*41194Sbostic if (side == winner) *score = s; else *score = -s;
1704*41194Sbostic }
1705*41194Sbostic
1706*41194Sbostic
ScoreKPK(side,winner,loser,king1,king2,sq)1707*41194Sbostic int ScoreKPK(side,winner,loser,king1,king2,sq)
1708*41194Sbostic short side,winner,loser,king1,king2,sq;
1709*41194Sbostic
1710*41194Sbostic /*
1711*41194Sbostic Score King and Pawns versus King endings.
1712*41194Sbostic */
1713*41194Sbostic
1714*41194Sbostic {
1715*41194Sbostic short s,r;
1716*41194Sbostic
1717*41194Sbostic if (PieceCnt[winner] == 1) s = 50; else s = 120;
1718*41194Sbostic if (winner == white)
1719*41194Sbostic {
1720*41194Sbostic if (side == loser) r = row[sq]-1; else r = row[sq];
1721*41194Sbostic if (row[king2] >= r && distance(sq,king2) < 8-r) s += 10*row[sq];
1722*41194Sbostic else s = 500+50*row[sq];
1723*41194Sbostic if (row[sq] < 6) sq += 16; else sq += 8;
1724*41194Sbostic }
1725*41194Sbostic else
1726*41194Sbostic {
1727*41194Sbostic if (side == loser) r = row[sq]+1; else r = row[sq];
1728*41194Sbostic if (row[king2] <= r && distance(sq,king2) < r+1) s += 10*(7-row[sq]);
1729*41194Sbostic else s = 500+50*(7-row[sq]);
1730*41194Sbostic if (row[sq] > 1) sq -= 16; else sq -= 8;
1731*41194Sbostic }
1732*41194Sbostic s += 8*(taxicab(king2,sq) - taxicab(king1,sq));
1733*41194Sbostic return(s);
1734*41194Sbostic }
1735*41194Sbostic
1736*41194Sbostic
ScoreKBNK(winner,king1,king2)1737*41194Sbostic int ScoreKBNK(winner,king1,king2)
1738*41194Sbostic short winner,king1,king2;
1739*41194Sbostic
1740*41194Sbostic /*
1741*41194Sbostic Score King+Bishop+Knight versus King endings.
1742*41194Sbostic This doesn't work all that well but it's better than nothing.
1743*41194Sbostic */
1744*41194Sbostic
1745*41194Sbostic {
1746*41194Sbostic short s;
1747*41194Sbostic s = emtl[winner] - 300;
1748*41194Sbostic if (KBNKsq == 0) s += KBNK[king2];
1749*41194Sbostic else s += KBNK[locn[row[king2]][7-column[king2]]];
1750*41194Sbostic s -= taxicab(king1,king2);
1751*41194Sbostic s -= distance(PieceList[winner][1],king2);
1752*41194Sbostic s -= distance(PieceList[winner][2],king2);
1753*41194Sbostic return(s);
1754*41194Sbostic }
1755*41194Sbostic
1756*41194Sbostic
SqValue(sq,side)1757*41194Sbostic SqValue(sq,side)
1758*41194Sbostic short sq,side;
1759*41194Sbostic
1760*41194Sbostic /*
1761*41194Sbostic Calculate the positional value for the piece on 'sq'.
1762*41194Sbostic */
1763*41194Sbostic
1764*41194Sbostic {
1765*41194Sbostic register short j,fyle,rank;
1766*41194Sbostic short s,piece,a1,a2,in_square,r,mob,e,c;
1767*41194Sbostic
1768*41194Sbostic piece = board[sq];
1769*41194Sbostic a1 = (atk1[sq] & 0x4FFF); a2 = (atk2[sq] & 0x4FFF);
1770*41194Sbostic rank = row[sq]; fyle = column[sq];
1771*41194Sbostic s = 0;
1772*41194Sbostic if (piece == pawn && c1 == white)
1773*41194Sbostic {
1774*41194Sbostic s = Mwpawn[sq];
1775*41194Sbostic if (sq == 11 || sq == 12)
1776*41194Sbostic if (color[sq+8] != neutral) s += PEDRNK2B;
1777*41194Sbostic if ((fyle == 0 || PC1[fyle-1] == 0) &&
1778*41194Sbostic (fyle == 7 || PC1[fyle+1] == 0))
1779*41194Sbostic s += ISOLANI[fyle];
1780*41194Sbostic else if (PC1[fyle] > 1) s += PDOUBLED;
1781*41194Sbostic if (a1 < ctlP && atk1[sq+8] < ctlP)
1782*41194Sbostic {
1783*41194Sbostic s += BACKWARD[a2 & 0xFF];
1784*41194Sbostic if (PC2[fyle] == 0) s += PWEAKH;
1785*41194Sbostic if (color[sq+8] != neutral) s += PBLOK;
1786*41194Sbostic }
1787*41194Sbostic if (PC2[fyle] == 0)
1788*41194Sbostic {
1789*41194Sbostic if (side == black) r = rank-1; else r = rank;
1790*41194Sbostic in_square = (row[bking] >= r && distance(sq,bking) < 8-r);
1791*41194Sbostic if (a2 == 0 || side == white) e = 0; else e = 1;
1792*41194Sbostic for (j = sq+8; j < 64; j += 8)
1793*41194Sbostic if (atk2[j] >= ctlP) { e = 2; break; }
1794*41194Sbostic else if (atk2[j] > 0 || color[j] != neutral) e = 1;
1795*41194Sbostic if (e == 2) s += (stage*PassedPawn3[rank]) / 10;
1796*41194Sbostic else if (in_square || e == 1) s += (stage*PassedPawn2[rank]) / 10;
1797*41194Sbostic else if (emtl[black] > 0) s += (stage*PassedPawn1[rank]) / 10;
1798*41194Sbostic else s += PassedPawn0[rank];
1799*41194Sbostic }
1800*41194Sbostic }
1801*41194Sbostic else if (piece == pawn && c1 == black)
1802*41194Sbostic {
1803*41194Sbostic s = Mbpawn[sq];
1804*41194Sbostic if (sq == 51 || sq == 52)
1805*41194Sbostic if (color[sq-8] != neutral) s += PEDRNK2B;
1806*41194Sbostic if ((fyle == 0 || PC1[fyle-1] == 0) &&
1807*41194Sbostic (fyle == 7 || PC1[fyle+1] == 0))
1808*41194Sbostic s += ISOLANI[fyle];
1809*41194Sbostic else if (PC1[fyle] > 1) s += PDOUBLED;
1810*41194Sbostic if (a1 < ctlP && atk1[sq-8] < ctlP)
1811*41194Sbostic {
1812*41194Sbostic s += BACKWARD[a2 & 0xFF];
1813*41194Sbostic if (PC2[fyle] == 0) s += PWEAKH;
1814*41194Sbostic if (color[sq-8] != neutral) s += PBLOK;
1815*41194Sbostic }
1816*41194Sbostic if (PC2[fyle] == 0)
1817*41194Sbostic {
1818*41194Sbostic if (side == white) r = rank+1; else r = rank;
1819*41194Sbostic in_square = (row[wking] <= r && distance(sq,wking) < r+1);
1820*41194Sbostic if (a2 == 0 || side == black) e = 0; else e = 1;
1821*41194Sbostic for (j = sq-8; j >= 0; j -= 8)
1822*41194Sbostic if (atk2[j] >= ctlP) { e = 2; break; }
1823*41194Sbostic else if (atk2[j] > 0 || color[j] != neutral) e = 1;
1824*41194Sbostic if (e == 2) s += (stage*PassedPawn3[7-rank]) / 10;
1825*41194Sbostic else if (in_square || e == 1) s += (stage*PassedPawn2[7-rank]) / 10;
1826*41194Sbostic else if (emtl[white] > 0) s += (stage*PassedPawn1[7-rank]) / 10;
1827*41194Sbostic else s += PassedPawn0[7-rank];
1828*41194Sbostic }
1829*41194Sbostic }
1830*41194Sbostic else if (piece == knight)
1831*41194Sbostic {
1832*41194Sbostic s = Mknight[c1][sq];
1833*41194Sbostic }
1834*41194Sbostic else if (piece == bishop)
1835*41194Sbostic {
1836*41194Sbostic s = Mbishop[c1][sq];
1837*41194Sbostic BRscan(sq,&s,&mob);
1838*41194Sbostic s += BMBLTY[mob];
1839*41194Sbostic }
1840*41194Sbostic else if (piece == rook)
1841*41194Sbostic {
1842*41194Sbostic s += RookBonus;
1843*41194Sbostic BRscan(sq,&s,&mob);
1844*41194Sbostic s += RMBLTY[mob];
1845*41194Sbostic if (PC1[fyle] == 0) s += RHOPN;
1846*41194Sbostic if (PC2[fyle] == 0) s += RHOPNX;
1847*41194Sbostic if (rank == rank7[c1] && pmtl[c2] > 100) s += 10;
1848*41194Sbostic if (stage > 2) s += 14 - taxicab(sq,EnemyKing);
1849*41194Sbostic }
1850*41194Sbostic else if (piece == queen)
1851*41194Sbostic {
1852*41194Sbostic if (stage > 2) s += 14 - taxicab(sq,EnemyKing);
1853*41194Sbostic if (distance(sq,EnemyKing) < 3) s += 12;
1854*41194Sbostic }
1855*41194Sbostic else if (piece == king)
1856*41194Sbostic {
1857*41194Sbostic s = Mking[c1][sq];
1858*41194Sbostic if (KSFTY > 0)
1859*41194Sbostic if (Developed[c2] || stage > 0) KingScan(sq,&s);
1860*41194Sbostic if (castld[c1]) s += KCASTLD;
1861*41194Sbostic else if (kingmoved[c1]) s += KMOVD;
1862*41194Sbostic
1863*41194Sbostic if (PC1[fyle] == 0) s += KHOPN;
1864*41194Sbostic if (PC2[fyle] == 0) s += KHOPNX;
1865*41194Sbostic if (fyle == 1 || fyle == 2 || fyle == 3 || fyle == 7)
1866*41194Sbostic {
1867*41194Sbostic if (PC1[fyle-1] == 0) s += KHOPN;
1868*41194Sbostic if (PC2[fyle-1] == 0) s += KHOPNX;
1869*41194Sbostic }
1870*41194Sbostic if (fyle == 4 || fyle == 5 || fyle == 6 || fyle == 0)
1871*41194Sbostic {
1872*41194Sbostic if (PC1[fyle+1] == 0) s += KHOPN;
1873*41194Sbostic if (PC2[fyle+1] == 0) s += KHOPNX;
1874*41194Sbostic }
1875*41194Sbostic if (fyle == 2)
1876*41194Sbostic {
1877*41194Sbostic if (PC1[0] == 0) s += KHOPN;
1878*41194Sbostic if (PC2[0] == 0) s += KHOPNX;
1879*41194Sbostic }
1880*41194Sbostic if (fyle == 5)
1881*41194Sbostic {
1882*41194Sbostic if (PC1[7] == 0) s += KHOPN;
1883*41194Sbostic if (PC2[7] == 0) s += KHOPNX;
1884*41194Sbostic }
1885*41194Sbostic }
1886*41194Sbostic
1887*41194Sbostic if (a2 > 0)
1888*41194Sbostic {
1889*41194Sbostic c = (control[piece] & 0x4FFF);
1890*41194Sbostic if (a1 == 0 || a2 > c+1)
1891*41194Sbostic {
1892*41194Sbostic s += HUNGP;
1893*41194Sbostic ++hung[c1];
1894*41194Sbostic if (piece != king && trapped(sq,piece)) ++hung[c1];
1895*41194Sbostic }
1896*41194Sbostic else if (piece != pawn || a2 > a1)
1897*41194Sbostic if (a2 >= c || a1 < ctlP) s += ATAKD;
1898*41194Sbostic }
1899*41194Sbostic return(s);
1900*41194Sbostic }
1901*41194Sbostic
1902*41194Sbostic #if (NEWMOVE > 6)
KingScan(sq,s)1903*41194Sbostic KingScan(sq,s)
1904*41194Sbostic short sq,*s;
1905*41194Sbostic
1906*41194Sbostic /*
1907*41194Sbostic Assign penalties if king can be threatened by checks, if squares
1908*41194Sbostic near the king are controlled by the enemy (especially the queen),
1909*41194Sbostic or if there are no pawns near the king.
1910*41194Sbostic */
1911*41194Sbostic
1912*41194Sbostic #define ScoreThreat\
1913*41194Sbostic if (color[u] != c2)\
1914*41194Sbostic if (atk1[u] == 0 || (atk2[u] & 0xFF) > 1) ++cnt;\
1915*41194Sbostic else *s -= 3
1916*41194Sbostic
1917*41194Sbostic {
1918*41194Sbostic register short m,u;
1919*41194Sbostic short d,i,m0,cnt,ok;
1920*41194Sbostic
1921*41194Sbostic cnt = 0;
1922*41194Sbostic m0 = map[sq];
1923*41194Sbostic if (HasBishop[c2] || HasQueen[c2])
1924*41194Sbostic for (i = Dstart[bishop]; i <= Dstop[bishop]; i++)
1925*41194Sbostic {
1926*41194Sbostic d = Dir[i]; m = m0+d;
1927*41194Sbostic while (!(m & 0x88))
1928*41194Sbostic {
1929*41194Sbostic u = unmap[m];
1930*41194Sbostic if (atk2[u] & ctlBQ) ScoreThreat;
1931*41194Sbostic if (color[u] != neutral) break;
1932*41194Sbostic m += d;
1933*41194Sbostic }
1934*41194Sbostic }
1935*41194Sbostic if (HasRook[c2] || HasQueen[c2])
1936*41194Sbostic for (i = Dstart[rook]; i <= Dstop[rook]; i++)
1937*41194Sbostic {
1938*41194Sbostic d = Dir[i]; m = m0+d;
1939*41194Sbostic while (!(m & 0x88))
1940*41194Sbostic {
1941*41194Sbostic u = unmap[m];
1942*41194Sbostic if (atk2[u] & ctlRQ) ScoreThreat;
1943*41194Sbostic if (color[u] != neutral) break;
1944*41194Sbostic m += d;
1945*41194Sbostic }
1946*41194Sbostic }
1947*41194Sbostic if (HasKnight[c2])
1948*41194Sbostic for (i = Dstart[knight]; i <= Dstop[knight]; i++)
1949*41194Sbostic if (!((m = m0+Dir[i]) & 0x88))
1950*41194Sbostic {
1951*41194Sbostic u = unmap[m];
1952*41194Sbostic if (atk2[u] & ctlNN) ScoreThreat;
1953*41194Sbostic }
1954*41194Sbostic *s += (KSFTY*Kthreat[cnt]) / 16;
1955*41194Sbostic
1956*41194Sbostic cnt = 0; ok = false;
1957*41194Sbostic m0 = map[sq];
1958*41194Sbostic for (i = Dstart[king]; i <= Dstop[king]; i++)
1959*41194Sbostic if (!((m = m0+Dir[i]) & 0x88))
1960*41194Sbostic {
1961*41194Sbostic u = unmap[m];
1962*41194Sbostic if (board[u] == pawn) ok = true;
1963*41194Sbostic if (atk2[u] > atk1[u])
1964*41194Sbostic {
1965*41194Sbostic ++cnt;
1966*41194Sbostic if (atk2[u] & ctlQ)
1967*41194Sbostic if (atk2[u] > ctlQ+1 && atk1[u] < ctlQ) *s -= 4*KSFTY;
1968*41194Sbostic }
1969*41194Sbostic }
1970*41194Sbostic if (!ok) *s -= KSFTY;
1971*41194Sbostic if (cnt > 1) *s -= KSFTY;
1972*41194Sbostic }
1973*41194Sbostic #endif
1974*41194Sbostic
1975*41194Sbostic #if (NEWMOVE < 4)
BRscan(sq,s,mob)1976*41194Sbostic BRscan(sq,s,mob)
1977*41194Sbostic short sq,*s,*mob;
1978*41194Sbostic
1979*41194Sbostic /*
1980*41194Sbostic Find Bishop and Rook mobility, XRAY attacks, and pins. Increment the
1981*41194Sbostic hung[] array if a pin is found.
1982*41194Sbostic */
1983*41194Sbostic
1984*41194Sbostic {
1985*41194Sbostic register short m,u;
1986*41194Sbostic short d,j,m0,piece,pin,*Kf;
1987*41194Sbostic
1988*41194Sbostic Kf = Kfield[c1];
1989*41194Sbostic *mob = 0;
1990*41194Sbostic m0 = map[sq]; piece = board[sq];
1991*41194Sbostic for (j = Dstart[piece]; j <= Dstop[piece]; j++)
1992*41194Sbostic {
1993*41194Sbostic pin = -1;
1994*41194Sbostic d = Dir[j]; m = m0+d;
1995*41194Sbostic while (!(m & 0x88))
1996*41194Sbostic {
1997*41194Sbostic u = unmap[m]; *s += Kf[u];
1998*41194Sbostic if (color[u] == neutral)
1999*41194Sbostic {
2000*41194Sbostic (*mob)++;
2001*41194Sbostic m += d;
2002*41194Sbostic }
2003*41194Sbostic else if (pin < 0)
2004*41194Sbostic {
2005*41194Sbostic if (board[u] == pawn || board[u] == king) break;
2006*41194Sbostic pin = u;
2007*41194Sbostic m += d;
2008*41194Sbostic }
2009*41194Sbostic else if (color[u] == c2 && (board[u] > piece || atk2[u] == 0))
2010*41194Sbostic {
2011*41194Sbostic if (color[pin] == c2)
2012*41194Sbostic {
2013*41194Sbostic *s += PINVAL;
2014*41194Sbostic if (atk2[pin] == 0 ||
2015*41194Sbostic atk1[pin] > control[board[pin]]+1)
2016*41194Sbostic ++hung[c2];
2017*41194Sbostic }
2018*41194Sbostic else *s += XRAY;
2019*41194Sbostic break;
2020*41194Sbostic }
2021*41194Sbostic else break;
2022*41194Sbostic }
2023*41194Sbostic }
2024*41194Sbostic }
2025*41194Sbostic #endif
2026*41194Sbostic
2027*41194Sbostic #if (NEWMOVE > 5)
trapped(sq,piece)2028*41194Sbostic int trapped(sq,piece)
2029*41194Sbostic short sq,piece;
2030*41194Sbostic
2031*41194Sbostic /*
2032*41194Sbostic See if the attacked piece has unattacked squares to move to.
2033*41194Sbostic */
2034*41194Sbostic
2035*41194Sbostic {
2036*41194Sbostic register short u,m,d;
2037*41194Sbostic short i,m0;
2038*41194Sbostic
2039*41194Sbostic m0 = map[sq];
2040*41194Sbostic if (sweep[piece])
2041*41194Sbostic for (i = Dstart[piece]; i <= Dstop[piece]; i++)
2042*41194Sbostic {
2043*41194Sbostic d = Dir[i]; m = m0+d;
2044*41194Sbostic while (!(m & 0x88))
2045*41194Sbostic {
2046*41194Sbostic u = unmap[m];
2047*41194Sbostic if (color[u] == c1) break;
2048*41194Sbostic if (atk2[u] == 0 || board[u] >= piece) return(false);
2049*41194Sbostic if (color[u] == c2) break;
2050*41194Sbostic m += d;
2051*41194Sbostic }
2052*41194Sbostic }
2053*41194Sbostic else if (piece == pawn)
2054*41194Sbostic {
2055*41194Sbostic if (c1 == white) u = sq+8; else u = sq-8;
2056*41194Sbostic if (color[u] == neutral && atk1[u] >= atk2[u])
2057*41194Sbostic return(false);
2058*41194Sbostic if (!((m = m0+Dir[Dpwn[c1]]) & 0x88))
2059*41194Sbostic if (color[unmap[m]] == c2) return(false);
2060*41194Sbostic if (!((m = m0+Dir[Dpwn[c1]+1]) & 0x88))
2061*41194Sbostic if (color[unmap[m]] == c2) return(false);
2062*41194Sbostic }
2063*41194Sbostic else
2064*41194Sbostic {
2065*41194Sbostic for (i = Dstart[piece]; i <= Dstop[piece]; i++)
2066*41194Sbostic if (!((m = m0+Dir[i]) & 0x88))
2067*41194Sbostic {
2068*41194Sbostic u = unmap[m];
2069*41194Sbostic if (color[u] != c1)
2070*41194Sbostic if (atk2[u] == 0 || board[u] >= piece) return(false);
2071*41194Sbostic }
2072*41194Sbostic }
2073*41194Sbostic return(true);
2074*41194Sbostic }
2075*41194Sbostic #endif
2076*41194Sbostic
ExaminePosition()2077*41194Sbostic ExaminePosition()
2078*41194Sbostic
2079*41194Sbostic /*
2080*41194Sbostic This is done one time before the search is started. Set up arrays
2081*41194Sbostic Mwpawn, Mbpawn, Mknight, Mbishop, Mking which are used in the
2082*41194Sbostic SqValue() function to determine the positional value of each piece.
2083*41194Sbostic */
2084*41194Sbostic
2085*41194Sbostic {
2086*41194Sbostic register short i,sq;
2087*41194Sbostic short wpadv,bpadv,wstrong,bstrong,z,side,pp,j,val,Pd,fyle,rank;
2088*41194Sbostic
2089*41194Sbostic wking = PieceList[white][0]; bking = PieceList[black][0];
2090*41194Sbostic ataks(white,atak[white]); ataks(black,atak[black]);
2091*41194Sbostic Zwmtl = Zbmtl = 0;
2092*41194Sbostic UpdateWeights();
2093*41194Sbostic HasPawn[white] = HasPawn[black] = 0;
2094*41194Sbostic HasKnight[white] = HasKnight[black] = 0;
2095*41194Sbostic HasBishop[white] = HasBishop[black] = 0;
2096*41194Sbostic HasRook[white] = HasRook[black] = 0;
2097*41194Sbostic HasQueen[white] = HasQueen[black] = 0;
2098*41194Sbostic for (side = white; side <= black; side++)
2099*41194Sbostic for (i = 0; i <= PieceCnt[side]; i++)
2100*41194Sbostic switch (board[PieceList[side][i]])
2101*41194Sbostic {
2102*41194Sbostic case pawn : ++HasPawn[side]; break;
2103*41194Sbostic case knight : ++HasKnight[side]; break;
2104*41194Sbostic case bishop : ++HasBishop[side]; break;
2105*41194Sbostic case rook : ++HasRook[side]; break;
2106*41194Sbostic case queen : ++HasQueen[side]; break;
2107*41194Sbostic }
2108*41194Sbostic if (!Developed[white])
2109*41194Sbostic Developed[white] = (board[1] != knight && board[2] != bishop &&
2110*41194Sbostic board[5] != bishop && board[6] != knight);
2111*41194Sbostic if (!Developed[black])
2112*41194Sbostic Developed[black] = (board[57] != knight && board[58] != bishop &&
2113*41194Sbostic board[61] != bishop && board[62] != knight);
2114*41194Sbostic if (!PawnStorm && stage < 5)
2115*41194Sbostic PawnStorm = ((column[wking] < 3 && column[bking] > 4) ||
2116*41194Sbostic (column[wking] > 4 && column[bking] < 3));
2117*41194Sbostic
2118*41194Sbostic CopyBoard(pknight,Mknight[white]);
2119*41194Sbostic CopyBoard(pknight,Mknight[black]);
2120*41194Sbostic CopyBoard(pbishop,Mbishop[white]);
2121*41194Sbostic CopyBoard(pbishop,Mbishop[black]);
2122*41194Sbostic BlendBoard(KingOpening,KingEnding,Mking[white]);
2123*41194Sbostic BlendBoard(KingOpening,KingEnding,Mking[black]);
2124*41194Sbostic
2125*41194Sbostic for (sq = 0; sq < 64; sq++)
2126*41194Sbostic {
2127*41194Sbostic fyle = column[sq]; rank = row[sq];
2128*41194Sbostic wstrong = bstrong = true;
2129*41194Sbostic for (i = sq; i < 64; i += 8)
2130*41194Sbostic if (atak[black][i] >= ctlP) wstrong = false;
2131*41194Sbostic for (i = sq; i >= 0; i -= 8)
2132*41194Sbostic if (atak[white][i] >= ctlP) bstrong = false;
2133*41194Sbostic wpadv = bpadv = PADVNCM;
2134*41194Sbostic if ((fyle == 0 || PawnCnt[white][fyle-1] == 0) &&
2135*41194Sbostic (fyle == 7 || PawnCnt[white][fyle+1] == 0)) wpadv = PADVNCI;
2136*41194Sbostic if ((fyle == 0 || PawnCnt[black][fyle-1] == 0) &&
2137*41194Sbostic (fyle == 7 || PawnCnt[black][fyle+1] == 0)) bpadv = PADVNCI;
2138*41194Sbostic Mwpawn[sq] = (wpadv*PawnAdvance[sq]) / 10;
2139*41194Sbostic Mbpawn[sq] = (bpadv*PawnAdvance[63-sq]) / 10;
2140*41194Sbostic Mwpawn[sq] += PawnBonus; Mbpawn[sq] += PawnBonus;
2141*41194Sbostic if (castld[white] || kingmoved[white])
2142*41194Sbostic {
2143*41194Sbostic if ((fyle < 3 || fyle > 4) && distance(sq,wking) < 3)
2144*41194Sbostic Mwpawn[sq] += PAWNSHIELD;
2145*41194Sbostic }
2146*41194Sbostic else if (rank < 3 && (fyle < 2 || fyle > 5))
2147*41194Sbostic Mwpawn[sq] += PAWNSHIELD / 2;
2148*41194Sbostic if (castld[black] || kingmoved[black])
2149*41194Sbostic {
2150*41194Sbostic if ((fyle < 3 || fyle > 4) && distance(sq,bking) < 3)
2151*41194Sbostic Mbpawn[sq] += PAWNSHIELD;
2152*41194Sbostic }
2153*41194Sbostic else if (rank > 4 && (fyle < 2 || fyle > 5))
2154*41194Sbostic Mbpawn[sq] += PAWNSHIELD / 2;
2155*41194Sbostic if (PawnStorm)
2156*41194Sbostic {
2157*41194Sbostic if ((column[wking] < 4 && fyle > 4) ||
2158*41194Sbostic (column[wking] > 3 && fyle < 3)) Mwpawn[sq] += 3*rank - 21;
2159*41194Sbostic if ((column[bking] < 4 && fyle > 4) ||
2160*41194Sbostic (column[bking] > 3 && fyle < 3)) Mbpawn[sq] -= 3*rank;
2161*41194Sbostic }
2162*41194Sbostic
2163*41194Sbostic Mknight[white][sq] += 5 - distance(sq,bking);
2164*41194Sbostic Mknight[white][sq] += 5 - distance(sq,wking);
2165*41194Sbostic Mknight[black][sq] += 5 - distance(sq,wking);
2166*41194Sbostic Mknight[black][sq] += 5 - distance(sq,bking);
2167*41194Sbostic Mbishop[white][sq] += BishopBonus;
2168*41194Sbostic Mbishop[black][sq] += BishopBonus;
2169*41194Sbostic for (i = 0; i <= PieceCnt[black]; i++)
2170*41194Sbostic if (distance(sq,PieceList[black][i]) < 3)
2171*41194Sbostic Mknight[white][sq] += KNIGHTPOST;
2172*41194Sbostic for (i = 0; i <= PieceCnt[white]; i++)
2173*41194Sbostic if (distance(sq,PieceList[white][i]) < 3)
2174*41194Sbostic Mknight[black][sq] += KNIGHTPOST;
2175*41194Sbostic if (wstrong) Mknight[white][sq] += KNIGHTSTRONG;
2176*41194Sbostic if (bstrong) Mknight[black][sq] += KNIGHTSTRONG;
2177*41194Sbostic if (wstrong) Mbishop[white][sq] += BISHOPSTRONG;
2178*41194Sbostic if (bstrong) Mbishop[black][sq] += BISHOPSTRONG;
2179*41194Sbostic
2180*41194Sbostic if (HasBishop[white] == 2) Mbishop[white][sq] += 8;
2181*41194Sbostic if (HasBishop[black] == 2) Mbishop[black][sq] += 8;
2182*41194Sbostic if (HasKnight[white] == 2) Mknight[white][sq] += 5;
2183*41194Sbostic if (HasKnight[black] == 2) Mknight[black][sq] += 5;
2184*41194Sbostic
2185*41194Sbostic if (board[sq] == bishop)
2186*41194Sbostic if (rank % 2 == fyle % 2) KBNKsq = 0; else KBNKsq = 7;
2187*41194Sbostic
2188*41194Sbostic Kfield[white][sq] = Kfield[black][sq] = 0;
2189*41194Sbostic if (distance(sq,wking) == 1) Kfield[black][sq] = KATAK;
2190*41194Sbostic if (distance(sq,bking) == 1) Kfield[white][sq] = KATAK;
2191*41194Sbostic
2192*41194Sbostic Pd = 0;
2193*41194Sbostic for (i = 0; i < 64; i++)
2194*41194Sbostic if (board[i] == pawn)
2195*41194Sbostic {
2196*41194Sbostic if (color[i] == white)
2197*41194Sbostic {
2198*41194Sbostic pp = true;
2199*41194Sbostic if (row[i] == 6) z = i+8; else z = i+16;
2200*41194Sbostic for (j = i+8; j < 64; j += 8)
2201*41194Sbostic if (atak[black][j] > ctlP || board[j] == pawn) pp = false;
2202*41194Sbostic }
2203*41194Sbostic else
2204*41194Sbostic {
2205*41194Sbostic pp = true;
2206*41194Sbostic if (row[i] == 1) z = i-8; else z = i-16;
2207*41194Sbostic for (j = i-8; j >= 0; j -= 8)
2208*41194Sbostic if (atak[white][j] > ctlP || board[j] == pawn) pp = false;
2209*41194Sbostic }
2210*41194Sbostic if (pp) Pd += 5*taxicab(sq,z); else Pd += taxicab(sq,z);
2211*41194Sbostic }
2212*41194Sbostic if (Pd != 0)
2213*41194Sbostic {
2214*41194Sbostic val = (Pd*stage2) / 10;
2215*41194Sbostic Mking[white][sq] -= val;
2216*41194Sbostic Mking[black][sq] -= val;
2217*41194Sbostic }
2218*41194Sbostic }
2219*41194Sbostic }
2220*41194Sbostic
2221*41194Sbostic
UpdateWeights()2222*41194Sbostic UpdateWeights()
2223*41194Sbostic
2224*41194Sbostic /*
2225*41194Sbostic If material balance has changed, determine the values for the
2226*41194Sbostic positional evaluation terms.
2227*41194Sbostic */
2228*41194Sbostic
2229*41194Sbostic {
2230*41194Sbostic short tmtl;
2231*41194Sbostic
2232*41194Sbostic if (mtl[white] != Zwmtl || mtl[black] != Zbmtl)
2233*41194Sbostic {
2234*41194Sbostic Zwmtl = mtl[white]; Zbmtl = mtl[black];
2235*41194Sbostic emtl[white] = Zwmtl - pmtl[white] - valueK;
2236*41194Sbostic emtl[black] = Zbmtl - pmtl[black] - valueK;
2237*41194Sbostic tmtl = emtl[white] + emtl[black];
2238*41194Sbostic if (tmtl > 6600) stage = 0;
2239*41194Sbostic else if (tmtl < 1400) stage = 10;
2240*41194Sbostic else stage = (6600-tmtl) / 520;
2241*41194Sbostic if (tmtl > 3600) stage2 = 0;
2242*41194Sbostic else if (tmtl < 1400) stage2 = 10;
2243*41194Sbostic else stage2 = (3600-tmtl) / 220;
2244*41194Sbostic
2245*41194Sbostic PEDRNK2B = -15; /* centre pawn on 2nd rank & blocked */
2246*41194Sbostic PBLOK = -4; /* blocked backward pawn */
2247*41194Sbostic PDOUBLED = -14; /* doubled pawn */
2248*41194Sbostic PWEAKH = -4; /* weak pawn on half open file */
2249*41194Sbostic PAWNSHIELD = 10-stage; /* pawn near friendly king */
2250*41194Sbostic PADVNCM = 10; /* advanced pawn multiplier */
2251*41194Sbostic PADVNCI = 7; /* muliplier for isolated pawn */
2252*41194Sbostic PawnBonus = stage;
2253*41194Sbostic
2254*41194Sbostic KNIGHTPOST = (stage+2)/3; /* knight near enemy pieces */
2255*41194Sbostic KNIGHTSTRONG = (stage+6)/2; /* occupies pawn hole */
2256*41194Sbostic
2257*41194Sbostic BISHOPSTRONG = (stage+6)/2; /* occupies pawn hole */
2258*41194Sbostic BishopBonus = 2*stage;
2259*41194Sbostic
2260*41194Sbostic RHOPN = 10; /* rook on half open file */
2261*41194Sbostic RHOPNX = 4;
2262*41194Sbostic RookBonus = 6*stage;
2263*41194Sbostic
2264*41194Sbostic XRAY = 8; /* Xray attack on piece */
2265*41194Sbostic PINVAL = 10; /* Pin */
2266*41194Sbostic
2267*41194Sbostic KHOPN = (3*stage-30) / 2; /* king on half open file */
2268*41194Sbostic KHOPNX = KHOPN / 2;
2269*41194Sbostic KCASTLD = 10 - stage;
2270*41194Sbostic KMOVD = -40 / (stage+1); /* king moved before castling */
2271*41194Sbostic KATAK = (10-stage) / 2; /* B,R attacks near enemy king */
2272*41194Sbostic if (stage < 8) KSFTY = 16-2*stage; else KSFTY = 0;
2273*41194Sbostic
2274*41194Sbostic ATAKD = -6; /* defender > attacker */
2275*41194Sbostic HUNGP = -8; /* each hung piece */
2276*41194Sbostic HUNGX = -12; /* extra for >1 hung piece */
2277*41194Sbostic }
2278*41194Sbostic }
2279*41194Sbostic
2280*41194Sbostic #if (NEWMOVE < 1)
distance(a,b)2281*41194Sbostic int distance(a,b)
2282*41194Sbostic short a,b;
2283*41194Sbostic {
2284*41194Sbostic register short d1,d2;
2285*41194Sbostic
2286*41194Sbostic d1 = abs(column[a]-column[b]);
2287*41194Sbostic d2 = abs(row[a]-row[b]);
2288*41194Sbostic return(d1 > d2 ? d1 : d2);
2289*41194Sbostic }
2290*41194Sbostic #endif
2291*41194Sbostic
BlendBoard(a,b,c)2292*41194Sbostic BlendBoard(a,b,c)
2293*41194Sbostic short a[64],b[64],c[64];
2294*41194Sbostic {
2295*41194Sbostic register int sq;
2296*41194Sbostic for (sq = 0; sq < 64; sq++)
2297*41194Sbostic c[sq] = (a[sq]*(10-stage) + b[sq]*stage) / 10;
2298*41194Sbostic }
2299*41194Sbostic
2300*41194Sbostic
CopyBoard(a,b)2301*41194Sbostic CopyBoard(a,b)
2302*41194Sbostic short a[64],b[64];
2303*41194Sbostic {
2304*41194Sbostic register int sq;
2305*41194Sbostic for (sq = 0; sq < 64; sq++)
2306*41194Sbostic b[sq] = a[sq];
2307*41194Sbostic }
2308