Fix crash after recursive aliasing
[capablanca.git] / lasker-2.2.3 / src / eco.c
1 /*
2    Copyright (c) 1993 Richard V. Nash.
3    Copyright (c) 2000 Dan Papasian
4    Copyright (C) Andrew Tridgell 2002
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21
22 #include "includes.h"
23
24 typedef struct {
25   char ECO[4];
26   char FENpos[74];
27 } ECO_entry;
28
29 typedef struct {
30   char NIC[6];
31   char FENpos[74];
32 } NIC_entry;
33
34 typedef struct {
35   char LONG[80];
36   char FENpos[74];
37 } LONG_entry;
38
39 static ECO_entry *ECO_book[1096];
40 static NIC_entry *NIC_book[1096];
41 static LONG_entry *LONG_book[4096];
42
43 static int ECO_entries, NIC_entries, LONG_entries;
44
45 /* This coverts a FEN position to a FICS board
46    it assumes FENpos contains a valid position 
47    the color tag has been separated and put in color*/
48
49 void FEN_to_board(char* FENpos, struct game_state_t* gs)
50 {
51   int f,r;
52   char next;
53 printf("FEN='%s', var='%s'\n", FENpos, gs->variant);
54   for (r=gs->ranks-1; r >=0; r--) {
55     f=0;
56     while (f<gs->files) {
57       next = *(FENpos++);
58       if (isalpha(next))
59         gs->board[f++][r] = CharToPiece(next, gs->variant);
60       else if (next != '/') {
61         int t = (next - '0');
62           if(*FENpos >= '0' && *FENpos <= '9') // [HGM] can be double-digit
63               t = 10*t + *(FENpos++) - '0';
64         do
65           gs->board[f++][r] = NOPIECE;
66         while (--t && f < gs->files);
67       }
68     }
69   }
70   if (*(FENpos + 1) == 'w') /* the char after the space */
71     gs->onMove = WHITE;
72   else
73     gs->onMove = BLACK;
74 }
75
76 /* converts a board to a FEN pos */
77
78 static void board_to_FEN(char* FENpos, struct game_state_t* gs)
79 {
80   int f,r,count;
81   char piece;  
82
83   for (r=gs->ranks-1; r>=0; r--) {
84     count = 0;
85     for (f=0;  f<gs->files; f++) {
86       if ((piece = PieceToChar(gs->board[f][r])) != ' ') {
87         if (count) { 
88             if(count > 9) { count -= 10; *(FENpos++) = '1'; }
89           *(FENpos++) = count + '0';
90           count = 0;
91         }
92         *(FENpos++) = piece;
93       } else {
94         if (f == gs->files-1) {
95             if(count > 8) { count -= 10; *(FENpos++) = '1'; }
96           *(FENpos++) = count + '0' + 1;
97         } else
98           count++;
99       }
100     }
101     *(FENpos++) = '/';
102   }
103
104   *(--FENpos) = ' ';
105
106   if (gs->onMove == WHITE)
107     *(++FENpos) = 'w';
108   else
109     *(++FENpos) = 'b';
110   *(++FENpos) = '\0';
111 }
112
113 char *boardToFEN(int g)
114 {
115   static char FENstring[74];
116
117   board_to_FEN (FENstring,&game_globals.garray[g].game_state);
118   return FENstring;
119 }
120
121 static void ECO_init()
122 {
123   FILE *fp;
124   char tmp[1024];
125   char *ptmp= tmp;
126   char FENpos[73], ECO[4], onMove[2];
127   int i=0;
128
129   fp= fopen_s(BOOK_DIR "/eco999.idx", "r");
130   if (!fp) {
131     d_printf( "Could not open ECO file\n");
132     exit(1);
133   }
134   while (!feof(fp)) {
135     strcpy(ptmp, "");
136     fgets(ptmp, 1024, fp);
137     if (feof(fp)) continue;
138     sscanf(ptmp, "%[\x21-z] %s", FENpos, onMove);
139     sprintf(FENpos, "%s %s", FENpos, onMove);
140     strcpy(ptmp, "");
141     fgets(ptmp, 1024, fp);
142     if (feof(fp)) continue;
143     sscanf(ptmp, "%[0-z]", ECO);
144     ECO_book[i]= (ECO_entry *) malloc(sizeof(ECO_entry));
145     if (ECO_book[i]==NULL) {
146       d_printf( "Cound not alloc mem for ECO entry %d.\n", i);
147       exit(1);
148     }
149     strcpy(ECO_book[i]->ECO, ECO);
150     strcpy(ECO_book[i]->FENpos, FENpos);
151     ++i;
152   }
153   fclose(fp);
154   ECO_book[i]=NULL;
155   ECO_entries = i;
156   
157   while (--i >= 0)
158     if (ECO_book[i] == NULL)
159       d_printf( "ERROR!  ECO book position number %d is NULL.", i);
160 }
161
162 static void NIC_init()
163 {
164   FILE *fp;
165   char tmp[1024];
166   char *ptmp= tmp;
167   char FENpos[73], NIC[6], onMove[2];  
168   int i=0;
169
170   fp= fopen_p("%s/nic999.idx", "r", BOOK_DIR);
171   if (!fp) {
172     d_printf( "Could not open NIC file\n");
173     exit(1);
174   }
175   while (!feof(fp)) {
176     strcpy(ptmp, "");
177     fgets(ptmp, 1024, fp);
178     if (feof(fp)) continue;
179     sscanf(ptmp, "%[\x21-z] %s", FENpos, onMove);
180     sprintf(FENpos, "%s %s", FENpos, onMove);
181     strcpy(ptmp, "");
182     fgets(ptmp, 1024, fp);
183     if (feof(fp)) continue;
184     sscanf(ptmp, "%[.-z]", NIC);
185     NIC_book[i]= (NIC_entry *) malloc(sizeof(NIC_entry));
186     if (NIC_book[i]==NULL) {
187       d_printf( "Cound not alloc mem for NIC entry %d.\n", i);
188       exit(1);
189     }
190     strcpy(NIC_book[i]->NIC, NIC);
191     strcpy(NIC_book[i]->FENpos, FENpos);
192     ++i;
193   }
194   fclose(fp);
195   NIC_book[i]=NULL;
196   NIC_entries = i;
197 }
198
199 static void LONG_init()
200 {
201   FILE *fp;
202   char tmp[1024];
203   char *ptmp= tmp;
204   char FENpos[74], LONG[256], onMove[2];  
205   int i=0;
206
207   fp= fopen_p("%s/long999.idx", "r", BOOK_DIR);
208   if (!fp) {
209     d_printf( "Could not open LONG file\n");
210     exit(1);
211   }
212   while (!feof(fp)) {
213     strcpy(ptmp, "");
214     fgets(ptmp, 1024, fp);
215     if (feof(fp)) continue;
216     sscanf(ptmp, "%[\x21-z] %s", FENpos, onMove);
217     sprintf(FENpos, "%s %s", FENpos, onMove);
218     strcpy(ptmp, "");
219     fgets(ptmp, 1024, fp);
220     if (feof(fp)) continue;
221     sscanf(ptmp, "%[^*\n]", LONG);
222     LONG_book[i]= (LONG_entry *) malloc(sizeof(LONG_entry));
223     if (LONG_book[i]==NULL) {
224       d_printf( "Cound not alloc mem for LONG entry %d.\n", i);
225       exit(1);
226     }
227     strcpy(LONG_book[i]->LONG, LONG);
228     strcpy(LONG_book[i]->FENpos, FENpos);
229     ++i;
230   }
231   fclose(fp);
232   LONG_book[i]=NULL;
233   LONG_entries = i;
234 }
235
236 /* free up any memory used by books */
237 void book_close(void)
238 {
239         int i;
240
241         for (i=0;ECO_book[i];i++) {
242                 free(ECO_book[i]);
243                 ECO_book[i] = NULL;
244         }
245         for (i=0;NIC_book[i];i++) {
246                 free(NIC_book[i]);
247                 NIC_book[i] = NULL;
248         }
249         for (i=0;LONG_book[i];i++) {
250                 free(LONG_book[i]);
251                 LONG_book[i] = NULL;
252         }
253 }
254
255 void book_open(void)
256 {
257         ECO_init();
258         NIC_init(); 
259         LONG_init(); 
260         d_printf("CHESSD: Loaded books\n");
261 }
262
263 char *getECO(int g)
264 {
265   static char ECO[4];
266
267   int i, flag, l = 0, r = ECO_entries - 1, x;
268
269
270     if (game_globals.garray[g].type == TYPE_WILD) {
271       strcpy(ECO, "---");
272       return ECO;
273     } else if (game_globals.garray[g].moveList == NULL) {
274       strcpy(ECO, "***");
275       return ECO;
276     } else {
277       strcpy(ECO, "A00");
278     }
279
280   for (flag=0,i=game_globals.garray[g].numHalfMoves; (i>0 && !flag); i--) {
281     l = 0;
282     r = ECO_entries - 1;
283     while ((r >= l) && !flag) {
284       x = (l+r)/2;
285       if ((strcmp(game_globals.garray[g].moveList[i].FENpos, ECO_book[x]->FENpos)) < 0)
286         r = x - 1;
287       else
288         l = x + 1;
289       if (!strcmp(game_globals.garray[g].moveList[i].FENpos, ECO_book[x]->FENpos)) {
290         strcpy(ECO, ECO_book[x]->ECO);
291         flag=1;
292       }
293     }
294   }
295
296   return ECO;
297 }
298
299 int com_eco(int p, param_list param)
300 {
301         struct player *pp = &player_globals.parray[p];
302         int i, flag = 0, x, l, r;
303         int g1, p1;
304         
305         
306         if (param[0].type == TYPE_NULL) {  /* own game */
307                 if (pp->game < 0) {
308                         pprintf(p, "You are not playing or examining a game.\n");
309                         return COM_OK;
310                 }
311                 g1=pp->game;
312                 if (((game_globals.garray[g1].status != GAME_EXAMINE) &&
313                      (game_globals.garray[g1].status != GAME_SETUP)) && !pIsPlaying(p))
314                         return COM_OK;
315         } else {
316                 g1 = GameNumFromParam (p, &p1, &param[0]);
317                 if (g1 < 0) return COM_OK;
318                 if ((g1 >= game_globals.g_num) || ((game_globals.garray[g1].status != GAME_ACTIVE) &&
319                                                    (game_globals.garray[g1].status != GAME_EXAMINE) && 
320                                                    (game_globals.garray[g1].status != GAME_SETUP))) {
321                         pprintf(p, "There is no such game.\n");
322                         return COM_OK;
323                 }
324         }
325
326         if (game_globals.garray[g1].status == GAME_SETUP) {
327                 pprintf (p,"The postion is still being set up.\n");
328                 return COM_OK;
329         }
330
331         if (game_globals.garray[g1].private &&
332             (p != game_globals.garray[g1].white) && (p != game_globals.garray[g1].black) &&
333             !check_admin(p, 1)) {
334                 pprintf(p, "Sorry - that game is private.\n");
335                 return COM_OK;
336         } else {
337                 if (game_globals.garray[g1].type == TYPE_WILD) {
338                         pprintf(p, "That game is a wild game.\n");
339                         return COM_OK;      
340                 }
341         }
342         
343         pprintf(p, "Info about game %d: \"%s vs. %s\"\n\n", g1+1, 
344                 game_globals.garray[g1].white_name,    
345                 game_globals.garray[g1].black_name);
346         
347         if (game_globals.garray[g1].moveList==NULL) {
348                 return COM_OK;
349         }
350         
351         for (flag=0,i=game_globals.garray[g1].numHalfMoves; (i>0 && !flag); i--) {
352                 l = 0;
353                 r = ECO_entries - 1;
354                 while ((r >= l) && !flag) {
355                         x = (l+r)/2;
356                         if ((strcmp(game_globals.garray[g1].moveList[i].FENpos, ECO_book[x]->FENpos)) < 0)
357                                 r = x - 1;
358                         else
359                                 l = x + 1;
360                         if (!strcmp(game_globals.garray[g1].moveList[i].FENpos, ECO_book[x]->FENpos)) {
361                                 pprintf(p, "  ECO[%3d]: %s\n", i, ECO_book[x]->ECO);
362                                 flag=1;
363                         }
364                 }
365         }
366         
367         for (flag=0, i=game_globals.garray[g1].numHalfMoves; ((i>0) && (!flag)); i--) {
368                 l = 0;
369                 r = NIC_entries - 1;
370                 while ((r >=l) && !flag) {
371                         x = (l+r)/2;
372                         if ((strcmp(game_globals.garray[g1].moveList[i].FENpos, NIC_book[x]->FENpos)) < 0)
373                                 r = x - 1;
374                         else
375                                 l = x + 1;
376                         if (!strcmp(game_globals.garray[g1].moveList[i].FENpos, NIC_book[x]->FENpos)) {
377                                 pprintf(p, "  NIC[%3d]: %s\n", i, NIC_book[x]->NIC);
378                                 flag=1;
379                         }
380                 }
381         }
382         
383         for (flag=0, i=game_globals.garray[g1].numHalfMoves; ((i>0) && (!flag)); i--) {
384                 l = 0;
385                 r = LONG_entries - 1;
386                 while ((r >=l) && !flag) {
387                         x = (l+r)/2;
388                         if ((strcmp(game_globals.garray[g1].moveList[i].FENpos, LONG_book[x]->FENpos)) < 0)
389                                 r = x - 1;
390                         else
391                                 l = x + 1;
392                         if (!strcmp(game_globals.garray[g1].moveList[i].FENpos, LONG_book[x]->FENpos)) {
393                                 pprintf(p, " LONG[%3d]: %s\n", i, LONG_book[x]->LONG);
394                                 flag=1;
395                         }
396                 }
397         }
398         
399         return COM_OK;
400 }