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