Support for g++-4.1.
[gf1.git] / thegame.cxx
blobc64451ca5c5453d9c251d6938138a55db579fa1f
1 /*
2 ** $Id$
3 **
4 ** functions and structures for a game of gipf
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 <sys/time.h>
28 #include <unistd.h>
29 #include <FL/fl_draw.H>
30 #include <FL/Fl.H>
32 #ifdef MSWIN
33 #include "gettimeofday.h"
34 #endif
36 #include "thegame.h"
37 #include "gipf_ui.H"
38 #include "board.h"
39 #include "callbacks.h"
40 #include "player_info.h"
41 #include "drawgif.h"
42 #include "xmlite.h"
44 char gametype[4][15] = {"basic", "standard", "tournament", "other game"};
45 char playertype[2][9] = {"human", "computer"};
48 ** show the window for starting a new game
50 ** if the user pressed OK, this will return a structure for starting
51 ** a new game
53 ** if you give a parameter different from NULL, then the window will be
54 ** initialised from this game, otherwise, defaults are used
56 gamestruct * show_new (gamestruct * oldgame)
58 Fl_Window * neww;
59 gamestruct * newgame;
61 neww = make_newwindow ();
63 // initialize values
64 if (oldgame != NULL)
66 // gametype
67 switch (oldgame->game_type)
69 case T_BASIC:
70 radio_basic->setonly();
71 break;
72 case T_STANDARD:
73 radio_standard->setonly();
74 break;
75 case T_TOURNAMENT:
76 radio_tournament->setonly();
77 break;
80 // player names
81 whiteplayername->value (oldgame->player[0].name);
82 blackplayername->value (oldgame->player[1].name);
84 // player type
85 if (oldgame->player[0].type)
86 radio_wcompu->setonly();
87 else
88 radio_whuman->setonly();
90 if (oldgame->player[1].type)
91 radio_bcompu->setonly();
92 else
93 radio_bhuman->setonly();
95 // timed game
96 if (oldgame->player[0].fulltime == -1)
98 toggle_timedgame->clear();
100 else
102 toggle_timedgame->set();
103 whitetime->value (oldgame->player[0].fulltime / 60);
104 blacktime->value (oldgame->player[1].fulltime / 60);
107 else
109 radio_tournament->setonly();
110 toggle_timedgame->clear();
111 radio_whuman->setonly();
112 radio_bcompu->setonly();
115 // show or hide the time-counters
116 if (toggle_timedgame->value())
118 whitetime->activate();
119 blacktime->activate();
121 else
123 whitetime->deactivate();
124 blacktime->deactivate();
127 neww->show();
129 while (1)
131 Fl::wait();
133 Fl_Widget *x;
134 while ((x = Fl::readqueue()))
136 if (x == toggle_timedgame)
138 if (toggle_timedgame->value())
140 whitetime->activate();
141 blacktime->activate();
143 else
145 whitetime->deactivate();
146 blacktime->deactivate();
149 else if (x == new_ok)
151 newgame = (gamestruct *) malloc (sizeof (gamestruct));
152 newgame->state = GAME_GO;
153 newgame->movecounter = 0;
155 if (radio_whuman->value())
156 newgame->player[0].type = 0;
157 else
158 newgame->player[0].type = 1;
159 if (radio_bhuman->value())
160 newgame->player[1].type = 0;
161 else
162 newgame->player[1].type = 1;
164 strcpy (newgame->player[0].name, whiteplayername->value());
165 strcpy (newgame->player[1].name, blackplayername->value());
167 if (toggle_timedgame->value())
169 newgame->player[0].fulltime = 60 * (int)whitetime->value();
170 newgame->player[0].timer =
171 (float) newgame->player[0].fulltime;
172 newgame->player[1].fulltime = 60 * (int)blacktime->value();
173 newgame->player[1].timer =
174 (float) newgame->player[1].fulltime;
176 else
178 newgame->player[0].fulltime = -1;
179 newgame->player[0].timer = 0.0;
180 newgame->player[1].fulltime = -1;
181 newgame->player[1].timer = 0.0;
184 if (radio_basic->value ()) { newgame->game_type = T_BASIC;}
185 else if (radio_standard->value ())
186 { newgame->game_type = T_STANDARD;}
187 else if (radio_tournament->value ())
188 { newgame->game_type = T_TOURNAMENT;}
189 else { return (NULL);}
191 newgame->boards[0] = b_new (newgame->game_type);
192 newgame->boards[1] = NULL;
193 newgame->boards[2] = NULL;
195 // initialize players
196 newgame->player[0].self =
197 (* players[newgame->player[0].type].newfunc)
198 ('o', newgame->game_type);
199 newgame->player[1].self =
200 (* players[newgame->player[1].type].newfunc)
201 ('x', newgame->game_type);
203 newgame->movelog = newlog (gametype[newgame->game_type],
204 newgame->player[0].name,
205 newgame->player[1].name);
207 delete neww;
209 setcurrentfilename ("\0");
211 return (newgame);
213 else if (x == new_cancel)
215 delete neww;
216 return (NULL);
221 return (NULL);
226 ** show the window for starting a game from a gameboard
228 ** if the user pressed OK, this will return a structure for starting
229 ** a the game
231 ** the parameter is the board to start from
233 gamestruct * show_start (board * startboard)
235 Fl_Window * startw;
236 gamestruct * newgame;
237 board * newboard;
239 if ((newboard = verify_board (startboard)) == NULL)
241 return (NULL);
244 startw = make_startwindow ();
246 /* put default settings in window */
247 radio_white->setonly ();
248 radio_s_whuman->setonly ();
249 radio_s_bcompu->setonly ();
250 if (newboard->typewhite == 'g')
251 toggle_s_whitegipf->set ();
252 else
253 toggle_s_whitegipf->deactivate ();
254 if (newboard->typeblack == 'g')
255 toggle_s_blackgipf->set ();
256 else
257 toggle_s_blackgipf->deactivate ();
259 startw->show();
261 while (1)
263 Fl::wait();
265 Fl_Widget *x;
266 while ((x = Fl::readqueue()))
268 if (x == start_ok)
270 newgame = (gamestruct *) malloc (sizeof (gamestruct));
271 newgame->state = GAME_GO;
272 newgame->movecounter = 0;
274 if (radio_s_whuman->value() != 0)
275 newgame->player[0].type = 0;
276 else
277 newgame->player[0].type = 1;
279 if (radio_s_bhuman->value() != 0)
280 newgame->player[1].type = 0;
281 else
282 newgame->player[1].type = 1;
284 strcpy (newgame->player[0].name, s_whiteplayername->value());
285 strcpy (newgame->player[1].name, s_blackplayername->value());
287 newgame->player[0].fulltime = -1;
288 newgame->player[0].timer = 0.0;
289 newgame->player[1].fulltime = -1;
290 newgame->player[1].timer = 0.0;
292 newgame->game_type = T_OTHER;
294 if ((newboard->typewhite == 'g') &&
295 (toggle_s_whitegipf->value () == 0))
296 newboard->typewhite = 'n';
297 if ((newboard->typeblack == 'g') &&
298 (toggle_s_blackgipf->value () == 0))
299 newboard->typeblack = 'n';
301 if (radio_white->value () != 0)
302 newboard->nextpiece = 'o';
303 else
304 newboard->nextpiece = 'x';
306 newgame->boards[0] = newboard;
307 newgame->boards[1] = NULL;
308 newgame->boards[2] = NULL;
310 // initialize players
311 newgame->player[0].self =
312 (* players[newgame->player[0].type].newfunc)
313 ('o', newgame->game_type);
314 newgame->player[1].self =
315 (* players[newgame->player[1].type].newfunc)
316 ('x', newgame->game_type);
318 newgame->movelog = newlog (gametype[newgame->game_type],
319 newgame->player[0].name,
320 newgame->player[1].name);
322 delete (startw);
324 setcurrentfilename ("\0");
326 return (newgame);
328 else if (x == start_cancel)
330 b_del (newboard);
331 delete (startw);
332 return (NULL);
337 return (NULL);
342 ** show the window for calculating one move starting from a gameboard
344 ** if the user pressed OK, this will return a structure for calculating
345 ** the one move
347 ** the parameter is the board to start from
349 gamestruct * show_onemove (board * startboard, configvalues * conf)
351 Fl_Window * onemovew;
352 gamestruct * newgame;
353 board * newboard;
354 int newlevel,
355 oldlevel;
357 if ((newboard = verify_board (startboard)) == NULL)
359 return (NULL);
362 onemovew = make_onemovewindow ();
364 radio_c_white->setonly ();
365 c_level3->setonly ();
367 onemovew->show();
369 while (1)
371 Fl::wait();
373 Fl_Widget *x;
374 while ((x = Fl::readqueue()))
376 if (x == one_ok)
378 newgame = (gamestruct *) malloc (sizeof (gamestruct));
379 newgame->state = GAME_GO;
380 newgame->movecounter = 0;
382 if (radio_c_white->value() != 0)
384 newgame->player[0].type = 1;
385 newgame->player[1].type = 0;
386 strcpy (newgame->player[0].name, "Computer");
387 strcpy (newgame->player[1].name, "None");
388 newboard->nextpiece = 'o';
390 else
392 newgame->player[0].type = 0;
393 newgame->player[1].type = 1;
394 strcpy (newgame->player[1].name, "Computer");
395 strcpy (newgame->player[0].name, "None");
396 newboard->nextpiece = 'x';
399 newgame->player[0].fulltime = -1;
400 newgame->player[0].timer = 0.0;
401 newgame->player[1].fulltime = -1;
402 newgame->player[1].timer = 0.0;
404 newgame->game_type = T_OTHER;
406 newgame->boards[0] = newboard;
407 newgame->boards[1] = NULL;
408 newgame->boards[2] = NULL;
410 newgame->config = conf;
412 // initialize players
413 newgame->player[0].self =
414 (* players[newgame->player[0].type].newfunc)
415 ('o', newgame->game_type);
416 newgame->player[1].self =
417 (* players[newgame->player[1].type].newfunc)
418 ('x', newgame->game_type);
420 newgame->movelog = newlog (gametype[newgame->game_type],
421 newgame->player[0].name,
422 newgame->player[1].name);
424 if ((c_level1->value ()) != 0) { newlevel = 1; }
425 else if ((c_level2->value ()) != 0) { newlevel = 2; }
426 else if ((c_level3->value ()) != 0) { newlevel = 3; }
427 else if ((c_level4->value ()) != 0) { newlevel = 4; }
428 else if ((c_level5->value ()) != 0) { newlevel = 5; }
429 else if ((c_level6->value ()) != 0) { newlevel = 6; }
430 else if ((c_level7->value ()) != 0) { newlevel = 7; }
431 else if ((c_level8->value ()) != 0) { newlevel = 8; }
433 oldlevel = conf->searchdepth;
434 if (newlevel != oldlevel)
436 conf->searchdepth = newlevel;
437 writeconfig (conf);
440 delete (onemovew);
442 setcurrentfilename ("\0");
444 /* execute the move here */
445 gameboard->setboard (newgame->boards[0]);
447 setupmove (newgame);
449 newgame->state = GAME_STOP;
450 changeinterface (INTERFACE_PLAY, newgame);
452 if (newlevel != oldlevel)
454 conf->searchdepth = oldlevel;
455 writeconfig (conf);
458 return (newgame);
460 else if (x == one_cancel)
462 b_del (newboard);
463 delete (onemovew);
464 return (NULL);
469 return (NULL);
474 ** check if a gameboard can be used to start a game from
476 ** returns a copy of sboard that is correctly setup
477 ** or NULL if there is a problem
479 board * verify_board (board * sboard)
481 board * nboard;
482 rem_row * row_ptr;
483 int i, j,
484 white = 0,
485 black = 0;
486 position * pos;
488 /* check if one of the players has no pieces left */
489 if (b_colour (sboard, 'o') == 0)
491 gf1_alert ("ERROR: no game possible from this boardsituation, player white has no pieces left.");
492 return (NULL);
494 if (b_colour (sboard, 'x') == 0)
496 gf1_alert ("ERROR: no game possible from this boardsituation, player black has no pieces left.");
497 return (NULL);
500 /* count pieces on the board */
501 pos = new_position ();
502 for (i = 1; i < 8; i++)
503 for (j = 2; j <= b_colsize (i); j++)
505 posp_col (pos) = i;
506 posp_row (pos) = j;
507 switch (b_ppiece (sboard, pos))
509 case 'o':
510 white += 1;
511 break;
512 case 'O':
513 white += 2;
514 break;
515 case 'x':
516 black += 1;
517 break;
518 case 'X':
519 black += 2;
520 break;
524 /* check if the board is empty */
525 if ((white == 0) && (black == 0))
527 gf1_alert ("ERROR: no game possible from this boardsituation, the gameboard is empty.");
528 return (NULL);
531 /* check for four-in-a-row */
532 for (i = 0; i < 21; i++)
534 if ((row_ptr = b_rowoffour (sboard, i)) != NULL)
536 del_rem_row ((void *) row_ptr);
537 gf1_alert ("ERROR: no game possible from this boardsituation, four-in-a-row found.");
538 return (NULL);
542 /* check if this is a basic game */
543 if ((b_colour_gipf (sboard, 'o') == 0) &&
544 (b_colour_gipf (sboard, 'x') == 0))
546 nboard = b_copy (sboard);
547 nboard->gipfwhite = -1;
548 nboard->gipfblack = -1;
549 nboard->typewhite = 'n';
550 nboard->typeblack = 'n';
552 /* turn this into a real basic game (if possible) */
553 if ((b_colour (nboard, 'o') > 3) && (b_colour (sboard, 'x') > 3))
555 nboard->white -= 3;
556 nboard->black -= 3;
559 return (nboard);
562 /* tournament or standard game, for me it's always tournament */
565 ** something is wrong when a player has normal pieces, but
566 ** no gipf-pieces
568 /* check if one of the player has single pieces, but no gipf-pieces */
569 if ((b_colour_gipf (sboard, 'o') == 0) && (b_colour (sboard, 'o') < 18))
571 gf1_alert ("ERROR: no game possible from this boardsituation, player white has no gipf-pieces.");
572 return (0);
574 if ((b_colour_gipf (sboard, 'x') == 0) && (b_colour (sboard, 'x') < 18))
576 gf1_alert ("ERROR: no game possible from this boardsituation, player black has no gipf-pieces.");
577 return (0);
580 nboard = b_copy (sboard);
581 nboard->typewhite = 'n';
582 nboard->typeblack = 'n';
583 if ((18 - b_colour_gipf (sboard, 'o') * 2) == b_colour (sboard, 'o'))
584 { /* only gipf-pieces, allow player to add more */
585 nboard->typewhite = 'g';
587 if ((18 - b_colour_gipf (sboard, 'x') * 2) == b_colour (sboard, 'x'))
588 { /* only gipf-pieces, allow player to add more */
589 nboard->typeblack = 'g';
592 ** I don't check here if the players have 18 pieces
593 ** which means that it's not completely correct
596 return (nboard);
600 void delete_game (gamestruct * gameptr)
602 int i;
604 if (gameptr == NULL)
605 return;
607 /* ask the player to cleanup its data */
608 if (gameptr->player[0].self != NULL)
610 (* players[gameptr->player[0].type].endfunc) (gameptr->player[0].self);
612 if (gameptr->player[1].self != NULL)
614 (* players[gameptr->player[1].type].endfunc) (gameptr->player[1].self);
617 for (i = 0; i < 3; i++)
619 b_del (gameptr->boards[i]);
622 deletelog (gameptr->movelog);
623 return;
628 ** REMARK: this is the old version
630 ** load a game from a file
632 ** return NULL if nothing loaded
634 gamestruct * oldloadgame (const char * filename)
636 char buffer[100],
637 tempstr[100];
638 FILE * fp;
639 int i,
640 tempnr;
641 gamestruct * newgame;
643 if ((fp = fopen (filename, "r")) == NULL)
645 gf1_alert (" ERROR: Can't open the file");
646 return (NULL);
649 newgame = (gamestruct *) malloc (sizeof (gamestruct));
650 newgame->state = GAME_GO;
652 fgets (buffer, 100, fp);
653 if (strncmp (buffer, "# saved game for gf1", 20) != 0)
655 gf1_alert (" ERROR: wrong inputfile format");
656 free (newgame);
657 return (NULL);
660 fgets (buffer, 100, fp);
661 if (sscanf (buffer, "# gametype: %d", &(newgame->game_type)) != 1)
663 gf1_alert (" ERROR: wrong inputfile format");
664 free (newgame);
665 return (NULL);
668 for (i = 0; i < 2; i++)
670 fgets (buffer, 100, fp);
671 if (sscanf (buffer, "# player%d type: %d",
672 &tempnr, &(newgame->player[i].type)) != 2)
674 gf1_alert (" ERROR: wrong inputfile format");
675 free (newgame);
676 return (NULL);
679 fgets (buffer, 100, fp);
680 sprintf (tempstr, "# player%d name: ", i);
681 if (strncmp (buffer, tempstr, 16) != 0)
683 gf1_alert (" ERROR: wrong inputfile format");
684 free (newgame);
685 return (NULL);
687 buffer[strlen(buffer) - 1] = '\0';
688 strcpy (newgame->player[i].name, buffer+16);
690 fgets (buffer, 100, fp);
691 if (sscanf (buffer, "# player%d fulltime: %d",
692 &tempnr, &(newgame->player[i].fulltime)) != 2)
694 gf1_alert (" ERROR: wrong inputfile format");
695 free (newgame);
696 return (NULL);
699 fgets (buffer, 100, fp);
700 if (sscanf (buffer, "# player%d timer: %f",
701 &tempnr, &(newgame->player[i].timer)) != 2)
703 gf1_alert (" ERROR: wrong inputfile format");
704 free (newgame);
705 return (NULL);
708 newgame->player[i].self = NULL;
711 fgets (buffer, 100, fp);
712 if ((newgame->boards[0] = b_from_file (fp)) == NULL)
714 gf1_alert (" ERROR: wrong inputfile format");
715 free (newgame);
716 return (NULL);
718 newgame->boards[1] = NULL;
719 newgame->boards[2] = NULL;
721 fgets (buffer, 100, fp);
722 if ((newgame->movelog = logfromfile (fp)) == NULL)
724 gf1_alert (" ERROR: wrong inputfile format");
725 free (newgame);
726 return (NULL);
728 newgame->movecounter = loglength (newgame->movelog);
730 fclose (fp);
732 // reading was succesfull, init the players
733 newgame->player[0].self =
734 (* players[newgame->player[0].type].newfunc) ('o', newgame->game_type);
735 newgame->player[1].self =
736 (* players[newgame->player[1].type].newfunc) ('x', newgame->game_type);
738 return (newgame);
743 ** load a game from a file
745 ** return NULL if nothing loaded
747 gamestruct * loadgame (void)
749 const char * filename;
750 char buffer[100],
751 tempstr[100];
752 FILE * fp;
753 int i;
754 gamestruct * newgame;
755 xmlite_entity * root, *x1;
756 xmlite_parser * theparser;
758 // ask for filename
759 if ((filename = file_chooser ("load game", "*.gf1", NULL)) == NULL)
761 return (NULL);
764 if ((fp = fopen (filename, "r")) == NULL)
766 gf1_alert (" ERROR: Can't open the file");
767 return (NULL);
770 fgets (buffer, 100, fp);
771 fclose (fp);
772 if (strncmp (buffer, "# saved game for gf1", 20) == 0)
773 { // old saveformat
774 return (oldloadgame (filename));
777 theparser = new xmlite_parser (filename);
778 root = theparser->parse ();
779 delete (theparser);
780 if (root == NULL)
782 delete (root);
783 gf1_alert (" ERROR: Can't parse savefile");
784 return (NULL);
787 if (root->getname() != "gipfgame")
789 delete (root);
790 gf1_alert (" ERROR: Not a savefile from gf1");
791 return (NULL);
794 if (atoi (root->getattribute("formatversion").c_str()) > 1)
796 delete (root);
797 gf1_alert (" ERROR: Don't know how to handle this fileversion");
798 return (NULL);
801 newgame = (gamestruct *) malloc (sizeof (gamestruct));
802 newgame->state = GAME_GO;
804 // gametype
805 strcpy (tempstr, root->getattribute("type").c_str());
806 newgame->game_type = 3; // put some default value in
807 for (i = 0; i < 4; i++)
809 if (strcmp (tempstr, gametype[i]) == 0)
811 newgame->game_type = i;
812 break;
816 // players
817 x1 = root->getcontentbyname ("whiteplayer");
818 strcpy (newgame->player[0].name, x1->getvalue().c_str());
819 newgame->player[0].type = x1->getattribute ("type") == "human" ? 0 : 1;
820 newgame->player[0].fulltime = atoi (x1->getattribute ("fulltime").c_str());
821 newgame->player[0].timer = atof (x1->getattribute ("timeleft").c_str());
822 newgame->player[0].self = NULL;
823 x1 = root->getcontentbyname ("blackplayer");
824 strcpy (newgame->player[1].name, x1->getvalue().c_str());
825 newgame->player[1].type = x1->getattribute ("type") == "human" ? 0 : 1;
826 newgame->player[1].fulltime = atoi (x1->getattribute ("fulltime").c_str());
827 newgame->player[1].timer = atof (x1->getattribute ("timeleft").c_str());
828 newgame->player[1].self = NULL;
830 // the boardsituation
831 newgame->boards[0] = b_from_xml (root->getcontentbyname ("board"));
832 newgame->boards[1] = NULL;
833 newgame->boards[2] = NULL;
835 // the log of moves
836 newgame->movelog = logfromxml (root->getcontentbyname ("gamelog"));
837 newgame->movecounter = loglength (newgame->movelog);
839 // reading was succesfull, init the players
840 newgame->player[0].self =
841 (* players[newgame->player[0].type].newfunc) ('o', newgame->game_type);
842 newgame->player[1].self =
843 (* players[newgame->player[1].type].newfunc) ('x', newgame->game_type);
845 delete (root);
847 setcurrentfilename (filename);
849 return (newgame);
854 ** save a game to a file
856 void savegame (gamestruct * gameptr)
858 const char * filename;
859 xmlite_entity *x1, *x2;
860 char tempstr[100],
861 * cfile;
863 if (gameptr == NULL)
865 gf1_alert (" no current game to be saved");
866 return;
869 // ask for filename
870 cfile = getcurrentfilename ();
871 if (cfile[0] == '\0')
872 strcpy (tempstr, "./savegame.gf1");
873 else
874 strcpy (tempstr, cfile);
875 if ((filename = file_chooser ("save game", "*.gf1", tempstr))
876 == NULL)
878 return;
881 // gipfgame
882 x1 = new xmlite_entity ("gipfgame");
883 x1->addattribute ("type", gametype[gameptr->game_type]);
884 x1->addattribute ("formatversion", "1");
886 // white player
887 x2 = new xmlite_entity ("whiteplayer");
888 sprintf (tempstr, "%f", gameptr->player[0].timer);
889 x2->addattribute ("timeleft", tempstr);
890 sprintf (tempstr, "%d", gameptr->player[0].fulltime);
891 x2->addattribute ("fulltime", tempstr);
892 x2->addattribute ("type", playertype[gameptr->player[0].type]);
893 x2->setvalue (gameptr->player[0].name);
894 x1->addcontent (x2);
896 // black player
897 x2 = new xmlite_entity ("blackplayer");
898 sprintf (tempstr, "%f", gameptr->player[1].timer);
899 x2->addattribute ("timeleft", tempstr);
900 sprintf (tempstr, "%d", gameptr->player[1].fulltime);
901 x2->addattribute ("fulltime", tempstr);
902 x2->addattribute ("type", playertype[gameptr->player[1].type]);
903 x2->setvalue (gameptr->player[1].name);
904 x1->addcontent (x2);
906 // last gameboard
907 x2 = b_to_xml (gameptr->boards[0]);
908 x1->addcontent (x2);
910 // gamelog
911 x2 = logtoxml (gameptr->movelog);
912 x1->addcontent (x2);
914 x1->writetofile (filename);
915 delete (x1);
917 setcurrentfilename (filename);
919 return;
923 void setupmove (gamestruct * thegame)
925 char tempstr[100],
926 nextpiece,
927 winner = ' ';
929 if ((thegame == NULL) || (thegame->state == GAME_STOP))
931 changeinterface (INTERFACE_PLAY, thegame);
932 return;
935 while (1)
937 Fl::check ();
939 if (thegame->player[0].fulltime != -1)
941 if (thegame->player[0].timer <= 0.0)
943 winner = 'x';
944 break;
946 if (thegame->player[1].timer <= 0.0)
948 winner = 'o';
949 break;
953 if (interrupt_computer)
955 stoptimer (thegame);
956 interrupt_computer = 0;
957 thegame->state = GAME_STOP;
958 break;
961 changeinterface (INTERFACE_PLAY, thegame);
963 if (b_status (thegame->boards[0]) == S_NORMAL)
965 nextpiece = b_next_piece (thegame->boards[0]);
966 /* check if gipf-pieces left */
967 if (thegame->game_type != T_BASIC)
969 if (((b_move_counter (thegame->boards[0]) > 1) ||
970 (thegame->game_type == T_OTHER) || (nextpiece == 'x')) &&
971 (b_white_gipf (thegame->boards[0]) == 0))
973 winner = 'x';
974 break;
976 else if ((b_move_counter (thegame->boards[0]) > 1) &&
977 (b_black_gipf (thegame->boards[0]) == 0))
979 winner = 'o';
980 break;
983 if (b_colour (thegame->boards[0], nextpiece) == 0)
984 { /* game finished */
985 winner = b_opponent (nextpiece);
986 break;
989 if (thegame->player[pnr(nextpiece)].type == 0)
990 { /* human player */
991 gameboard->setto (NULL);
992 gameboard->setfrom (NULL);
993 if (b_colour_type (thegame->boards[0], nextpiece) == 'g')
994 gameboard->setgipfpossible (1);
995 else
996 gameboard->setgipfpossible (0);
998 starttimer (thegame, nextpiece);
999 break;
1001 else
1002 { /* computer player */
1003 fl_cursor (FL_CURSOR_WAIT);
1004 Fl::check ();
1006 computermove (thegame);
1008 fl_cursor (FL_CURSOR_DEFAULT);
1011 else if (b_status (thegame->boards[0]) == S_REMOVEGIPF)
1013 gipf_questions (thegame);
1015 else if (b_status (thegame->boards[0]) == S_REMOVEROW)
1017 row_questions (thegame);
1021 if (winner != ' ')
1023 sprintf (tempstr, "Player %s, you have won after %d moves !",
1024 thegame->player[pnr(winner)].name,
1025 b_move_counter (thegame->boards[0]));
1026 gf1_alert (tempstr);
1027 thegame->state = GAME_STOP;
1030 changeinterface (INTERFACE_PLAY, thegame);
1031 Fl::check ();
1032 return;
1036 void computermove (gamestruct * thegame)
1038 char nextpiece,
1039 piecetype,
1040 from[3] = " ",
1041 to[3] =" ",
1042 piece;
1043 int playertype;
1044 board * temp_board,
1045 * new_board = NULL;
1046 Fl_Window * thinkwindow;
1048 temp_board = b_copy (thegame->boards[0]);
1049 nextpiece = b_next_piece (thegame->boards[0]);
1050 piecetype = b_colour_type (thegame->boards[0], nextpiece);
1051 playertype = thegame->player[pnr(nextpiece)].type;
1053 starttimer (thegame, nextpiece);
1055 thinkwindow = create_thinkwindow ();
1057 (* players[playertype].movefunc)
1058 (temp_board, thegame->player[pnr(nextpiece)].self,
1059 thegame->player[pnr(nextpiece)].timer,
1060 &piecetype, from, to);
1062 Fl::check ();
1063 delete thinkwindow;
1065 stoptimer (thegame);
1066 if (interrupt_computer)
1067 return;
1069 if ((b_colour_type (thegame->boards[0], nextpiece) != 'g') &&
1070 (piecetype == 'g'))
1072 piecetype = 'n';
1075 piece = piecetype == 'g' ? b_otherpiece (nextpiece) : nextpiece;
1077 b_setlog (thegame->boards[0], thegame->movelog);
1078 new_board = b_move (thegame->boards[0], from, to, piece);
1079 b_nolog (thegame->boards[0]);
1080 b_nolog (new_board);
1082 b_del (temp_board);
1083 if (new_board == NULL)
1085 gf1_alert ("the computer-player executed an invalid move !!");
1087 // b_del (thegame->boards[0]);
1088 // (* players[thegame->player[0].type].endfunc)(thegame->player[0].self);
1089 // (* players[thegame->player[1].type].endfunc)(thegame->player[1].self);
1090 // thegame->boards[0] = NULL;
1092 else
1094 b_del (thegame->boards[2]);
1095 thegame->boards[2] = thegame->boards[1];
1096 thegame->boards[1] = thegame->boards[0];
1097 thegame->boards[0] = new_board;
1099 analysemove (thegame, playertype);
1101 gameboard->setboard (thegame->boards[0]);
1104 return;
1108 int humanmove (gamestruct * thegame)
1110 char nextpiece,
1111 piece;
1112 int playertype;
1113 board * new_board = NULL;
1114 char * from,
1115 * to,
1116 piecetype;
1118 if (thegame->state == GAME_STOP)
1119 return (0);
1121 from = postostr (gameboard->getfrom ());
1122 to = postostr (gameboard->getto ());
1123 if (gameboard->getptype ())
1124 piecetype = 'g';
1125 else
1126 piecetype = 'n';
1128 nextpiece = b_next_piece (thegame->boards[0]);
1129 playertype = thegame->player[pnr(nextpiece)].type;
1131 if ((b_colour_type (thegame->boards[0], nextpiece) != 'g') &&
1132 (piecetype == 'g'))
1134 piecetype = 'n';
1137 piece = piecetype == 'g' ? b_otherpiece (nextpiece) : nextpiece;
1139 b_setlog (thegame->boards[0], thegame->movelog);
1140 new_board = b_move (thegame->boards[0], from, to, piece);
1141 b_nolog (thegame->boards[0]);
1142 if (new_board != NULL)
1143 b_nolog (new_board);
1145 free (from);
1146 free (to);
1148 if (new_board == NULL)
1150 return (-1);
1153 stoptimer (thegame);
1155 b_del (thegame->boards[2]);
1156 thegame->boards[2] = thegame->boards[1];
1157 thegame->boards[1] = thegame->boards[0];
1158 thegame->boards[0] = new_board;
1160 analysemove (thegame, 0);
1162 gameboard->setto (NULL);
1163 gameboard->setfrom (NULL);
1164 gameboard->setboard (thegame->boards[0]);
1166 return (0);
1170 void row_questions (gamestruct * thegame)
1172 board * temp_board,
1173 * new_board;
1174 int counter;
1175 rem_row * row;
1176 listheader * rowlist;
1177 char owner,
1178 response,
1179 * start,
1180 * end,
1181 tempstr1[100],
1182 tempstr2[100];
1183 int answer;
1185 temp_board = b_copy (thegame->boards[0]);
1186 counter = 1;
1187 rowlist = b_row_extra (thegame->boards[0]);
1188 while ((row = (rem_row *) llitembynr (rowlist, counter)) != NULL)
1190 counter++;
1191 start = postostr (row->startpos);
1192 end = postostr (row->endpos);
1193 owner = row_owner (row);
1195 starttimer (thegame, owner);
1196 if (thegame->player[pnr(owner)].type == 0)
1197 { /* human */
1198 gameboard->setrow (row->piecelist);
1199 gameboard->setboard (thegame->boards[0]);
1201 sprintf (tempstr1, "Player %s, do you want to remove",
1202 thegame->player[pnr(owner)].name);
1203 sprintf (tempstr2, "the row from %s to %s", start, end);
1205 answer = 2;
1206 while (answer == 2)
1208 answer = gf1_questionsave (tempstr1, tempstr2);
1210 if (answer == 2)
1211 savegame (thegame);
1212 else if (answer == 1)
1213 response = 'y';
1214 else
1215 response = 'n';
1218 gameboard->setrow (NULL);
1220 else
1221 { /* computer */
1222 Fl_Window * thinkwindow;
1224 thinkwindow = create_thinkwindow ();
1226 response =
1227 (* players[thegame->player[pnr(owner)].type].rowfunc)
1228 (temp_board, thegame->player[pnr(owner)].self,
1229 thegame->player[pnr(owner)].timer, start, end);
1231 delete thinkwindow;
1233 stoptimer (thegame);
1234 if (interrupt_computer)
1235 return;
1237 free (start);
1238 free (end);
1240 if (response == 'y')
1242 b_setlog (thegame->boards[0], thegame->movelog);
1243 new_board = b_remove_row (thegame->boards[0], counter-1);
1244 b_nolog (new_board);
1245 b_del (thegame->boards[0]);
1246 thegame->boards[0] = new_board;
1248 analysemove (thegame, thegame->player[pnr(owner)].type);
1250 gameboard->setboard (thegame->boards[0]);
1252 break;
1255 b_del (temp_board);
1257 return;
1261 void gipf_questions (gamestruct * thegame)
1263 int counter;
1264 rem_gipf * gipf;
1265 board * nboard,
1266 * new_board,
1267 * temp_board;
1268 listheader * gipflist;
1269 char owner,
1270 * strpos,
1271 response;
1272 char tempstr1[100],
1273 tempstr2[100];
1274 int answer;
1276 counter = 1;
1277 gipflist = b_gipf_extra (thegame->boards[0]);
1278 new_board = thegame->boards[0];
1280 while ((gipf = (rem_gipf *) llitembynr (gipflist, counter)) != NULL)
1282 counter++;
1283 strpos = b_gipf_position (gipf);
1284 owner = b_gipf_owner (gipf);
1286 starttimer (thegame, owner);
1287 if (thegame->player[pnr(owner)].type == 0)
1288 { /* human */
1289 gameboard->setto (gipf->pos);
1290 gameboard->setboard (new_board);
1292 sprintf (tempstr1, "Player %s, do you want to remove",
1293 thegame->player[pnr(owner)].name);
1294 sprintf (tempstr2, "the GIPF at %s", strpos);
1296 answer = 2;
1297 while (answer == 2)
1300 ** only allow saving of the game at the first question
1301 ** for removing a gipf.
1302 ** things get fishy if you would save from here after a gipf
1303 ** has been removed already.
1304 ** (the problem doesn't occur immediatly, but when you load
1305 ** the game again)
1307 if (counter == 2)
1308 answer = gf1_questionsave (tempstr1, tempstr2);
1309 else
1310 answer = gf1_question (tempstr1, tempstr2);
1313 if (answer == 2)
1314 savegame (thegame);
1315 else if (answer == 1)
1316 response = 'y';
1317 else
1318 response = 'n';
1321 gameboard->setto (NULL);
1323 else
1324 { /* computer */
1325 Fl_Window * thinkwindow;
1327 thinkwindow = create_thinkwindow ();
1329 temp_board = b_copy (new_board);
1330 response = (* players[thegame->player[pnr(owner)].type].gipffunc)
1331 (temp_board, thegame->player[pnr(owner)].self,
1332 thegame->player[pnr(owner)].timer, strpos);
1333 b_del (temp_board);
1335 delete thinkwindow;
1337 stoptimer (thegame);
1338 if (interrupt_computer)
1339 return;
1341 if ((response == 'y') || (response == 'Y'))
1343 b_setlog (new_board, thegame->movelog);
1344 nboard = b_remove_gipf (new_board, gipf);
1345 b_nolog (new_board);
1346 b_nolog (nboard);
1348 if (new_board != thegame->boards[0])
1349 b_del (new_board);
1351 new_board = nboard;
1353 analysemove (thegame, thegame->player[pnr(owner)].type);
1355 gameboard->setboard (new_board);
1357 free (strpos);
1360 b_setlog (new_board, thegame->movelog);
1361 nboard = b_checkfour (new_board);
1362 b_nolog (new_board);
1363 b_nolog (nboard);
1364 if (new_board != thegame->boards[0])
1365 b_del (new_board);
1367 b_del (thegame->boards[0]);
1368 thegame->boards[0] = nboard;
1370 analysemove (thegame, 1);
1372 gameboard->setboard (thegame->boards[0]);
1374 return;
1378 //time_t basetime = 0;
1379 struct timeval basetime;
1380 char timercolor;
1382 void starttimer (gamestruct * thegame, char color)
1384 struct timezone tz;
1386 if (thegame->player[0].fulltime == -1)
1388 basetime.tv_sec = 0;
1389 return;
1392 // basetime = time (NULL);
1393 gettimeofday (&basetime, &tz);
1394 timercolor = color;
1396 Fl::add_timeout (1.0, updatetimer, (void *) thegame);
1398 return;
1402 void stoptimer (gamestruct * thegame)
1404 // time_t newtime;
1405 struct timezone tz;
1406 struct timeval tv;
1407 float timedif;
1408 char tempstr[20];
1410 if ((thegame == NULL) || (basetime.tv_sec == 0))
1411 return;
1413 Fl::remove_timeout (updatetimer, (void *) thegame);
1415 // newtime = time (NULL);
1416 gettimeofday (&tv, &tz);
1417 timedif = (tv.tv_sec - basetime.tv_sec) +
1418 (float) (tv.tv_usec - basetime.tv_usec)/1000000;
1420 if (timercolor == 'o')
1422 if (interrupt_computer == 0)
1423 thegame->player[0].timer -= timedif;
1424 timertostr (thegame->player[0].timer, tempstr);
1425 whitetimer->value (tempstr);
1427 else
1429 if (interrupt_computer == 0)
1430 thegame->player[1].timer -= timedif;
1431 timertostr (thegame->player[1].timer, tempstr);
1432 blacktimer->value (tempstr);
1435 basetime.tv_sec = 0;
1436 return;
1440 void updatetimer (void * data)
1442 gamestruct * thegame = (gamestruct *) data;
1443 // time_t newtime;
1444 struct timezone tz;
1445 struct timeval tv;
1446 float timedif;
1447 float newtimer;
1448 char tempstr[20];
1450 // newtime = time (NULL);
1451 gettimeofday (&tv, &tz);
1452 timedif = (tv.tv_sec - basetime.tv_sec) +
1453 (float) (tv.tv_usec - basetime.tv_usec)/1000000;
1455 if (timercolor == 'o')
1457 newtimer = thegame->player[0].timer - timedif;
1458 timertostr (newtimer, tempstr);
1459 whitetimer->value (tempstr);
1461 else
1463 newtimer = thegame->player[1].timer - timedif;
1464 timertostr (newtimer, tempstr);
1465 blacktimer->value (tempstr);
1468 if (newtimer > 0.0)
1469 Fl::add_timeout (1.0, updatetimer, data);
1470 else
1471 { /* timer ran out, show if this is a human move */
1472 if (timercolor == 'o')
1474 if (thegame->player[0].type == 0)
1476 thegame->player[0].timer = newtimer;
1478 setupmove (thegame);
1481 else if (thegame->player[1].type == 0)
1483 thegame->player[1].timer = newtimer;
1485 setupmove (thegame);
1489 return;
1494 ** analyse the entries added to the gamelog
1495 ** since the last time we ran this function
1496 ** show what needs to be shown to the user
1498 void analysemove (gamestruct * thegame, int playertype)
1500 int counter = thegame->movecounter + 1;
1501 logitem * item;
1503 while ((item = logitemnr (thegame->movelog, counter)) != NULL)
1505 switch (logitem_type (item))
1507 case LOGMOVE:
1508 showmove (thegame, playertype, item);
1509 break;
1510 case LOGREMGIPF:
1511 showremgipf (thegame, playertype, item);
1512 break;
1513 case LOGREMROW:
1514 showremrow (thegame, playertype, item);
1515 break;
1518 counter++;
1519 playertype = 1; /* necessary in case a row is removed automatically */
1521 thegame->movecounter = counter - 1;
1523 /* show the correct board */
1524 gameboard->setboard (thegame->boards[0]);
1526 return;
1530 void showmove (gamestruct * thegame, int playertype, logitem * item)
1532 char start[3] = " ",
1533 end[3] = " ";
1534 position * startpos,
1535 * endpos,
1536 * topos;
1537 int dir,
1538 counter;
1539 listheader * plist;
1540 struct movepiece {
1541 char piece;
1542 position * from;
1543 position * to;
1544 } * mpiece;
1545 board * oldboard,
1546 * newboard,
1547 * nboard;
1549 strncpy (start, logitem_start (item), 2);
1550 strncpy (end, logitem_end (item), 2);
1551 startpos = strtopos (start);
1552 endpos = strtopos (end);
1553 topos = new_position ();
1556 **from the start and the end of the move we can find the to-position
1557 ** and the direction of the move
1559 if (posp_col (startpos) == posp_col (endpos))
1561 posp_col (topos) = posp_col (startpos);
1562 if (posp_row (startpos) > posp_row (endpos))
1564 posp_row (topos) = posp_row (startpos) - 1;
1565 dir = 2;
1567 else
1569 posp_row (topos) = posp_row (startpos) + 1;
1570 dir = 3;
1573 else if (posp_col (startpos) < posp_col (endpos))
1575 posp_col (topos) = posp_col (startpos) + 1;
1576 if (posp_row (startpos) >= posp_row (endpos))
1578 posp_row (topos) = posp_row (startpos);
1579 dir = 4;
1581 else
1583 posp_row (topos) = posp_row (startpos) + 1;
1584 dir = 5;
1587 else
1589 posp_col (topos) = posp_col (startpos) - 1;
1590 if (posp_row (startpos) >= posp_row (endpos))
1592 posp_row (topos) = posp_row (startpos);
1593 dir = 0;
1595 else
1597 posp_row (topos) = posp_row (startpos) + 1;
1598 dir = 1;
1603 ** reasons to wait before showing the move
1604 ** - waitcomputer > 0
1605 ** - move by the computer
1607 if ((playertype != 0) &&
1608 (thegame->config->waitcomputer > 0))
1609 { /* computerplayer */
1610 if ((logitem_player (item) == 'O') ||
1611 (logitem_player (item) == 'X'))
1613 gameboard->setgipfpossible (1);
1615 else
1617 gameboard->setgipfpossible (0);
1619 gameboard->setfrom (startpos);
1620 gameboard->setto (topos);
1622 /* the first Fl::wait is necessary to reset the start of the timer */
1623 Fl::wait (0);
1624 for (float time = thegame->config->waitcomputer * 1.0; time > 0; )
1625 time = Fl::wait(time);
1626 #if 0
1627 Fl::check ();
1628 #ifdef MSWIN
1629 sleep (thegame->config->waitcomputer * 1000);
1630 #else
1631 sleep (thegame->config->waitcomputer);
1632 #endif
1633 #endif
1635 gameboard->setto (NULL);
1636 gameboard->setfrom (NULL);
1640 ** make a list of all the pieces that move
1641 ** + from and to position
1643 plist = (listheader *) malloc (sizeof (listheader));
1644 newlist (plist);
1645 mpiece = (struct movepiece *) malloc (sizeof (struct movepiece));
1646 mpiece->piece = logitem_player (item);
1647 mpiece->from = (position *) copy_position ((void *) startpos);
1648 mpiece->to = (position *) copy_position ((void *) topos);
1649 pushll (plist, mpiece);
1650 while ((posp_col (topos) != posp_col (endpos)) ||
1651 (posp_row (topos) != posp_row (endpos)))
1653 posp_col (startpos) = posp_col (topos);
1654 posp_row (startpos) = posp_row (topos);
1655 posp_col (topos) =
1656 b_buren[posp_col (startpos)][posp_row (startpos)][dir][0];
1657 posp_row (topos) =
1658 b_buren[posp_col (startpos)][posp_row (startpos)][dir][1];
1660 mpiece = (struct movepiece *) malloc (sizeof (struct movepiece));
1661 mpiece->piece = b_ppiece (gameboard->getboard (), startpos);
1662 mpiece->from = (position *) copy_position ((void *) startpos);
1663 mpiece->to = (position *) copy_position ((void *) topos);
1664 pushll (plist, mpiece);
1668 ** reason to animate the move
1669 ** - animate > 0
1671 if (thegame->config->animate > 0)
1672 { /* animate */
1673 int steps = 10;
1674 switch (thegame->config->animate)
1676 case 1: /* slow */
1677 steps = 20;
1678 break;
1679 case 2: /* medium */
1680 steps = 13;
1681 break;
1682 case 3: /* fast */
1683 steps = 8;
1684 break;
1686 gameboard->initanim (steps, plist);
1688 // Fl::wait (0);
1689 for (int i = 0; i <= steps; i++)
1691 gameboard->animstep (i);
1692 #ifdef MSWIN
1693 /* this timing looks a little better on ms windows */
1694 for (float time = 0.02; time > 0; )
1695 time = Fl::wait(time);
1696 #else
1697 for (float time = 0.03; time > 0; )
1698 time = Fl::wait(time);
1699 #endif
1703 /* update board */
1704 nboard = oldboard = gameboard->getboard ();
1705 counter = 1;
1706 while ((mpiece = (struct movepiece *) llitembynr (plist, counter))
1707 != NULL)
1709 counter++;
1710 newboard = b_edit_piece (nboard, mpiece->to, mpiece->piece);
1711 if (nboard != oldboard)
1712 b_del (nboard);
1713 nboard = newboard;
1715 gameboard->setboard (nboard);
1716 if (nboard != oldboard)
1717 b_del (nboard);
1719 /* cleanup */
1720 while ((mpiece = (struct movepiece *) llrembynr (plist, 1)) != NULL)
1722 free (mpiece->from);
1723 free (mpiece->to);
1724 free (mpiece);
1726 free (plist);
1727 del_position (startpos);
1728 del_position (endpos);
1729 del_position (topos);
1731 return;
1735 void showremgipf (gamestruct * thegame, int playertype, logitem * item)
1737 listheader * piecelist;
1738 char * piece,
1739 posstr[3] = " ";
1740 position * ppos;
1741 board * oldboard,
1742 * newboard;
1744 piecelist = logitem_plist (item);
1745 piece = (char *) llitembynr (piecelist, 1);
1746 strncpy (posstr, piece, 2);
1747 ppos = strtopos (posstr);
1750 ** reasons for showing the removal of a gipf
1751 ** - waitremove > 0
1752 ** - gipf removed by a computer-player
1754 if ((playertype != 0) &&
1755 (thegame->config->waitremove > 0))
1756 { /* computerplayer */
1757 gameboard->setfrom (NULL);
1758 gameboard->setto (ppos);
1760 /* the first Fl::wait is necessary to reset the start of the timer */
1761 Fl::wait (0);
1762 for (float time = thegame->config->waitremove * 1.0; time > 0; )
1763 time = Fl::wait(time);
1764 #if 0
1765 Fl::check ();
1766 #ifdef MSWIN
1767 sleep (thegame->config->waitremove * 1000);
1768 #else
1769 sleep (thegame->config->waitremove);
1770 #endif
1771 #endif
1773 gameboard->setto (NULL);
1775 /* now we update the gameboard */
1776 oldboard = gameboard->getboard ();
1777 newboard = b_edit_piece (oldboard, ppos, '.');
1778 gameboard->setboard (newboard);
1779 b_del (newboard);
1781 del_position (ppos);
1783 return;
1787 void showremrow (gamestruct * thegame, int playertype, logitem * item)
1789 listheader * poslist,
1790 * piecelist;
1791 char start[3] = " ",
1792 end[3] = " ",
1793 posstr[3] = " ",
1794 * ptr;
1795 int dir,
1796 counter;
1797 position * ppos,
1798 * prevpos,
1799 * startpos,
1800 * endpos;
1801 board * oldboard,
1802 * newboard,
1803 * nboard;
1805 strncpy (start, logitem_start (item), 2);
1806 strncpy (end, logitem_end (item), 2);
1807 startpos = strtopos (start);
1808 endpos = strtopos (end);
1810 /* find the direction between start and end */
1811 if (posp_col (startpos) == posp_col (endpos))
1813 if (posp_row (startpos) > posp_row (endpos))
1814 dir = 2;
1815 else
1816 dir = 3;
1818 else if (posp_col (startpos) < posp_col (endpos))
1820 if (posp_row (startpos) > posp_row (endpos))
1821 dir = 4;
1822 else if (posp_row (startpos) < posp_row (endpos))
1823 dir = 5;
1824 else
1826 if (posp_col (startpos) < 4)
1827 dir = 4;
1828 else
1829 dir = 5;
1832 else
1834 if (posp_row (startpos) > posp_row (endpos))
1835 dir = 0;
1836 else if (posp_row (startpos) < posp_row (endpos))
1837 dir = 1;
1838 else
1840 if (posp_col (startpos) > 4)
1841 dir = 0;
1842 else
1843 dir = 1;
1848 /* make a list with all positions between start and end */
1849 piecelist = logitem_plist (item);
1850 poslist = (listheader *) malloc (sizeof (listheader));
1851 newlist (poslist);
1853 pushll (poslist, startpos);
1855 prevpos = startpos;
1856 while ((b_buren[posp_col(prevpos)][posp_row(prevpos)][dir][0]
1857 != posp_col(endpos)) ||
1858 (b_buren[posp_col(prevpos)][posp_row(prevpos)][dir][1]
1859 != posp_row(endpos)))
1861 ppos = new_position ();
1862 posp_col(ppos) = b_buren[posp_col(prevpos)][posp_row(prevpos)][dir][0];
1863 posp_row(ppos) = b_buren[posp_col(prevpos)][posp_row(prevpos)][dir][1];
1865 pushll (poslist, ppos);
1866 prevpos = ppos;
1868 pushll (poslist, endpos);
1871 ** reasons for showing the removal of a row
1872 ** - waitremove > 0
1873 ** - row automatically removed
1874 ** or row removed by a computer-player
1876 if ((playertype != 0) &&
1877 (thegame->config->waitremove > 0))
1878 { /* computerplayer */
1879 gameboard->setrow (poslist);
1881 /* the first Fl::wait is necessary to reset the start of the timer */
1882 Fl::wait (0);
1883 for (float time = thegame->config->waitremove * 1.0; time > 0; )
1884 time = Fl::wait(time);
1885 #if 0
1886 Fl::check ();
1887 #ifdef MSWIN
1888 sleep (thegame->config->waitremove * 1000);
1889 #else
1890 sleep (thegame->config->waitremove);
1891 #endif
1892 #endif
1894 gameboard->setrow (NULL);
1896 /* cleanup */
1897 while ((ppos = (position *) llrembynr (poslist, 1)) != NULL)
1899 free (ppos);
1901 free (poslist);
1903 /* now we update the gameboard */
1904 poslist = logitem_plist (item);
1905 oldboard = gameboard->getboard ();
1906 nboard = oldboard;
1907 counter = 1;
1908 while ((ptr = (char *) llitembynr (poslist, counter)) != 0)
1910 counter++;
1911 strncpy (posstr, ptr, 2);
1912 ppos = strtopos (posstr);
1913 newboard = b_edit_piece (nboard, ppos, '.');
1914 if (nboard != oldboard)
1915 b_del (nboard);
1916 nboard = newboard;
1917 free (ppos);
1919 gameboard->setboard (nboard);
1921 if (nboard != oldboard)
1922 b_del (nboard);
1924 return;
1929 ** this doesn't make gif-files anymore, but png-files
1931 void show_makegif (board * game)
1933 #ifdef HAVEGD
1934 Fl_Window * gifw;
1935 drawgif drawing;
1936 const char * str;
1937 int i;
1938 static int def_size = 300,
1939 def_colour = 1;
1941 gifw = make_gifwindow ();
1943 // set default values
1944 gif_filename->value ("./game.png");
1945 gif_size->value (def_size);
1946 if (def_colour)
1947 gif_colour->setonly ();
1948 else
1949 gif_bw->setonly ();
1950 gif_extratext->value (NULL);
1952 gifw->show ();
1954 while (1)
1956 Fl::wait();
1958 Fl_Widget *x;
1959 while ((x = Fl::readqueue()))
1961 if (x == gif_choose)
1963 if ((str = file_chooser ("Filename", "*.gif",
1964 gif_filename->value ())) != NULL)
1966 gif_filename->value (str);
1969 else if (x == gif_ok)
1971 drawing.filename (gif_filename->value ());
1972 def_size = (int) gif_size->value ();
1973 drawing.gifsize (def_size);
1974 drawing.gifboard (game);
1975 if (gif_colour->value ())
1976 def_colour = 1;
1977 else
1978 def_colour = 0;
1979 drawing.gifcolour (def_colour);
1981 str = gif_extratext->value ();
1982 // check if the string contains something
1983 for (i = 0; i < strlen (str); i++)
1985 if (! isspace ((int) str[i]))
1987 drawing.addtext (str);
1988 break;
1991 drawing.draw ();
1993 delete gifw;
1994 return;
1996 else if (x == gif_cancel)
1998 delete gifw;
1999 return;
2003 #endif
2005 return;