Support for g++-4.1.
[gf1.git] / gamelog.c
blobae8a18dbea5bef944cbb2f2168f18f55db325a8f
1 /*
2 ** $Id$
3 **
4 ** a lot of things for dealing with the log from a gipf-game
5 */
6 /*
7 ** Copyright (C) 1998 Kurt Van den Branden
8 **
9 ** This program is free software; you can redistribute it and/or modify
10 ** it under the terms of the GNU General Public License as published by
11 ** the Free Software Foundation; either version 2 of the License, or
12 ** (at your option) any later version.
13 **
14 ** This program is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ** GNU General Public License for more details.
18 **
19 ** You should have received a copy of the GNU General Public License
20 ** along with this program; if not, write to the Free Software
21 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <stdio.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <malloc.h>
29 #include "gamelog.h"
32 ** create a new, empty log structure
34 ** parameters:
35 ** type: gametype (string)
36 ** wname: name of the player with white
37 ** bname: name of the player with black
39 gamelog * newlog (char * type, char * wname, char * bname)
41 gamelog * log;
43 log = (gamelog *) malloc (sizeof (gamelog));
44 log->gametype = strdup (type);
45 log->whitename = strdup (wname);
46 log->blackname = strdup (bname);
48 log->moves = (listheader *) malloc (sizeof (listheader));
49 newlist (log->moves);
51 return (log);
56 ** delete a complete gamelog structure
58 void deletelog (gamelog * log)
60 logitem * item;
61 char * pos;
63 free (log->gametype);
64 free (log->whitename);
65 free (log->blackname);
67 while ((item = (logitem *) llrembynr (log->moves, 1)) != NULL)
69 if (item->plist != NULL)
71 while ((pos = (char *) llrembynr (item->plist, 1)) != NULL)
73 free (pos);
75 free (item->plist);
78 free (item);
80 free (log->moves);
82 return;
86 ** add to the gamelog
88 ** the contents of 'data' depend on 'type'
89 ** LOGMOVE: <piece>:<from>:<last moved piece>
90 ** LOGREMGIPF: <gipfowner>:<gipf position><piece>
91 ** LOGREMROW: <rowowner>:<rowstart>:<rowend>:[<piece position><piece>:]...
92 ** (remark: the data for LOGREMROW must end on ':')
94 int addtolog (gamelog * log, int type, char * data)
96 logitem * item;
97 char * kar,
98 piece,
99 start[10]=" ",
100 end[10]=" ",
101 pos[10]=" ";
103 item = (logitem *) malloc (sizeof (logitem));
104 item->plist = NULL;
105 item->type = type;
107 switch (type)
109 case LOGMOVE:
110 if (sscanf (data, "%c:%2s:%2s", &piece, start, end) != 3)
112 free (item);
113 return (-1);
115 break;
116 case LOGREMGIPF:
117 if (sscanf (data, "%c:%3s", &piece, pos) != 2)
119 free (item);
120 return (-1);
122 item->plist = (listheader *) malloc (sizeof (listheader));
123 newlist (item->plist);
124 pushll (item->plist, (void *) strdup (pos));
125 break;
126 case LOGREMROW:
127 if (sscanf (data, "%c:%2s:%2s:", &piece, start, end) != 3)
129 free (item);
130 return (-1);
132 item->plist = (listheader *) malloc (sizeof (listheader));
133 newlist (item->plist);
134 kar = data + 8;
135 while (kar[0] != '\0')
137 strncpy (pos, kar, 3);
138 pushll (item->plist, (void *) strdup (pos));
139 kar += 4;
141 break;
143 item->player = piece;
144 strcpy (item->start, start);
145 strcpy (item->end, end);
147 pushll (log->moves, (void *) item);
148 return (0);
153 ** write contents of a gamelog-structure to a file
155 ** parameters:
156 ** log: gamelog structure
157 ** fp: pointer to an open file
159 int logtofile (gamelog * log, FILE * fp)
161 logitem * item;
162 char * pos;
163 int counter = 1,
164 counter2;
166 if (log == NULL)
168 return (-1);
171 fprintf (fp, "game: %s\n", log->gametype);
172 fprintf (fp, "white player: %s\n", log->whitename);
173 fprintf (fp, "black player: %s\n", log->blackname);
174 fprintf (fp, "\nmoves:\n");
176 while ((item = (logitem *) llitembynr (log->moves, counter)) != NULL)
178 counter++;
180 switch (item->type)
182 case LOGMOVE:
183 fprintf (fp, "%c: %s-%s\n", item->player, item->start, item->end);
184 break;
185 case LOGREMGIPF:
186 pos = (char *) llitembynr (item->plist, 1);
187 fprintf (fp, " %c removegipf: %s\n", item->player, pos);
188 break;
189 case LOGREMROW:
190 fprintf (fp, " %c removerow (%s-%s):", item->player,
191 item->start, item->end);
192 counter2 = 1;
193 while ((pos = (char *) llitembynr (item->plist, counter2)) != NULL)
195 counter2++;
196 fprintf (fp, " %s", pos);
198 fprintf (fp, "\n");
199 break;
200 default: ;
204 fprintf (fp, "end of gamelog\n");
206 return (0);
211 ** read log from a file and put it in a gamelog-structure
212 ** (the layout must be the same as written by logtofile)
214 ** the inputfile must already be open and should be at the first
215 ** line from the gamelog
217 gamelog * logfromfile (FILE * fp)
219 gamelog * log;
220 char buffer[100],
221 type[100],
222 wname[100],
223 bname[100];
224 logitem * item;
225 char * kar,
226 piece,
227 start[10]=" ",
228 end[10]=" ",
229 pos[10]=" ";
231 if (fgets (buffer, 100, fp) == NULL)
232 return (NULL);
233 buffer[strlen(buffer)-1] = '\0';
234 if (strncmp (buffer, "game: ", 6) != 0)
235 return (NULL);
236 strcpy (type, buffer+6);
238 if (fgets (buffer, 100, fp) == NULL)
239 return (NULL);
240 buffer[strlen(buffer)-1] = '\0';
241 if (strncmp (buffer, "white player: ", 14) != 0)
242 return (NULL);
243 strcpy (wname, buffer+14);
245 if (fgets (buffer, 100, fp) == NULL)
246 return (NULL);
247 buffer[strlen(buffer)-1] = '\0';
248 if (strncmp (buffer, "black player: ", 14) != 0)
249 return (NULL);
250 strcpy (bname, buffer+14);
252 log = newlog (type, wname, bname);
254 fgets (buffer, 100, fp);
255 fgets (buffer, 100, fp);
257 while (1)
259 if (fgets (buffer, 100, fp) == NULL)
261 deletelog (log);
262 return (NULL);
264 if (strncmp (buffer, "end of gamelog", 14) == 0)
265 break;
267 item = (logitem *) malloc (sizeof (logitem));
268 item->plist = NULL;
270 if (sscanf (buffer, "%c: %2s-%2s", &piece, start, end) == 3)
272 item->type = LOGMOVE;
274 else if (sscanf (buffer, " %c removegipf: %3s", &piece, pos) == 2)
276 item->type = LOGREMGIPF;
277 item->plist = (listheader *) malloc (sizeof (listheader));
278 newlist (item->plist);
279 pushll (item->plist, (void *) strdup (pos));
281 else if (sscanf (buffer, " %c removerow (%2s-%2s):",
282 &piece, start, end) == 3)
284 item->type = LOGREMROW;
285 item->plist = (listheader *) malloc (sizeof (listheader));
286 newlist (item->plist);
288 /* find pieces */
289 kar = strchr (buffer, ':');
290 kar++;
291 while (1)
293 while (isspace ((int) kar[0]))
294 kar++;
295 if (sscanf (kar, "%3s", pos) != 1)
296 break;
297 pushll (item->plist, (void *) strdup (pos));
298 kar += 4;
301 item->player = piece;
302 strcpy (item->start, start);
303 strcpy (item->end, end);
305 pushll (log->moves, (void *) item);
308 return (log);
313 ** take the contents of a gamelog-structure and format it in
314 ** a nice way to show in an fltk browser-widget
316 ** this function returs a list of lines that can be sent to the
317 ** widget without change
319 ** !! don't forget to cleanup the list !!
321 listheader * logtobrowser (gamelog * log)
323 listheader * lines;
324 char * newline,
325 whitepieces[50] = "",
326 blackpieces[50] = "",
327 owner = ' ',
328 * tempstr;
329 int movecounter = 0,
330 count = 1,
331 count2;
332 logitem * item;
334 lines = (listheader *) malloc (sizeof (listheader));
335 newlist (lines);
337 newline = (char *) malloc (40); /* is 40 always enough ? */
338 sprintf (newline, "@b%s", log->gametype);
339 pushll (lines, newline);
340 newline = (char *) malloc (1);
341 newline[0] = '\0';
342 pushll (lines, newline);
344 newline = (char *) malloc (40); /* is 40 always enough ? */
345 sprintf (newline, "@iwhite: %s", log->whitename);
346 pushll (lines, newline);
347 newline = (char *) malloc (40); /* is 40 always enough ? */
348 sprintf (newline, "@iblack: %s", log->blackname);
349 pushll (lines, newline);
350 newline = (char *) malloc (1);
351 newline[0] = '\0';
352 pushll (lines, newline);
354 while ((item = (logitem *) llitembynr (log->moves, count)) != NULL)
356 count++;
358 if ((owner != ' ') &&
359 ((item->type == LOGMOVE) || (item->type == LOGREMROW)))
361 newline = (char *) malloc (50); /* is 50 enough ? */
362 if (owner == 'o')
363 sprintf (newline, "@s w: %sx %s",
364 whitepieces, blackpieces);
365 else
366 sprintf (newline, "@s b: %sx %s",
367 blackpieces, whitepieces);
369 pushll (lines, newline);
371 owner = ' ';
372 whitepieces[0] = '\0';
373 blackpieces[0] = '\0';
376 if (item->type == LOGMOVE)
378 if ((movecounter % 2) == 0)
379 { /* need to show the nr of the move here */
380 newline = (char *) malloc (40); /* is 40 always enough ? */
381 sprintf (newline, "@c@b%d", movecounter/2 + 1);
382 pushll (lines, newline);
384 movecounter++;
386 newline = (char *) malloc (40); /* is 40 always enough ? */
387 if (tolower (item->player) == 'o')
388 sprintf (newline, "white: ");
389 else
390 sprintf (newline, "black: ");
392 if ((item->player == 'O') || (item->player == 'X'))
393 sprintf (newline + 7, "G");
395 sprintf (newline + strlen (newline), "%2s-%2s",
396 item->start, item->end);
398 pushll (lines, newline);
400 else if (item->type == LOGREMGIPF)
402 tempstr = (char *) llitembynr (item->plist, 1);
403 if (tolower (tempstr[2]) == 'o')
404 sprintf (whitepieces + strlen (whitepieces), "G%2.2s ",
405 tempstr);
406 else
407 sprintf (blackpieces + strlen (blackpieces), "G%2.2s ",
408 tempstr);
410 else /* must be LOGREMROW now */
412 count2 = 1;
413 owner = tolower (item->player);
415 while ((tempstr = (char *) llitembynr (item->plist, count2))
416 != NULL)
418 count2++;
419 if (tolower (tempstr[2]) == 'o')
420 sprintf (whitepieces + strlen (whitepieces), "%2.2s ",
421 tempstr);
422 else
423 sprintf (blackpieces + strlen (blackpieces), "%2.2s ",
424 tempstr);
429 if (owner != ' ')
431 newline = (char *) malloc (50); /* is 50 enough ? */
432 if (owner == 'o')
433 sprintf (newline, "@s w: %sx %s",
434 whitepieces, blackpieces);
435 else
436 sprintf (newline, "@s b: %sx %s",
437 blackpieces, whitepieces);
439 pushll (lines, newline);
442 return (lines);
447 ** return 1 if this logitem represents a move
449 int isamove (void * data)
451 logitem * item = data;
453 if (item->type == LOGMOVE)
454 return (1);
456 return (0);
461 ** remove the last move from a gamelog
462 ** (include all the removerows and removegipfs)
464 ** returns:
465 ** -1: error
466 ** number of items removed from the log
468 int remlastmove (gamelog * log)
470 int nr,
471 counter = 0;
472 logitem * item;
473 char * pos;
475 if ((nr = findlastll (log->moves, isamove)) == 0)
477 return (-1);
480 /* delete everything from the last move to the end of the list */
481 while ((item = (logitem *) llrembynr (log->moves, nr)) != NULL)
483 if (item->plist != NULL)
485 while ((pos = (char *) llrembynr (item->plist, 1)) != NULL)
487 free (pos);
489 free (item->plist);
492 free (item);
493 counter++;
496 return (counter);