5 ** Copyright (C) 1998 Kurt Van den Branden
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.
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.
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.
23 ** keep a tree of all searched nodes
24 ** this is not useful for the normal minimax with alfabeta-pruning
25 ** but can be used for negascout or mtd(f), algoritms wich do re-searching
31 extern void checkwindowevents (void);
32 extern int interrupt_computer
;
35 /* structures for keeping my own info in */
47 listheader
* movelist
; /* list of items of type nextmove */
51 int remtype
; /* REM_GIPF or REM_ROW */
52 listheader
* gipflist
; /* list of items of type gipfdata */
66 listheader
* movelist
; /* list of items of type nextmove */
85 /* things for the node-tree */
90 listheader
* children
; /* list of treeitems */
99 {{3, 4}, 2},{{3, 5}, 2},{{4, 6}, 2},{{5, 5}, 2},{{5, 4}, 2},{{4, 4}, 2},
100 {{2, 3}, 1},{{2, 4}, 1},{{2, 5}, 1},{{3, 6}, 1},{{4, 7}, 1},{{5, 6}, 1},
101 {{6, 5}, 1},{{6, 4}, 1},{{6, 3}, 1},{{5, 3}, 1},{{4, 3}, 1},{{3, 3}, 1}
107 #define min(x, y) (x < y ? x : y)
108 #define max(x, y) (x > y ? x : y)
110 movestruct
* mtdf_id (board
* oboard
, treenode
* node
, int f
, mtdf_info
* me
,
112 movestruct
* mtdf (board
* oboard
, treenode
* node
, int f
, mtdf_info
* me
,
115 movestruct
* mem_ab_move (board
* oboard
, treenode
* node
, int alfa
, int beta
,
116 int minmax
, int depth
, mtdf_info
* me
);
117 movestruct
* mem_move (board
* oboard
, treenode
* node
, int alfa
, int beta
,
118 int minmax
, int depth
, mtdf_info
* me
, fromto
* todo
,
120 movestruct
* mem_ab_gipf (board
* oboard
, treenode
* node
, int alfa
, int beta
,
121 int minmax
, int depth
, mtdf_info
* me
);
122 movestruct
* mem_rem_gipflist (board
* oboard
, treenode
* node
, int alfa
,
123 int beta
, int minmax
, int depth
,
124 mtdf_info
* me
, listheader
* myg
,
125 listheader
* otherg
);
126 movestruct
* mem_ab_row (board
* oboard
, treenode
* node
, int alfa
, int beta
,
127 int minmax
, int depth
, mtdf_info
* me
);
128 movestruct
* mem_rem_row (board
* oboard
, treenode
* node
, int alfa
, int beta
,
129 int minmax
, int depth
, mtdf_info
* me
, int rem
);
130 int mem_evaluate (board
* oboard
, mtdf_info
* me
);
131 void mem_del_move (movestruct
* todel
);
133 void mem_deltree (treenode
* node
);
134 void mem_delnode (void * item
);
135 treenode
* mem_makeroot (board
* father
, mtdf_info
* me
);
136 treenode
* mem_child (treenode
* node
, int nr
, mtdf_info
* me
, int depth
);
137 void mem_resetul (void * item
);
139 int mem_equ_l (int nr1
, int nr2
, int * chance
, mtdf_info
* me
);
140 int mem_equ_h (int nr1
, int nr2
, int * chance
, mtdf_info
* me
);
142 void * mtdf_new (char colour
, int game
)
145 listheader
* configlist
;
147 me
= (mtdf_info
*) malloc (sizeof (mtdf_info
));
153 /* check for config-values from the config-file */
154 configlist
= readconfigfile ("gf1.cfg");
156 me
->config
.searchdepth
= findconfigvalue (configlist
, "searchdepth",
158 me
->config
.remoppgipf
= findconfigvalue (configlist
, "remoppgipf",
160 me
->config
.maxgipf
= findconfigvalue (configlist
, "maxgipf",
162 me
->config
.memorydepth
= findconfigvalue (configlist
, "memorydepth",
164 me
->config
.randomchoose
= findconfigvalue (configlist
, "randomchoose",
167 clearconfiglist (configlist
);
169 return ((void *) me
);
173 void mtdf_move (board
* oboard
, void * self
,
174 char * type
, char * from
, char * to
)
176 mtdf_info
* me
= self
;
182 root
= mem_makeroot (oboard
, me
);
184 move = mtdf (oboard, root, me->lastvalue, me, 1);
186 move
= mtdf_id (oboard
, root
, me
->lastvalue
, me
, 1);
190 from
[0] = move
->from
[0];
191 from
[1] = move
->from
[1];
196 me
->movelist
= move
->movelist
;
198 move
->movelist
= NULL
;
205 char mtdf_gipf (board
* oboard
, void * self
, char * pos
)
207 mtdf_info
* me
= self
;
216 /* check if movelist contains info about removing gipf-pieces */
217 if (me
->movelist
== NULL
)
220 ** no info in movelist, my opponent made 4 in a row
221 ** with my pieces (only possible explanation)
225 /* remark: I have to start this as a min-node,
226 ** because this is really my opponents move */
227 root
= mem_makeroot (oboard
, me
);
229 nmove = mtdf (oboard, root, me->lastvalue, me, 2);
231 nmove
= mtdf_id (oboard
, root
, me
->lastvalue
, me
, 2);
234 me
->movelist
= nmove
->movelist
;
235 nmove
->movelist
= NULL
;
236 mem_del_move (nmove
);
239 /* now check the movelist for the move we have to make */
240 if (((movedata
= (nextmove
*) llitembynr (me
->movelist
, 1)) == NULL
) ||
241 (movedata
->remtype
!= REM_GIPF
))
247 /* look for the gipf to remove */
249 while ((gipfd
= (gipfdata
*) llitembynr (movedata
->gipflist
, counter
))
252 if ((gipfd
->pos
[0] == pos
[0]) && (gipfd
->pos
[1] == pos
[1]))
263 /* remove gipf from list */
264 gipfd
= (gipfdata
*) llrembynr (movedata
->gipflist
, counter
);
266 /* remove nextmove from movelist if gipflist is empty */
267 if (llitembynr (movedata
->gipflist
, 1) == NULL
)
269 movedata
= (nextmove
*) llrembynr (me
->movelist
, 1);
270 free (movedata
->gipflist
);
273 /* remove movelist if empty */
274 if (llitembynr (me
->movelist
, 1) == NULL
)
288 char mtdf_row (board
* oboard
, void * self
, char * start
, char * end
)
290 mtdf_info
* me
= self
;
297 /* check if movelist contains info about removing rows */
298 if (me
->movelist
== NULL
)
301 ** no info in movelist, my opponent made several "4 in a row"s
302 ** with my pieces (only possible explanation)
306 /* remark: I have to start this as a min-node,
307 ** because this is really my opponents move */
308 root
= mem_makeroot (oboard
, me
);
310 nmove = mtdf (oboard, root, me->lastvalue, me, 3);
312 nmove
= mtdf_id (oboard
, root
, me
->lastvalue
, me
, 3);
315 me
->movelist
= nmove
->movelist
;
316 nmove
->movelist
= NULL
;
317 mem_del_move (nmove
);
320 /* now check the movelist for the move we have to make */
321 if (((movedata
= (nextmove
*) llitembynr (me
->movelist
, 1)) == NULL
) ||
322 (movedata
->remtype
!= REM_ROW
))
329 /* check if this is the correct row to be removed */
330 if ((start
[0] == movedata
->rowdata
.start
[0]) &&
331 (start
[1] == movedata
->rowdata
.start
[1]))
333 if ((end
[0] == movedata
->rowdata
.end
[0]) &&
334 (end
[1] == movedata
->rowdata
.end
[1]))
339 else if ((start
[0] == movedata
->rowdata
.end
[0]) &&
340 (start
[1] == movedata
->rowdata
.end
[1]))
342 if ((end
[0] == movedata
->rowdata
.start
[0]) &&
343 (end
[1] == movedata
->rowdata
.start
[1]))
351 /* remove nextmove from movelist */
352 movedata
= (nextmove
*) llrembynr (me
->movelist
, 1);
353 free (movedata
->rowdata
.start
);
354 free (movedata
->rowdata
.end
);
357 /* remove movelist if empty */
358 if (llitembynr (me
->movelist
, 1) == NULL
)
367 /* don't remove the row */
372 void mtdf_end (void * self
)
374 mtdf_info
* me
= self
;
376 /* do I have to clean up the movelist first */
384 ** iterative deepening around mtdf
386 ** REMARK: doesn't work, don't know why yet
388 movestruct
* mtdf_id (board
* oboard
, treenode
* node
, int f
, mtdf_info
* me
,
393 movestruct
* bestmove
= NULL
;
395 savemaxdepth
= me
->config
.searchdepth
;
397 for (i
= 1; i
<= savemaxdepth
; i
++)
399 if (bestmove
!= NULL
)
401 mem_del_move (bestmove
);
403 /* reset upper and lower limits in the memory-tree */
407 me
->config
.searchdepth
= i
;
408 bestmove
= mtdf (oboard
, node
, f
, me
, type
);
411 me
->config
.searchdepth
= savemaxdepth
;
416 movestruct
* mtdf (board
* oboard
, treenode
* node
, int f
, mtdf_info
* me
,
423 movestruct
* bestmove
= NULL
;
429 while (lower
< upper
)
440 if (bestmove
!= NULL
)
442 mem_del_move (bestmove
);
448 bestmove
= mem_ab_move (oboard
, node
, beta
-1, beta
,
453 bestmove
= mem_ab_gipf (oboard
, node
, beta
-1, beta
,
458 bestmove
= mem_ab_row (oboard
, node
, beta
-1, beta
,
462 value
= bestmove
->value
;
474 me
->lastvalue
= value
;
479 movestruct
* mem_ab_move (board
* oboard
, treenode
* node
, int alfa
, int beta
,
480 int minmax
, int depth
, mtdf_info
* me
)
490 treenode
* childnode
;
492 /* maximum search depth or end of game */
493 if ((b_game_finished (oboard
)) ||
494 (depth
> me
->config
.searchdepth
))
496 nmove
= (movestruct
*) malloc (sizeof (movestruct
));
497 nmove
->from
[0] = '\0';
500 nmove
->movelist
= NULL
;
501 nmove
->value
= mem_evaluate (oboard
, me
);
506 if ((depth
== 1) || (depth
< me
->config
.searchdepth
))
508 checkwindowevents ();
512 /* list of moves to try depends on the question if we can
513 ** place a gipf or not.
514 ** cutoff after a predetermined number of gipf-pieces */
515 if ((b_colour_type (oboard
, b_next_piece (oboard
)) == 'g') &&
516 (b_colour_gipf (oboard
, b_next_piece (oboard
)) <
519 allmoves
= allmovesg
;
524 allmoves
= allmovesn
;
528 lastmove
.sboard
= NULL
;
530 if (minmax
== MAXNODE
)
534 for (i
= 0; i
< maxmoves
; i
++)
536 childnode
= mem_child (node
, i
+1, me
, depth
);
537 nmove
= mem_move (oboard
, childnode
, alfa
, beta
, minmax
,
538 depth
, me
, &(allmoves
[i
]), &lastmove
);
543 if (mem_equ_h (nmove
->value
, value
, &chance
, me
))
545 value
= nmove
->value
;
546 if (bestmove
!= NULL
)
548 mem_del_move (bestmove
);
554 mem_del_move (nmove
);
556 alfa
= max (alfa
, value
);
561 ** problems if value is the same as beta, this means that
562 ** when randomly selecting a move from the moves with the
563 ** same value, this one could be chosen.
564 ** solution: change value to (-1001 or 1001)
565 ** or the current value (+1 or -1)
567 ** is this correct? or does it depend on the fact if
568 ** this was called from a min- or a max-node?
578 for (i
= 0; i
< maxmoves
; i
++)
580 childnode
= mem_child (node
, i
+1, me
, depth
);
581 nmove
= mem_move (oboard
, childnode
, alfa
, beta
, minmax
,
582 depth
, me
, &(allmoves
[i
]), &lastmove
);
587 if (mem_equ_l (nmove
->value
, value
, &chance
, me
))
589 value
= nmove
->value
;
590 if (bestmove
!= NULL
)
592 mem_del_move (bestmove
);
598 mem_del_move (nmove
);
600 beta
= min (beta
, value
);
609 if ((childnode
== NULL
) && (lastmove
.sboard
!= NULL
))
611 b_del (lastmove
.sboard
);
618 movestruct
* mem_move (board
* oboard
, treenode
* node
, int alfa
, int beta
,
619 int minmax
, int depth
, mtdf_info
* me
, fromto
* todo
,
628 if ((node
!= NULL
) && (node
->children
!= NULL
))
629 { /* node already visited, reuse from memory */
630 if (node
->father
== NULL
)
634 newboard
= node
->father
;
638 ** removing this solves the problem of bad play
639 ** but it makes the computerplayer twice as slow as ai_minimax
641 ** it also solves the problem of iterative deepening not working
643 if (node
->lower
>= beta
)
645 nmove
= (movestruct
*) malloc (sizeof (movestruct
));
646 nmove
->from
[0] = todo
->from
[0];
647 nmove
->from
[1] = todo
->from
[1];
648 nmove
->to
[0] = todo
->to
[0];
649 nmove
->to
[1] = todo
->to
[1];
651 nmove
->movelist
= NULL
;
652 nmove
->value
= node
->lower
;
655 if (node
->upper
<= alfa
)
657 nmove
= (movestruct
*) malloc (sizeof (movestruct
));
658 nmove
->from
[0] = todo
->from
[0];
659 nmove
->from
[1] = todo
->from
[1];
660 nmove
->to
[0] = todo
->to
[0];
661 nmove
->to
[1] = todo
->to
[1];
662 nmove
->type
= todo
->type
;
663 nmove
->movelist
= NULL
;
664 nmove
->value
= node
->upper
;
667 alfa
= max (alfa
, node
->lower
);
668 beta
= min (beta
, node
->upper
);
675 /* create children list */
676 node
->children
= (listheader
*) malloc (sizeof (listheader
));
677 newlist (node
->children
);
680 if (todo
->type
== 'g')
682 piece
= b_otherpiece (b_next_piece (oboard
));
686 piece
= b_next_piece (oboard
);
689 newboard
= b_move (oboard
, todo
->from
, todo
->to
, piece
);
692 node
->father
= newboard
;
695 if (newboard
== NULL
)
700 /* check if the result is the same as the last move */
701 if ((lmove
->sboard
!= NULL
) &&
702 ((lmove
->to
[0] == todo
->to
[0]) && (lmove
->to
[1] == todo
->to
[1])) &&
703 (b_compare (newboard
, lmove
->sboard
) == 0))
712 if ((node
== NULL
) && (lmove
->sboard
!= NULL
))
714 b_del (lmove
->sboard
);
716 lmove
->sboard
= newboard
; /* don't delete the board at the end */
717 lmove
->to
[0] = todo
->to
[0];
718 lmove
->to
[1] = todo
->to
[1];
721 /* create new movestruct */
722 mymove
= (movestruct
*) malloc (sizeof (movestruct
));
723 mymove
->from
[0] = todo
->from
[0];
724 mymove
->from
[1] = todo
->from
[1];
725 mymove
->to
[0] = todo
->to
[0];
726 mymove
->to
[1] = todo
->to
[1];
727 mymove
->type
= todo
->type
;
728 mymove
->movelist
= NULL
;
730 newminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
731 if ((b_status (newboard
) == S_NORMAL
) ||
732 (b_status (newboard
) == S_FINISHED
))
734 nmove
= mem_ab_move (newboard
, node
, alfa
, beta
, newminmax
,
736 mymove
->value
= nmove
->value
;
737 mem_del_move (nmove
);
739 else if (b_status (newboard
) == S_REMOVEROW
)
741 nmove
= mem_ab_row (newboard
, node
, alfa
, beta
, minmax
, depth
, me
);
742 mymove
->movelist
= nmove
->movelist
;
743 mymove
->value
= nmove
->value
;
744 nmove
->movelist
= NULL
;
745 mem_del_move (nmove
);
747 else if (b_status (newboard
) == S_REMOVEGIPF
)
749 nmove
= mem_ab_gipf (newboard
, node
, alfa
, beta
, minmax
, depth
, me
);
750 mymove
->movelist
= nmove
->movelist
;
751 mymove
->value
= nmove
->value
;
752 nmove
->movelist
= NULL
;
753 mem_del_move (nmove
);
762 if (mymove
->value
<= alfa
)
764 node
->upper
= mymove
->value
;
766 else if ((mymove
->value
> alfa
) && (mymove
->value
< beta
))
767 { /* this shouldn't happen with zero window searches */
768 node
->upper
= node
->lower
= mymove
->value
;
770 else if (mymove
->value
>= beta
)
772 node
->lower
= mymove
->value
;
780 movestruct
* mem_ab_gipf (board
* oboard
, treenode
* node
, int alfa
, int beta
,
781 int minmax
, int depth
, mtdf_info
* me
)
798 treenode
* childnode
;
800 gipfi
= (rem_gipf
*) llitembynr (b_gipf_extra (oboard
), 1);
803 ** I may have to change if I am a min or a max-node here
804 ** it's possible that my opponent won a row, so he has to
805 ** decide if gipf-pieces must be removed
807 if (b_gipf_owner(gipfi
) == b_next_piece (oboard
))
809 realminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
816 /* always remove gipf-pieces from my opponent if the flag is set */
817 myg
= (listheader
*) malloc (sizeof (listheader
));
819 otherg
= (listheader
*) malloc (sizeof (listheader
));
823 while ((gipfi
= (rem_gipf
*) llitembynr (b_gipf_extra (oboard
), counter
))
827 gipfflag
= (gipfitem
*) malloc (sizeof (gipfitem
));
828 gipfflag
->gipf
= gipfi
;
831 gipfpos
= b_gipf_position (gipfi
);
832 if ((me
->config
.remoppgipf
== 1) &&
833 (b_otherpiece (b_gipf_owner (gipfi
)) !=
834 b_piece (oboard
, gipfpos
)))
836 pushll (otherg
, (void *) gipfflag
);
841 pushll (myg
, (void *) gipfflag
);
846 maxnr
= 1 << mynr
; /* 2 ^ mynr */
848 if (realminmax
== MAXNODE
)
852 for (bits1
= 0; bits1
< maxnr
; bits1
++)
855 for (i
= 0; i
< mynr
; i
++)
857 gipfflag
= (gipfitem
*) llitembynr (myg
, i
+1);
858 gipfflag
->flag
= bits2
& 1;
861 childnode
= mem_child (node
, bits1
+ 1, me
, depth
);
862 nmove
= mem_rem_gipflist (oboard
, childnode
, alfa
, beta
,
863 minmax
, depth
, me
, myg
, otherg
);
865 if (nmove
->value
> value
)
867 value
= nmove
->value
;
868 if (bestmove
!= NULL
)
870 mem_del_move (bestmove
);
876 mem_del_move (nmove
);
878 alfa
= max (alfa
, value
);
890 for (bits1
= 0; bits1
< maxnr
; bits1
++)
893 for (i
= 0; i
< mynr
; i
++)
895 gipfflag
= (gipfitem
*) llitembynr (myg
, i
+1);
896 gipfflag
->flag
= bits2
& 1;
899 childnode
= mem_child (node
, bits1
+ 1, me
, depth
);
900 nmove
= mem_rem_gipflist (oboard
, childnode
, alfa
, beta
,
901 minmax
, depth
, me
, myg
, otherg
);
903 if (nmove
->value
< value
)
905 value
= nmove
->value
;
906 if (bestmove
!= NULL
)
908 mem_del_move (bestmove
);
914 mem_del_move (nmove
);
916 beta
= min (beta
, value
);
925 /* cleanup temporary lists */
926 while ((gipfflag
= (gipfitem
*) llrembynr (myg
, 1)) != NULL
)
931 while ((gipfflag
= (gipfitem
*) llrembynr (otherg
, 1)) != NULL
)
941 movestruct
* mem_rem_gipflist (board
* oboard
, treenode
* node
, int alfa
,
942 int beta
, int minmax
, int depth
,
943 mtdf_info
* me
, listheader
* myg
,
952 listheader
* remlist
;
959 if ((node
!= NULL
) && (node
->children
!= NULL
))
960 { /* node already visited, reuse from memory */
961 if (node
->father
== NULL
)
965 newboard
= node
->father
;
967 /* I have to produce remlist here again */
968 remlist
= (listheader
*) malloc (sizeof (listheader
));;
970 /* list of gipf-pieces that may or may not have to be removed */
972 while ((gipfflag
= (gipfitem
*) llitembynr (myg
, counter
)) != NULL
)
975 gipfd
= (gipfdata
*) malloc (sizeof (gipfdata
));
976 strpos
= b_gipf_position (gipfflag
->gipf
);
977 owner
= b_gipf_owner (gipfflag
->gipf
);
978 gipfd
->pos
[0] = strpos
[0];
979 gipfd
->pos
[1] = strpos
[1];
980 gipfd
->pos
[2] = '\0';
983 if (gipfflag
->flag
== 1)
991 pushll (remlist
, (void *) gipfd
);
993 /* list of gipf-pieces that always have to be removed */
995 while ((gipfflag
= (gipfitem
*) llitembynr (otherg
, counter
)) != NULL
)
998 gipfd
= (gipfdata
*) malloc (sizeof (gipfdata
));
999 strpos
= b_gipf_position (gipfflag
->gipf
);
1000 owner
= b_gipf_owner (gipfflag
->gipf
);
1001 gipfd
->pos
[0] = strpos
[0];
1002 gipfd
->pos
[1] = strpos
[1];
1003 gipfd
->pos
[2] = '\0';
1007 pushll (remlist
, (void *) gipfd
);
1015 /* create children list */
1016 node
->children
= (listheader
*) malloc (sizeof (listheader
));
1017 newlist (node
->children
);
1021 remlist
= (listheader
*) malloc (sizeof (listheader
));;
1023 /* list of gipf-pieces that may or may not have to be removed */
1025 while ((gipfflag
= (gipfitem
*) llitembynr (myg
, counter
)) != NULL
)
1028 gipfd
= (gipfdata
*) malloc (sizeof (gipfdata
));
1029 strpos
= b_gipf_position (gipfflag
->gipf
);
1030 owner
= b_gipf_owner (gipfflag
->gipf
);
1031 gipfd
->pos
[0] = strpos
[0];
1032 gipfd
->pos
[1] = strpos
[1];
1033 gipfd
->pos
[2] = '\0';
1036 if (gipfflag
->flag
== 1)
1039 nboard
= b_remove_gipf (newboard
, gipfflag
->gipf
);
1040 if (newboard
!= oboard
)
1050 pushll (remlist
, (void *) gipfd
);
1053 /* list of gipf-pieces that always have to be removed */
1055 while ((gipfflag
= (gipfitem
*) llitembynr (otherg
, counter
)) != NULL
)
1058 gipfd
= (gipfdata
*) malloc (sizeof (gipfdata
));
1059 strpos
= b_gipf_position (gipfflag
->gipf
);
1060 owner
= b_gipf_owner (gipfflag
->gipf
);
1061 gipfd
->pos
[0] = strpos
[0];
1062 gipfd
->pos
[1] = strpos
[1];
1063 gipfd
->pos
[2] = '\0';
1067 nboard
= b_remove_gipf (newboard
, gipfflag
->gipf
);
1068 if (newboard
!= oboard
)
1073 pushll (remlist
, (void *) gipfd
);
1076 /* check again for 4 in a row */
1077 nboard
= b_checkfour (newboard
);
1078 if (newboard
!= oboard
)
1086 node
->father
= newboard
;
1090 mymove
= (movestruct
*) malloc (sizeof (movestruct
));
1091 mymove
->from
[0] = '\0';
1092 mymove
->to
[0] = '\0';
1094 mymove
->movelist
= (listheader
*) malloc (sizeof (listheader
));
1095 newlist (mymove
->movelist
);
1098 ** only add actions to the movelist if they have to be executed
1099 ** by the max-player
1100 ** this means moves for the min-player will not be executable,
1101 ** but that really isn't necessary
1103 if (me
->colour
== owner
)
1105 movedata
= (nextmove
*) malloc (sizeof (nextmove
));
1106 movedata
->remtype
= REM_GIPF
;
1107 movedata
->gipflist
= remlist
;
1108 pushll (mymove
->movelist
, (void *) movedata
);
1111 { /* remove remlist, we don't need it here */
1112 while ((gipfd
= (gipfdata
*) llrembynr (remlist
, 1)) != NULL
)
1119 newminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
1121 if ((b_status (newboard
) == S_NORMAL
) ||
1122 (b_status (newboard
) == S_FINISHED
))
1124 nmove
= mem_ab_move (newboard
, node
, alfa
, beta
, newminmax
,
1126 mymove
->value
= nmove
->value
;
1127 mem_del_move (nmove
);
1129 else if (b_status (newboard
) == S_REMOVEROW
)
1131 nmove
= mem_ab_row (newboard
, node
, alfa
, beta
, minmax
, depth
, me
);
1133 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
1136 pushll (mymove
->movelist
, (void *) movedata
);
1139 mymove
->value
= nmove
->value
;
1140 mem_del_move (nmove
);
1142 else if (b_status (newboard
) == S_REMOVEGIPF
)
1144 nmove
= mem_ab_gipf (newboard
, node
, alfa
, beta
, minmax
, depth
, me
);
1146 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
1149 pushll (mymove
->movelist
, (void *) movedata
);
1152 mymove
->value
= nmove
->value
;
1153 mem_del_move (nmove
);
1160 /* check if the movelist of mymove contains something */
1161 if (llitembynr (mymove
->movelist
, 1) == NULL
)
1163 free (mymove
->movelist
);
1164 mymove
->movelist
= NULL
;
1173 if (mymove
->value
<= alfa
)
1175 node
->upper
= mymove
->value
;
1177 else if ((mymove
->value
> alfa
) && (mymove
->value
< beta
))
1178 { /* this shouldn't happen with zero window searches */
1179 node
->upper
= node
->lower
= mymove
->value
;
1181 else if (mymove
->value
>= beta
)
1183 node
->lower
= mymove
->value
;
1192 movestruct
* mem_ab_row (board
* oboard
, treenode
* node
, int alfa
, int beta
,
1193 int minmax
, int depth
, mtdf_info
* me
)
1201 listheader
* rowlist
;
1202 treenode
* childnode
;
1204 rowlist
= b_row_extra (oboard
);
1205 rowi
= (rem_row
*) llitembynr (rowlist
, 1);
1208 ** I may have to change if I am a min or a max-node here
1209 ** it's possible that my opponent won several rows, so he has to
1210 ** decide what row to remove
1212 if (row_owner(rowi
) == b_next_piece (oboard
))
1214 realminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
1218 realminmax
= minmax
;
1221 if (realminmax
== MAXNODE
)
1226 while ((rowi
= (rem_row
*) llitembynr (rowlist
, counter
))
1229 childnode
= mem_child (node
, counter
, me
, depth
);
1230 nmove
= mem_rem_row (oboard
, childnode
, alfa
, beta
, minmax
,
1231 depth
, me
, counter
);
1234 if (nmove
->value
> value
)
1236 value
= nmove
->value
;
1237 if (bestmove
!= NULL
)
1239 mem_del_move (bestmove
);
1245 mem_del_move (nmove
);
1247 alfa
= max (alfa
, value
);
1260 while ((rowi
= (rem_row
*) llitembynr (rowlist
, counter
))
1263 childnode
= mem_child (node
, counter
, me
, depth
);
1264 nmove
= mem_rem_row (oboard
, childnode
, alfa
, beta
, minmax
,
1265 depth
, me
, counter
);
1268 if (nmove
->value
< value
)
1270 value
= nmove
->value
;
1271 if (bestmove
!= NULL
)
1273 mem_del_move (bestmove
);
1279 mem_del_move (nmove
);
1281 beta
= min (beta
, value
);
1294 movestruct
* mem_rem_row (board
* oboard
, treenode
* node
, int alfa
, int beta
,
1295 int minmax
, int depth
, mtdf_info
* me
, int rem
)
1301 nextmove
* movedata
;
1304 if ((node
!= NULL
) && (node
->children
!= NULL
))
1305 { /* node already visited, reuse from memory */
1306 if (node
->father
== NULL
)
1310 newboard
= node
->father
;
1316 /* create children list */
1317 node
->children
= (listheader
*) malloc (sizeof (listheader
));
1318 newlist (node
->children
);
1321 newboard
= b_remove_row (oboard
, rem
);
1324 node
->father
= newboard
;
1328 mymove
= (movestruct
*) malloc (sizeof (movestruct
));
1329 mymove
->from
[0] = '\0';
1330 mymove
->to
[0] = '\0';
1332 mymove
->movelist
= (listheader
*) malloc (sizeof (listheader
));
1333 newlist (mymove
->movelist
);
1336 ** only add actions to the movelist if they have to be executed
1337 ** by the max-player
1338 ** this means moves for the min-player will not be executable,
1339 ** but that really isn't necessary
1341 remi
= (rem_row
*) llitembynr (b_row_extra (oboard
), rem
);
1342 if (me
->colour
== row_owner (remi
))
1344 movedata
= (nextmove
*) malloc (sizeof (nextmove
));
1345 movedata
->remtype
= REM_ROW
;
1346 movedata
->gipflist
= NULL
;
1347 movedata
->rowdata
.start
= postostr (remi
->startpos
);
1348 movedata
->rowdata
.end
= postostr (remi
->endpos
);
1349 pushll (mymove
->movelist
, (void *) movedata
);
1352 newminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
1354 if ((b_status (newboard
) == S_NORMAL
) ||
1355 (b_status (newboard
) == S_FINISHED
))
1357 nmove
= mem_ab_move (newboard
, node
, alfa
, beta
, newminmax
,
1359 mymove
->value
= nmove
->value
;
1360 mem_del_move (nmove
);
1362 else if (b_status (newboard
) == S_REMOVEROW
)
1364 nmove
= mem_ab_row (newboard
, node
, alfa
, beta
, minmax
, depth
, me
);
1366 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
1369 pushll (mymove
->movelist
, (void *) movedata
);
1372 mymove
->value
= nmove
->value
;
1373 mem_del_move (nmove
);
1375 else if (b_status (newboard
) == S_REMOVEGIPF
)
1377 nmove
= mem_ab_gipf (newboard
, node
, alfa
, beta
, minmax
, depth
, me
);
1379 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
1382 pushll (mymove
->movelist
, (void *) movedata
);
1385 mymove
->value
= nmove
->value
;
1386 mem_del_move (nmove
);
1393 /* check if the movelist of mymove contains something */
1394 if (llitembynr (mymove
->movelist
, 1) == NULL
)
1396 free (mymove
->movelist
);
1397 mymove
->movelist
= NULL
;
1406 if (mymove
->value
<= alfa
)
1408 node
->upper
= mymove
->value
;
1410 else if ((mymove
->value
> alfa
) && (mymove
->value
< beta
))
1411 { /* this shouldn't happen with zero window searches */
1412 node
->upper
= node
->lower
= mymove
->value
;
1414 else if (mymove
->value
>= beta
)
1416 node
->lower
= mymove
->value
;
1425 ** calculate the value of a certain board position
1427 ** returns a value between 1000 and -1000 (inclusive)
1429 ** -1000 : my opponent wins
1431 int mem_evaluate (board
* oboard
, mtdf_info
* me
)
1443 otherc
= b_opponent (myc
);
1445 if (b_game_finished (oboard
))
1447 if (b_winner (oboard
) == myc
)
1457 /* maybe I can return 1000 or -1000, but I'm not completely sure */
1458 if (b_colour (oboard
, myc
) == 0)
1462 else if (b_colour (oboard
, otherc
) == 0)
1467 /* I need to start with a base-value, or I get a lot of
1468 ** problems at the start of tournament games */
1472 /* capturing a piece from your opponent is worth 20 points */
1473 wvalue
+= 20 * b_black_lost (oboard
);
1474 bvalue
+= 20 * b_white_lost (oboard
);
1476 /* 1 point for each piece in use on the board */
1477 if (b_white_gipf (oboard
) == -1)
1482 wvalue
+= total
- b_white (oboard
) - b_white_lost (oboard
);
1483 bvalue
+= total
- b_black (oboard
) - b_black_lost (oboard
);
1485 /* 2 pieces or less left is getting dangerous */
1487 /* one gipf left can be dangerous, subtract 5 points */
1488 if (b_white_gipf (oboard
) == 1)
1492 if (b_black_gipf (oboard
) == 1)
1497 /* pieces closer to the center have a higher value */
1498 for (i
= 0; i
< 19; i
++)
1500 pos
= &(mem_pos_val
[i
].coor
);
1501 switch (b_ppiece (oboard
, pos
))
1507 wvalue
+= mem_pos_val
[i
].value
;
1511 wvalue
+= mem_pos_val
[i
].value
* 1.5;
1515 bvalue
+= mem_pos_val
[i
].value
;
1519 bvalue
+= mem_pos_val
[i
].value
* 1.5;
1522 piece = b_ppiece (oboard, pos);
1529 wvalue += mem_pos_val[i].value;
1531 else if (piece == 'O')
1533 wvalue += mem_pos_val[i].value * 1.5;
1535 else if (piece == 'x')
1537 bvalue += mem_pos_val[i].value;
1541 bvalue += mem_pos_val[i].value * 1.5;
1546 /* normalize the result, should be between 1000 and -1000 */
1549 value
= (int) ((wvalue
- bvalue
) * 1000 / (wvalue
+ bvalue
));
1553 value
= (int) ((bvalue
- wvalue
) * 1000 / (wvalue
+ bvalue
));
1559 void mem_del_move (movestruct
* todel
)
1561 nextmove
* movedata
;
1564 if (todel
->movelist
!= NULL
)
1566 while ((movedata
= (nextmove
*) llrembynr (todel
->movelist
, 1))
1569 if (movedata
->remtype
== REM_ROW
)
1571 free (movedata
->rowdata
.start
);
1572 free (movedata
->rowdata
.end
);
1576 while ((gipfd
= (gipfdata
*)
1577 llrembynr (movedata
->gipflist
, 1)) != NULL
)
1581 free (movedata
->gipflist
);
1586 free (todel
->movelist
);
1595 ** create the root of the tree
1598 ** father: the board at the root of the tree
1600 treenode
* mem_makeroot (board
* father
, mtdf_info
* me
)
1604 if (me
->config
.memorydepth
== 0)
1609 newnode
= (treenode
*) malloc (sizeof (treenode
));
1610 newnode
->father
= father
;
1611 newnode
->upper
= 1001;
1612 newnode
->lower
= -1001;
1614 newnode
->children
= (listheader
*) malloc (sizeof (listheader
));
1615 newlist (newnode
->children
);
1623 ** don't delete the father from the root-node
1625 void mem_deltree (treenode
* node
)
1632 emptyll (node
->children
, mem_delnode
);
1633 free (node
->children
);
1639 void mem_delnode (void * item
)
1641 treenode
* node
= item
;
1643 b_del (node
->father
);
1644 emptyll (node
->children
, mem_delnode
);
1645 free (node
->children
);
1653 ** reset upper and lower limits in the memory-tree
1655 void mem_resetul (void * item
)
1657 treenode
* node
= item
;
1660 node
->lower
= -1001;
1661 doll (node
->children
, mem_resetul
);
1668 ** check if a child-node already exists,
1669 ** if not, create a new one
1671 treenode
* mem_child (treenode
* node
, int nr
, mtdf_info
* me
, int depth
)
1675 if (me
->config
.memorydepth
< depth
)
1680 newnode
= (treenode
*) llitembynr (node
->children
, nr
);
1681 if (newnode
!= NULL
)
1682 { /* this node has already been handled, return it */
1687 /* just for testing */
1688 /* check if the previous nr exists, it should */
1689 if ((nr
> 1) && (llitembynr (node
->children
, nr
-1) == NULL
))
1691 printf ("\nERROR: mem_child\n\n");
1696 /* create a new node */
1697 newnode
= (treenode
*) malloc (sizeof (treenode
));
1698 newnode
->father
= NULL
;
1699 newnode
->children
= NULL
;
1700 newnode
->upper
= 1001;
1701 newnode
->lower
= -1001;
1702 pushll (node
->children
, newnode
);
1708 ** just like a normal compare (<)
1712 ** 0/1: when nr1 and nr2 are equal, chooses one at random
1714 ** chance is the chance that nr1 will be chosen if nr1 == nr2
1715 ** this parameter will be incremented each time an equal occurs
1716 ** and will be set to 1 if nr1 < nr2
1717 ** (it should be initialised to 1 by the caller and then left alone)
1719 int mem_equ_l (int nr1
, int nr2
, int * chance
, mtdf_info
* me
)
1723 if (me
->config
.randomchoose
== 0)
1736 randnr
= (int) ( (*chance
+ 1.0) * rand() / (RAND_MAX
+1.0) );
1749 ** just like a normal compare (>)
1753 ** 0/1: when nr1 and nr2 are equal, chooses one at random
1755 ** chance is the chance that nr1 will be chosen if nr1 == nr2
1756 ** this parameter will be incremented each time an equal occurs
1757 ** and will be set to 1 if nr1 > nr2
1758 ** (it should be initialised to 1 by the caller and then left alone)
1760 int mem_equ_h (int nr1
, int nr2
, int * chance
, mtdf_info
* me
)
1764 if (me
->config
.randomchoose
== 0)
1777 randnr
= (int) ( (*chance
+ 1.0) * rand() / (RAND_MAX
+1.0) );