bc3a1155c74c6ffecc5cc0bc0eaa98b49bc08c75
[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  
54   
55   for (r=7; r >=0; r--) {
56     f=0;
57     while (f<8) {
58       next = *(FENpos++);
59       if (isalpha(next))
60         gs->board[f++][r] = CharToPiece(next);
61       else if (next != '/') {
62         int t = (next - '0');
63         do
64           gs->board[f++][r] = NOPIECE;
65         while (--t);
66       }
67     }
68   }
69   if (*(FENpos + 1) == 'w') /* the char after the space */
70     gs->onMove = WHITE;
71   else
72     gs->onMove = BLACK;
73 }
74
75 /* converts a board to a FEN pos */
76
77 static void board_to_FEN(char* FENpos, struct game_state_t* gs)
78 {
79   int f,r,count;
80   char piece;  
81
82   for (r=7; r>=0; r--) {
83     count = 0;
84     for (f=0;  f<8; f++) {
85       if ((piece = PieceToChar(gs->board[f][r])) != ' ') {
86         if (count) { 
87           *(FENpos++) = count + '0';
88           count = 0;
89         }
90         *(FENpos++) = piece;
91       } else {
92         if (f == 7)
93           *(FENpos++) = count + '0' + 1;
94         else
95           count++;
96       }
97     }
98     *(FENpos++) = '/';
99   }
100
101   *(--FENpos) = ' ';
102
103   if (gs->onMove == WHITE)
104     *(++FENpos) = 'w';
105   else
106     *(++FENpos) = 'b';
107   *(++FENpos) = '\0';
108 }
109
110 char *boardToFEN(int g)
111 {
112   static char FENstring[74];
113
114   board_to_FEN (FENstring,&game_globals.garray[g].game_state);
115   return FENstring;
116 }
117
118 static void ECO_init()
119 {
120   FILE *fp;
121   char tmp[1024];
122   char *ptmp= tmp;
123   char FENpos[73], ECO[4], onMove[2];
124   int i=0;
125
126   fp= fopen_s(BOOK_DIR "/eco999.idx", "r");
127   if (!fp) {
128     d_printf( "Could not open ECO file\n");
129     exit(1);
130   }
131   while (!feof(fp)) {
132     strcpy(ptmp, "");
133     fgets(ptmp, 1024, fp);
134     if (feof(fp)) continue;
135     sscanf(ptmp, "%[\x21-z] %s", FENpos, onMove);
136     sprintf(FENpos, "%s %s", FENpos, onMove);
137     strcpy(ptmp, "");
138     fgets(ptmp, 1024, fp);
139     if (feof(fp)) continue;
140     sscanf(ptmp, "%[0-z]", ECO);
141     ECO_book[i]= (ECO_entry *) malloc(sizeof(ECO_entry));
142     if (ECO_book[i]==NULL) {
143       d_printf( "Cound not alloc mem for ECO entry %d.\n", i);
144       exit(1);
145     }
146     strcpy(ECO_book[i]->ECO, ECO);
147     strcpy(ECO_book[i]->FENpos, FENpos);
148     ++i;
149   }
150   fclose(fp);
151   ECO_book[i]=NULL;
152   ECO_entries = i;
153   
154   while (--i >= 0)
155     if (ECO_book[i] == NULL)
156       d_printf( "ERROR!  ECO book position number %d is NULL.", i);
157 }
158
159 static void NIC_init()
160 {
161   FILE *fp;
162   char tmp[1024];
163   char *ptmp= tmp;
164   char FENpos[73], NIC[6], onMove[2];  
165   int i=0;
166
167   fp= fopen_p("%s/nic999.idx", "r", BOOK_DIR);
168   if (!fp) {
169     d_printf( "Could not open NIC file\n");
170     exit(1);
171   }
172   while (!feof(fp)) {
173     strcpy(ptmp, "");
174     fgets(ptmp, 1024, fp);
175     if (feof(fp)) continue;
176     sscanf(ptmp, "%[\x21-z] %s", FENpos, onMove);
177     sprintf(FENpos, "%s %s", FENpos, onMove);
178     strcpy(ptmp, "");
179     fgets(ptmp, 1024, fp);
180     if (feof(fp)) continue;
181     sscanf(ptmp, "%[.-z]", NIC);
182     NIC_book[i]= (NIC_entry *) malloc(sizeof(NIC_entry));
183     if (NIC_book[i]==NULL) {
184       d_printf( "Cound not alloc mem for NIC entry %d.\n", i);
185       exit(1);
186     }
187     strcpy(NIC_book[i]->NIC, NIC);
188     strcpy(NIC_book[i]->FENpos, FENpos);
189     ++i;
190   }
191   fclose(fp);
192   NIC_book[i]=NULL;
193   NIC_entries = i;
194 }
195
196 static void LONG_init()
197 {
198   FILE *fp;
199   char tmp[1024];
200   char *ptmp= tmp;
201   char FENpos[74], LONG[256], onMove[2];  
202   int i=0;
203
204   fp= fopen_p("%s/long999.idx", "r", BOOK_DIR);
205   if (!fp) {
206     d_printf( "Could not open LONG file\n");
207     exit(1);
208   }
209   while (!feof(fp)) {
210     strcpy(ptmp, "");
211     fgets(ptmp, 1024, fp);
212     if (feof(fp)) continue;
213     sscanf(ptmp, "%[\x21-z] %s", FENpos, onMove);
214     sprintf(FENpos, "%s %s", FENpos, onMove);
215     strcpy(ptmp, "");
216     fgets(ptmp, 1024, fp);
217     if (feof(fp)) continue;
218     sscanf(ptmp, "%[^*\n]", LONG);
219     LONG_book[i]= (LONG_entry *) malloc(sizeof(LONG_entry));
220     if (LONG_book[i]==NULL) {
221       d_printf( "Cound not alloc mem for LONG entry %d.\n", i);
222       exit(1);
223     }
224     strcpy(LONG_book[i]->LONG, LONG);
225     strcpy(LONG_book[i]->FENpos, FENpos);
226     ++i;
227   }
228   fclose(fp);
229   LONG_book[i]=NULL;
230   LONG_entries = i;
231 }
232
233 /* free up any memory used by books */
234 void book_close(void)
235 {
236         int i;
237
238         for (i=0;ECO_book[i];i++) {
239                 free(ECO_book[i]);
240                 ECO_book[i] = NULL;
241         }
242         for (i=0;NIC_book[i];i++) {
243                 free(NIC_book[i]);
244                 NIC_book[i] = NULL;
245         }
246         for (i=0;LONG_book[i];i++) {
247                 free(LONG_book[i]);
248                 LONG_book[i] = NULL;
249         }
250 }
251
252 void book_open(void)
253 {
254         ECO_init();
255         NIC_init(); 
256         LONG_init(); 
257         d_printf("CHESSD: Loaded books\n");
258 }
259
260 char *getECO(int g)
261 {
262   static char ECO[4];
263
264   int i, flag, l = 0, r = ECO_entries - 1, x;
265
266
267     if (game_globals.garray[g].type == TYPE_WILD) {
268       strcpy(ECO, "---");
269       return ECO;
270     } else if (game_globals.garray[g].moveList == NULL) {
271       strcpy(ECO, "***");
272       return ECO;
273     } else {
274       strcpy(ECO, "A00");
275     }
276
277   for (flag=0,i=game_globals.garray[g].numHalfMoves; (i>0 && !flag); i--) {
278     l = 0;
279     r = ECO_entries - 1;
280     while ((r >= l) && !flag) {
281       x = (l+r)/2;
282       if ((strcmp(game_globals.garray[g].moveList[i].FENpos, ECO_book[x]->FENpos)) < 0)
283         r = x - 1;
284       else
285         l = x + 1;
286       if (!strcmp(game_globals.garray[g].moveList[i].FENpos, ECO_book[x]->FENpos)) {
287         strcpy(ECO, ECO_book[x]->ECO);
288         flag=1;
289       }
290     }
291   }
292
293   return ECO;
294 }
295
296 int com_eco(int p, param_list param)
297 {
298         struct player *pp = &player_globals.parray[p];
299         int i, flag = 0, x, l, r;
300         int g1, p1;
301         
302         
303         if (param[0].type == TYPE_NULL) {  /* own game */
304                 if (pp->game < 0) {
305                         pprintf(p, "You are not playing or examining a game.\n");
306                         return COM_OK;
307                 }
308                 g1=pp->game;
309                 if (((game_globals.garray[g1].status != GAME_EXAMINE) &&
310                      (game_globals.garray[g1].status != GAME_SETUP)) && !pIsPlaying(p))
311                         return COM_OK;
312         } else {
313                 g1 = GameNumFromParam (p, &p1, &param[0]);
314                 if (g1 < 0) return COM_OK;
315                 if ((g1 >= game_globals.g_num) || ((game_globals.garray[g1].status != GAME_ACTIVE) &&
316                                                    (game_globals.garray[g1].status != GAME_EXAMINE) && 
317                                                    (game_globals.garray[g1].status != GAME_SETUP))) {
318                         pprintf(p, "There is no such game.\n");
319                         return COM_OK;
320                 }
321         }
322
323         if (game_globals.garray[g1].status == GAME_SETUP) {
324                 pprintf (p,"The postion is still being set up.\n");
325                 return COM_OK;
326         }
327
328         if (game_globals.garray[g1].private &&
329             (p != game_globals.garray[g1].white) && (p != game_globals.garray[g1].black) &&
330             !check_admin(p, 1)) {
331                 pprintf(p, "Sorry - that game is private.\n");
332                 return COM_OK;
333         } else {
334                 if (game_globals.garray[g1].type == TYPE_WILD) {
335                         pprintf(p, "That game is a wild game.\n");
336                         return COM_OK;      
337                 }
338         }
339         
340         pprintf(p, "Info about game %d: \"%s vs. %s\"\n\n", g1+1, 
341                 game_globals.garray[g1].white_name,    
342                 game_globals.garray[g1].black_name);
343         
344         if (game_globals.garray[g1].moveList==NULL) {
345                 return COM_OK;
346         }
347         
348         for (flag=0,i=game_globals.garray[g1].numHalfMoves; (i>0 && !flag); i--) {
349                 l = 0;
350                 r = ECO_entries - 1;
351                 while ((r >= l) && !flag) {
352                         x = (l+r)/2;
353                         if ((strcmp(game_globals.garray[g1].moveList[i].FENpos, ECO_book[x]->FENpos)) < 0)
354                                 r = x - 1;
355                         else
356                                 l = x + 1;
357                         if (!strcmp(game_globals.garray[g1].moveList[i].FENpos, ECO_book[x]->FENpos)) {
358                                 pprintf(p, "  ECO[%3d]: %s\n", i, ECO_book[x]->ECO);
359                                 flag=1;
360                         }
361                 }
362         }
363         
364         for (flag=0, i=game_globals.garray[g1].numHalfMoves; ((i>0) && (!flag)); i--) {
365                 l = 0;
366                 r = NIC_entries - 1;
367                 while ((r >=l) && !flag) {
368                         x = (l+r)/2;
369                         if ((strcmp(game_globals.garray[g1].moveList[i].FENpos, NIC_book[x]->FENpos)) < 0)
370                                 r = x - 1;
371                         else
372                                 l = x + 1;
373                         if (!strcmp(game_globals.garray[g1].moveList[i].FENpos, NIC_book[x]->FENpos)) {
374                                 pprintf(p, "  NIC[%3d]: %s\n", i, NIC_book[x]->NIC);
375                                 flag=1;
376                         }
377                 }
378         }
379         
380         for (flag=0, i=game_globals.garray[g1].numHalfMoves; ((i>0) && (!flag)); i--) {
381                 l = 0;
382                 r = LONG_entries - 1;
383                 while ((r >=l) && !flag) {
384                         x = (l+r)/2;
385                         if ((strcmp(game_globals.garray[g1].moveList[i].FENpos, LONG_book[x]->FENpos)) < 0)
386                                 r = x - 1;
387                         else
388                                 l = x + 1;
389                         if (!strcmp(game_globals.garray[g1].moveList[i].FENpos, LONG_book[x]->FENpos)) {
390                                 pprintf(p, " LONG[%3d]: %s\n", i, LONG_book[x]->LONG);
391                                 flag=1;
392                         }
393                 }
394         }
395         
396         return COM_OK;
397 }