(Temporarily) set "animate" to "none" by default (broken feature).
[gf1.git] / thegame.cxx
blobdf4a0cb18fbb22e8ea4df945ef5cf4a23c412887
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 <cstdio>
25 #include <cstdlib>
26 #include <cstring>
27 #include <cctype>
28 #include <ctime>
29 #include <unistd.h>
30 #include <FL/fl_draw.H>
31 #include <FL/Fl.H>
33 #ifdef MSWIN
34 #include "gettimeofday.h"
35 #endif
37 #include "thegame.h"
38 #include "gipf_ui.H"
39 #include "board.h"
40 #include "callbacks.h"
41 #include "player_info.h"
42 #include "drawgif.h"
43 #include "xmlite.h"
45 char gametype[4][15] = {"basic", "standard", "tournament", "other game"};
46 char playertype[2][9] = {"human", "computer"};
49 ** show the window for starting a new game
51 ** if the user pressed OK, this will return a structure for starting
52 ** a new game
54 ** if you give a parameter different from NULL, then the window will be
55 ** initialised from this game, otherwise, defaults are used
57 gamestruct * show_new (gamestruct * oldgame)
59 Fl_Window * neww;
60 gamestruct * newgame;
62 neww = make_newwindow ();
64 // initialize values
65 if (oldgame != NULL)
67 // gametype
68 switch (oldgame->game_type)
70 case T_BASIC:
71 radio_basic->setonly();
72 break;
73 case T_STANDARD:
74 radio_standard->setonly();
75 break;
76 case T_TOURNAMENT:
77 radio_tournament->setonly();
78 break;
81 // player names
82 whiteplayername->value (oldgame->player[0].name);
83 blackplayername->value (oldgame->player[1].name);
85 // player type
86 if (oldgame->player[0].type)
87 radio_wcompu->setonly();
88 else
89 radio_whuman->setonly();
91 if (oldgame->player[1].type)
92 radio_bcompu->setonly();
93 else
94 radio_bhuman->setonly();
96 // timed game
97 if (oldgame->player[0].fulltime == -1)
99 toggle_timedgame->clear();
101 else
103 toggle_timedgame->set();
104 whitetime->value (oldgame->player[0].fulltime / 60);
105 blacktime->value (oldgame->player[1].fulltime / 60);
108 else
110 radio_tournament->setonly();
111 toggle_timedgame->clear();
112 radio_whuman->setonly();
113 radio_bcompu->setonly();
116 // show or hide the time-counters
117 if (toggle_timedgame->value())
119 whitetime->activate();
120 blacktime->activate();
122 else
124 whitetime->deactivate();
125 blacktime->deactivate();
128 neww->show();
130 while (1)
132 Fl::wait();
134 Fl_Widget *x;
135 while ((x = Fl::readqueue()))
137 if (x == toggle_timedgame)
139 if (toggle_timedgame->value())
141 whitetime->activate();
142 blacktime->activate();
144 else
146 whitetime->deactivate();
147 blacktime->deactivate();
150 else if (x == new_ok)
152 newgame = (gamestruct *) malloc (sizeof (gamestruct));
153 newgame->state = GAME_GO;
154 newgame->movecounter = 0;
156 if (radio_whuman->value())
157 newgame->player[0].type = 0;
158 else
159 newgame->player[0].type = 1;
160 if (radio_bhuman->value())
161 newgame->player[1].type = 0;
162 else
163 newgame->player[1].type = 1;
165 strcpy (newgame->player[0].name, whiteplayername->value());
166 strcpy (newgame->player[1].name, blackplayername->value());
168 if (toggle_timedgame->value())
170 newgame->player[0].fulltime = 60 * (int)whitetime->value();
171 newgame->player[0].timer =
172 (float) newgame->player[0].fulltime;
173 newgame->player[1].fulltime = 60 * (int)blacktime->value();
174 newgame->player[1].timer =
175 (float) newgame->player[1].fulltime;
177 else
179 newgame->player[0].fulltime = -1;
180 newgame->player[0].timer = 0.0;
181 newgame->player[1].fulltime = -1;
182 newgame->player[1].timer = 0.0;
185 if (radio_basic->value ()) { newgame->game_type = T_BASIC;}
186 else if (radio_standard->value ())
187 { newgame->game_type = T_STANDARD;}
188 else if (radio_tournament->value ())
189 { newgame->game_type = T_TOURNAMENT;}
190 else { return (NULL);}
192 newgame->boards[0] = b_new (newgame->game_type);
193 newgame->boards[1] = NULL;
194 newgame->boards[2] = NULL;
196 // initialize players
197 newgame->player[0].self =
198 (* players[newgame->player[0].type].newfunc)
199 ('o', newgame->game_type);
200 newgame->player[1].self =
201 (* players[newgame->player[1].type].newfunc)
202 ('x', newgame->game_type);
204 newgame->movelog = newlog (gametype[newgame->game_type],
205 newgame->player[0].name,
206 newgame->player[1].name);
208 delete neww;
210 setcurrentfilename ("\0");
212 return (newgame);
214 else if (x == new_cancel)
216 delete neww;
217 return (NULL);
222 return (NULL);
227 ** show the window for starting a game from a gameboard
229 ** if the user pressed OK, this will return a structure for starting
230 ** a the game
232 ** the parameter is the board to start from
234 gamestruct * show_start (board * startboard)
236 Fl_Window * startw;
237 gamestruct * newgame;
238 board * newboard;
240 if ((newboard = verify_board (startboard)) == NULL)
242 return (NULL);
245 startw = make_startwindow ();
247 /* put default settings in window */
248 radio_white->setonly ();
249 radio_s_whuman->setonly ();
250 radio_s_bcompu->setonly ();
251 if (newboard->typewhite == 'g')
252 toggle_s_whitegipf->set ();
253 else
254 toggle_s_whitegipf->deactivate ();
255 if (newboard->typeblack == 'g')
256 toggle_s_blackgipf->set ();
257 else
258 toggle_s_blackgipf->deactivate ();
260 startw->show();
262 while (1)
264 Fl::wait();
266 Fl_Widget *x;
267 while ((x = Fl::readqueue()))
269 if (x == start_ok)
271 newgame = (gamestruct *) malloc (sizeof (gamestruct));
272 newgame->state = GAME_GO;
273 newgame->movecounter = 0;
275 if (radio_s_whuman->value() != 0)
276 newgame->player[0].type = 0;
277 else
278 newgame->player[0].type = 1;
280 if (radio_s_bhuman->value() != 0)
281 newgame->player[1].type = 0;
282 else
283 newgame->player[1].type = 1;
285 strcpy (newgame->player[0].name, s_whiteplayername->value());
286 strcpy (newgame->player[1].name, s_blackplayername->value());
288 newgame->player[0].fulltime = -1;
289 newgame->player[0].timer = 0.0;
290 newgame->player[1].fulltime = -1;
291 newgame->player[1].timer = 0.0;
293 newgame->game_type = T_OTHER;
295 if ((newboard->typewhite == 'g') &&
296 (toggle_s_whitegipf->value () == 0))
297 newboard->typewhite = 'n';
298 if ((newboard->typeblack == 'g') &&
299 (toggle_s_blackgipf->value () == 0))
300 newboard->typeblack = 'n';
302 if (radio_white->value () != 0)
303 newboard->nextpiece = 'o';
304 else
305 newboard->nextpiece = 'x';
307 newgame->boards[0] = newboard;
308 newgame->boards[1] = NULL;
309 newgame->boards[2] = NULL;
311 // initialize players
312 newgame->player[0].self =
313 (* players[newgame->player[0].type].newfunc)
314 ('o', newgame->game_type);
315 newgame->player[1].self =
316 (* players[newgame->player[1].type].newfunc)
317 ('x', newgame->game_type);
319 newgame->movelog = newlog (gametype[newgame->game_type],
320 newgame->player[0].name,
321 newgame->player[1].name);
323 delete (startw);
325 setcurrentfilename ("\0");
327 return (newgame);
329 else if (x == start_cancel)
331 b_del (newboard);
332 delete (startw);
333 return (NULL);
338 return (NULL);
343 ** show the window for calculating one move starting from a gameboard
345 ** if the user pressed OK, this will return a structure for calculating
346 ** the one move
348 ** the parameter is the board to start from
350 gamestruct * show_onemove (board * startboard, configvalues * conf)
352 Fl_Window * onemovew;
353 gamestruct * newgame;
354 board * newboard;
355 int newlevel,
356 oldlevel;
358 if ((newboard = verify_board (startboard)) == NULL)
360 return (NULL);
363 onemovew = make_onemovewindow ();
365 radio_c_white->setonly ();
366 c_level3->setonly ();
368 onemovew->show();
370 while (1)
372 Fl::wait();
374 Fl_Widget *x;
375 while ((x = Fl::readqueue()))
377 if (x == one_ok)
379 newgame = (gamestruct *) malloc (sizeof (gamestruct));
380 newgame->state = GAME_GO;
381 newgame->movecounter = 0;
383 if (radio_c_white->value() != 0)
385 newgame->player[0].type = 1;
386 newgame->player[1].type = 0;
387 strcpy (newgame->player[0].name, "Computer");
388 strcpy (newgame->player[1].name, "None");
389 newboard->nextpiece = 'o';
391 else
393 newgame->player[0].type = 0;
394 newgame->player[1].type = 1;
395 strcpy (newgame->player[1].name, "Computer");
396 strcpy (newgame->player[0].name, "None");
397 newboard->nextpiece = 'x';
400 newgame->player[0].fulltime = -1;
401 newgame->player[0].timer = 0.0;
402 newgame->player[1].fulltime = -1;
403 newgame->player[1].timer = 0.0;
405 newgame->game_type = T_OTHER;
407 newgame->boards[0] = newboard;
408 newgame->boards[1] = NULL;
409 newgame->boards[2] = NULL;
411 newgame->config = conf;
413 // initialize players
414 newgame->player[0].self =
415 (* players[newgame->player[0].type].newfunc)
416 ('o', newgame->game_type);
417 newgame->player[1].self =
418 (* players[newgame->player[1].type].newfunc)
419 ('x', newgame->game_type);
421 newgame->movelog = newlog (gametype[newgame->game_type],
422 newgame->player[0].name,
423 newgame->player[1].name);
425 if ((c_level1->value ()) != 0) { newlevel = 1; }
426 else if ((c_level2->value ()) != 0) { newlevel = 2; }
427 else if ((c_level3->value ()) != 0) { newlevel = 3; }
428 else if ((c_level4->value ()) != 0) { newlevel = 4; }
429 else if ((c_level5->value ()) != 0) { newlevel = 5; }
430 else if ((c_level6->value ()) != 0) { newlevel = 6; }
431 else if ((c_level7->value ()) != 0) { newlevel = 7; }
432 else if ((c_level8->value ()) != 0) { newlevel = 8; }
434 oldlevel = conf->searchdepth;
435 if (newlevel != oldlevel)
437 conf->searchdepth = newlevel;
438 writeconfig (conf);
441 delete (onemovew);
443 setcurrentfilename ("\0");
445 /* execute the move here */
446 gameboard->setboard (newgame->boards[0]);
448 setupmove (newgame);
450 newgame->state = GAME_STOP;
451 changeinterface (INTERFACE_PLAY, newgame);
453 if (newlevel != oldlevel)
455 conf->searchdepth = oldlevel;
456 writeconfig (conf);
459 return (newgame);
461 else if (x == one_cancel)
463 b_del (newboard);
464 delete (onemovew);
465 return (NULL);
470 return (NULL);
475 ** check if a gameboard can be used to start a game from
477 ** returns a copy of sboard that is correctly setup
478 ** or NULL if there is a problem
480 board * verify_board (board * sboard)
482 board * nboard;
483 rem_row * row_ptr;
484 int i, j,
485 white = 0,
486 black = 0;
487 position * pos;
489 /* check if one of the players has no pieces left */
490 if (b_colour (sboard, 'o') == 0)
492 gf1_alert ("ERROR: no game possible from this boardsituation, player white has no pieces left.");
493 return (NULL);
495 if (b_colour (sboard, 'x') == 0)
497 gf1_alert ("ERROR: no game possible from this boardsituation, player black has no pieces left.");
498 return (NULL);
501 /* count pieces on the board */
502 pos = new_position ();
503 for (i = 1; i < 8; i++)
504 for (j = 2; j <= b_colsize (i); j++)
506 posp_col (pos) = i;
507 posp_row (pos) = j;
508 switch (b_ppiece (sboard, pos))
510 case 'o':
511 white += 1;
512 break;
513 case 'O':
514 white += 2;
515 break;
516 case 'x':
517 black += 1;
518 break;
519 case 'X':
520 black += 2;
521 break;
525 /* check if the board is empty */
526 if ((white == 0) && (black == 0))
528 gf1_alert ("ERROR: no game possible from this boardsituation, the gameboard is empty.");
529 return (NULL);
532 /* check for four-in-a-row */
533 for (i = 0; i < 21; i++)
535 if ((row_ptr = b_rowoffour (sboard, i)) != NULL)
537 del_rem_row ((void *) row_ptr);
538 gf1_alert ("ERROR: no game possible from this boardsituation, four-in-a-row found.");
539 return (NULL);
543 /* check if this is a basic game */
544 if ((b_colour_gipf (sboard, 'o') == 0) &&
545 (b_colour_gipf (sboard, 'x') == 0))
547 nboard = b_copy (sboard);
548 nboard->gipfwhite = -1;
549 nboard->gipfblack = -1;
550 nboard->typewhite = 'n';
551 nboard->typeblack = 'n';
553 /* turn this into a real basic game (if possible) */
554 if ((b_colour (nboard, 'o') > 3) && (b_colour (sboard, 'x') > 3))
556 nboard->white -= 3;
557 nboard->black -= 3;
560 return (nboard);
563 /* tournament or standard game, for me it's always tournament */
566 ** something is wrong when a player has normal pieces, but
567 ** no gipf-pieces
569 /* check if one of the player has single pieces, but no gipf-pieces */
570 if ((b_colour_gipf (sboard, 'o') == 0) && (b_colour (sboard, 'o') < 18))
572 gf1_alert ("ERROR: no game possible from this boardsituation, player white has no gipf-pieces.");
573 return (0);
575 if ((b_colour_gipf (sboard, 'x') == 0) && (b_colour (sboard, 'x') < 18))
577 gf1_alert ("ERROR: no game possible from this boardsituation, player black has no gipf-pieces.");
578 return (0);
581 nboard = b_copy (sboard);
582 nboard->typewhite = 'n';
583 nboard->typeblack = 'n';
584 if ((18 - b_colour_gipf (sboard, 'o') * 2) == b_colour (sboard, 'o'))
585 { /* only gipf-pieces, allow player to add more */
586 nboard->typewhite = 'g';
588 if ((18 - b_colour_gipf (sboard, 'x') * 2) == b_colour (sboard, 'x'))
589 { /* only gipf-pieces, allow player to add more */
590 nboard->typeblack = 'g';
593 ** I don't check here if the players have 18 pieces
594 ** which means that it's not completely correct
597 return (nboard);
601 void delete_game (gamestruct * gameptr)
603 int i;
605 if (gameptr == NULL)
606 return;
608 /* ask the player to cleanup its data */
609 if (gameptr->player[0].self != NULL)
611 (* players[gameptr->player[0].type].endfunc) (gameptr->player[0].self);
613 if (gameptr->player[1].self != NULL)
615 (* players[gameptr->player[1].type].endfunc) (gameptr->player[1].self);
618 for (i = 0; i < 3; i++)
620 b_del (gameptr->boards[i]);
623 deletelog (gameptr->movelog);
624 return;
629 ** REMARK: this is the old version
631 ** load a game from a file
633 ** return NULL if nothing loaded
635 gamestruct * oldloadgame (const char * filename)
637 char buffer[100],
638 tempstr[100];
639 FILE * fp;
640 int i,
641 tempnr;
642 gamestruct * newgame;
644 if ((fp = fopen (filename, "r")) == NULL)
646 gf1_alert (" ERROR: Can't open the file");
647 return (NULL);
650 newgame = (gamestruct *) malloc (sizeof (gamestruct));
651 newgame->state = GAME_GO;
653 fgets (buffer, 100, fp);
654 if (strncmp (buffer, "# saved game for gf1", 20) != 0)
656 gf1_alert (" ERROR: wrong inputfile format");
657 free (newgame);
658 return (NULL);
661 fgets (buffer, 100, fp);
662 if (sscanf (buffer, "# gametype: %d", &(newgame->game_type)) != 1)
664 gf1_alert (" ERROR: wrong inputfile format");
665 free (newgame);
666 return (NULL);
669 for (i = 0; i < 2; i++)
671 fgets (buffer, 100, fp);
672 if (sscanf (buffer, "# player%d type: %d",
673 &tempnr, &(newgame->player[i].type)) != 2)
675 gf1_alert (" ERROR: wrong inputfile format");
676 free (newgame);
677 return (NULL);
680 fgets (buffer, 100, fp);
681 sprintf (tempstr, "# player%d name: ", i);
682 if (strncmp (buffer, tempstr, 16) != 0)
684 gf1_alert (" ERROR: wrong inputfile format");
685 free (newgame);
686 return (NULL);
688 buffer[strlen(buffer) - 1] = '\0';
689 strcpy (newgame->player[i].name, buffer+16);
691 fgets (buffer, 100, fp);
692 if (sscanf (buffer, "# player%d fulltime: %d",
693 &tempnr, &(newgame->player[i].fulltime)) != 2)
695 gf1_alert (" ERROR: wrong inputfile format");
696 free (newgame);
697 return (NULL);
700 fgets (buffer, 100, fp);
701 if (sscanf (buffer, "# player%d timer: %f",
702 &tempnr, &(newgame->player[i].timer)) != 2)
704 gf1_alert (" ERROR: wrong inputfile format");
705 free (newgame);
706 return (NULL);
709 newgame->player[i].self = NULL;
712 fgets (buffer, 100, fp);
713 if ((newgame->boards[0] = b_from_file (fp)) == NULL)
715 gf1_alert (" ERROR: wrong inputfile format");
716 free (newgame);
717 return (NULL);
719 newgame->boards[1] = NULL;
720 newgame->boards[2] = NULL;
722 fgets (buffer, 100, fp);
723 if ((newgame->movelog = logfromfile (fp)) == NULL)
725 gf1_alert (" ERROR: wrong inputfile format");
726 free (newgame);
727 return (NULL);
729 newgame->movecounter = loglength (newgame->movelog);
731 fclose (fp);
733 // reading was succesfull, init the players
734 newgame->player[0].self =
735 (* players[newgame->player[0].type].newfunc) ('o', newgame->game_type);
736 newgame->player[1].self =
737 (* players[newgame->player[1].type].newfunc) ('x', newgame->game_type);
739 return (newgame);
744 ** load a game from a file
746 ** return NULL if nothing loaded
748 gamestruct * loadgame (void)
750 const char * filename;
751 char buffer[100],
752 tempstr[100];
753 FILE * fp;
754 int i;
755 gamestruct * newgame;
756 xmlite_entity * root, *x1;
757 xmlite_parser * theparser;
759 // ask for filename
760 if ((filename = file_chooser ("load game", "*.gf1", NULL)) == NULL)
762 return (NULL);
765 if ((fp = fopen (filename, "r")) == NULL)
767 gf1_alert (" ERROR: Can't open the file");
768 return (NULL);
771 fgets (buffer, 100, fp);
772 fclose (fp);
773 if (strncmp (buffer, "# saved game for gf1", 20) == 0)
774 { // old saveformat
775 return (oldloadgame (filename));
778 theparser = new xmlite_parser (filename);
779 root = theparser->parse ();
780 delete (theparser);
781 if (root == NULL)
783 delete (root);
784 gf1_alert (" ERROR: Can't parse savefile");
785 return (NULL);
788 if (root->getname() != "gipfgame")
790 delete (root);
791 gf1_alert (" ERROR: Not a savefile from gf1");
792 return (NULL);
795 if (atoi (root->getattribute("formatversion").c_str()) > 1)
797 delete (root);
798 gf1_alert (" ERROR: Don't know how to handle this fileversion");
799 return (NULL);
802 newgame = (gamestruct *) malloc (sizeof (gamestruct));
803 newgame->state = GAME_GO;
805 // gametype
806 strcpy (tempstr, root->getattribute("type").c_str());
807 newgame->game_type = 3; // put some default value in
808 for (i = 0; i < 4; i++)
810 if (strcmp (tempstr, gametype[i]) == 0)
812 newgame->game_type = i;
813 break;
817 // players
818 x1 = root->getcontentbyname ("whiteplayer");
819 strcpy (newgame->player[0].name, x1->getvalue().c_str());
820 newgame->player[0].type = x1->getattribute ("type") == "human" ? 0 : 1;
821 newgame->player[0].fulltime = atoi (x1->getattribute ("fulltime").c_str());
822 newgame->player[0].timer = atof (x1->getattribute ("timeleft").c_str());
823 newgame->player[0].self = NULL;
824 x1 = root->getcontentbyname ("blackplayer");
825 strcpy (newgame->player[1].name, x1->getvalue().c_str());
826 newgame->player[1].type = x1->getattribute ("type") == "human" ? 0 : 1;
827 newgame->player[1].fulltime = atoi (x1->getattribute ("fulltime").c_str());
828 newgame->player[1].timer = atof (x1->getattribute ("timeleft").c_str());
829 newgame->player[1].self = NULL;
831 // the boardsituation
832 newgame->boards[0] = b_from_xml (root->getcontentbyname ("board"));
833 newgame->boards[1] = NULL;
834 newgame->boards[2] = NULL;
836 // the log of moves
837 newgame->movelog = logfromxml (root->getcontentbyname ("gamelog"));
838 newgame->movecounter = loglength (newgame->movelog);
840 // reading was succesfull, init the players
841 newgame->player[0].self =
842 (* players[newgame->player[0].type].newfunc) ('o', newgame->game_type);
843 newgame->player[1].self =
844 (* players[newgame->player[1].type].newfunc) ('x', newgame->game_type);
846 delete (root);
848 setcurrentfilename (filename);
850 return (newgame);
855 ** save a game to a file
857 void savegame (gamestruct * gameptr)
859 const char * filename;
860 xmlite_entity *x1, *x2;
861 char tempstr[100],
862 * cfile;
864 if (gameptr == NULL)
866 gf1_alert (" no current game to be saved");
867 return;
870 // ask for filename
871 cfile = getcurrentfilename ();
872 if (cfile[0] == '\0')
873 strcpy (tempstr, "./savegame.gf1");
874 else
875 strcpy (tempstr, cfile);
876 if ((filename = file_chooser ("save game", "*.gf1", tempstr))
877 == NULL)
879 return;
882 // gipfgame
883 x1 = new xmlite_entity ("gipfgame");
884 x1->addattribute ("type", gametype[gameptr->game_type]);
885 x1->addattribute ("formatversion", "1");
887 // white player
888 x2 = new xmlite_entity ("whiteplayer");
889 sprintf (tempstr, "%f", gameptr->player[0].timer);
890 x2->addattribute ("timeleft", tempstr);
891 sprintf (tempstr, "%d", gameptr->player[0].fulltime);
892 x2->addattribute ("fulltime", tempstr);
893 x2->addattribute ("type", playertype[gameptr->player[0].type]);
894 x2->setvalue (gameptr->player[0].name);
895 x1->addcontent (x2);
897 // black player
898 x2 = new xmlite_entity ("blackplayer");
899 sprintf (tempstr, "%f", gameptr->player[1].timer);
900 x2->addattribute ("timeleft", tempstr);
901 sprintf (tempstr, "%d", gameptr->player[1].fulltime);
902 x2->addattribute ("fulltime", tempstr);
903 x2->addattribute ("type", playertype[gameptr->player[1].type]);
904 x2->setvalue (gameptr->player[1].name);
905 x1->addcontent (x2);
907 // last gameboard
908 x2 = b_to_xml (gameptr->boards[0]);
909 x1->addcontent (x2);
911 // gamelog
912 x2 = logtoxml (gameptr->movelog);
913 x1->addcontent (x2);
915 x1->writetofile (filename);
916 delete (x1);
918 setcurrentfilename (filename);
920 return;
924 void setupmove (gamestruct * thegame)
926 char tempstr[100],
927 nextpiece,
928 winner = ' ';
930 if ((thegame == NULL) || (thegame->state == GAME_STOP))
932 changeinterface (INTERFACE_PLAY, thegame);
933 return;
936 while (1)
938 Fl::check ();
940 if (thegame->player[0].fulltime != -1)
942 if (thegame->player[0].timer <= 0.0)
944 winner = 'x';
945 break;
947 if (thegame->player[1].timer <= 0.0)
949 winner = 'o';
950 break;
954 if (interrupt_computer)
956 stoptimer (thegame);
957 interrupt_computer = 0;
958 thegame->state = GAME_STOP;
959 break;
962 changeinterface (INTERFACE_PLAY, thegame);
964 if (b_status (thegame->boards[0]) == S_NORMAL)
966 nextpiece = b_next_piece (thegame->boards[0]);
967 /* check if gipf-pieces left */
968 if (thegame->game_type != T_BASIC)
970 if (((b_move_counter (thegame->boards[0]) > 1) ||
971 (thegame->game_type == T_OTHER) || (nextpiece == 'x')) &&
972 (b_white_gipf (thegame->boards[0]) == 0))
974 winner = 'x';
975 break;
977 else if ((b_move_counter (thegame->boards[0]) > 1) &&
978 (b_black_gipf (thegame->boards[0]) == 0))
980 winner = 'o';
981 break;
984 if (b_colour (thegame->boards[0], nextpiece) == 0)
985 { /* game finished */
986 winner = b_opponent (nextpiece);
987 break;
990 if (thegame->player[pnr(nextpiece)].type == 0)
991 { /* human player */
992 gameboard->setto (NULL);
993 gameboard->setfrom (NULL);
994 if (b_colour_type (thegame->boards[0], nextpiece) == 'g')
995 gameboard->setgipfpossible (1);
996 else
997 gameboard->setgipfpossible (0);
999 starttimer (thegame, nextpiece);
1000 break;
1002 else
1003 { /* computer player */
1004 fl_cursor (FL_CURSOR_WAIT);
1005 Fl::check ();
1007 computermove (thegame);
1009 fl_cursor (FL_CURSOR_DEFAULT);
1012 else if (b_status (thegame->boards[0]) == S_REMOVEGIPF)
1014 gipf_questions (thegame);
1016 else if (b_status (thegame->boards[0]) == S_REMOVEROW)
1018 row_questions (thegame);
1022 if (winner != ' ')
1024 sprintf (tempstr, "Player %s, you have won after %d moves !",
1025 thegame->player[pnr(winner)].name,
1026 b_move_counter (thegame->boards[0]));
1027 gf1_alert (tempstr);
1028 thegame->state = GAME_STOP;
1031 changeinterface (INTERFACE_PLAY, thegame);
1032 Fl::check ();
1033 return;
1037 void computermove (gamestruct * thegame)
1039 char nextpiece,
1040 piecetype,
1041 from[3] = " ",
1042 to[3] =" ",
1043 piece;
1044 int playertype;
1045 board * temp_board,
1046 * new_board = NULL;
1047 Fl_Window * thinkwindow;
1049 temp_board = b_copy (thegame->boards[0]);
1050 nextpiece = b_next_piece (thegame->boards[0]);
1051 piecetype = b_colour_type (thegame->boards[0], nextpiece);
1052 playertype = thegame->player[pnr(nextpiece)].type;
1054 starttimer (thegame, nextpiece);
1056 thinkwindow = create_thinkwindow ();
1058 (* players[playertype].movefunc)
1059 (temp_board, thegame->player[pnr(nextpiece)].self,
1060 thegame->player[pnr(nextpiece)].timer,
1061 &piecetype, from, to);
1063 Fl::check ();
1064 delete thinkwindow;
1066 stoptimer (thegame);
1067 if (interrupt_computer)
1068 return;
1070 if ((b_colour_type (thegame->boards[0], nextpiece) != 'g') &&
1071 (piecetype == 'g'))
1073 piecetype = 'n';
1076 piece = piecetype == 'g' ? b_otherpiece (nextpiece) : nextpiece;
1078 b_setlog (thegame->boards[0], thegame->movelog);
1079 new_board = b_move (thegame->boards[0], from, to, piece);
1080 b_nolog (thegame->boards[0]);
1081 b_nolog (new_board);
1083 b_del (temp_board);
1084 if (new_board == NULL)
1086 gf1_alert ("the computer-player executed an invalid move !!");
1088 // b_del (thegame->boards[0]);
1089 // (* players[thegame->player[0].type].endfunc)(thegame->player[0].self);
1090 // (* players[thegame->player[1].type].endfunc)(thegame->player[1].self);
1091 // thegame->boards[0] = NULL;
1093 else
1095 b_del (thegame->boards[2]);
1096 thegame->boards[2] = thegame->boards[1];
1097 thegame->boards[1] = thegame->boards[0];
1098 thegame->boards[0] = new_board;
1100 analysemove (thegame, playertype);
1102 gameboard->setboard (thegame->boards[0]);
1105 return;
1109 int humanmove (gamestruct * thegame)
1111 char nextpiece,
1112 piece;
1113 int playertype;
1114 board * new_board = NULL;
1115 char * from,
1116 * to,
1117 piecetype;
1119 if (thegame->state == GAME_STOP)
1120 return (0);
1122 from = postostr (gameboard->getfrom ());
1123 to = postostr (gameboard->getto ());
1124 if (gameboard->getptype ())
1125 piecetype = 'g';
1126 else
1127 piecetype = 'n';
1129 nextpiece = b_next_piece (thegame->boards[0]);
1130 playertype = thegame->player[pnr(nextpiece)].type;
1132 if ((b_colour_type (thegame->boards[0], nextpiece) != 'g') &&
1133 (piecetype == 'g'))
1135 piecetype = 'n';
1138 piece = piecetype == 'g' ? b_otherpiece (nextpiece) : nextpiece;
1140 b_setlog (thegame->boards[0], thegame->movelog);
1141 new_board = b_move (thegame->boards[0], from, to, piece);
1142 b_nolog (thegame->boards[0]);
1143 if (new_board != NULL)
1144 b_nolog (new_board);
1146 free (from);
1147 free (to);
1149 if (new_board == NULL)
1151 return (-1);
1154 stoptimer (thegame);
1156 b_del (thegame->boards[2]);
1157 thegame->boards[2] = thegame->boards[1];
1158 thegame->boards[1] = thegame->boards[0];
1159 thegame->boards[0] = new_board;
1161 analysemove (thegame, 0);
1163 gameboard->setto (NULL);
1164 gameboard->setfrom (NULL);
1165 gameboard->setboard (thegame->boards[0]);
1167 return (0);
1171 void row_questions (gamestruct * thegame)
1173 board * temp_board,
1174 * new_board;
1175 int counter;
1176 rem_row * row;
1177 listheader * rowlist;
1178 char owner,
1179 response,
1180 * start,
1181 * end,
1182 tempstr1[100],
1183 tempstr2[100];
1184 int answer;
1186 temp_board = b_copy (thegame->boards[0]);
1187 counter = 1;
1188 rowlist = b_row_extra (thegame->boards[0]);
1189 while ((row = (rem_row *) llitembynr (rowlist, counter)) != NULL)
1191 counter++;
1192 start = postostr (row->startpos);
1193 end = postostr (row->endpos);
1194 owner = row_owner (row);
1196 starttimer (thegame, owner);
1197 if (thegame->player[pnr(owner)].type == 0)
1198 { /* human */
1199 gameboard->setrow (row->piecelist);
1200 gameboard->setboard (thegame->boards[0]);
1202 sprintf (tempstr1, "Player %s, do you want to remove",
1203 thegame->player[pnr(owner)].name);
1204 sprintf (tempstr2, "the row from %s to %s", start, end);
1206 answer = 2;
1207 while (answer == 2)
1209 answer = gf1_questionsave (tempstr1, tempstr2);
1211 if (answer == 2)
1212 savegame (thegame);
1213 else if (answer == 1)
1214 response = 'y';
1215 else
1216 response = 'n';
1219 gameboard->setrow (NULL);
1221 else
1222 { /* computer */
1223 Fl_Window * thinkwindow;
1225 thinkwindow = create_thinkwindow ();
1227 response =
1228 (* players[thegame->player[pnr(owner)].type].rowfunc)
1229 (temp_board, thegame->player[pnr(owner)].self,
1230 thegame->player[pnr(owner)].timer, start, end);
1232 delete thinkwindow;
1234 stoptimer (thegame);
1235 if (interrupt_computer)
1236 return;
1238 free (start);
1239 free (end);
1241 if (response == 'y')
1243 b_setlog (thegame->boards[0], thegame->movelog);
1244 new_board = b_remove_row (thegame->boards[0], counter-1);
1245 b_nolog (new_board);
1246 b_del (thegame->boards[0]);
1247 thegame->boards[0] = new_board;
1249 analysemove (thegame, thegame->player[pnr(owner)].type);
1251 gameboard->setboard (thegame->boards[0]);
1253 break;
1256 b_del (temp_board);
1258 return;
1262 void gipf_questions (gamestruct * thegame)
1264 int counter;
1265 rem_gipf * gipf;
1266 board * nboard,
1267 * new_board,
1268 * temp_board;
1269 listheader * gipflist;
1270 char owner,
1271 * strpos,
1272 response;
1273 char tempstr1[100],
1274 tempstr2[100];
1275 int answer;
1277 counter = 1;
1278 gipflist = b_gipf_extra (thegame->boards[0]);
1279 new_board = thegame->boards[0];
1281 while ((gipf = (rem_gipf *) llitembynr (gipflist, counter)) != NULL)
1283 counter++;
1284 strpos = b_gipf_position (gipf);
1285 owner = b_gipf_owner (gipf);
1287 starttimer (thegame, owner);
1288 if (thegame->player[pnr(owner)].type == 0)
1289 { /* human */
1290 gameboard->setto (gipf->pos);
1291 gameboard->setboard (new_board);
1293 sprintf (tempstr1, "Player %s, do you want to remove",
1294 thegame->player[pnr(owner)].name);
1295 sprintf (tempstr2, "the GIPF at %s", strpos);
1297 answer = 2;
1298 while (answer == 2)
1301 ** only allow saving of the game at the first question
1302 ** for removing a gipf.
1303 ** things get fishy if you would save from here after a gipf
1304 ** has been removed already.
1305 ** (the problem doesn't occur immediatly, but when you load
1306 ** the game again)
1308 if (counter == 2)
1309 answer = gf1_questionsave (tempstr1, tempstr2);
1310 else
1311 answer = gf1_question (tempstr1, tempstr2);
1314 if (answer == 2)
1315 savegame (thegame);
1316 else if (answer == 1)
1317 response = 'y';
1318 else
1319 response = 'n';
1322 gameboard->setto (NULL);
1324 else
1325 { /* computer */
1326 Fl_Window * thinkwindow;
1328 thinkwindow = create_thinkwindow ();
1330 temp_board = b_copy (new_board);
1331 response = (* players[thegame->player[pnr(owner)].type].gipffunc)
1332 (temp_board, thegame->player[pnr(owner)].self,
1333 thegame->player[pnr(owner)].timer, strpos);
1334 b_del (temp_board);
1336 delete thinkwindow;
1338 stoptimer (thegame);
1339 if (interrupt_computer)
1340 return;
1342 if ((response == 'y') || (response == 'Y'))
1344 b_setlog (new_board, thegame->movelog);
1345 nboard = b_remove_gipf (new_board, gipf);
1346 b_nolog (new_board);
1347 b_nolog (nboard);
1349 if (new_board != thegame->boards[0])
1350 b_del (new_board);
1352 new_board = nboard;
1354 analysemove (thegame, thegame->player[pnr(owner)].type);
1356 gameboard->setboard (new_board);
1358 free (strpos);
1361 b_setlog (new_board, thegame->movelog);
1362 nboard = b_checkfour (new_board);
1363 b_nolog (new_board);
1364 b_nolog (nboard);
1365 if (new_board != thegame->boards[0])
1366 b_del (new_board);
1368 b_del (thegame->boards[0]);
1369 thegame->boards[0] = nboard;
1371 analysemove (thegame, 1);
1373 gameboard->setboard (thegame->boards[0]);
1375 return;
1379 //time_t basetime = 0;
1380 struct timeval basetime;
1381 char timercolor;
1383 void starttimer (gamestruct * thegame, char color)
1385 struct timezone tz;
1387 if (thegame->player[0].fulltime == -1)
1389 basetime.tv_sec = 0;
1390 return;
1393 // basetime = time (NULL);
1394 gettimeofday (&basetime, &tz);
1395 timercolor = color;
1397 Fl::add_timeout (1.0, updatetimer, (void *) thegame);
1399 return;
1403 void stoptimer (gamestruct * thegame)
1405 // time_t newtime;
1406 struct timezone tz;
1407 struct timeval tv;
1408 float timedif;
1409 char tempstr[20];
1411 if ((thegame == NULL) || (basetime.tv_sec == 0))
1412 return;
1414 Fl::remove_timeout (updatetimer, (void *) thegame);
1416 // newtime = time (NULL);
1417 gettimeofday (&tv, &tz);
1418 timedif = (tv.tv_sec - basetime.tv_sec) +
1419 (float) (tv.tv_usec - basetime.tv_usec)/1000000;
1421 if (timercolor == 'o')
1423 if (interrupt_computer == 0)
1424 thegame->player[0].timer -= timedif;
1425 timertostr (thegame->player[0].timer, tempstr);
1426 whitetimer->value (tempstr);
1428 else
1430 if (interrupt_computer == 0)
1431 thegame->player[1].timer -= timedif;
1432 timertostr (thegame->player[1].timer, tempstr);
1433 blacktimer->value (tempstr);
1436 basetime.tv_sec = 0;
1437 return;
1441 void updatetimer (void * data)
1443 gamestruct * thegame = (gamestruct *) data;
1444 // time_t newtime;
1445 struct timezone tz;
1446 struct timeval tv;
1447 float timedif;
1448 float newtimer;
1449 char tempstr[20];
1451 // newtime = time (NULL);
1452 gettimeofday (&tv, &tz);
1453 timedif = (tv.tv_sec - basetime.tv_sec) +
1454 (float) (tv.tv_usec - basetime.tv_usec)/1000000;
1456 if (timercolor == 'o')
1458 newtimer = thegame->player[0].timer - timedif;
1459 timertostr (newtimer, tempstr);
1460 whitetimer->value (tempstr);
1462 else
1464 newtimer = thegame->player[1].timer - timedif;
1465 timertostr (newtimer, tempstr);
1466 blacktimer->value (tempstr);
1469 if (newtimer > 0.0)
1470 Fl::add_timeout (1.0, updatetimer, data);
1471 else
1472 { /* timer ran out, show if this is a human move */
1473 if (timercolor == 'o')
1475 if (thegame->player[0].type == 0)
1477 thegame->player[0].timer = newtimer;
1479 setupmove (thegame);
1482 else if (thegame->player[1].type == 0)
1484 thegame->player[1].timer = newtimer;
1486 setupmove (thegame);
1490 return;
1495 ** analyse the entries added to the gamelog
1496 ** since the last time we ran this function
1497 ** show what needs to be shown to the user
1499 void analysemove (gamestruct * thegame, int playertype)
1501 int counter = thegame->movecounter + 1;
1502 logitem * item;
1504 while ((item = logitemnr (thegame->movelog, counter)) != NULL)
1506 switch (logitem_type (item))
1508 case LOGMOVE:
1509 showmove (thegame, playertype, item);
1510 break;
1511 case LOGREMGIPF:
1512 showremgipf (thegame, playertype, item);
1513 break;
1514 case LOGREMROW:
1515 showremrow (thegame, playertype, item);
1516 break;
1519 counter++;
1520 playertype = 1; /* necessary in case a row is removed automatically */
1522 thegame->movecounter = counter - 1;
1524 /* show the correct board */
1525 gameboard->setboard (thegame->boards[0]);
1527 return;
1531 void showmove (gamestruct * thegame, int playertype, logitem * item)
1533 char start[3] = " ",
1534 end[3] = " ";
1535 position * startpos,
1536 * endpos,
1537 * topos;
1538 int dir,
1539 counter;
1540 listheader * plist;
1541 struct movepiece {
1542 char piece;
1543 position * from;
1544 position * to;
1545 } * mpiece;
1546 board * oldboard,
1547 * newboard,
1548 * nboard;
1550 strncpy (start, logitem_start (item), 2);
1551 strncpy (end, logitem_end (item), 2);
1552 startpos = strtopos (start);
1553 endpos = strtopos (end);
1554 topos = new_position ();
1557 **from the start and the end of the move we can find the to-position
1558 ** and the direction of the move
1560 if (posp_col (startpos) == posp_col (endpos))
1562 posp_col (topos) = posp_col (startpos);
1563 if (posp_row (startpos) > posp_row (endpos))
1565 posp_row (topos) = posp_row (startpos) - 1;
1566 dir = 2;
1568 else
1570 posp_row (topos) = posp_row (startpos) + 1;
1571 dir = 3;
1574 else if (posp_col (startpos) < posp_col (endpos))
1576 posp_col (topos) = posp_col (startpos) + 1;
1577 if (posp_row (startpos) >= posp_row (endpos))
1579 posp_row (topos) = posp_row (startpos);
1580 dir = 4;
1582 else
1584 posp_row (topos) = posp_row (startpos) + 1;
1585 dir = 5;
1588 else
1590 posp_col (topos) = posp_col (startpos) - 1;
1591 if (posp_row (startpos) >= posp_row (endpos))
1593 posp_row (topos) = posp_row (startpos);
1594 dir = 0;
1596 else
1598 posp_row (topos) = posp_row (startpos) + 1;
1599 dir = 1;
1604 ** reasons to wait before showing the move
1605 ** - waitcomputer > 0
1606 ** - move by the computer
1608 if ((playertype != 0) &&
1609 (thegame->config->waitcomputer > 0))
1610 { /* computerplayer */
1611 if ((logitem_player (item) == 'O') ||
1612 (logitem_player (item) == 'X'))
1614 gameboard->setgipfpossible (1);
1616 else
1618 gameboard->setgipfpossible (0);
1620 gameboard->setfrom (startpos);
1621 gameboard->setto (topos);
1623 /* the first Fl::wait is necessary to reset the start of the timer */
1624 Fl::wait (0);
1625 for (float time = thegame->config->waitcomputer * 1.0; time > 0; )
1626 time = Fl::wait(time);
1627 #if 0
1628 Fl::check ();
1629 #ifdef MSWIN
1630 sleep (thegame->config->waitcomputer * 1000);
1631 #else
1632 sleep (thegame->config->waitcomputer);
1633 #endif
1634 #endif
1636 gameboard->setto (NULL);
1637 gameboard->setfrom (NULL);
1641 ** make a list of all the pieces that move
1642 ** + from and to position
1644 plist = (listheader *) malloc (sizeof (listheader));
1645 newlist (plist);
1646 mpiece = (struct movepiece *) malloc (sizeof (struct movepiece));
1647 mpiece->piece = logitem_player (item);
1648 mpiece->from = (position *) copy_position ((void *) startpos);
1649 mpiece->to = (position *) copy_position ((void *) topos);
1650 pushll (plist, mpiece);
1651 while ((posp_col (topos) != posp_col (endpos)) ||
1652 (posp_row (topos) != posp_row (endpos)))
1654 posp_col (startpos) = posp_col (topos);
1655 posp_row (startpos) = posp_row (topos);
1656 posp_col (topos) =
1657 b_buren[posp_col (startpos)][posp_row (startpos)][dir][0];
1658 posp_row (topos) =
1659 b_buren[posp_col (startpos)][posp_row (startpos)][dir][1];
1661 mpiece = (struct movepiece *) malloc (sizeof (struct movepiece));
1662 mpiece->piece = b_ppiece (gameboard->getboard (), startpos);
1663 mpiece->from = (position *) copy_position ((void *) startpos);
1664 mpiece->to = (position *) copy_position ((void *) topos);
1665 pushll (plist, mpiece);
1669 ** reason to animate the move
1670 ** - animate > 0
1672 if (thegame->config->animate > 0)
1673 { /* animate */
1674 int steps = 10;
1675 switch (thegame->config->animate)
1677 case 1: /* slow */
1678 steps = 20;
1679 break;
1680 case 2: /* medium */
1681 steps = 13;
1682 break;
1683 case 3: /* fast */
1684 steps = 8;
1685 break;
1687 gameboard->initanim (steps, plist);
1689 // Fl::wait (0);
1690 for (int i = 0; i <= steps; i++)
1692 gameboard->animstep (i);
1693 #ifdef MSWIN
1694 /* this timing looks a little better on ms windows */
1695 for (float time = 0.02; time > 0; )
1696 time = Fl::wait(time);
1697 #else
1698 for (float time = 0.03; time > 0; )
1699 time = Fl::wait(time);
1700 #endif
1704 /* update board */
1705 nboard = oldboard = gameboard->getboard ();
1706 counter = 1;
1707 while ((mpiece = (struct movepiece *) llitembynr (plist, counter))
1708 != NULL)
1710 counter++;
1711 newboard = b_edit_piece (nboard, mpiece->to, mpiece->piece);
1712 if (nboard != oldboard)
1713 b_del (nboard);
1714 nboard = newboard;
1716 gameboard->setboard (nboard);
1717 if (nboard != oldboard)
1718 b_del (nboard);
1720 /* cleanup */
1721 while ((mpiece = (struct movepiece *) llrembynr (plist, 1)) != NULL)
1723 free (mpiece->from);
1724 free (mpiece->to);
1725 free (mpiece);
1727 free (plist);
1728 del_position (startpos);
1729 del_position (endpos);
1730 del_position (topos);
1732 return;
1736 void showremgipf (gamestruct * thegame, int playertype, logitem * item)
1738 listheader * piecelist;
1739 char * piece,
1740 posstr[3] = " ";
1741 position * ppos;
1742 board * oldboard,
1743 * newboard;
1745 piecelist = logitem_plist (item);
1746 piece = (char *) llitembynr (piecelist, 1);
1747 strncpy (posstr, piece, 2);
1748 ppos = strtopos (posstr);
1751 ** reasons for showing the removal of a gipf
1752 ** - waitremove > 0
1753 ** - gipf removed by a computer-player
1755 if ((playertype != 0) &&
1756 (thegame->config->waitremove > 0))
1757 { /* computerplayer */
1758 gameboard->setfrom (NULL);
1759 gameboard->setto (ppos);
1761 /* the first Fl::wait is necessary to reset the start of the timer */
1762 Fl::wait (0);
1763 for (float time = thegame->config->waitremove * 1.0; time > 0; )
1764 time = Fl::wait(time);
1765 #if 0
1766 Fl::check ();
1767 #ifdef MSWIN
1768 sleep (thegame->config->waitremove * 1000);
1769 #else
1770 sleep (thegame->config->waitremove);
1771 #endif
1772 #endif
1774 gameboard->setto (NULL);
1776 /* now we update the gameboard */
1777 oldboard = gameboard->getboard ();
1778 newboard = b_edit_piece (oldboard, ppos, '.');
1779 gameboard->setboard (newboard);
1780 b_del (newboard);
1782 del_position (ppos);
1784 return;
1788 void showremrow (gamestruct * thegame, int playertype, logitem * item)
1790 listheader * poslist,
1791 * piecelist;
1792 char start[3] = " ",
1793 end[3] = " ",
1794 posstr[3] = " ",
1795 * ptr;
1796 int dir,
1797 counter;
1798 position * ppos,
1799 * prevpos,
1800 * startpos,
1801 * endpos;
1802 board * oldboard,
1803 * newboard,
1804 * nboard;
1806 strncpy (start, logitem_start (item), 2);
1807 strncpy (end, logitem_end (item), 2);
1808 startpos = strtopos (start);
1809 endpos = strtopos (end);
1811 /* find the direction between start and end */
1812 if (posp_col (startpos) == posp_col (endpos))
1814 if (posp_row (startpos) > posp_row (endpos))
1815 dir = 2;
1816 else
1817 dir = 3;
1819 else if (posp_col (startpos) < posp_col (endpos))
1821 if (posp_row (startpos) > posp_row (endpos))
1822 dir = 4;
1823 else if (posp_row (startpos) < posp_row (endpos))
1824 dir = 5;
1825 else
1827 if (posp_col (startpos) < 4)
1828 dir = 4;
1829 else
1830 dir = 5;
1833 else
1835 if (posp_row (startpos) > posp_row (endpos))
1836 dir = 0;
1837 else if (posp_row (startpos) < posp_row (endpos))
1838 dir = 1;
1839 else
1841 if (posp_col (startpos) > 4)
1842 dir = 0;
1843 else
1844 dir = 1;
1849 /* make a list with all positions between start and end */
1850 piecelist = logitem_plist (item);
1851 poslist = (listheader *) malloc (sizeof (listheader));
1852 newlist (poslist);
1854 pushll (poslist, startpos);
1856 prevpos = startpos;
1857 while ((b_buren[posp_col(prevpos)][posp_row(prevpos)][dir][0]
1858 != posp_col(endpos)) ||
1859 (b_buren[posp_col(prevpos)][posp_row(prevpos)][dir][1]
1860 != posp_row(endpos)))
1862 ppos = new_position ();
1863 posp_col(ppos) = b_buren[posp_col(prevpos)][posp_row(prevpos)][dir][0];
1864 posp_row(ppos) = b_buren[posp_col(prevpos)][posp_row(prevpos)][dir][1];
1866 pushll (poslist, ppos);
1867 prevpos = ppos;
1869 pushll (poslist, endpos);
1872 ** reasons for showing the removal of a row
1873 ** - waitremove > 0
1874 ** - row automatically removed
1875 ** or row removed by a computer-player
1877 if ((playertype != 0) &&
1878 (thegame->config->waitremove > 0))
1879 { /* computerplayer */
1880 gameboard->setrow (poslist);
1882 /* the first Fl::wait is necessary to reset the start of the timer */
1883 Fl::wait (0);
1884 for (float time = thegame->config->waitremove * 1.0; time > 0; )
1885 time = Fl::wait(time);
1886 #if 0
1887 Fl::check ();
1888 #ifdef MSWIN
1889 sleep (thegame->config->waitremove * 1000);
1890 #else
1891 sleep (thegame->config->waitremove);
1892 #endif
1893 #endif
1895 gameboard->setrow (NULL);
1897 /* cleanup */
1898 while ((ppos = (position *) llrembynr (poslist, 1)) != NULL)
1900 free (ppos);
1902 free (poslist);
1904 /* now we update the gameboard */
1905 poslist = logitem_plist (item);
1906 oldboard = gameboard->getboard ();
1907 nboard = oldboard;
1908 counter = 1;
1909 while ((ptr = (char *) llitembynr (poslist, counter)) != 0)
1911 counter++;
1912 strncpy (posstr, ptr, 2);
1913 ppos = strtopos (posstr);
1914 newboard = b_edit_piece (nboard, ppos, '.');
1915 if (nboard != oldboard)
1916 b_del (nboard);
1917 nboard = newboard;
1918 free (ppos);
1920 gameboard->setboard (nboard);
1922 if (nboard != oldboard)
1923 b_del (nboard);
1925 return;
1930 ** this doesn't make gif-files anymore, but png-files
1932 void show_makegif (board * game)
1934 #ifdef HAVEGD
1935 Fl_Window * gifw;
1936 drawgif drawing;
1937 const char * str;
1938 unsigned i;
1939 static int def_size = 300,
1940 def_colour = 1;
1942 gifw = make_gifwindow ();
1944 // set default values
1945 gif_filename->value ("./game.png");
1946 gif_size->value (def_size);
1947 if (def_colour)
1948 gif_colour->setonly ();
1949 else
1950 gif_bw->setonly ();
1951 gif_extratext->value (NULL);
1953 gifw->show ();
1955 while (1)
1957 Fl::wait();
1959 Fl_Widget *x;
1960 while ((x = Fl::readqueue()))
1962 if (x == gif_choose)
1964 if ((str = file_chooser ("Filename", "*.gif",
1965 gif_filename->value ())) != NULL)
1967 gif_filename->value (str);
1970 else if (x == gif_ok)
1972 drawing.filename (gif_filename->value ());
1973 def_size = (int) gif_size->value ();
1974 drawing.gifsize (def_size);
1975 drawing.gifboard (game);
1976 if (gif_colour->value ())
1977 def_colour = 1;
1978 else
1979 def_colour = 0;
1980 drawing.gifcolour (def_colour);
1982 str = gif_extratext->value ();
1983 // check if the string contains something
1984 for (i = 0; i < strlen (str); i++)
1986 if (! isspace ((int) str[i]))
1988 drawing.addtext (str);
1989 break;
1992 drawing.draw ();
1994 delete gifw;
1995 return;
1997 else if (x == gif_cancel)
1999 delete gifw;
2000 return;
2004 #endif
2006 return;