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.
22 #include "ai_minimax.h"
25 extern void checkwindowevents (void);
26 extern int interrupt_computer
;
30 /*#define PRINTMOVES*/
32 /* structures for keeping my own info in */
44 listheader
* movelist
; /* list of items of type nextmove */
48 int remtype
; /* REM_GIPF or REM_ROW */
49 listheader
* gipflist
; /* list of items of type gipfdata */
63 listheader
* movelist
; /* list of items of type nextmove */
86 movestruct
* alfabeta_move (board
* oboard
, int alfa
, int beta
, int minmax
,
87 int depth
, minimax_info
* me
);
88 movestruct
* move (board
* oboard
, int alfa
, int beta
, int minmax
, int depth
,
89 minimax_info
* me
, fromto
* todo
, saveboard
* lmove
);
90 movestruct
* alfabeta_gipf (board
* oboard
, int alfa
, int beta
, int minmax
,
91 int depth
, minimax_info
* me
);
92 movestruct
* remove_gipflist (board
* oboard
, int alfa
, int beta
, int minmax
,
93 int depth
, minimax_info
* me
, listheader
* myg
,
95 movestruct
* alfabeta_row (board
* oboard
, int alfa
, int beta
, int minmax
,
96 int depth
, minimax_info
* me
);
97 movestruct
* remove_row (board
* oboard
, int alfa
, int beta
, int minmax
,
98 int depth
, minimax_info
* me
, int rem
);
99 int evaluate (board
* oboard
, minimax_info
* me
);
100 void del_move (movestruct
* todel
);
103 int equ_l (int nr1
, int nr2
, int * chance
, minimax_info
* me
, int depth
);
104 int equ_h (int nr1
, int nr2
, int * chance
, minimax_info
* me
, int depth
);
107 void * minimax_new (char colour
, int game
)
110 listheader
* configlist
;
112 me
= (minimax_info
*) malloc (sizeof (minimax_info
));
117 /* check for config-values from the config-file */
118 configlist
= readconfigfile ("gf1.cfg");
120 me
->config
.searchdepth
= findconfigvalue (configlist
, "searchdepth",
122 me
->config
.remoppgipf
= findconfigvalue (configlist
, "remoppgipf",
124 me
->config
.maxgipf
= findconfigvalue (configlist
, "maxgipf",
127 me
->config
.randomchoose
= findconfigvalue (configlist
, "randomchoose",
131 clearconfiglist (configlist
);
133 return ((void *) me
);
137 void minimax_move (board
* oboard
, void * self
,
138 char * type
, char * from
, char * to
)
140 minimax_info
* me
= self
;
146 move
= alfabeta_move (oboard
, -1001, 1001, MAXNODE
, depth
, me
);
148 from
[0] = move
->from
[0];
149 from
[1] = move
->from
[1];
154 me
->movelist
= move
->movelist
;
157 printf ("ai_minimax %c (%d): move %2s-%2s\n",
158 me
->colour
, move
->value
, from
, to
);
161 move
->movelist
= NULL
;
168 char minimax_gipf (board
* oboard
, void * self
, char * pos
)
170 minimax_info
* me
= self
;
178 /* check if movelist contains info about removing gipf-pieces */
179 if (me
->movelist
== NULL
)
182 ** no info in movelist, my opponent made 4 in a row
183 ** with my pieces (only possible explanation)
188 /* remark: I have to start this as a min-node,
189 ** because this is really my opponents move */
190 nmove
= alfabeta_gipf (oboard
, -1001, 1001, MINNODE
, depth
, me
);
191 me
->movelist
= nmove
->movelist
;
192 nmove
->movelist
= NULL
;
196 /* now check the movelist for the move we have to make */
197 if (((movedata
= (nextmove
*) llitembynr (me
->movelist
, 1)) == NULL
) ||
198 (movedata
->remtype
!= REM_GIPF
))
202 printf ("action removegipf, but nextmove contains something else\n\n");
207 /* look for the gipf to remove */
209 while ((gipfd
= (gipfdata
*) llitembynr (movedata
->gipflist
, counter
))
212 if ((gipfd
->pos
[0] == pos
[0]) && (gipfd
->pos
[1] == pos
[1]))
222 printf ("action removegipf, but the gipf isn't in nextmove\n\n");
226 /* remove gipf from list */
227 gipfd
= (gipfdata
*) llrembynr (movedata
->gipflist
, counter
);
229 /* remove nextmove from movelist if gipflist is empty */
230 if (llitembynr (movedata
->gipflist
, 1) == NULL
)
232 movedata
= (nextmove
*) llrembynr (me
->movelist
, 1);
233 free (movedata
->gipflist
);
236 /* remove movelist if empty */
237 if (llitembynr (me
->movelist
, 1) == NULL
)
248 printf ("ai_minimax %c: remove gipf %2s (%c)\n", me
->colour
, pos
, val
);
254 char minimax_row (board
* oboard
, void * self
, char * start
, char * end
)
256 minimax_info
* me
= self
;
262 /* check if movelist contains info about removing rows */
263 if (me
->movelist
== NULL
)
266 ** no info in movelist, my opponent made several "4 in a row"s
267 ** with my pieces (only possible explanation)
272 /* remark: I have to start this as a min-node,
273 ** because this is really my opponents move */
274 nmove
= alfabeta_row (oboard
, -1001, 1001, MINNODE
, depth
, me
);
275 me
->movelist
= nmove
->movelist
;
276 nmove
->movelist
= NULL
;
280 /* now check the movelist for the move we have to make */
281 if (((movedata
= (nextmove
*) llitembynr (me
->movelist
, 1)) == NULL
) ||
282 (movedata
->remtype
!= REM_ROW
))
286 printf ("action removerow, but nextmove contains something else\n\n");
292 /* check if this is the correct row to be removed */
293 if ((start
[0] == movedata
->rowdata
.start
[0]) &&
294 (start
[1] == movedata
->rowdata
.start
[1]))
296 if ((end
[0] == movedata
->rowdata
.end
[0]) &&
297 (end
[1] == movedata
->rowdata
.end
[1]))
302 else if ((start
[0] == movedata
->rowdata
.end
[0]) &&
303 (start
[1] == movedata
->rowdata
.end
[1]))
305 if ((end
[0] == movedata
->rowdata
.start
[0]) &&
306 (end
[1] == movedata
->rowdata
.start
[1]))
314 /* remove nextmove from movelist */
315 movedata
= (nextmove
*) llrembynr (me
->movelist
, 1);
316 free (movedata
->rowdata
.start
);
317 free (movedata
->rowdata
.end
);
320 /* remove movelist if empty */
321 if (llitembynr (me
->movelist
, 1) == NULL
)
328 printf ("ai_minimax %c: remove row %2s-%2s\n", me
->colour
, start
, end
);
333 /* don't remove the row */
335 printf ("ai_minimax %c: don't remove row %2s-%2s\n",
336 me
->colour
, start
, end
);
343 void minimax_end (void * self
)
345 minimax_info
* me
= self
;
347 /* do I have to clean up the movelist first */
354 movestruct
* alfabeta_move (board
* oboard
, int alfa
, int beta
, int minmax
,
355 int depth
, minimax_info
* me
)
366 /* maximum search depth or end of game */
367 if ((b_game_finished (oboard
)) ||
368 (depth
> me
->config
.searchdepth
))
370 nmove
= (movestruct
*) malloc (sizeof (movestruct
));
371 nmove
->from
[0] = '\0';
374 nmove
->movelist
= NULL
;
375 nmove
->value
= evaluate (oboard
, me
);
380 if ((depth
== 1) || (depth
< me
->config
.searchdepth
))
382 checkwindowevents ();
386 /* list of moves to try depends on the question if we can
387 ** place a gipf or not.
388 ** cutoff after a predetermined number of gipf-pieces */
389 if ((b_colour_type (oboard
, b_next_piece (oboard
)) == 'g') &&
390 (b_colour_gipf (oboard
, b_next_piece (oboard
)) < me
->config
.maxgipf
))
392 allmoves
= allmovesg
;
397 allmoves
= allmovesn
;
401 lastmove
.sboard
= NULL
;
403 if (minmax
== MAXNODE
)
407 for (i
= 0; i
< maxmoves
; i
++)
409 nmove
= move (oboard
, alfa
, beta
, minmax
, depth
, me
,
410 &(allmoves
[i
]), &lastmove
);
416 if (equ_h (nmove
->value
, value
, &chance
, me
, depth
))
418 if (nmove
->value
> value
)
421 value
= nmove
->value
;
422 if (bestmove
!= NULL
)
432 alfa
= max (alfa
, value
);
441 ** problems if value is the same as beta, this means that
442 ** when randomly selecting a move from the moves with the
443 ** same value, this one could be chosen.
444 ** solution: change value to (-1001 or 1001)
445 ** or the current value (+1 or -1)
447 ** is this correct? or does it depend on the fact if
448 ** this was called from a min- or a max-node?
458 for (i
= 0; i
< maxmoves
; i
++)
460 nmove
= move (oboard
, alfa
, beta
, minmax
, depth
, me
,
461 &(allmoves
[i
]), &lastmove
);
467 if (equ_l (nmove
->value
, value
, &chance
, me
, depth
))
469 if (nmove
->value
< value
)
472 value
= nmove
->value
;
473 if (bestmove
!= NULL
)
483 /* how and when did I throw this out ?????? */
484 beta
= min (beta
, value
);
497 if (lastmove
.sboard
!= NULL
)
499 b_del (lastmove
.sboard
);
506 movestruct
* move (board
* oboard
, int alfa
, int beta
, int minmax
, int depth
,
507 minimax_info
* me
, fromto
* todo
, saveboard
* lmove
)
515 if (todo
->type
== 'g')
517 piece
= b_otherpiece (b_next_piece (oboard
));
521 piece
= b_next_piece (oboard
);
524 newboard
= b_move (oboard
, todo
->from
, todo
->to
, piece
);
526 if (newboard
== NULL
)
531 /* check if the result is the same as the last move */
532 if ((lmove
->sboard
!= NULL
) &&
533 ((lmove
->to
[0] == todo
->to
[0]) && (lmove
->to
[1] == todo
->to
[1])) &&
534 (b_compare (newboard
, lmove
->sboard
) == 0))
539 if (lmove
->sboard
!= NULL
)
541 b_del (lmove
->sboard
);
543 lmove
->sboard
= newboard
; /* don't delete the board at the end */
544 lmove
->to
[0] = todo
->to
[0];
545 lmove
->to
[1] = todo
->to
[1];
547 /* create new movestruct */
548 mymove
= (movestruct
*) malloc (sizeof (movestruct
));
549 mymove
->from
[0] = todo
->from
[0];
550 mymove
->from
[1] = todo
->from
[1];
551 mymove
->to
[0] = todo
->to
[0];
552 mymove
->to
[1] = todo
->to
[1];
553 mymove
->type
= todo
->type
;
554 mymove
->movelist
= NULL
;
556 newminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
557 if ((b_status (newboard
) == S_NORMAL
) ||
558 (b_status (newboard
) == S_FINISHED
))
560 nmove
= alfabeta_move (newboard
, alfa
, beta
, newminmax
, depth
+1, me
);
561 mymove
->value
= nmove
->value
;
564 else if (b_status (newboard
) == S_REMOVEROW
)
566 nmove
= alfabeta_row (newboard
, alfa
, beta
, minmax
, depth
, me
);
567 mymove
->movelist
= nmove
->movelist
;
568 mymove
->value
= nmove
->value
;
569 nmove
->movelist
= NULL
;
572 else if (b_status (newboard
) == S_REMOVEGIPF
)
574 nmove
= alfabeta_gipf (newboard
, alfa
, beta
, minmax
, depth
, me
);
575 mymove
->movelist
= nmove
->movelist
;
576 mymove
->value
= nmove
->value
;
577 nmove
->movelist
= NULL
;
583 printf ("ERROR: impossible in ai_minimax::move\n\n");
588 /* don't cleanup newboard here */
593 movestruct
* alfabeta_gipf (board
* oboard
, int alfa
, int beta
, int minmax
,
594 int depth
, minimax_info
* me
)
612 gipfi
= (rem_gipf
*) llitembynr (b_gipf_extra (oboard
), 1);
615 ** I may have to change if I am a min or a max-node here
616 ** it's possible that my opponent won a row, so he has to
617 ** decide if gipf-pieces must be removed
619 if (b_gipf_owner(gipfi
) == b_next_piece (oboard
))
621 realminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
628 /* always remove gipf-pieces from my opponent if the flag is set */
629 myg
= (listheader
*) malloc (sizeof (listheader
));
631 otherg
= (listheader
*) malloc (sizeof (listheader
));
635 while ((gipfi
= (rem_gipf
*) llitembynr (b_gipf_extra (oboard
), counter
))
639 gipfflag
= (gipfitem
*) malloc (sizeof (gipfitem
));
640 gipfflag
->gipf
= gipfi
;
643 gipfpos
= b_gipf_position (gipfi
);
644 if ((me
->config
.remoppgipf
== 1) &&
645 (b_otherpiece (b_gipf_owner (gipfi
)) !=
646 b_piece (oboard
, gipfpos
)))
648 pushll (otherg
, (void *) gipfflag
);
653 pushll (myg
, (void *) gipfflag
);
658 maxnr
= 1 << mynr
; /* 2 ^ mynr */
660 if (realminmax
== MAXNODE
)
664 for (bits1
= 0; bits1
< maxnr
; bits1
++)
667 for (i
= 0; i
< mynr
; i
++)
669 gipfflag
= (gipfitem
*) llitembynr (myg
, i
+1);
670 gipfflag
->flag
= bits2
& 1;
673 nmove
= remove_gipflist (oboard
, alfa
, beta
, minmax
, depth
, me
,
676 if (nmove
->value
> value
)
678 value
= nmove
->value
;
679 if (bestmove
!= NULL
)
689 alfa
= max (alfa
, value
);
705 for (bits1
= 0; bits1
< maxnr
; bits1
++)
708 for (i
= 0; i
< mynr
; i
++)
710 gipfflag
= (gipfitem
*) llitembynr (myg
, i
+1);
711 gipfflag
->flag
= bits2
& 1;
714 nmove
= remove_gipflist (oboard
, alfa
, beta
, minmax
, depth
, me
,
717 if (nmove
->value
< value
)
719 value
= nmove
->value
;
720 if (bestmove
!= NULL
)
730 beta
= min (beta
, value
);
743 /* cleanup temporary lists */
744 while ((gipfflag
= (gipfitem
*) llrembynr (myg
, 1)) != NULL
)
749 while ((gipfflag
= (gipfitem
*) llrembynr (otherg
, 1)) != NULL
)
759 movestruct
* remove_gipflist (board
* oboard
, int alfa
, int beta
, int minmax
,
760 int depth
, minimax_info
* me
, listheader
* myg
,
769 listheader
* remlist
;
777 remlist
= (listheader
*) malloc (sizeof (listheader
));;
779 /* list of gipf-pieces that may or may not have to be removed */
781 while ((gipfflag
= (gipfitem
*) llitembynr (myg
, counter
)) != NULL
)
784 gipfd
= (gipfdata
*) malloc (sizeof (gipfdata
));
785 strpos
= b_gipf_position (gipfflag
->gipf
);
786 owner
= b_gipf_owner (gipfflag
->gipf
);
787 gipfd
->pos
[0] = strpos
[0];
788 gipfd
->pos
[1] = strpos
[1];
789 gipfd
->pos
[2] = '\0';
792 if (gipfflag
->flag
== 1)
795 nboard
= b_remove_gipf (newboard
, gipfflag
->gipf
);
796 if (newboard
!= oboard
)
806 pushll (remlist
, (void *) gipfd
);
809 /* list of gipf-pieces that always have to be removed */
811 while ((gipfflag
= (gipfitem
*) llitembynr (otherg
, counter
)) != NULL
)
814 gipfd
= (gipfdata
*) malloc (sizeof (gipfdata
));
815 strpos
= b_gipf_position (gipfflag
->gipf
);
816 owner
= b_gipf_owner (gipfflag
->gipf
);
817 gipfd
->pos
[0] = strpos
[0];
818 gipfd
->pos
[1] = strpos
[1];
819 gipfd
->pos
[2] = '\0';
823 nboard
= b_remove_gipf (newboard
, gipfflag
->gipf
);
824 if (newboard
!= oboard
)
829 pushll (remlist
, (void *) gipfd
);
832 /* check again for 4 in a row */
833 nboard
= b_checkfour (newboard
);
834 if (newboard
!= oboard
)
840 mymove
= (movestruct
*) malloc (sizeof (movestruct
));
841 mymove
->from
[0] = '\0';
842 mymove
->to
[0] = '\0';
844 mymove
->movelist
= (listheader
*) malloc (sizeof (listheader
));
845 newlist (mymove
->movelist
);
848 ** only add actions to the movelist if they have to be executed
850 ** this means moves for the min-player will not be executable,
851 ** but that really isn't necessary
853 if (me
->colour
== owner
)
855 movedata
= (nextmove
*) malloc (sizeof (nextmove
));
856 movedata
->remtype
= REM_GIPF
;
857 movedata
->gipflist
= remlist
;
858 pushll (mymove
->movelist
, (void *) movedata
);
861 { /* remove remlist, we don't need it here */
862 while ((gipfd
= (gipfdata
*) llrembynr (remlist
, 1)) != NULL
)
869 newminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
871 if ((b_status (newboard
) == S_NORMAL
) ||
872 (b_status (newboard
) == S_FINISHED
))
874 nmove
= alfabeta_move (newboard
, alfa
, beta
, newminmax
, depth
+1, me
);
875 mymove
->value
= nmove
->value
;
878 else if (b_status (newboard
) == S_REMOVEROW
)
880 nmove
= alfabeta_row (newboard
, alfa
, beta
, minmax
, depth
, me
);
882 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
885 pushll (mymove
->movelist
, (void *) movedata
);
888 mymove
->value
= nmove
->value
;
891 else if (b_status (newboard
) == S_REMOVEGIPF
)
893 nmove
= alfabeta_gipf (newboard
, alfa
, beta
, minmax
, depth
, me
);
895 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
898 pushll (mymove
->movelist
, (void *) movedata
);
901 mymove
->value
= nmove
->value
;
907 printf ("ERROR: impossible in ai_minimax::remove_gipf\n\n");
914 /* check if the movelist of mymove contains something */
915 if (llitembynr (mymove
->movelist
, 1) == NULL
)
917 free (mymove
->movelist
);
918 mymove
->movelist
= NULL
;
925 movestruct
* alfabeta_row (board
* oboard
, int alfa
, int beta
, int minmax
,
926 int depth
, minimax_info
* me
)
934 listheader
* rowlist
;
936 rowlist
= b_row_extra (oboard
);
937 rowi
= (rem_row
*) llitembynr (rowlist
, 1);
940 ** I may have to change if I am a min or a max-node here
941 ** it's possible that my opponent won several rows, so he has to
942 ** decide what row to remove
944 if (row_owner(rowi
) == b_next_piece (oboard
))
946 realminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
953 if (realminmax
== MAXNODE
)
958 while ((rowi
= (rem_row
*) llitembynr (rowlist
, counter
))
961 nmove
= remove_row (oboard
, alfa
, beta
, minmax
, depth
, me
,
965 if (nmove
->value
> value
)
967 value
= nmove
->value
;
968 if (bestmove
!= NULL
)
978 alfa
= max (alfa
, value
);
995 while ((rowi
= (rem_row
*) llitembynr (rowlist
, counter
))
998 nmove
= remove_row (oboard
, alfa
, beta
, minmax
, depth
, me
,
1002 if (nmove
->value
< value
)
1004 value
= nmove
->value
;
1005 if (bestmove
!= NULL
)
1007 del_move (bestmove
);
1015 beta
= min (beta
, value
);
1032 movestruct
* remove_row (board
* oboard
, int alfa
, int beta
, int minmax
,
1033 int depth
, minimax_info
* me
, int rem
)
1039 nextmove
* movedata
;
1042 newboard
= b_remove_row (oboard
, rem
);
1044 mymove
= (movestruct
*) malloc (sizeof (movestruct
));
1045 mymove
->from
[0] = '\0';
1046 mymove
->to
[0] = '\0';
1048 mymove
->movelist
= (listheader
*) malloc (sizeof (listheader
));
1049 newlist (mymove
->movelist
);
1052 ** only add actions to the movelist if they have to be executed
1053 ** by the max-player
1054 ** this means moves for the min-player will not be executable,
1055 ** but that really isn't necessary
1057 remi
= (rem_row
*) llitembynr (b_row_extra (oboard
), rem
);
1058 if (me
->colour
== row_owner (remi
))
1060 movedata
= (nextmove
*) malloc (sizeof (nextmove
));
1061 movedata
->remtype
= REM_ROW
;
1062 movedata
->gipflist
= NULL
;
1063 movedata
->rowdata
.start
= postostr (remi
->startpos
);
1064 movedata
->rowdata
.end
= postostr (remi
->endpos
);
1065 pushll (mymove
->movelist
, (void *) movedata
);
1068 newminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
1070 if ((b_status (newboard
) == S_NORMAL
) ||
1071 (b_status (newboard
) == S_FINISHED
))
1073 nmove
= alfabeta_move (newboard
, alfa
, beta
, newminmax
, depth
+1, me
);
1074 mymove
->value
= nmove
->value
;
1077 else if (b_status (newboard
) == S_REMOVEROW
)
1079 nmove
= alfabeta_row (newboard
, alfa
, beta
, minmax
, depth
, me
);
1081 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
1084 pushll (mymove
->movelist
, (void *) movedata
);
1087 mymove
->value
= nmove
->value
;
1090 else if (b_status (newboard
) == S_REMOVEGIPF
)
1092 nmove
= alfabeta_gipf (newboard
, alfa
, beta
, minmax
, depth
, me
);
1094 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
1097 pushll (mymove
->movelist
, (void *) movedata
);
1100 mymove
->value
= nmove
->value
;
1106 printf ("ERROR: impossible in ai_minimax::remove_row\n\n");
1113 /* check if the movelist of mymove contains something */
1114 if (llitembynr (mymove
->movelist
, 1) == NULL
)
1116 free (mymove
->movelist
);
1117 mymove
->movelist
= NULL
;
1128 {{3, 4}, 2},{{3, 5}, 2},{{4, 6}, 2},{{5, 5}, 2},{{5, 4}, 2},{{4, 4}, 2},
1129 {{2, 3}, 1},{{2, 4}, 1},{{2, 5}, 1},{{3, 6}, 1},{{4, 7}, 1},{{5, 6}, 1},
1130 {{6, 5}, 1},{{6, 4}, 1},{{6, 3}, 1},{{5, 3}, 1},{{4, 3}, 1},{{3, 3}, 1}
1134 ** calculate the value of a certain board position
1136 ** returns a value between 1000 and -1000 (inclusive)
1138 ** -1000 : my opponent wins
1140 int evaluate (board
* oboard
, minimax_info
* me
)
1153 otherc
= b_opponent (myc
);
1155 if (b_game_finished (oboard
))
1157 if (b_winner (oboard
) == myc
)
1167 /* maybe I can return 1000 or -1000, but I'm not completely sure */
1168 if (b_colour (oboard
, myc
) == 0)
1172 else if (b_colour (oboard
, otherc
) == 0)
1177 /* I need to start with a base-value, or I get a lot of
1178 ** problems at the start of tournament games */
1182 /* capturing a piece from your opponent is worth 20 points */
1183 wvalue
+= 20 * b_black_lost (oboard
);
1184 bvalue
+= 20 * b_white_lost (oboard
);
1186 /* 1 point for each piece in use on the board */
1187 if (b_white_gipf (oboard
) == -1)
1192 wvalue
+= total
- b_white (oboard
) - b_white_lost (oboard
);
1193 bvalue
+= total
- b_black (oboard
) - b_black_lost (oboard
);
1195 /* 2 pieces or less left is getting dangerous */
1197 /* one gipf left can be dangerous, subtract 5 points */
1198 if (b_white_gipf (oboard
) == 1)
1202 if (b_black_gipf (oboard
) == 1)
1207 /* pieces closer to the center have a higher value */
1208 for (i
= 0; i
< 19; i
++)
1210 pos
= &(pos_val
[i
].coor
);
1211 piece
= b_ppiece (oboard
, pos
);
1218 wvalue
+= pos_val
[i
].value
;
1220 else if (piece
== 'O')
1222 wvalue
+= pos_val
[i
].value
* 1.5;
1224 else if (piece
== 'x')
1226 bvalue
+= pos_val
[i
].value
;
1230 bvalue
+= pos_val
[i
].value
* 1.5;
1234 /* normalize the result, should be between 1000 and -1000 */
1237 value
= (int) ((wvalue
- bvalue
) * 1000 / (wvalue
+ bvalue
));
1241 value
= (int) ((bvalue
- wvalue
) * 1000 / (wvalue
+ bvalue
));
1248 void del_move (movestruct
* todel
)
1250 nextmove
* movedata
;
1253 if (todel
->movelist
!= NULL
)
1255 while ((movedata
= (nextmove
*) llrembynr (todel
->movelist
, 1))
1258 if (movedata
->remtype
== REM_ROW
)
1260 free (movedata
->rowdata
.start
);
1261 free (movedata
->rowdata
.end
);
1265 while ((gipfd
= (gipfdata
*)
1266 llrembynr (movedata
->gipflist
, 1)) != NULL
)
1270 free (movedata
->gipflist
);
1275 free (todel
->movelist
);
1284 ** just like a normal compare (<)
1288 ** 0/1: when nr1 and nr2 are equal, chooses one at random
1290 ** chance is the chance that nr1 will be chosen if nr1 == nr2
1291 ** this parameter will be incremented each time an equal occurs
1292 ** and will be set to 1 if nr1 < nr2
1293 ** (it should be initialised to 1 by the caller and then left alone)
1295 int equ_l (int nr1
, int nr2
, int * chance
, minimax_info
* me
, int depth
)
1299 if ((me
->config
.randomchoose
== 0) || (depth
> 1))
1312 randnr
= (int) ( (*chance
+ 1.0) * rand() / (RAND_MAX
+1.0) );
1325 ** just like a normal compare (>)
1329 ** 0/1: when nr1 and nr2 are equal, chooses one at random
1331 ** chance is the chance that nr1 will be chosen if nr1 == nr2
1332 ** this parameter will be incremented each time an equal occurs
1333 ** and will be set to 1 if nr1 > nr2
1334 ** (it should be initialised to 1 by the caller and then left alone)
1336 int equ_h (int nr1
, int nr2
, int * chance
, minimax_info
* me
, int depth
)
1340 if ((me
->config
.randomchoose
== 0) || (depth
> 1))
1353 randnr
= (int) ( (*chance
+ 1.0) * rand() / (RAND_MAX
+1.0) );