home *** CD-ROM | disk | FTP | other *** search
- /* #[info: */
- /************************************************************************
- * *
- * #### #### #### # # # ##### #### *
- * # # # # # # # # # # *
- * # # # # # # # # # # *
- * # ## # # ### # # # ### ### *
- * # # # # # # # # # # # *
- * # # # # # # # # # # # *
- * #### #### # # ####### ###### ##### #### *
- * *
- * Jan van der Steen *
- * *
- * Centre for Mathematics and Computer Science *
- * Amsterdam, the Netherlands *
- * *
- *----------------------------------------------------------------------*
- * File : gorules.c *
- * Purpose : Implement the Japanese Go Rules *
- * Version : 1.2 *
- * Modified: 2/12/93 16:41:25 *
- * Author : Jan van der Steen (jansteen@cwi.nl) *
- ************************************************************************/
- /* #]info: */
- /* #[include: */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "tools.h"
- #include "gogame.h"
- #include "gorules.h"
-
- /* #]include: */
- /* #[static: */
-
- static int theside = 0;
- static int thelibs = 0;
-
- /* #]static: */
- /* #[prototype: */
-
- #ifdef __STDC__
- # define PROTO(s) s
- #else
- # define PROTO(s) ()
- #endif
-
- static int goban_loop PROTO(( GOGAME *gogame,
- GONODE *gonode,
- int (*f)PROTO(( GOGAME *gogame,
- GONODE *gonode))));
- static int goban_do PROTO(( GOGAME *gogame,
- GONODE *gonode,
- int (*f)PROTO(( GOGAME *gogame,
- GONODE *gonode))));
- static int rules_liberty PROTO(( GOGAME *gogame, GONODE *gonode));
- static int rules_remove PROTO(( GOGAME *gogame, GONODE *gonode));
-
- #undef PROTO
-
- /* #]prototype: */
-
- /* #[goban_loop: */
-
- #ifdef __STDC__
- # define PROTO(s) s
- #else
- # define PROTO(s) ()
- #endif
-
- static int
- goban_loop(gogame, gonode, f)
- /*
- * Visit "all" goban points and execute f()
- */
- GOGAME *gogame;
- GONODE *gonode;
- int (*f)PROTO((GOGAME *gogame, GONODE *gonode));
- {
- (gogame->gm_goban->gb_loop)++;
-
- return goban_do(gogame, gonode, f);
- }
-
- #undef PROTO
-
- /* #]goban_loop: */
- /* #[goban_do: */
-
- #ifdef __STDC__
- # define PROTO(s) s
- #else
- # define PROTO(s) ()
- #endif
-
- static int
- goban_do(gogame, gonode, f)
- /*
- * Visit "all" goban points and execute f()
- */
- GOGAME *gogame;
- GONODE *gonode;
- int (*f)PROTO((GOGAME *gogame, GONODE *gonode));
- {
- /*
- * On the goban?
- */
- if (gonode == (GONODE *) 0) return 0;
-
- /*
- * First time?
- */
- if (gonode->gn_loop == gogame->gm_goban->gb_loop) return 0;
-
- /*
- * Mark goban point
- */
- gonode->gn_loop = gogame->gm_goban->gb_loop;
-
- if (! (*f)(gogame, gonode)) return 0;
-
- return (
- goban_do(gogame, gonode->gn_n, f) +
- goban_do(gogame, gonode->gn_e, f) +
- goban_do(gogame, gonode->gn_s, f) +
- goban_do(gogame, gonode->gn_w, f));
- }
-
- #undef PROTO
-
- /* #]goban_do: */
- /* #[rules_liberty: */
-
- static int
- rules_liberty(gogame, gonode)
- /*
- * Calculate the liberties of a chain
- */
- GOGAME *gogame;
- GONODE *gonode;
- {
- if (gonode->gn_stone == (GOMOVE *) 0) {
- /*
- * Update liberties
- */
- thelibs++;
- return 0;
- }
- return (gonode->gn_stone->mv_side == theside);
- }
-
- /* #]rules_liberty: */
- /* #[rules_remove: */
-
- static int
- rules_remove(gogame, gonode)
- /*
- * Remove the members of a chain
- */
- GOGAME *gogame;
- GONODE *gonode;
- {
- if (gonode->gn_stone == (GOMOVE *) 0) return 0;
- if (gonode->gn_stone->mv_side == theside) {
- /*
- * Remove stone from the board
- */
- capture_store(gogame, gonode);
- gonode->gn_stone = (GOMOVE *) 0;
- return 1;
- }
- return 0;
- }
-
- /* #]rules_remove: */
- /* #[rules_check: */
-
- int
- rules_check(gogame, place, side)
- /*
- * Check whether a stone in "gogame" from "side" at "place" is legal
- * (according to the Japanese Go Rules)
- */
- GOGAME *gogame;
- PLACE place;
- int side;
- {
- GONODE *n = NODE(gogame, place);
-
- /* #[RULES_OUTSIDE: */
-
- if (0 > place || place >= gogame->gm_size * gogame->gm_size)
- return RULES_OUTSIDE;
-
- /* #]RULES_OUTSIDE: */
- /* #[RULES_OCCUPIED: */
-
- if (n->gn_stone != (GOMOVE *) 0) return RULES_OCCUPIED;
- n->gn_stone = gogame->gm_movelast;
-
- /* #]RULES_OCCUPIED: */
- /* #[RULES_KO: */
- /* #]RULES_KO: */
- /* #[RULES_SUICIDE: */
-
- /*
- * First calculate the liberties of enemy chains (remove them if nessesary)
- */
- theside = (side == BLACK) ? WHITE : BLACK;
- thelibs = 0; goban_loop(gogame, n->gn_n, rules_liberty);
- if (thelibs == 0) goban_loop(gogame, n->gn_n, rules_remove);
- thelibs = 0; goban_loop(gogame, n->gn_e, rules_liberty);
- if (thelibs == 0) goban_loop(gogame, n->gn_e, rules_remove);
- thelibs = 0; goban_loop(gogame, n->gn_s, rules_liberty);
- if (thelibs == 0) goban_loop(gogame, n->gn_s, rules_remove);
- thelibs = 0; goban_loop(gogame, n->gn_w, rules_liberty);
- if (thelibs == 0) goban_loop(gogame, n->gn_w, rules_remove);
-
- /*
- * Next calculate liberties of friendly chain
- */
- theside = side;
- thelibs = 0;
- goban_loop(gogame, n, rules_liberty);
- if (thelibs == 0) return RULES_SUICIDE;
-
- /* #]RULES_SUICIDE: */
-
- return RULES_LEGAL;
- }
-
- /* #]rules_check: */
-