(Temporarily) set "animate" to "none" by default (broken feature).
[gf1.git] / ai_gipf.cxx
blob942cad6c23c3521dec23cc68057a8bde083d6edd
1 /*
2 ** $Id$
3 */
4 /*
5 ** Copyright (C) 1998-1999 Kurt Van den Branden
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <iostream>
23 #include <cstring>
25 #include "ai_gipf.h"
26 #include "configfile.h"
27 #include "board.h"
29 #ifdef WINGIPF
30 extern "C" void checkwindowevents (void);
31 extern int interrupt_computer;
32 #endif
34 #define TIMEDIVIDER 20
36 /* 84 different possible moves, with gipf-pieces */
37 fromto newmoves[] = {
38 {"b1","b2",'g'}, {"a1","b2",'g'}, {"a2","b2",'g'},
39 {"a2","b3",'g'}, {"a3","b3",'g'},
40 {"a3","b4",'g'}, {"a4","b4",'g'},
41 {"a4","b5",'g'}, {"a5","b5",'g'}, {"b6","b5",'g'},
42 {"b6","c6",'g'}, {"c7","c6",'g'},
43 {"c7","d7",'g'}, {"d8","d7",'g'},
44 {"d8","e8",'g'}, {"e9","e8",'g'}, {"f8","e8",'g'},
45 {"f8","f7",'g'}, {"g7","f7",'g'},
46 {"g7","g6",'g'}, {"h6","g6",'g'},
47 {"h6","h5",'g'}, {"i5","h5",'g'}, {"i4","h5",'g'},
48 {"i4","h4",'g'}, {"i3","h4",'g'},
49 {"i3","h3",'g'}, {"i2","h3",'g'},
50 {"i2","h2",'g'}, {"i1","h2",'g'}, {"h1","h2",'g'},
51 {"h1","g2",'g'}, {"g1","g2",'g'},
52 {"g1","f2",'g'}, {"f1","f2",'g'},
53 {"f1","e2",'g'}, {"e1","e2",'g'}, {"d1","e2",'g'},
54 {"d1","d2",'g'}, {"c1","d2",'g'},
55 {"c1","c2",'g'}, {"b1","c2",'g'},
56 {"b1","b2",'n'}, {"a1","b2",'n'}, {"a2","b2",'n'},
57 {"a2","b3",'n'}, {"a3","b3",'n'},
58 {"a3","b4",'n'}, {"a4","b4",'n'},
59 {"a4","b5",'n'}, {"a5","b5",'n'}, {"b6","b5",'n'},
60 {"b6","c6",'n'}, {"c7","c6",'n'},
61 {"c7","d7",'n'}, {"d8","d7",'n'},
62 {"d8","e8",'n'}, {"e9","e8",'n'}, {"f8","e8",'n'},
63 {"f8","f7",'n'}, {"g7","f7",'n'},
64 {"g7","g6",'n'}, {"h6","g6",'n'},
65 {"h6","h5",'n'}, {"i5","h5",'n'}, {"i4","h5",'n'},
66 {"i4","h4",'n'}, {"i3","h4",'n'},
67 {"i3","h3",'n'}, {"i2","h3",'n'},
68 {"i2","h2",'n'}, {"i1","h2",'n'}, {"h1","h2",'n'},
69 {"h1","g2",'n'}, {"g1","g2",'n'},
70 {"g1","f2",'n'}, {"f1","f2",'n'},
71 {"f1","e2",'n'}, {"e1","e2",'n'}, {"d1","e2",'n'},
72 {"d1","d2",'n'}, {"c1","d2",'n'},
73 {"c1","c2",'n'}, {"b1","c2",'n'}
76 // constructor
77 ai_gipf::ai_gipf (char playercolour, int gametype)
79 listheader * configlist;
80 int sd,
81 md,
82 rc;
84 movelist = NULL;
85 colour = playercolour;
86 game = gametype;
88 if (colour == 'o')
89 maxplayer (PLAYER1);
90 else
91 maxplayer (PLAYER2);
93 /* check for config-values from the config-file */
94 configlist = readconfigfile ("gf1.cfg");
96 sd = findconfigvalue (configlist, "searchdepth", colour, 3);
97 searchdepth (sd);
98 md = findconfigvalue (configlist, "memorydepth", colour, 2);
99 memdepth (md);
100 rc = findconfigvalue (configlist, "randomchoose", colour, 1);
101 random (rc);
103 remoppgipf = findconfigvalue (configlist, "remoppgipf", colour, 0);
104 maxgipf = findconfigvalue (configlist, "maxgipf", colour, 3);
105 randomfirstmove = findconfigvalue (configlist, "randomfirstmove",
106 colour, 1);
108 clearconfiglist (configlist);
110 return;
114 // destructor
115 ai_gipf::~ai_gipf ()
117 if (movelist != NULL)
119 int len = movelist->size(),
122 for (i = 0; i < len; i++)
123 delete (*movelist)[i];
125 delete movelist;
128 return;
132 static struct {
133 position coor;
134 int value;
135 } pos_val[] = {
136 {{4, 5}, 5},
137 {{3, 4}, 2},{{3, 5}, 2},{{4, 6}, 2},{{5, 5}, 2},{{5, 4}, 2},{{4, 4}, 2},
138 {{2, 3}, 1},{{2, 4}, 1},{{2, 5}, 1},{{3, 6}, 1},{{4, 7}, 1},{{5, 6}, 1},
139 {{6, 5}, 1},{{6, 4}, 1},{{6, 3}, 1},{{5, 3}, 1},{{4, 3}, 1},{{3, 3}, 1}
142 int ai_gipf::evalfunc (void * game, int maxplayer)
144 board * oboard = (board *) game;
145 int total,
147 value;
148 double wvalue,
149 bvalue;
150 char myc,
151 otherc,
152 piece;
153 position * pos;
155 myc = (maxplayer == PLAYER1 ? 'o': 'x');
156 otherc = b_opponent (myc);
158 if (b_game_finished (oboard))
160 if (b_winner (oboard) == myc)
162 return (1000);
164 else
166 return (-1000);
170 /* maybe I can return 1000 or -1000, but I'm not completely sure */
172 ** not sure at all anymore
173 ** what if you start with only GIPF-pieces and remove a GIPF
174 ** only at the start of your move
176 if (b_colour (oboard, myc) == 0)
178 return (-999);
180 else if (b_colour (oboard, otherc) == 0)
182 return (999);
185 /* I need to start with a base-value, or I get a lot of
186 ** problems at the start of tournament games */
187 wvalue = 20;
188 bvalue = 20;
190 /* capturing a piece from your opponent is worth 20 points */
191 wvalue += 20 * b_black_lost (oboard);
192 bvalue += 20 * b_white_lost (oboard);
194 /* 1 point for each piece in use on the board */
195 if (b_white_gipf (oboard) == -1)
196 total = 15;
197 else
198 total = 18;
200 wvalue += total - b_white (oboard) - b_white_lost (oboard);
201 bvalue += total - b_black (oboard) - b_black_lost (oboard);
203 /* 2 pieces or less left is getting dangerous */
205 /* one gipf left can be dangerous, subtract 5 points */
206 if (b_white_gipf (oboard) == 1)
208 wvalue -= 5;
210 if (b_black_gipf (oboard) == 1)
212 bvalue -= 5;
215 /* pieces closer to the center have a higher value */
216 for (i = 0; i < 19; i++)
218 pos = &(pos_val[i].coor);
219 piece = b_ppiece (oboard, pos);
220 if (piece == '.')
222 continue;
224 if (piece == 'o')
226 wvalue += pos_val[i].value;
228 else if (piece == 'O')
230 wvalue += pos_val[i].value * 1.5;
232 else if (piece == 'x')
234 bvalue += pos_val[i].value;
236 else
238 bvalue += pos_val[i].value * 1.5;
242 /* normalize the result, should be between 1000 and -1000 */
243 if (myc == 'o')
245 value = (int) ((wvalue - bvalue) * 1000 / (wvalue + bvalue));
247 else
249 value = (int) ((bvalue - wvalue) * 1000 / (wvalue + bvalue));
252 return (value);
256 int ai_gipf::stopfunc (void)
258 checkwindowevents ();
260 if (interrupt_computer)
261 return (1);
263 return (0);
267 void ai_gipf::listfunc (void * game, vector<basemove *> & movelist)
269 board * oboard = (board *) game;
270 #if 0
271 listheader * movelist;
273 movelist = (listheader *) malloc (sizeof (listheader));
274 newlist (movelist);
275 #endif
277 switch (b_status (oboard))
279 case S_NORMAL:
281 int firstmove,
283 gipf_move * move;
285 if ((b_colour_type (oboard, b_next_piece (oboard)) == 'g') &&
286 (b_colour_gipf (oboard, b_next_piece (oboard)) < maxgipf))
288 firstmove = 0;
290 else
292 firstmove = 42;
295 for (i = firstmove; i < 84; i++)
297 if ((i > firstmove) &&
298 (newmoves[i].to[0] == newmoves[i-1].to[0]) &&
299 (newmoves[i].to[1] == newmoves[i-1].to[1]) &&
300 (b_piece (oboard, newmoves[i].to) == '.'))
301 { /*
302 ** don't add this move, it would have exactly the same
303 ** result as the previous one
305 continue;
307 move = new gipf_move;
309 move->type = G_MOVE;
310 move->piece.nr = i;
312 // pushll (movelist, (void *) move);
313 movelist.push_back (move);
315 break;
318 case S_REMOVEROW:
320 listheader * rowlist;
321 gipf_move * move;
322 rem_row * rowi;
323 char * tempstr;
324 int counter = 1;
326 rowlist = b_row_extra (oboard);
327 while ((rowi = (rem_row *) llitembynr (rowlist, counter))
328 != NULL)
330 counter++;
332 move = new gipf_move;
334 move->type = G_REMROW;
335 move->remrow.owner = row_owner (rowi);
337 tempstr = postostr (row_start(rowi));
338 move->remrow.from[0] = tempstr[0];
339 move->remrow.from[1] = tempstr[1];
340 move->remrow.from[2] = '\0';
341 free (tempstr);
343 tempstr = postostr (row_end(rowi));
344 move->remrow.to[0] = tempstr[0];
345 move->remrow.to[1] = tempstr[1];
346 move->remrow.to[2] = '\0';
347 free (tempstr);
349 // pushll (movelist, (void *) move);
350 movelist.push_back (move);
352 break;
355 case S_REMOVEGIPF:
357 gipf_move * move;
358 rem_gipf * gipfi;
359 int mypieces = 0,
360 counter = 1,
361 maxnr,
362 bits1, bits2;
363 char * tempstr;
365 while ((gipfi = (rem_gipf *)
366 llitembynr (b_gipf_extra (oboard) ,counter)) != NULL)
368 counter++;
370 if (remoppgipf != 0)
372 if (b_otherpiece (b_ppiece (oboard, gipfi->pos))
373 == gipfi->owner)
375 mypieces++;
378 else
380 mypieces++;
384 maxnr = 1 << mypieces; /* 2 ^ mynr */
386 for (bits1 = 0; bits1 < maxnr; bits1++)
388 bits2 = bits1;
390 move = new gipf_move;
392 move->type = G_REMGIPF;
394 // move->remgipf.gipflist =
395 // (listheader *) malloc (sizeof (listheader));
396 // newlist (move->remgipf.gipflist);
398 counter = 1;
399 while ((gipfi = (rem_gipf *)
400 llitembynr (b_gipf_extra (oboard) ,counter)) != NULL)
402 counter++;
403 move->remgipf.owner = gipfi->owner;
405 tempstr = b_gipf_position (gipfi);
406 tempstr = (char *) realloc (tempstr, 4);
407 tempstr[2] = 'n';
408 tempstr[3] = '\0';
410 if ((b_otherpiece (b_ppiece (oboard, gipfi->pos))
411 == gipfi->owner) || (remoppgipf == 0))
413 if (bits2 & 1)
415 tempstr[2] = 'y';
417 bits2 = bits2 >> 1;
419 else
421 tempstr[2] = 'y';
423 // pushll (move->remgipf.gipflist, tempstr);
424 move->remgipf.gipflist.push_back (tempstr);
427 // pushll (movelist, (void *) move);
428 movelist.push_back (move);
430 break;
433 case S_FINISHED: // not normal
434 break;
437 return;
441 void * ai_gipf::newfunc (void * game, basemove * move, int * finished,
442 int * depthdelta, int * nodetype)
444 board * oboard = (board *) game,
445 * nboard;
446 gipf_move * gmove = (gipf_move *) move;
448 switch (gmove->type)
450 case G_MOVE:
452 char piece;
454 piece = b_next_piece (oboard);
456 if (newmoves[gmove->piece.nr].type == 'g')
457 piece = b_otherpiece (piece);
458 nboard = b_move (oboard, newmoves[gmove->piece.nr].from,
459 newmoves[gmove->piece.nr].to, piece);
461 if (nboard == NULL)
462 return (NULL);
464 break;
467 case G_REMGIPF:
469 rem_gipf * gipfi;
470 int counter1 = 1;
471 // int counter2;
472 board * tboard;
473 char * tempstr;
474 // char * str;
475 vector<char *>::iterator curg, lastg;
477 nboard = oboard;
478 while ((gipfi = (rem_gipf *)
479 llitembynr (b_gipf_extra (oboard) ,counter1)) != NULL)
481 counter1++;
483 tempstr = b_gipf_position (gipfi);
484 // counter2 = 1;
486 curg = gmove->remgipf.gipflist.begin();
487 lastg = gmove->remgipf.gipflist.end();
488 while (curg != lastg)
489 // while ((str = (char *)
490 // llitembynr (gmove->remgipf.gipflist, counter2)) != NULL)
492 // counter2++;
493 if (((*curg)[0] == tempstr[0]) && ((*curg)[1] == tempstr[1]))
495 if ((*curg)[2] == 'y')
497 tboard = b_remove_gipf (nboard, gipfi);
498 if (nboard != oboard)
499 b_del (nboard);
500 nboard = tboard;
502 break;
504 curg++;
507 free (tempstr);
510 /* check again for 4 in a row */
511 tboard = b_checkfour (nboard);
512 if (nboard != oboard)
514 b_del (nboard);
516 nboard = tboard;
518 break;
521 case G_REMROW:
523 listheader * rowlist;
524 rem_row * rowi;
525 char * tempstr;
526 int counter = 1;
528 rowlist = b_row_extra (oboard);
529 while ((rowi = (rem_row *) llitembynr (rowlist, counter))
530 != NULL)
532 counter++;
534 tempstr = postostr (rowi->startpos);
535 if ((tempstr[0] != gmove->remrow.from[0]) ||
536 (tempstr[1] != gmove->remrow.from[1]))
538 free (tempstr);
539 continue;
541 free (tempstr);
543 tempstr = postostr (rowi->endpos);
544 if ((tempstr[0] != gmove->remrow.to[0]) ||
545 (tempstr[1] != gmove->remrow.to[1]))
547 free (tempstr);
548 continue;
550 free (tempstr);
552 break;
554 nboard = b_remove_row (oboard, counter - 1);
555 break;
557 default:
558 break;
561 switch (b_status (nboard))
563 case S_NORMAL:
564 *finished = b_game_finished (nboard);
565 *depthdelta = 1;
567 if (((b_next_piece (nboard) == 'o') && (maxplayer () == PLAYER1)) ||
568 ((b_next_piece (nboard) == 'x') && (maxplayer () == PLAYER2)))
569 *nodetype = MAX;
570 else
571 *nodetype = MIN;
572 break;
574 case S_REMOVEROW:
576 listheader * rowlist = b_row_extra (nboard);
577 rem_row * rowi = (rem_row *) llitembynr (rowlist, 1);
579 *finished = 2;
580 *depthdelta = 0;
582 if (((row_owner (rowi) == 'o') && (maxplayer () == PLAYER1)) ||
583 ((row_owner (rowi) == 'x') && (maxplayer () == PLAYER2)))
584 *nodetype = MAX;
585 else
586 *nodetype = MIN;
588 break;
591 case S_REMOVEGIPF:
593 rem_gipf * gipfi = (rem_gipf *) llitembynr (b_gipf_extra (nboard) ,1);
595 *finished = 2;
596 *depthdelta = 0;
598 if (((b_gipf_owner (gipfi) == 'o') && (maxplayer () == PLAYER1)) ||
599 ((b_gipf_owner (gipfi) == 'x') && (maxplayer () == PLAYER2)))
600 *nodetype = MAX;
601 else
602 *nodetype = MIN;
603 break;
606 case S_FINISHED: // not normal
607 break;
611 return ((void *) nboard);
615 #if 0
616 //void * ai_gipf::copymovefunc (void * move)
617 gipf_move::gipf_move (gipf_move & tocopy)
619 // gipf_move * omove = (gipf_move *) move,
620 // * nmove;
621 int counter;
622 char * opos,
623 char * npos;
625 // nmove = (gipf_move *) malloc (sizeof (gipf_move));
627 this->type = tocopy.type;
628 switch (this->type)
630 case G_MOVE:
631 this->piece.nr = tocopy.piece.nr;
632 break;
633 case G_REMROW:
634 this->remrow.from[0] = tocopy.remrow.from[0];
635 this->remrow.from[1] = tocopy.remrow.from[1];
636 this->remrow.from[2] = '\0';
637 this->remrow.to[0] = tocopy.remrow.to[0];
638 this->remrow.to[1] = tocopy.remrow.to[1];
639 this->remrow.to[2] = '\0';
640 this->remrow.owner = tocopy.remrow.owner;
641 break;
642 case G_REMGIPF:
643 this->remgipf.owner = tocopy.remgipf.owner;
645 this->remgipf.gipflist = (listheader *) malloc (sizeof (listheader));
646 newlist (this->remgipf.gipflist);
647 counter = 1;
648 while ((opos = (char *)
649 llitembynr (tocopy.remgipf.gipflist, counter)) != NULL)
651 counter++;
652 npos = (char *) malloc (4);
653 npos[0] = opos[0];
654 npos[1] = opos[1];
655 npos[2] = opos[2];
656 npos[3] = '\0';
657 pushll (this->remgipf.gipflist, (void *) npos);
659 break;
663 return;
665 #endif
667 basemove * gipf_move::copy (void)
669 gipf_move * nmove = new gipf_move;
670 // int counter;
671 // char * opos,
672 char * npos;
673 vector<char *>::iterator curg, lastg;
675 nmove->type = this->type;
676 switch (nmove->type)
678 case G_MOVE:
679 nmove->piece.nr = this->piece.nr;
680 break;
681 case G_REMROW:
682 nmove->remrow.from[0] = this->remrow.from[0];
683 nmove->remrow.from[1] = this->remrow.from[1];
684 nmove->remrow.from[2] = '\0';
685 nmove->remrow.to[0] = this->remrow.to[0];
686 nmove->remrow.to[1] = this->remrow.to[1];
687 nmove->remrow.to[2] = '\0';
688 nmove->remrow.owner = this->remrow.owner;
689 break;
690 case G_REMGIPF:
691 nmove->remgipf.owner = this->remgipf.owner;
693 curg = this->remgipf.gipflist.begin();
694 lastg = this->remgipf.gipflist.end();
695 // nmove->remgipf.gipflist = (listheader *) malloc (sizeof (listheader));
696 // newlist (nmove->remgipf.gipflist);
697 // counter = 1;
698 // while ((opos = (char *)
699 // llitembynr (this->remgipf.gipflist, counter)) != NULL)
700 while (curg != lastg)
702 // counter++;
703 npos = (char *) malloc (4);
704 npos[0] = (*curg)[0];
705 npos[1] = (*curg)[1];
706 npos[2] = (*curg)[2];
707 npos[3] = '\0';
708 // pushll (nmove->remgipf.gipflist, (void *) npos);
709 nmove->remgipf.gipflist.push_back(npos);
710 curg++;
712 break;
715 return (nmove);
719 //void ai_gipf::delmovefunc (void * move)
720 gipf_move::~gipf_move ()
722 // char * opos;
724 if ((type == G_REMGIPF) && (!remgipf.gipflist.empty()))
726 // while ((opos = (char *)
727 // llrembynr (remgipf.gipflist, 1)) != NULL)
728 // free (opos);
730 // free (remgipf.gipflist);
731 vector<char *>::iterator curg = remgipf.gipflist.begin(),
732 lastg = remgipf.gipflist.end();
733 while (curg != lastg)
735 delete (*curg);
736 curg++;
740 return;
744 void ai_gipf::delgamefunc (void * game)
746 board * oboard = (board *) game;
748 if (oboard == NULL)
749 return;
751 b_del (oboard);
753 return;
757 void ai_gipf::game_move (board * oboard, float timeleft,
758 char * type, char * from, char * to)
760 vector<basemove *> * newmovelist;
761 gipf_move * move;
762 int savedepth = -1;
764 if (movelist != NULL)
767 ** this is probably a problem
768 ** signal it and then ignore it
770 cout << "\n WARNING (ai_gipf::game_move):\n";
771 cout << " movelist is not empty!!\n\n";
773 int len = movelist->size(),
776 for (i = 0; i < len; i++)
777 delete (*movelist)[i];
779 delete movelist;
780 movelist = NULL;
784 ** if this is the first move of the game, reduce memorydepth
785 ** to 1, it's not necessary to waste time when there are really
786 ** only 2 possible moves
788 /* question: should I only do this for tournament games ? */
789 if (randomfirstmove && // flag must be one
790 (b_move_counter (oboard) == 0) && // first move
791 (((b_white_gipf (oboard) == 0) &&
792 (b_white (oboard) == 18) && (b_black (oboard) == 18)) ||
793 ((b_white_gipf (oboard) == 3) &&
794 (b_white (oboard) == 12) && (b_black (oboard) == 12)) ||
795 ((b_white_gipf (oboard) == -1) &&
796 (b_white (oboard) == 12) && (b_black (oboard) == 12))))
798 savedepth = searchdepth ();
799 searchdepth (1);
802 newmovelist = mtdf_id ((void *) oboard, MAX, timeleft/TIMEDIVIDER);
804 /* reset the correct searchdepth if necessary */
805 if (savedepth != -1)
807 searchdepth (savedepth);
810 if (newmovelist == NULL)
812 // have to check what happened here
813 if (status () == AI_STOPPED)
814 return;
817 cleanupmovelist (newmovelist);
818 movelist = newmovelist;
820 // remove the first item from the movelist
821 move = (gipf_move *) (*movelist)[0];
822 movelist->erase (movelist->begin());
823 // move = (gipf_move *) llrembynr (movelist, 1);
825 if (movelist->empty())
827 delete movelist;
828 movelist = NULL;
830 // if (llitembynr (movelist, 1) == NULL)
831 // { // delete movelist if empty
832 // free (movelist);
833 // movelist = NULL;
834 // }
836 if (move->type != G_MOVE)
837 { // very wrong, what happened here ?
840 from[0] = newmoves[move->piece.nr].from[0];
841 from[1] = newmoves[move->piece.nr].from[1];
842 to[0] = newmoves[move->piece.nr].to[0];
843 to[1] = newmoves[move->piece.nr].to[1];
844 *type = newmoves[move->piece.nr].type;
846 delete move;
848 return;
852 char ai_gipf::game_gipf (board * oboard, float timeleft,
853 char * pos)
855 vector<basemove *> * newmovelist;
856 gipf_move * move;
857 // char * gipfpos;
858 char result;
859 //int counter;
860 vector<char *>::iterator curg,
861 lastg;
863 if (movelist == NULL)
865 newmovelist = mtdf_id ((void *) oboard, MAX, timeleft/TIMEDIVIDER);
867 if (newmovelist == NULL)
869 // have to check what happened here
870 if (status () == AI_STOPPED)
871 return (' ');
874 cleanupmovelist (newmovelist);
875 movelist = newmovelist;
878 // move = (gipf_move *) llitembynr (movelist, 1);
879 move = (gipf_move *) (*movelist)[0];
880 if ((move == NULL) || (move->type != G_REMGIPF))
881 { // very wrong, what happened here ?
884 // counter = 1;
885 // while ((gipfpos = (char *)
886 // llitembynr (move->remgipf.gipflist, counter)) != NULL)
887 curg = move->remgipf.gipflist.begin();
888 lastg = move->remgipf.gipflist.end();
889 while (curg != lastg)
891 if (strncmp (*curg, pos, 2) == 0)
893 break;
895 // counter++;
896 curg++;
899 // if (gipfpos == NULL)
900 if (curg == lastg)
901 { // very wrong, gipf-position not found
904 result = (*curg)[2];
905 free (*curg);
906 move->remgipf.gipflist.erase (curg);
907 // result = gipfpos[2];
908 // gipfpos = (char *) llrembynr (move->remgipf.gipflist, counter);
909 // free (gipfpos);
911 // if (llitembynr (move->remgipf.gipflist, 1) == NULL)
912 if (move->remgipf.gipflist.empty())
914 delete move;
916 movelist->erase (movelist->begin());
918 if (movelist->empty())
919 { // delete movelist if empty
920 delete movelist;
921 movelist = NULL;
925 return (result);
929 char ai_gipf::game_row (board * oboard, float timeleft,
930 char * start, char * end)
932 vector<basemove *> * newmovelist;
933 gipf_move * move;
934 char result = 'n';
936 if (movelist == NULL)
938 newmovelist = mtdf_id ((void *) oboard, MAX, timeleft/TIMEDIVIDER);
940 if (newmovelist == NULL)
942 // have to check what happened here
943 if (status () == AI_STOPPED)
944 return (' ');
947 cleanupmovelist (newmovelist);
948 movelist = newmovelist;
951 move = (gipf_move *) (*movelist)[0];
952 // move = (gipf_move *) llitembynr (movelist, 1);
953 if ((move == NULL) || (move->type != G_REMROW))
954 { // very wrong, what happened here ?
957 if (strncmp (start, move->remrow.from, 2) == 0)
959 if (strncmp (end, move->remrow.to, 2) == 0)
960 result = 'y';
962 else if (strncmp (start, move->remrow.to, 2) == 0)
964 if (strncmp (end, move->remrow.from, 2) == 0)
965 result = 'y';
968 if (result == 'y')
970 delete move;
972 movelist->erase (movelist->begin());
974 if (movelist->empty())
975 { // delete movelist if empty
976 delete movelist;
977 movelist = NULL;
981 return (result);
986 ** cleanup a list of moves as returned by minimax_ab, mtdf or mtdf_id
987 ** keep only the necessary moves.
988 ** this means:
989 ** - remove G_MOVE if it is not the first item in the list and remove
990 ** everything after it. (only keep everything for the first move)
991 ** - remove everything that is not an action for the current player.
993 void ai_gipf::cleanupmovelist (vector<basemove *> * mlist)
995 int counter = 1, /* skip the first item */
996 len = mlist->size(),
998 gipf_move * moveitem;
1000 /* look for the first item that can be deleted */
1001 for (; counter < len; counter++)
1002 // while ((moveitem = (gipf_move *) llitembynr (mlist, counter)) != NULL)
1004 moveitem = (gipf_move *) (*mlist)[counter];
1005 if ((moveitem->type == G_MOVE) ||
1006 ((moveitem->type == G_REMGIPF) &&
1007 (moveitem->remgipf.owner != colour)) ||
1008 ((moveitem->type == G_REMROW) &&
1009 (moveitem->remrow.owner != colour)))
1011 break;
1013 // counter++;
1016 /* delete everything from now on */
1017 for (i = len - 1; i >= counter; i--)
1018 // while ((item = (gipf_move *) llrembynr (mlist, counter)) != NULL)
1020 delete (* mlist)[i];
1021 mlist->pop_back();
1024 return;
1029 ** C-functions for calling from the main program
1032 void * ai_gipf_new (char colour, int game)
1034 ai_gipf * newgame;
1036 newgame = new ai_gipf (colour, game);
1038 return ((void *) newgame);
1041 void ai_gipf_move (board * oboard, void * self, float timeleft,
1042 char * type, char * from, char * to)
1044 ai_gipf * game = (ai_gipf *) self;
1046 game->game_move (oboard, timeleft, type, from, to);
1047 return;
1050 char ai_gipf_gipf (board * oboard, void * self, float timeleft,
1051 char * pos)
1053 ai_gipf * game = (ai_gipf *) self;
1055 return (game->game_gipf (oboard, timeleft, pos));
1058 char ai_gipf_row (board * oboard, void * self, float timeleft,
1059 char * start, char * end)
1061 ai_gipf * game = (ai_gipf *) self;
1063 return (game->game_row (oboard, timeleft, start, end));
1066 void ai_gipf_end (void * self)
1068 ai_gipf * delgame = (ai_gipf *) self;
1070 delete delgame;
1072 return;