5 ** logging will only occur if the log-flag for a board is different from NULL
8 ** Copyright (C) 1998 Kurt Van den Branden
10 ** This program is free software; you can redistribute it and/or modify
11 ** it under the terms of the GNU General Public License as published by
12 ** the Free Software Foundation; either version 2 of the License, or
13 ** (at your option) any later version.
15 ** This program is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 ** GNU General Public License for more details.
20 ** You should have received a copy of the GNU General Public License
21 ** along with this program; if not, write to the Free Software
22 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 extern void waitremrow (board
* oldb
, rem_row
* row
, board
* newb
);
31 extern void waitremgipf (board
* oldb
, position
* gipf
, board
* newb
);
33 extern void animatemove (board
* oldb
, listheader
* pieces
, board
* newb
);
42 int _colsize
[] = {0, 5, 6, 7, 8, 7, 6, 5, 0};
44 char _colchar
[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'};
46 /* 42 different possible moves, without gipf-pieces */
47 fromto allmovesn
[] = {
48 {"b1","b2",'n'}, {"a1","b2",'n'}, {"a2","b2",'n'},
49 {"a2","b3",'n'}, {"a3","b3",'n'},
50 {"a3","b4",'n'}, {"a4","b4",'n'},
51 {"a4","b5",'n'}, {"a5","b5",'n'}, {"b6","b5",'n'},
52 {"b6","c6",'n'}, {"c7","c6",'n'},
53 {"c7","d7",'n'}, {"d8","d7",'n'},
54 {"d8","e8",'n'}, {"e9","e8",'n'}, {"f8","e8",'n'},
55 {"f8","f7",'n'}, {"g7","f7",'n'},
56 {"g7","g6",'n'}, {"h6","g6",'n'},
57 {"h6","h5",'n'}, {"i5","h5",'n'}, {"i4","h5",'n'},
58 {"i4","h4",'n'}, {"i3","h4",'n'},
59 {"i3","h3",'n'}, {"i2","h3",'n'},
60 {"i2","h2",'n'}, {"i1","h2",'n'}, {"h1","h2",'n'},
61 {"h1","g2",'n'}, {"g1","g2",'n'},
62 {"g1","f2",'n'}, {"f1","f2",'n'},
63 {"f1","e2",'n'}, {"e1","e2",'n'}, {"d1","e2",'n'},
64 {"d1","d2",'n'}, {"c1","d2",'n'},
65 {"c1","c2",'n'}, {"b1","c2",'n'}
68 /* 84 different possible moves, with gipf-pieces */
69 fromto allmovesg
[] = {
70 {"b1","b2",'g'}, {"a1","b2",'g'}, {"a2","b2",'g'},
71 {"a2","b3",'g'}, {"a3","b3",'g'},
72 {"a3","b4",'g'}, {"a4","b4",'g'},
73 {"a4","b5",'g'}, {"a5","b5",'g'}, {"b6","b5",'g'},
74 {"b6","c6",'g'}, {"c7","c6",'g'},
75 {"c7","d7",'g'}, {"d8","d7",'g'},
76 {"d8","e8",'g'}, {"e9","e8",'g'}, {"f8","e8",'g'},
77 {"f8","f7",'g'}, {"g7","f7",'g'},
78 {"g7","g6",'g'}, {"h6","g6",'g'},
79 {"h6","h5",'g'}, {"i5","h5",'g'}, {"i4","h5",'g'},
80 {"i4","h4",'g'}, {"i3","h4",'g'},
81 {"i3","h3",'g'}, {"i2","h3",'g'},
82 {"i2","h2",'g'}, {"i1","h2",'g'}, {"h1","h2",'g'},
83 {"h1","g2",'g'}, {"g1","g2",'g'},
84 {"g1","f2",'g'}, {"f1","f2",'g'},
85 {"f1","e2",'g'}, {"e1","e2",'g'}, {"d1","e2",'g'},
86 {"d1","d2",'g'}, {"c1","d2",'g'},
87 {"c1","c2",'g'}, {"b1","c2",'g'},
88 {"b1","b2",'n'}, {"a1","b2",'n'}, {"a2","b2",'n'},
89 {"a2","b3",'n'}, {"a3","b3",'n'},
90 {"a3","b4",'n'}, {"a4","b4",'n'},
91 {"a4","b5",'n'}, {"a5","b5",'n'}, {"b6","b5",'n'},
92 {"b6","c6",'n'}, {"c7","c6",'n'},
93 {"c7","d7",'n'}, {"d8","d7",'n'},
94 {"d8","e8",'n'}, {"e9","e8",'n'}, {"f8","e8",'n'},
95 {"f8","f7",'n'}, {"g7","f7",'n'},
96 {"g7","g6",'n'}, {"h6","g6",'n'},
97 {"h6","h5",'n'}, {"i5","h5",'n'}, {"i4","h5",'n'},
98 {"i4","h4",'n'}, {"i3","h4",'n'},
99 {"i3","h3",'n'}, {"i2","h3",'n'},
100 {"i2","h2",'n'}, {"i1","h2",'n'}, {"h1","h2",'n'},
101 {"h1","g2",'n'}, {"g1","g2",'n'},
102 {"g1","f2",'n'}, {"f1","f2",'n'},
103 {"f1","e2",'n'}, {"e1","e2",'n'}, {"d1","e2",'n'},
104 {"d1","d2",'n'}, {"c1","d2",'n'},
105 {"c1","c2",'n'}, {"b1","c2",'n'}
110 ** list of all the neighbours of a board-position
118 unsigned char b_buren
[9][9][6][2] = {
123 {{0, 0}, {0, 0}, {0, 0}, {1, 3}, {2, 2}, {2, 3}}, /* b2 */
124 {{0, 0}, {0, 0}, {1, 2}, {1, 4}, {2, 3}, {2, 4}}, /* b3 */
125 {{0, 0}, {0, 0}, {1, 3}, {1, 5}, {2, 4}, {2, 5}}, /* b4 */
126 {{0, 0}, {0, 0}, {1, 4}, {0, 0}, {2, 5}, {2, 6}} /* b5 */
131 {{0, 0}, {1, 2}, {0, 0}, {2, 3}, {3, 2}, {3, 3}}, /* c2 */
132 {{1, 2}, {1, 3}, {2, 2}, {2, 4}, {3, 3}, {3, 4}}, /* c3 */
133 {{1, 3}, {1, 4}, {2, 3}, {2, 5}, {3, 4}, {3, 5}}, /* c4 */
134 {{1, 4}, {1, 5}, {2, 4}, {2, 6}, {3, 5}, {3, 6}}, /* c5 */
135 {{1, 5}, {0, 0}, {2, 5}, {0, 0}, {3, 6}, {3, 7}} /* c6 */
140 {{0, 0}, {2, 2}, {0, 0}, {3, 3}, {4, 2}, {4, 3}}, /* d2 */
141 {{2, 2}, {2, 3}, {3, 2}, {3, 4}, {4, 3}, {4, 4}}, /* d3 */
142 {{2, 3}, {2, 4}, {3, 3}, {3, 5}, {4, 4}, {4, 5}}, /* d4 */
143 {{2, 4}, {2, 5}, {3, 4}, {3, 6}, {4, 5}, {4, 6}}, /* d5 */
144 {{2, 5}, {2, 6}, {3, 5}, {3, 7}, {4, 6}, {4, 7}}, /* d6 */
145 {{2, 6}, {0, 0}, {3, 6}, {0, 0}, {4, 7}, {4, 8}} /* d7 */
150 {{0, 0}, {3, 2}, {0, 0}, {4, 3}, {0, 0}, {5, 2}}, /* e2 */
151 {{3, 2}, {3, 3}, {4, 2}, {4, 4}, {5, 2}, {5, 3}}, /* e3 */
152 {{3, 3}, {3, 4}, {4, 3}, {4, 5}, {5, 3}, {5, 4}}, /* e4 */
153 {{3, 4}, {3, 5}, {4, 4}, {4, 6}, {5, 4}, {5, 5}}, /* e5 */
154 {{3, 5}, {3, 6}, {4, 5}, {4, 7}, {5, 5}, {5, 6}}, /* e6 */
155 {{3, 6}, {3, 7}, {4, 6}, {4, 8}, {5, 6}, {5, 7}}, /* e7 */
156 {{3, 7}, {0, 0}, {4, 7}, {0, 0}, {5, 7}, {0, 0}} /* e8 */
161 {{4, 2}, {4, 3}, {0, 0}, {5, 3}, {0, 0}, {6, 2}}, /* f2 */
162 {{4, 3}, {4, 4}, {5, 2}, {5, 4}, {6, 2}, {6, 3}}, /* f3 */
163 {{4, 4}, {4, 5}, {5, 3}, {5, 5}, {6, 3}, {6, 4}}, /* f4 */
164 {{4, 5}, {4, 6}, {5, 4}, {5, 6}, {6, 4}, {6, 5}}, /* f5 */
165 {{4, 6}, {4, 7}, {5, 5}, {5, 7}, {6, 5}, {6, 6}}, /* f6 */
166 {{4, 7}, {4, 8}, {5, 6}, {0, 0}, {6, 6}, {0, 0}} /* f7 */
171 {{5, 2}, {5, 3}, {0, 0}, {6, 3}, {0, 0}, {7, 2}}, /* g2 */
172 {{5, 3}, {5, 4}, {6, 2}, {6, 4}, {7, 2}, {7, 3}}, /* g3 */
173 {{5, 4}, {5, 5}, {6, 3}, {6, 5}, {7, 3}, {7, 4}}, /* g4 */
174 {{5, 5}, {5, 6}, {6, 4}, {6, 6}, {7, 4}, {7, 5}}, /* g5 */
175 {{5, 6}, {5, 7}, {6, 5}, {0, 0}, {7, 5}, {0, 0}} /* g6 */
180 {{6, 2}, {6, 3}, {0, 0}, {7, 3}, {0, 0}, {0, 0}}, /* h2 */
181 {{6, 3}, {6, 4}, {7, 2}, {7, 4}, {0, 0}, {0, 0}}, /* h3 */
182 {{6, 4}, {6, 5}, {7, 3}, {7, 5}, {0, 0}, {0, 0}}, /* h4 */
183 {{6, 5}, {6, 6}, {7, 4}, {0, 0}, {0, 0}, {0, 0}} /* h5 */
190 ** each item of the list contains:
191 ** - middle point for the row
192 ** - first direction for this row (second direction = 5 - first direction)
193 ** - second direction
194 ** - minimum nr of pieces necessary in the first direction
222 board
* b_new (int board_type
)
227 board_ref
= b_newboard();
228 for (i
= 0; i
< 8; i
++)
229 for (j
= 0; j
< 9; j
++)
230 board_ref
->pieces
[i
][j
] = '.';
232 board_ref
->status
= S_NORMAL
;
233 board_ref
->nextpiece
= 'o';
234 board_ref
->gipfextra
= NULL
;
235 board_ref
->rowextraw
= NULL
;
236 board_ref
->rowextrab
= NULL
;
237 board_ref
->white
= 18;
238 board_ref
->lostwhite
= 0;
239 board_ref
->gipfwhite
= 0;
240 board_ref
->typewhite
= 'n';
241 board_ref
->black
= 18;
242 board_ref
->lostblack
= 0;
243 board_ref
->gipfblack
= 0;
244 board_ref
->typeblack
= 'n';
245 board_ref
->winner
= '.';
246 board_ref
->checkfour
= 'n';
247 board_ref
->log
= NULL
;
248 board_ref
->movecounter
= 0;
250 board_ref
->removewait
= 0;
251 board_ref
->animate
= 0;
254 if (board_type
== T_BASIC
)
256 board_ref
->white
= 12;
257 board_ref
->black
= 12;
258 board_ref
->pieces
[1][5] = 'o';
259 board_ref
->pieces
[7][5] = 'o';
260 board_ref
->pieces
[4][2] = 'o';
261 board_ref
->pieces
[1][2] = 'x';
262 board_ref
->pieces
[4][8] = 'x';
263 board_ref
->pieces
[7][2] = 'x';
264 board_ref
->gipfwhite
= -1;
265 board_ref
->gipfblack
= -1;
267 else if (board_type
== T_STANDARD
)
269 board_ref
->white
= 12;
270 board_ref
->black
= 12;
271 board_ref
->pieces
[1][5] = 'O';
272 board_ref
->pieces
[7][5] = 'O';
273 board_ref
->pieces
[4][2] = 'O';
274 board_ref
->pieces
[1][2] = 'X';
275 board_ref
->pieces
[4][8] = 'X';
276 board_ref
->pieces
[7][2] = 'X';
277 board_ref
->gipfwhite
= 3;
278 board_ref
->gipfblack
= 3;
282 board_ref
->typewhite
= 'g';
283 board_ref
->typeblack
= 'g';
289 board
* b_copy (board
* orig_board
)
294 if (orig_board
== NULL
)
297 new_board
= b_newboard();
301 for (i
= 1; i
< 8; i
++)
302 for (j
= 2; j
<= b_colsize (i
); j
++)
303 new_board
->pieces
[i
][j
] = orig_board
->pieces
[i
][j
];
305 new_board
->status
= orig_board
->status
;
306 new_board
->nextpiece
= orig_board
->nextpiece
;
307 new_board
->winner
= orig_board
->winner
;
308 new_board
->checkfour
= orig_board
->checkfour
;
309 new_board
->log
= orig_board
->log
;
310 new_board
->movecounter
= orig_board
->movecounter
;
312 new_board
->white
= orig_board
->white
;
313 new_board
->typewhite
= orig_board
->typewhite
;
314 new_board
->lostwhite
= orig_board
->lostwhite
;
315 new_board
->gipfwhite
= orig_board
->gipfwhite
;
316 new_board
->black
= orig_board
->black
;
317 new_board
->typeblack
= orig_board
->typeblack
;
318 new_board
->lostblack
= orig_board
->lostblack
;
319 new_board
->gipfblack
= orig_board
->gipfblack
;
321 memcpy (new_board
, orig_board
, sizeof (board
));
324 if (orig_board
->gipfextra
!= NULL
)
326 new_board
->gipfextra
= copy_rem_gipf_row (orig_board
->gipfextra
);
328 if (orig_board
->rowextraw
!= NULL
)
330 new_board
->rowextraw
= copy_rem_row_row (orig_board
->rowextraw
);
332 if (orig_board
->rowextrab
!= NULL
)
334 new_board
->rowextrab
= copy_rem_row_row (orig_board
->rowextrab
);
340 void b_print (board
* boardp
)
345 printf ("\nERROR: the boardp-pointer is NULL (b_print)\n\n");
349 printf ("A B C D E F G H I\n");
350 printf ("5 6 7 8 9 8 7 6 5\n\n");
353 printf (" * %c *\n", boardp
->pieces
[4][8]);
354 printf (" * %c %c *\n",
355 boardp
->pieces
[3][7], boardp
->pieces
[5][7]);
356 printf ("* %c %c %c *\n",
357 boardp
->pieces
[2][6], boardp
->pieces
[4][7], boardp
->pieces
[6][6]);
358 printf (" %c %c %c %c\n",
359 boardp
->pieces
[1][5], boardp
->pieces
[3][6],
360 boardp
->pieces
[5][6], boardp
->pieces
[7][5]);
361 printf ("* %c %c %c *\n",
362 boardp
->pieces
[2][5], boardp
->pieces
[4][6], boardp
->pieces
[6][5]);
363 printf (" %c %c %c %c\n",
364 boardp
->pieces
[1][4], boardp
->pieces
[3][5],
365 boardp
->pieces
[5][5], boardp
->pieces
[7][4]);
366 printf ("* %c %c %c *\n",
367 boardp
->pieces
[2][4], boardp
->pieces
[4][5], boardp
->pieces
[6][4]);
368 printf (" %c %c %c %c\n",
369 boardp
->pieces
[1][3], boardp
->pieces
[3][4],
370 boardp
->pieces
[5][4], boardp
->pieces
[7][3]);
371 printf ("* %c %c %c *\n",
372 boardp
->pieces
[2][3], boardp
->pieces
[4][4], boardp
->pieces
[6][3]);
373 printf (" %c %c %c %c\n",
374 boardp
->pieces
[1][2], boardp
->pieces
[3][3],
375 boardp
->pieces
[5][3], boardp
->pieces
[7][2]);
376 printf ("* %c %c %c *\n",
377 boardp
->pieces
[2][2], boardp
->pieces
[4][3], boardp
->pieces
[6][2]);
378 printf (" * %c %c *\n",
379 boardp
->pieces
[3][2], boardp
->pieces
[5][2]);
380 printf (" * %c *\n", boardp
->pieces
[4][2]);
382 printf (" * white: %d\n",
384 printf (" lostwhite: %d\n",
386 printf ("1 1 1 1 1 1 1 1 1 black: %d\n",
388 printf ("A B C D E F G H I lostblack: %d\n",
395 void b_del (board
* dboard
)
399 if (dboard
->gipfextra
!= NULL
)
401 emptyll (dboard
->gipfextra
, del_rem_gipf
);
402 free (dboard
->gipfextra
);
404 if (dboard
->rowextraw
!= NULL
)
406 emptyll (dboard
->rowextraw
, del_rem_row
);
407 free (dboard
->rowextraw
);
409 if (dboard
->rowextrab
!= NULL
)
411 emptyll (dboard
->rowextrab
, del_rem_row
);
412 free (dboard
->rowextrab
);
422 ** b_move : move a piece on a gipf-board
425 ** oboard : pointer to original board
426 ** from : string with from-position
427 ** to : string with to-position
428 ** npiece: piece to add to the board (o, O, x, X)
431 ** pointer to a new board
434 board
* b_move (board
* oboard
, char * from
, char * to
, char npiece
)
452 /* check if oboard is in the correct state */
453 if (oboard
->status
== S_REMOVEROW
)
457 if ((npiece
!= oboard
->nextpiece
) &&
458 (b_otherpiece (npiece
) != oboard
->nextpiece
))
463 /* check if the player has pieces left */
464 if ((npiece
== 'o') || (npiece
== 'O'))
466 if (oboard
->white
<= 0)
471 else if (oboard
->black
<= 0)
476 /* if the player wants to place a gipf, check if this is allowed */
477 if ((npiece
== 'O') && (oboard
->typewhite
!= 'g'))
481 else if ((npiece
== 'X') && (oboard
->typeblack
!= 'g'))
487 from_p
= strtopos (from
);
488 to_p
= strtopos (to
);
489 if ((from_p
== NULL
) || (to_p
== NULL
))
490 { /* invalid from or to position */
491 del_position (from_p
);
495 next_p
= (position
*) copy_position ((void *) to_p
);
496 row_dif
= to_p
->row
- from_p
->row
;
497 col_dif
= to_p
->col
- from_p
->col
;
499 /* valid to-position ? */
500 if (((to_p
->col
< 1) || (to_p
->col
> 7)) ||
501 ((to_p
->col
!= 1) && (to_p
->col
!= 7) &&
502 (to_p
->row
!= 2) && (to_p
->row
!= b_colsize (to_p
->col
))) ||
503 (((to_p
->col
== 1) | (to_p
->col
== 7)) &&
504 ((to_p
->row
<2) || (to_p
->row
>5))))
507 printf ("invalid move (to): (%s, %s)\n", from
, to
);
509 del_position (from_p
);
511 del_position (next_p
);
515 /* valid from-position ? */
516 if ((abs (row_dif
) > 1) ||
517 (abs (col_dif
) > 1) ||
518 (((from_p
->col
== 0) || (from_p
->col
== 8)) && (row_dif
< 0)) ||
519 (( from_p
->row
== 1) && (((from_p
->col
< 5) && (col_dif
< 0)) ||
520 ((from_p
->col
> 3) && (col_dif
> 0)))) ||
521 ((from_p
->col
> 0) && (from_p
->col
< 8) &&
522 (from_p
->row
!= 1) && (from_p
->row
!= b_colsize (from_p
->col
) + 1)))
525 printf ("invalid move (from): (%s, %s)\n", from
, to
);
527 del_position (from_p
);
529 del_position (next_p
);
533 nboard
= b_copy (oboard
);
534 if (nboard
->gipfextra
!= NULL
)
536 emptyll (nboard
->gipfextra
, del_rem_gipf
);
537 free (nboard
->gipfextra
);
538 nboard
->gipfextra
= NULL
;
541 nboard
->status
= S_NORMAL
;
542 if (oboard
->nextpiece
== 'o')
544 nboard
->movecounter
++;
548 pmoves
= (listheader
*) malloc (sizeof (listheader
));
551 piecem
= (piecemove
*) malloc (sizeof (piecemove
));
552 piecem
->piece
= npiece
;
553 piecem
->from
.col
= from_p
->col
;
554 piecem
->from
.row
= from_p
->row
;
555 piecem
->to
.col
= to_p
->col
;
556 piecem
->to
.row
= to_p
->row
;
557 pushll (pmoves
, (void *) piecem
);
560 save_piece
= nboard
->pieces
[to_p
->col
][to_p
->row
];
561 nboard
->pieces
[to_p
->col
][to_p
->row
] = npiece
;
562 while (save_piece
!= '.')
565 piecem
= (piecemove
*) malloc (sizeof (piecemove
));
566 piecem
->piece
= save_piece
;
567 piecem
->from
.col
= next_p
->col
;
568 piecem
->from
.row
= next_p
->row
;
571 { /* going diagonally */
572 if (next_p
->col
== 4)
573 { /* going over the middle line */
576 next_p
->col
+= col_dif
;
578 next_p
->row
+= row_dif
;
579 if ((next_p
->col
== 0) ||
580 (next_p
->col
== 8) ||
582 (next_p
->row
> b_colsize (next_p
->col
)))
583 { /* the row is full, no pieces can be added */
584 del_position (from_p
);
585 del_position (next_p
);
590 while ((piecem
= (piecemove
*) llrembynr (pmoves
, 1)) != NULL
)
599 piecem
->to
.col
= next_p
->col
;
600 piecem
->to
.row
= next_p
->row
;
601 pushll (pmoves
, (void *) piecem
);
604 save_piece
= nboard
->pieces
[next_p
->col
][next_p
->row
];
605 nboard
->pieces
[next_p
->col
][next_p
->row
] = piece
;
607 lastmoved
= postostr (next_p
); /* just for logging-purposes */
612 nboard
->typewhite
= 'n';
614 else if (npiece
== 'O')
619 else if (npiece
== 'x')
622 nboard
->typeblack
= 'n';
629 nboard
->nextpiece
= b_opponent (nboard
->nextpiece
);
633 sprintf (tempstr
, "%c:%2s:%2s", npiece
, from
, lastmoved
);
634 addtolog (nboard
->log
, LOGMOVE
, tempstr
);
642 animatemove (oboard
, pmoves
, nboard
);
645 while ((piecem
= (piecemove
*) llrembynr (pmoves
, 1)) != NULL
)
652 /* check for 4 in a row */
653 nboard
->checkfour
= 'y';
654 new_board
= b_checkfour (nboard
);
657 del_position (from_p
);
658 del_position (next_p
);
667 ** b_remove_row: remove a row from the playing field, adapt the different
671 ** oboard : pointer to gipf-board
672 ** rownr : nr of the row to be removed from gipfextra
675 ** pointer to a new gipf-board
678 board
* b_remove_row (board
* oboard
, int rownr
)
701 if ((oboard
->rowextraw
!= NULL
) &&
702 ((oboard
->nextpiece
== 'x') || (oboard
->rowextrab
== NULL
)))
705 rowextra_o
= oboard
->rowextraw
;
707 else if (oboard
->rowextrab
!= NULL
)
710 rowextra_o
= oboard
->rowextrab
;
717 row_ptr
= (rem_row
*) llitembynr (rowextra_o
, rownr
);
718 /* this shouldn't happen */
724 glist
= (listheader
*) malloc (sizeof (listheader
));
726 nboard
= b_copy (oboard
);
727 if (nboard
->gipfextra
!= NULL
)
729 emptyll (nboard
->gipfextra
, del_rem_gipf
);
730 free (nboard
->gipfextra
);
731 nboard
->gipfextra
= NULL
;
734 nboard
->status
= S_NORMAL
;
735 plist
= row_ptr
->piecelist
;
736 winpiece
= row_owner (row_ptr
);
740 start
= postostr (row_start (row_ptr
));
741 end
= postostr (row_end (row_ptr
));
742 sprintf (tempstr
, "%c:%s:%s:", winpiece
, start
, end
);
749 while ((coor
= (position
*) llitembynr (plist
, counter
)) != NULL
)
753 piece
= nboard
->pieces
[coor
->col
][coor
->row
];
754 if ((piece
== 'O') || (piece
== 'X'))
757 gipf_ptr
= new_rem_gipf ();
758 gipf_ptr
->pos
= (position
*) copy_position ((void *) coor
);
759 gipf_ptr
->owner
= winpiece
;
760 pushll (glist
, (void *) gipf_ptr
);
766 strpos
= postostr (coor
);
767 sprintf (tempstr
+ str_offset
, "%2s%c:", strpos
, piece
);
774 if (piece
== winpiece
)
785 if (piece
== winpiece
)
795 nboard
->pieces
[coor
->col
][coor
->row
] = '.';
800 addtolog (nboard
->log
, LOGREMROW
, tempstr
);
804 if (nboard
->removewait
)
806 waitremrow (oboard
, row_ptr
, nboard
);
811 ** remove the row that was just removed from rowextra
812 ** and check if the other rows are still complete
814 /* check white rowlist */
815 if (nboard
->rowextraw
!= NULL
)
817 /* check if all rows are still valid */
818 emptyll (nboard
->rowextraw
, del_rem_row
);/* I now have an empty list */
821 while ((row_ptr
= (rem_row
*) llitembynr (oboard
->rowextraw
, counter
))
825 if ((colour
== 'o') && ((counter
- 1) == rownr
))
829 if ((n_row
= b_rowoffour (nboard
, row_ptr
->rowindex
)) != NULL
)
831 pushll (nboard
->rowextraw
, n_row
);
835 if (llitembynr (nboard
->rowextraw
, 1) == NULL
)
837 free (nboard
->rowextraw
);
838 nboard
->rowextraw
= NULL
;
842 /* check black rowlist */
843 if (nboard
->rowextrab
!= NULL
)
845 /* check if all rows are still valid */
847 emptyll (nboard
->rowextrab
, del_rem_row
);/* I now have an empty list */
850 while ((row_ptr
= (rem_row
*) llitembynr (oboard
->rowextrab
, counter
))
854 if ((colour
== 'x') && ((counter
- 1) == rownr
))
858 if ((n_row
= b_rowoffour (nboard
, row_ptr
->rowindex
)) != NULL
)
860 pushll (nboard
->rowextrab
, n_row
);
864 if (llitembynr (nboard
->rowextrab
, 1) == NULL
)
866 free (nboard
->rowextrab
);
867 nboard
->rowextrab
= NULL
;
871 if ((nboard
->rowextraw
== NULL
) && (nboard
->rowextrab
== NULL
))
873 nboard
->checkfour
= 'n';
878 nboard
->gipfextra
= glist
;
879 nboard
->status
= S_REMOVEGIPF
;
882 else if (nboard
->checkfour
== 'y')
885 new_board
= b_checkfour (nboard
);
898 ** remove a gipf from the board and add the retrieved pieces to the
902 ** oboard: pointer to gipf-board
905 ** pointer to new board
908 board
* b_remove_gipf (board
* oboard
, rem_gipf
* rgipf
)
919 piece
= oboard
->pieces
[rgipf
->pos
->col
][rgipf
->pos
->row
];
920 winpiece
= b_otherpiece (rgipf
->owner
);
922 if ((piece
!= 'O') && (piece
!= 'X'))
927 nboard
= b_copy (oboard
);
929 if (nboard
->gipfextra
!= NULL
)
931 emptyll (nboard
->gipfextra
, del_rem_gipf
);
932 free (nboard
->gipfextra
);
933 nboard
->gipfextra
= NULL
;
936 nboard
->status
= S_NORMAL
;
938 nboard
->pieces
[rgipf
->pos
->col
][rgipf
->pos
->row
] = '.';
942 strpos
= postostr (rgipf
->pos
);
943 sprintf (tempstr
, "%c:%2s%c", rgipf
->owner
, strpos
, piece
);
945 addtolog (nboard
->log
, LOGREMGIPF
, tempstr
);
951 if (piece
== winpiece
)
957 nboard
->lostwhite
+= 2;
963 if (piece
== winpiece
)
969 nboard
->lostblack
+= 2;
973 /* check white rowlist */
974 if (nboard
->rowextraw
!= NULL
)
976 /* check if all rows are still valid */
977 emptyll (nboard
->rowextraw
, del_rem_row
);/* I now have an empty list */
980 while ((row_ptr
= (rem_row
*) llitembynr (oboard
->rowextraw
, counter
))
984 if ((n_row
= b_rowoffour (nboard
, row_ptr
->rowindex
)) != NULL
)
986 pushll (nboard
->rowextraw
, n_row
);
990 if (llitembynr (nboard
->rowextraw
, 1) == NULL
)
992 free (nboard
->rowextraw
);
993 nboard
->rowextraw
= NULL
;
997 /* check black rowlist */
998 if (nboard
->rowextrab
!= NULL
)
1000 /* check if all rows are still valid */
1002 emptyll (nboard
->rowextrab
, del_rem_row
);/* I now have an empty list */
1005 while ((row_ptr
= (rem_row
*) llitembynr (oboard
->rowextrab
, counter
))
1009 if ((n_row
= b_rowoffour (nboard
, row_ptr
->rowindex
)) != NULL
)
1011 pushll (nboard
->rowextrab
, n_row
);
1015 if (llitembynr (nboard
->rowextrab
, 1) == NULL
)
1017 free (nboard
->rowextrab
);
1018 nboard
->rowextrab
= NULL
;
1022 if ((nboard
->rowextraw
== NULL
) && (nboard
->rowextrab
== NULL
))
1024 nboard
->checkfour
= 'n';
1028 if (nboard
->removewait
)
1030 waitremgipf (oboard
, rgipf
->pos
, nboard
);
1039 ** b_checkfour: check for 4 in a row
1042 ** oboard: pointer to gipf-board
1045 ** pointer to a new gipf-board
1047 board
* b_checkfour (board
* oboard
)
1057 listheader
* row4list_w
= NULL
,
1058 * row4list_b
= NULL
;
1066 if (oboard
->checkfour
== 'n')
1068 nboard
= b_copy (oboard
);
1069 nboard
->status
= S_NORMAL
;
1072 if ((oboard
->rowextraw
!= NULL
) &&
1073 ((oboard
->nextpiece
== 'x') || (oboard
->rowextrab
== NULL
)))
1075 if (llitembynr (oboard
->rowextraw
, 2) == NULL
)
1077 nboard
= b_remove_row (oboard
, 1);
1082 nboard
= b_copy (oboard
);
1083 nboard
->status
= S_REMOVEROW
;
1087 else if (oboard
->rowextrab
!= NULL
)
1089 if (llitembynr (oboard
->rowextrab
, 2) == NULL
)
1091 nboard
= b_remove_row (oboard
, 1);
1096 nboard
= b_copy (oboard
);
1097 nboard
->status
= S_REMOVEROW
;
1102 /* base = new_position ();
1103 next = new_position ();*/
1105 for (rownr
=0; rownr
<21; rownr
++)
1107 base
.col
= rowlist
[rownr
][0];
1108 base
.row
= rowlist
[rownr
][1];
1110 if (oboard
->pieces
[base
.col
][base
.row
] == '.')
1117 base_piece
= oboard
->pieces
[base
.col
][base
.row
];
1118 base_piece2
= b_otherpiece (base_piece
);
1120 /* first direction */
1121 dir
= rowlist
[rownr
][2];
1123 /* next.col = base.col;
1124 next.row = base.row;
1126 save_col = next.col;
1127 next.col = b_buren[save_col][next.row][dir][0];
1128 next.row = b_buren[save_col][next.row][dir][1];*/
1129 next
.col
= b_buren
[base
.col
][base
.row
][dir
][0];
1130 next
.row
= b_buren
[base
.col
][base
.row
][dir
][1];
1132 piece
= oboard
->pieces
[next
.col
][next
.row
];
1133 while ((next
.col
!= 0) && (piece
!= '.'))
1135 if ((piece
== base_piece
) || (piece
== base_piece2
))
1143 save_col
= next
.col
;
1144 next
.col
= b_buren
[save_col
][next
.row
][dir
][0];
1145 next
.row
= b_buren
[save_col
][next
.row
][dir
][1];
1147 piece
= oboard
->pieces
[next
.col
][next
.row
];
1150 if (countrow
< rowlist
[rownr
][4])
1151 { /* not possible to get 4 in a row anymore */
1155 /* second direction */
1156 /*dir = rowlist[rownr][3];*/
1159 /* next.col = base.col;
1160 next.row = base.row;
1162 save_col = next.col;
1163 next.col = b_buren[save_col][next.row][dir][0];
1164 next.row = b_buren[save_col][next.row][dir][1];*/
1165 next
.col
= b_buren
[base
.col
][base
.row
][dir
][0];
1166 next
.row
= b_buren
[base
.col
][base
.row
][dir
][1];
1168 piece
= oboard
->pieces
[next
.col
][next
.row
];
1169 while ((next
.col
!= 0) && (piece
!= '.'))
1171 if ((piece
== base_piece
) || (piece
== base_piece2
))
1179 save_col
= next
.col
;
1180 next
.col
= b_buren
[save_col
][next
.row
][dir
][0];
1181 next
.row
= b_buren
[save_col
][next
.row
][dir
][1];
1183 piece
= oboard
->pieces
[next
.col
][next
.row
];
1188 rowp
= b_rowoffour (oboard
, rownr
);
1190 if ((base_piece
== 'o') || (base_piece
== 'O'))
1193 if (row4list_w
== NULL
)
1195 row4list_w
= (listheader
*) malloc (sizeof (listheader
));
1196 newlist (row4list_w
);
1198 pushll (row4list_w
, rowp
);
1203 if (row4list_b
== NULL
)
1205 row4list_b
= (listheader
*) malloc (sizeof (listheader
));
1206 newlist (row4list_b
);
1208 pushll (row4list_b
, rowp
);
1213 /* del_position (base);
1214 del_position (next);*/
1216 nboard
= b_copy (oboard
);
1220 nboard
->rowextraw
= row4list_w
;
1224 nboard
->rowextrab
= row4list_b
;
1227 if ((inrow4_w
== 0) && (inrow4_b
== 0))
1229 nboard
->status
= S_NORMAL
;
1230 nboard
->checkfour
= 'n';
1233 if ((nboard
->rowextraw
!= NULL
) &&
1234 ((nboard
->nextpiece
== 'x') || (nboard
->rowextrab
== NULL
)))
1238 new_board
= b_remove_row (nboard
, 1);
1244 nboard
->status
= S_REMOVEROW
;
1252 new_board
= b_remove_row (nboard
, 1);
1258 nboard
->status
= S_REMOVEROW
;
1266 ** b_rowoffour: check if a certain row has four in a row
1269 ** oboard: pointer to gipf-board
1270 ** rownr: nr of row in rowlist
1273 ** pointer to rem_row-structure
1274 ** NULL (if no 4 in a row found)
1276 rem_row
* b_rowoffour (board
* oboard
, int rownr
)
1282 listheader
* temprow
;
1292 temprow
= (listheader
*) malloc (sizeof (listheader
));
1296 base
= new_position();
1297 base
->col
= rowlist
[rownr
][0];
1298 base
->row
= rowlist
[rownr
][1];
1299 start
= (position
*) copy_position ((void *) base
);
1300 end
= (position
*) copy_position ((void *) base
);
1301 next
= (position
*) copy_position ((void *) base
);
1303 if (oboard
->pieces
[base
->col
][base
->row
] == '.')
1307 del_position ((void *) base
);
1308 del_position ((void *) start
);
1309 del_position ((void *) end
);
1310 del_position ((void *) next
);
1314 base_piece
= oboard
->pieces
[base
->col
][base
->row
];
1315 base_piece2
= b_otherpiece (base_piece
);
1316 pushll (temprow
, copy_position ((void *) base
));
1318 /* first direction */
1319 dir
= rowlist
[rownr
][2];
1322 /* b_moveto (next, col_dif, &row_dif);*/
1323 save_col
= next
->col
;
1324 next
->col
= b_buren
[save_col
][next
->row
][dir
][0];
1325 next
->row
= b_buren
[save_col
][next
->row
][dir
][1];
1327 piece
= oboard
->pieces
[next
->col
][next
->row
];
1328 while ((next
->col
!= 0) && (piece
!= '.'))
1330 pushll (temprow
, copy_position ((void *) next
));
1332 ((piece
== base_piece
) || (piece
== base_piece2
)))
1335 start
->col
= next
->col
;
1336 start
->row
= next
->row
;
1342 /* b_moveto (next, col_dif, &row_dif);*/
1343 save_col
= next
->col
;
1344 next
->col
= b_buren
[save_col
][next
->row
][dir
][0];
1345 next
->row
= b_buren
[save_col
][next
->row
][dir
][1];
1347 piece
= oboard
->pieces
[next
->col
][next
->row
];
1350 /* second direction */
1351 /*dir = rowlist[rownr][3];*/
1354 next
->col
= base
->col
;
1355 next
->row
= base
->row
;
1358 /* b_moveto (next, col_dif, &row_dif);*/
1359 save_col
= next
->col
;
1360 next
->col
= b_buren
[save_col
][next
->row
][dir
][0];
1361 next
->row
= b_buren
[save_col
][next
->row
][dir
][1];
1363 piece
= oboard
->pieces
[next
->col
][next
->row
];
1364 while ((next
->col
!= 0) && (piece
!= '.'))
1366 pushll (temprow
, copy_position ((void *) next
));
1368 ((piece
== base_piece
) || (piece
== base_piece2
)))
1371 end
->col
= next
->col
;
1372 end
->row
= next
->row
;
1378 /* b_moveto (next, col_dif, &row_dif);*/
1379 save_col
= next
->col
;
1380 next
->col
= b_buren
[save_col
][next
->row
][dir
][0];
1381 next
->row
= b_buren
[save_col
][next
->row
][dir
][1];
1383 piece
= oboard
->pieces
[next
->col
][next
->row
];
1388 rowp
= new_rem_row ();
1389 rowp
->startpos
= start
;
1391 rowp
->piecelist
= temprow
;
1392 rowp
->rowindex
= rownr
;
1393 if ((base_piece
== 'o') || (base_piece
== 'x'))
1395 rowp
->owner
= base_piece
;
1399 rowp
->owner
= base_piece2
;
1404 emptyll (temprow
, del_position_f
);
1406 del_position (start
);
1410 del_position (base
);
1411 del_position (next
);
1418 ** b_moveto: give coor of new position
1421 ** pos: startpos, endpos after run
1422 ** col_dif: column difference
1423 ** row_dif: row difference
1425 inline void b_moveto (position
* pos
, int col_dif
, int * row_dif
)
1433 pos
->col
+= col_dif
;
1436 pos
->row
+= (*row_dif
);
1437 if ((pos
->col
== 0) ||
1440 (pos
->row
> b_colsize(pos
->col
)))
1450 ** b_colour: return the number of available pieces for a colour
1453 ** oboard : pointer to gipf-board
1454 ** colour : o, O, x, X
1459 int b_colour (board
* oboard
, char colour
)
1461 if ((colour
== 'o') || (colour
== 'O'))
1463 return (oboard
->white
);
1465 else if ((colour
== 'x') || (colour
== 'X'))
1467 return (oboard
->black
);
1474 ** b_colour_gipf: return the number of gipfpieces for a colour
1477 ** oboard : pointer to gipf-board
1478 ** colour : o, O, x, X
1483 int b_colour_gipf (board
* oboard
, char colour
)
1485 if ((colour
== 'o') || (colour
== 'O'))
1487 return (oboard
->gipfwhite
);
1489 else if ((colour
== 'x') || (colour
== 'X'))
1491 return (oboard
->gipfblack
);
1498 ** b_colour_lost: return the number of lost pieces for a colour
1501 ** oboard : pointer to gipf-board
1502 ** colour : o, O, x, X
1507 int b_colour_lost (board
* oboard
, char colour
)
1509 if ((colour
== 'o') || (colour
== 'O'))
1511 return (oboard
->lostwhite
);
1513 else if ((colour
== 'x') || (colour
== 'X'))
1515 return (oboard
->lostblack
);
1522 ** b_colour_type: return the type of pieces this colour can place
1525 ** oboard : pointer to gipf-board
1526 ** colour : o, O, x, X
1531 char b_colour_type (board
* oboard
, char colour
)
1533 if ((colour
== 'o') || (colour
== 'O'))
1535 return (oboard
->typewhite
);
1537 else if ((colour
== 'x') || (colour
== 'X'))
1539 return (oboard
->typeblack
);
1546 ** b_piece: return piece at position
1549 ** oboard: pointer to gipf-board
1550 ** pos: position-string (ex. b4)
1555 char b_piece (board
* oboard
, char * strpos
)
1560 pos
= strtopos (strpos
);
1561 piece
= oboard
->pieces
[pos
->col
][pos
->row
];
1569 ** b_game_finished : check if game is finished
1572 ** oboard: gipf-board
1575 ** 0: game not finished
1578 ** REMARK: only do this if no more rows can be removed from the board
1580 int b_game_finished (board
* oboard
)
1583 ** check if a player has no gipf-pieces left
1584 ** but only do this at the second move
1586 if ((oboard
->movecounter
> 0) &&
1587 (oboard
->gipfwhite
== 0))
1589 oboard
->status
= S_FINISHED
;
1590 oboard
->winner
= 'x';
1594 if (((oboard
->movecounter
> 1) ||
1595 ((oboard
->nextpiece
== 'o') && (oboard
->movecounter
== 1))) &&
1596 (oboard
->gipfblack
== 0))
1598 oboard
->status
= S_FINISHED
;
1599 oboard
->winner
= 'o';
1603 /* check if the next player has pieces left */
1604 if (b_colour (oboard
, oboard
->nextpiece
) == 0)
1606 oboard
->status
= S_FINISHED
;
1607 oboard
->winner
= b_opponent (oboard
->nextpiece
);
1616 ** b_compare: compare the contents of 2 gipf-boards
1626 int b_compare (board
* board1
, board
* board2
)
1632 if ((board1
== NULL
) || (board2
== NULL
))
1637 /* compare the different counters */
1638 if ((board1
->nextpiece
!= board2
->nextpiece
) ||
1639 (board1
->movecounter
!= board2
->movecounter
) ||
1640 (board1
->white
!= board2
->white
) ||
1641 (board1
->lostwhite
!= board2
->lostwhite
) ||
1642 (board1
->gipfwhite
!= board2
->gipfwhite
) ||
1643 (board1
->typewhite
!= board2
->typewhite
) ||
1644 (board1
->black
!= board2
->black
) ||
1645 (board1
->lostblack
!= board2
->lostblack
) ||
1646 (board1
->gipfblack
!= board2
->gipfblack
) ||
1647 (board1
->typeblack
!= board2
->typeblack
))
1654 /* compare board-contents */
1655 for (i
= 1; i
< 8; i
++)
1656 for (j
= 2; j
<= b_colsize (i
); j
++)
1657 if (board1
->pieces
[i
][j
] != board2
->pieces
[i
][j
])
1660 if (memcmp (&(board1
->pieces
), &(board2
->pieces
), 72) != 0)
1670 listheader
* b_row_extra (board
* oboard
)
1672 if ((oboard
->rowextraw
!= NULL
) &&
1673 ((oboard
->nextpiece
== 'x') || (oboard
->rowextrab
== NULL
)))
1675 return (oboard
->rowextraw
);
1679 return (oboard
->rowextrab
);
1685 ** replace the piece at position 'pos' with 'piece'
1686 ** try to adapt the counters
1691 board
* b_edit_piece (board
* oboard
, position
* pos
, char piece
)
1695 nboard
= b_copy (oboard
);
1697 if (nboard
->pieces
[pos
->col
][pos
->row
] == piece
)
1703 switch (nboard
->pieces
[pos
->col
][pos
->row
])
1710 nboard
->gipfwhite
-= 1;
1717 nboard
->gipfblack
-= 1;
1727 if (nboard
->white
== 0)
1735 if (nboard
->white
< 2)
1741 nboard
->gipfwhite
+= 1;
1744 if (nboard
->black
== 0)
1752 if (nboard
->black
< 2)
1758 nboard
->gipfblack
+= 1;
1764 nboard
->pieces
[pos
->col
][pos
->row
] = piece
;
1770 board
* b_edit_lostwhite (board
* oboard
, int newval
)
1774 if ((oboard
->white
+ oboard
->lostwhite
- newval
) < 0)
1779 nboard
= b_copy (oboard
);
1780 nboard
->white
= nboard
->white
+ nboard
->lostwhite
- newval
;
1781 nboard
->lostwhite
= newval
;
1787 board
* b_edit_lostblack (board
* oboard
, int newval
)
1791 if ((oboard
->black
+ oboard
->lostblack
- newval
) < 0)
1796 nboard
= b_copy (oboard
);
1797 nboard
->black
= nboard
->black
+ nboard
->lostblack
- newval
;
1798 nboard
->lostblack
= newval
;
1805 ** write a boardsituation to a file
1806 ** use a format that can be read by b_from_file
1807 ** (should also be readable by gipfdraw, so you can easily
1808 ** make gif's from a board-position)
1810 ** returns -1 on failure, otherwise 0
1812 ** REMARK: the board must be in a stable state (S_NORMAL or S_FINISHED)
1813 ** otherwise the save will fail
1815 int b_to_file (board
* oboard
, FILE * fp
)
1824 if ((oboard
->status
!= S_NORMAL
) && (oboard
->status
!= S_FINISHED
))
1829 fprintf (fp
, "whitepieces:%d\n", oboard
->white
);
1830 fprintf (fp
, "whitelost:%d\n", oboard
->lostwhite
);
1832 fprintf (fp
, "blackpieces:%d\n", oboard
->black
);
1833 fprintf (fp
, "blacklost:%d\n", oboard
->lostblack
);
1835 fprintf (fp
, "nextplayer:%c\n", oboard
->nextpiece
);
1837 temppos
= (position
*) malloc (sizeof (position
));
1838 for (i
= 1; i
< 8; i
++)
1841 for (j
= 2; j
<= b_colsize (i
); j
++)
1844 if (b_ppiece (oboard
, temppos
) != '.')
1846 tempstr
= postostr (temppos
);
1847 fprintf (fp
, "%c:%2s\n",
1848 b_ppiece (oboard
, temppos
), tempstr
);
1855 fprintf (fp
, "# end of board\n");
1862 ** read a boardsituation from a file and store it in a
1865 ** returns NULL on failure
1867 board
* b_from_file (FILE * fp
)
1869 char buffer
[100]="",
1876 nboard
= b_new (T_TOURNAMENT
);
1877 nboard
->typewhite
= 'n';
1878 nboard
->typeblack
= 'n';
1880 while (strncmp (buffer
, "# end of board", 14) != 0)
1882 if (fgets (buffer
, 100, fp
) == NULL
)
1888 if (sscanf (buffer
, "whitepieces:%d", &tempnr
) == 1)
1890 nboard
->white
= tempnr
;
1892 else if (sscanf (buffer
, "whitelost:%d", &tempnr
) == 1)
1894 nboard
->lostwhite
= tempnr
;
1896 else if (sscanf (buffer
, "blackpieces:%d", &tempnr
) == 1)
1898 nboard
->black
= tempnr
;
1900 else if (sscanf (buffer
, "blacklost:%d", &tempnr
) == 1)
1902 nboard
->lostblack
= tempnr
;
1904 else if (sscanf (buffer
, "nextplayer:%c", &tempchar
) == 1)
1906 nboard
->nextpiece
= tempchar
;
1908 else if (sscanf (buffer
, "%c:%s", &tempchar
, tempstr
) == 2)
1910 temppos
= strtopos (tempstr
);
1911 nboard
->pieces
[temppos
->col
][temppos
->row
] = tempchar
;
1915 nboard
->gipfwhite
+= 1;
1918 nboard
->gipfblack
+= 1;
1921 del_position (temppos
);
1925 if ((nboard
->gipfwhite
== 0) && (nboard
->gipfblack
== 0))
1927 nboard
->gipfwhite
= -1;
1928 nboard
->gipfblack
= -1;