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 #define min(x, y) (x < y ? x : y)
87 #define max(x, y) (x > y ? x : y)
89 movestruct
* alfabeta_move (board
* oboard
, int alfa
, int beta
, int minmax
,
90 int depth
, minimax_info
* me
);
91 movestruct
* move (board
* oboard
, int alfa
, int beta
, int minmax
, int depth
,
92 minimax_info
* me
, fromto
* todo
, saveboard
* lmove
);
93 movestruct
* alfabeta_gipf (board
* oboard
, int alfa
, int beta
, int minmax
,
94 int depth
, minimax_info
* me
);
95 movestruct
* remove_gipflist (board
* oboard
, int alfa
, int beta
, int minmax
,
96 int depth
, minimax_info
* me
, listheader
* myg
,
98 movestruct
* alfabeta_row (board
* oboard
, int alfa
, int beta
, int minmax
,
99 int depth
, minimax_info
* me
);
100 movestruct
* remove_row (board
* oboard
, int alfa
, int beta
, int minmax
,
101 int depth
, minimax_info
* me
, int rem
);
102 int evaluate (board
* oboard
, minimax_info
* me
);
103 void del_move (movestruct
* todel
);
106 int equ_l (int nr1
, int nr2
, int * chance
, minimax_info
* me
, int depth
);
107 int equ_h (int nr1
, int nr2
, int * chance
, minimax_info
* me
, int depth
);
110 void * minimax_new (char colour
, int game
)
113 listheader
* configlist
;
115 me
= (minimax_info
*) malloc (sizeof (minimax_info
));
120 /* check for config-values from the config-file */
121 configlist
= readconfigfile ("gf1.cfg");
123 me
->config
.searchdepth
= findconfigvalue (configlist
, "searchdepth",
125 me
->config
.remoppgipf
= findconfigvalue (configlist
, "remoppgipf",
127 me
->config
.maxgipf
= findconfigvalue (configlist
, "maxgipf",
130 me
->config
.randomchoose
= findconfigvalue (configlist
, "randomchoose",
134 clearconfiglist (configlist
);
136 return ((void *) me
);
140 void minimax_move (board
* oboard
, void * self
,
141 char * type
, char * from
, char * to
)
143 minimax_info
* me
= self
;
149 move
= alfabeta_move (oboard
, -1001, 1001, MAXNODE
, depth
, me
);
151 from
[0] = move
->from
[0];
152 from
[1] = move
->from
[1];
157 me
->movelist
= move
->movelist
;
160 printf ("ai_minimax %c (%d): move %2s-%2s\n",
161 me
->colour
, move
->value
, from
, to
);
164 move
->movelist
= NULL
;
171 char minimax_gipf (board
* oboard
, void * self
, char * pos
)
173 minimax_info
* me
= self
;
181 /* check if movelist contains info about removing gipf-pieces */
182 if (me
->movelist
== NULL
)
185 ** no info in movelist, my opponent made 4 in a row
186 ** with my pieces (only possible explanation)
191 /* remark: I have to start this as a min-node,
192 ** because this is really my opponents move */
193 nmove
= alfabeta_gipf (oboard
, -1001, 1001, MINNODE
, depth
, me
);
194 me
->movelist
= nmove
->movelist
;
195 nmove
->movelist
= NULL
;
199 /* now check the movelist for the move we have to make */
200 if (((movedata
= (nextmove
*) llitembynr (me
->movelist
, 1)) == NULL
) ||
201 (movedata
->remtype
!= REM_GIPF
))
205 printf ("action removegipf, but nextmove contains something else\n\n");
210 /* look for the gipf to remove */
212 while ((gipfd
= (gipfdata
*) llitembynr (movedata
->gipflist
, counter
))
215 if ((gipfd
->pos
[0] == pos
[0]) && (gipfd
->pos
[1] == pos
[1]))
225 printf ("action removegipf, but the gipf isn't in nextmove\n\n");
229 /* remove gipf from list */
230 gipfd
= (gipfdata
*) llrembynr (movedata
->gipflist
, counter
);
232 /* remove nextmove from movelist if gipflist is empty */
233 if (llitembynr (movedata
->gipflist
, 1) == NULL
)
235 movedata
= (nextmove
*) llrembynr (me
->movelist
, 1);
236 free (movedata
->gipflist
);
239 /* remove movelist if empty */
240 if (llitembynr (me
->movelist
, 1) == NULL
)
251 printf ("ai_minimax %c: remove gipf %2s (%c)\n", me
->colour
, pos
, val
);
257 char minimax_row (board
* oboard
, void * self
, char * start
, char * end
)
259 minimax_info
* me
= self
;
265 /* check if movelist contains info about removing rows */
266 if (me
->movelist
== NULL
)
269 ** no info in movelist, my opponent made several "4 in a row"s
270 ** with my pieces (only possible explanation)
275 /* remark: I have to start this as a min-node,
276 ** because this is really my opponents move */
277 nmove
= alfabeta_row (oboard
, -1001, 1001, MINNODE
, depth
, me
);
278 me
->movelist
= nmove
->movelist
;
279 nmove
->movelist
= NULL
;
283 /* now check the movelist for the move we have to make */
284 if (((movedata
= (nextmove
*) llitembynr (me
->movelist
, 1)) == NULL
) ||
285 (movedata
->remtype
!= REM_ROW
))
289 printf ("action removerow, but nextmove contains something else\n\n");
295 /* check if this is the correct row to be removed */
296 if ((start
[0] == movedata
->rowdata
.start
[0]) &&
297 (start
[1] == movedata
->rowdata
.start
[1]))
299 if ((end
[0] == movedata
->rowdata
.end
[0]) &&
300 (end
[1] == movedata
->rowdata
.end
[1]))
305 else if ((start
[0] == movedata
->rowdata
.end
[0]) &&
306 (start
[1] == movedata
->rowdata
.end
[1]))
308 if ((end
[0] == movedata
->rowdata
.start
[0]) &&
309 (end
[1] == movedata
->rowdata
.start
[1]))
317 /* remove nextmove from movelist */
318 movedata
= (nextmove
*) llrembynr (me
->movelist
, 1);
319 free (movedata
->rowdata
.start
);
320 free (movedata
->rowdata
.end
);
323 /* remove movelist if empty */
324 if (llitembynr (me
->movelist
, 1) == NULL
)
331 printf ("ai_minimax %c: remove row %2s-%2s\n", me
->colour
, start
, end
);
336 /* don't remove the row */
338 printf ("ai_minimax %c: don't remove row %2s-%2s\n",
339 me
->colour
, start
, end
);
346 void minimax_end (void * self
)
348 minimax_info
* me
= self
;
350 /* do I have to clean up the movelist first */
357 movestruct
* alfabeta_move (board
* oboard
, int alfa
, int beta
, int minmax
,
358 int depth
, minimax_info
* me
)
369 /* maximum search depth or end of game */
370 if ((b_game_finished (oboard
)) ||
371 (depth
> me
->config
.searchdepth
))
373 nmove
= (movestruct
*) malloc (sizeof (movestruct
));
374 nmove
->from
[0] = '\0';
377 nmove
->movelist
= NULL
;
378 nmove
->value
= evaluate (oboard
, me
);
383 if ((depth
== 1) || (depth
< me
->config
.searchdepth
))
385 checkwindowevents ();
389 /* list of moves to try depends on the question if we can
390 ** place a gipf or not.
391 ** cutoff after a predetermined number of gipf-pieces */
392 if ((b_colour_type (oboard
, b_next_piece (oboard
)) == 'g') &&
393 (b_colour_gipf (oboard
, b_next_piece (oboard
)) < me
->config
.maxgipf
))
395 allmoves
= allmovesg
;
400 allmoves
= allmovesn
;
404 lastmove
.sboard
= NULL
;
406 if (minmax
== MAXNODE
)
410 for (i
= 0; i
< maxmoves
; i
++)
412 nmove
= move (oboard
, alfa
, beta
, minmax
, depth
, me
,
413 &(allmoves
[i
]), &lastmove
);
419 if (equ_h (nmove
->value
, value
, &chance
, me
, depth
))
421 if (nmove
->value
> value
)
424 value
= nmove
->value
;
425 if (bestmove
!= NULL
)
435 alfa
= max (alfa
, value
);
444 ** problems if value is the same as beta, this means that
445 ** when randomly selecting a move from the moves with the
446 ** same value, this one could be chosen.
447 ** solution: change value to (-1001 or 1001)
448 ** or the current value (+1 or -1)
450 ** is this correct? or does it depend on the fact if
451 ** this was called from a min- or a max-node?
461 for (i
= 0; i
< maxmoves
; i
++)
463 nmove
= move (oboard
, alfa
, beta
, minmax
, depth
, me
,
464 &(allmoves
[i
]), &lastmove
);
470 if (equ_l (nmove
->value
, value
, &chance
, me
, depth
))
472 if (nmove
->value
< value
)
475 value
= nmove
->value
;
476 if (bestmove
!= NULL
)
486 /* how and when did I throw this out ?????? */
487 beta
= min (beta
, value
);
500 if (lastmove
.sboard
!= NULL
)
502 b_del (lastmove
.sboard
);
509 movestruct
* move (board
* oboard
, int alfa
, int beta
, int minmax
, int depth
,
510 minimax_info
* me
, fromto
* todo
, saveboard
* lmove
)
518 if (todo
->type
== 'g')
520 piece
= b_otherpiece (b_next_piece (oboard
));
524 piece
= b_next_piece (oboard
);
527 newboard
= b_move (oboard
, todo
->from
, todo
->to
, piece
);
529 if (newboard
== NULL
)
534 /* check if the result is the same as the last move */
535 if ((lmove
->sboard
!= NULL
) &&
536 ((lmove
->to
[0] == todo
->to
[0]) && (lmove
->to
[1] == todo
->to
[1])) &&
537 (b_compare (newboard
, lmove
->sboard
) == 0))
542 if (lmove
->sboard
!= NULL
)
544 b_del (lmove
->sboard
);
546 lmove
->sboard
= newboard
; /* don't delete the board at the end */
547 lmove
->to
[0] = todo
->to
[0];
548 lmove
->to
[1] = todo
->to
[1];
550 /* create new movestruct */
551 mymove
= (movestruct
*) malloc (sizeof (movestruct
));
552 mymove
->from
[0] = todo
->from
[0];
553 mymove
->from
[1] = todo
->from
[1];
554 mymove
->to
[0] = todo
->to
[0];
555 mymove
->to
[1] = todo
->to
[1];
556 mymove
->type
= todo
->type
;
557 mymove
->movelist
= NULL
;
559 newminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
560 if ((b_status (newboard
) == S_NORMAL
) ||
561 (b_status (newboard
) == S_FINISHED
))
563 nmove
= alfabeta_move (newboard
, alfa
, beta
, newminmax
, depth
+1, me
);
564 mymove
->value
= nmove
->value
;
567 else if (b_status (newboard
) == S_REMOVEROW
)
569 nmove
= alfabeta_row (newboard
, alfa
, beta
, minmax
, depth
, me
);
570 mymove
->movelist
= nmove
->movelist
;
571 mymove
->value
= nmove
->value
;
572 nmove
->movelist
= NULL
;
575 else if (b_status (newboard
) == S_REMOVEGIPF
)
577 nmove
= alfabeta_gipf (newboard
, alfa
, beta
, minmax
, depth
, me
);
578 mymove
->movelist
= nmove
->movelist
;
579 mymove
->value
= nmove
->value
;
580 nmove
->movelist
= NULL
;
586 printf ("ERROR: impossible in ai_minimax::move\n\n");
591 /* don't cleanup newboard here */
596 movestruct
* alfabeta_gipf (board
* oboard
, int alfa
, int beta
, int minmax
,
597 int depth
, minimax_info
* me
)
615 gipfi
= (rem_gipf
*) llitembynr (b_gipf_extra (oboard
), 1);
618 ** I may have to change if I am a min or a max-node here
619 ** it's possible that my opponent won a row, so he has to
620 ** decide if gipf-pieces must be removed
622 if (b_gipf_owner(gipfi
) == b_next_piece (oboard
))
624 realminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
631 /* always remove gipf-pieces from my opponent if the flag is set */
632 myg
= (listheader
*) malloc (sizeof (listheader
));
634 otherg
= (listheader
*) malloc (sizeof (listheader
));
638 while ((gipfi
= (rem_gipf
*) llitembynr (b_gipf_extra (oboard
), counter
))
642 gipfflag
= (gipfitem
*) malloc (sizeof (gipfitem
));
643 gipfflag
->gipf
= gipfi
;
646 gipfpos
= b_gipf_position (gipfi
);
647 if ((me
->config
.remoppgipf
== 1) &&
648 (b_otherpiece (b_gipf_owner (gipfi
)) !=
649 b_piece (oboard
, gipfpos
)))
651 pushll (otherg
, (void *) gipfflag
);
656 pushll (myg
, (void *) gipfflag
);
661 maxnr
= 1 << mynr
; /* 2 ^ mynr */
663 if (realminmax
== MAXNODE
)
667 for (bits1
= 0; bits1
< maxnr
; bits1
++)
670 for (i
= 0; i
< mynr
; i
++)
672 gipfflag
= (gipfitem
*) llitembynr (myg
, i
+1);
673 gipfflag
->flag
= bits2
& 1;
676 nmove
= remove_gipflist (oboard
, alfa
, beta
, minmax
, depth
, me
,
679 if (nmove
->value
> value
)
681 value
= nmove
->value
;
682 if (bestmove
!= NULL
)
692 alfa
= max (alfa
, value
);
708 for (bits1
= 0; bits1
< maxnr
; bits1
++)
711 for (i
= 0; i
< mynr
; i
++)
713 gipfflag
= (gipfitem
*) llitembynr (myg
, i
+1);
714 gipfflag
->flag
= bits2
& 1;
717 nmove
= remove_gipflist (oboard
, alfa
, beta
, minmax
, depth
, me
,
720 if (nmove
->value
< value
)
722 value
= nmove
->value
;
723 if (bestmove
!= NULL
)
733 beta
= min (beta
, value
);
746 /* cleanup temporary lists */
747 while ((gipfflag
= (gipfitem
*) llrembynr (myg
, 1)) != NULL
)
752 while ((gipfflag
= (gipfitem
*) llrembynr (otherg
, 1)) != NULL
)
762 movestruct
* remove_gipflist (board
* oboard
, int alfa
, int beta
, int minmax
,
763 int depth
, minimax_info
* me
, listheader
* myg
,
772 listheader
* remlist
;
780 remlist
= (listheader
*) malloc (sizeof (listheader
));;
782 /* list of gipf-pieces that may or may not have to be removed */
784 while ((gipfflag
= (gipfitem
*) llitembynr (myg
, counter
)) != NULL
)
787 gipfd
= (gipfdata
*) malloc (sizeof (gipfdata
));
788 strpos
= b_gipf_position (gipfflag
->gipf
);
789 owner
= b_gipf_owner (gipfflag
->gipf
);
790 gipfd
->pos
[0] = strpos
[0];
791 gipfd
->pos
[1] = strpos
[1];
792 gipfd
->pos
[2] = '\0';
795 if (gipfflag
->flag
== 1)
798 nboard
= b_remove_gipf (newboard
, gipfflag
->gipf
);
799 if (newboard
!= oboard
)
809 pushll (remlist
, (void *) gipfd
);
812 /* list of gipf-pieces that always have to be removed */
814 while ((gipfflag
= (gipfitem
*) llitembynr (otherg
, counter
)) != NULL
)
817 gipfd
= (gipfdata
*) malloc (sizeof (gipfdata
));
818 strpos
= b_gipf_position (gipfflag
->gipf
);
819 owner
= b_gipf_owner (gipfflag
->gipf
);
820 gipfd
->pos
[0] = strpos
[0];
821 gipfd
->pos
[1] = strpos
[1];
822 gipfd
->pos
[2] = '\0';
826 nboard
= b_remove_gipf (newboard
, gipfflag
->gipf
);
827 if (newboard
!= oboard
)
832 pushll (remlist
, (void *) gipfd
);
835 /* check again for 4 in a row */
836 nboard
= b_checkfour (newboard
);
837 if (newboard
!= oboard
)
843 mymove
= (movestruct
*) malloc (sizeof (movestruct
));
844 mymove
->from
[0] = '\0';
845 mymove
->to
[0] = '\0';
847 mymove
->movelist
= (listheader
*) malloc (sizeof (listheader
));
848 newlist (mymove
->movelist
);
851 ** only add actions to the movelist if they have to be executed
853 ** this means moves for the min-player will not be executable,
854 ** but that really isn't necessary
856 if (me
->colour
== owner
)
858 movedata
= (nextmove
*) malloc (sizeof (nextmove
));
859 movedata
->remtype
= REM_GIPF
;
860 movedata
->gipflist
= remlist
;
861 pushll (mymove
->movelist
, (void *) movedata
);
864 { /* remove remlist, we don't need it here */
865 while ((gipfd
= (gipfdata
*) llrembynr (remlist
, 1)) != NULL
)
872 newminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
874 if ((b_status (newboard
) == S_NORMAL
) ||
875 (b_status (newboard
) == S_FINISHED
))
877 nmove
= alfabeta_move (newboard
, alfa
, beta
, newminmax
, depth
+1, me
);
878 mymove
->value
= nmove
->value
;
881 else if (b_status (newboard
) == S_REMOVEROW
)
883 nmove
= alfabeta_row (newboard
, alfa
, beta
, minmax
, depth
, me
);
885 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
888 pushll (mymove
->movelist
, (void *) movedata
);
891 mymove
->value
= nmove
->value
;
894 else if (b_status (newboard
) == S_REMOVEGIPF
)
896 nmove
= alfabeta_gipf (newboard
, alfa
, beta
, minmax
, depth
, me
);
898 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
901 pushll (mymove
->movelist
, (void *) movedata
);
904 mymove
->value
= nmove
->value
;
910 printf ("ERROR: impossible in ai_minimax::remove_gipf\n\n");
917 /* check if the movelist of mymove contains something */
918 if (llitembynr (mymove
->movelist
, 1) == NULL
)
920 free (mymove
->movelist
);
921 mymove
->movelist
= NULL
;
928 movestruct
* alfabeta_row (board
* oboard
, int alfa
, int beta
, int minmax
,
929 int depth
, minimax_info
* me
)
937 listheader
* rowlist
;
939 rowlist
= b_row_extra (oboard
);
940 rowi
= (rem_row
*) llitembynr (rowlist
, 1);
943 ** I may have to change if I am a min or a max-node here
944 ** it's possible that my opponent won several rows, so he has to
945 ** decide what row to remove
947 if (row_owner(rowi
) == b_next_piece (oboard
))
949 realminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
956 if (realminmax
== MAXNODE
)
961 while ((rowi
= (rem_row
*) llitembynr (rowlist
, counter
))
964 nmove
= remove_row (oboard
, alfa
, beta
, minmax
, depth
, me
,
968 if (nmove
->value
> value
)
970 value
= nmove
->value
;
971 if (bestmove
!= NULL
)
981 alfa
= max (alfa
, value
);
998 while ((rowi
= (rem_row
*) llitembynr (rowlist
, counter
))
1001 nmove
= remove_row (oboard
, alfa
, beta
, minmax
, depth
, me
,
1005 if (nmove
->value
< value
)
1007 value
= nmove
->value
;
1008 if (bestmove
!= NULL
)
1010 del_move (bestmove
);
1018 beta
= min (beta
, value
);
1035 movestruct
* remove_row (board
* oboard
, int alfa
, int beta
, int minmax
,
1036 int depth
, minimax_info
* me
, int rem
)
1042 nextmove
* movedata
;
1045 newboard
= b_remove_row (oboard
, rem
);
1047 mymove
= (movestruct
*) malloc (sizeof (movestruct
));
1048 mymove
->from
[0] = '\0';
1049 mymove
->to
[0] = '\0';
1051 mymove
->movelist
= (listheader
*) malloc (sizeof (listheader
));
1052 newlist (mymove
->movelist
);
1055 ** only add actions to the movelist if they have to be executed
1056 ** by the max-player
1057 ** this means moves for the min-player will not be executable,
1058 ** but that really isn't necessary
1060 remi
= (rem_row
*) llitembynr (b_row_extra (oboard
), rem
);
1061 if (me
->colour
== row_owner (remi
))
1063 movedata
= (nextmove
*) malloc (sizeof (nextmove
));
1064 movedata
->remtype
= REM_ROW
;
1065 movedata
->gipflist
= NULL
;
1066 movedata
->rowdata
.start
= postostr (remi
->startpos
);
1067 movedata
->rowdata
.end
= postostr (remi
->endpos
);
1068 pushll (mymove
->movelist
, (void *) movedata
);
1071 newminmax
= (minmax
== MINNODE
? MAXNODE
: MINNODE
);
1073 if ((b_status (newboard
) == S_NORMAL
) ||
1074 (b_status (newboard
) == S_FINISHED
))
1076 nmove
= alfabeta_move (newboard
, alfa
, beta
, newminmax
, depth
+1, me
);
1077 mymove
->value
= nmove
->value
;
1080 else if (b_status (newboard
) == S_REMOVEROW
)
1082 nmove
= alfabeta_row (newboard
, alfa
, beta
, minmax
, depth
, me
);
1084 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
1087 pushll (mymove
->movelist
, (void *) movedata
);
1090 mymove
->value
= nmove
->value
;
1093 else if (b_status (newboard
) == S_REMOVEGIPF
)
1095 nmove
= alfabeta_gipf (newboard
, alfa
, beta
, minmax
, depth
, me
);
1097 while ((movedata
= (nextmove
*) llrembynr (nmove
->movelist
, 1))
1100 pushll (mymove
->movelist
, (void *) movedata
);
1103 mymove
->value
= nmove
->value
;
1109 printf ("ERROR: impossible in ai_minimax::remove_row\n\n");
1116 /* check if the movelist of mymove contains something */
1117 if (llitembynr (mymove
->movelist
, 1) == NULL
)
1119 free (mymove
->movelist
);
1120 mymove
->movelist
= NULL
;
1131 {{3, 4}, 2},{{3, 5}, 2},{{4, 6}, 2},{{5, 5}, 2},{{5, 4}, 2},{{4, 4}, 2},
1132 {{2, 3}, 1},{{2, 4}, 1},{{2, 5}, 1},{{3, 6}, 1},{{4, 7}, 1},{{5, 6}, 1},
1133 {{6, 5}, 1},{{6, 4}, 1},{{6, 3}, 1},{{5, 3}, 1},{{4, 3}, 1},{{3, 3}, 1}
1137 ** calculate the value of a certain board position
1139 ** returns a value between 1000 and -1000 (inclusive)
1141 ** -1000 : my opponent wins
1143 int evaluate (board
* oboard
, minimax_info
* me
)
1156 otherc
= b_opponent (myc
);
1158 if (b_game_finished (oboard
))
1160 if (b_winner (oboard
) == myc
)
1170 /* maybe I can return 1000 or -1000, but I'm not completely sure */
1171 if (b_colour (oboard
, myc
) == 0)
1175 else if (b_colour (oboard
, otherc
) == 0)
1180 /* I need to start with a base-value, or I get a lot of
1181 ** problems at the start of tournament games */
1185 /* capturing a piece from your opponent is worth 20 points */
1186 wvalue
+= 20 * b_black_lost (oboard
);
1187 bvalue
+= 20 * b_white_lost (oboard
);
1189 /* 1 point for each piece in use on the board */
1190 if (b_white_gipf (oboard
) == -1)
1195 wvalue
+= total
- b_white (oboard
) - b_white_lost (oboard
);
1196 bvalue
+= total
- b_black (oboard
) - b_black_lost (oboard
);
1198 /* 2 pieces or less left is getting dangerous */
1200 /* one gipf left can be dangerous, subtract 5 points */
1201 if (b_white_gipf (oboard
) == 1)
1205 if (b_black_gipf (oboard
) == 1)
1210 /* pieces closer to the center have a higher value */
1211 for (i
= 0; i
< 19; i
++)
1213 pos
= &(pos_val
[i
].coor
);
1214 piece
= b_ppiece (oboard
, pos
);
1221 wvalue
+= pos_val
[i
].value
;
1223 else if (piece
== 'O')
1225 wvalue
+= pos_val
[i
].value
* 1.5;
1227 else if (piece
== 'x')
1229 bvalue
+= pos_val
[i
].value
;
1233 bvalue
+= pos_val
[i
].value
* 1.5;
1237 /* normalize the result, should be between 1000 and -1000 */
1240 value
= (int) ((wvalue
- bvalue
) * 1000 / (wvalue
+ bvalue
));
1244 value
= (int) ((bvalue
- wvalue
) * 1000 / (wvalue
+ bvalue
));
1251 void del_move (movestruct
* todel
)
1253 nextmove
* movedata
;
1256 if (todel
->movelist
!= NULL
)
1258 while ((movedata
= (nextmove
*) llrembynr (todel
->movelist
, 1))
1261 if (movedata
->remtype
== REM_ROW
)
1263 free (movedata
->rowdata
.start
);
1264 free (movedata
->rowdata
.end
);
1268 while ((gipfd
= (gipfdata
*)
1269 llrembynr (movedata
->gipflist
, 1)) != NULL
)
1273 free (movedata
->gipflist
);
1278 free (todel
->movelist
);
1287 ** just like a normal compare (<)
1291 ** 0/1: when nr1 and nr2 are equal, chooses one at random
1293 ** chance is the chance that nr1 will be chosen if nr1 == nr2
1294 ** this parameter will be incremented each time an equal occurs
1295 ** and will be set to 1 if nr1 < nr2
1296 ** (it should be initialised to 1 by the caller and then left alone)
1298 int equ_l (int nr1
, int nr2
, int * chance
, minimax_info
* me
, int depth
)
1302 if ((me
->config
.randomchoose
== 0) || (depth
> 1))
1315 randnr
= (int) ( (*chance
+ 1.0) * rand() / (RAND_MAX
+1.0) );
1328 ** just like a normal compare (>)
1332 ** 0/1: when nr1 and nr2 are equal, chooses one at random
1334 ** chance is the chance that nr1 will be chosen if nr1 == nr2
1335 ** this parameter will be incremented each time an equal occurs
1336 ** and will be set to 1 if nr1 > nr2
1337 ** (it should be initialised to 1 by the caller and then left alone)
1339 int equ_h (int nr1
, int nr2
, int * chance
, minimax_info
* me
, int depth
)
1343 if ((me
->config
.randomchoose
== 0) || (depth
> 1))
1356 randnr
= (int) ( (*chance
+ 1.0) * rand() / (RAND_MAX
+1.0) );