home *** CD-ROM | disk | FTP | other *** search
- /* move.c 8/5/91
- *
- * Copyright 1991 Perry R. Ross
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation without fee is hereby granted, subject to the restrictions
- * detailed in the README file, which is included here by reference.
- * Any other use requires written permission from the author. This software
- * is distributed "as is" without any warranty, including any implied
- * warranties of merchantability or fitness for a particular purpose.
- * The author shall not be liable for any damages resulting from the
- * use of this software. By using this software, the user agrees
- * to these terms.
- */
-
- #include "ldb.h"
-
- /*-----------------------------------------------------------------------
- * apply -- apply a move to a board
- *
- * Apply applies a move to a board, detecting the following errors:
- * RJ_NOROLL The mv struct did not contain a valid roll.
- * RJ_ONBAR The move attempted to move from a point other than
- * the bar when pieces are on the bar.
- * RJ_NOOFF The move attempted to move pieces off before all
- * pieces are in the inner table.
- * RJ_NOPIECE The move attempted to take a piece from an empty point.
- * RJ_NOTYOURS The move attempted to move the opponent's piece.
- * RJ_OCC The move attempted to move to an occupied point.
- * RJ_EXACT The move attempted to bear off a piece with a
- * larger roll than necessary when that piece was
- * not the outermost piece.
- * If the move was legal, apply returns:
- * MVOK if no blot was hit, or
- * point number where the blot was before it was hit.
- * Note that blot numbers are in the range [1-24], MVOK is 0, and
- * the reject codes are negative. When the move is rejected,
- * the board is unchanged. When a blot is hit, it is moved to the
- * appropriate bar point automatically.
- *
- * If A_REDRAW is set in flags, apply redraws the relevant portions of
- * the screen to reflect the move. If A_CHKONLY is set in flags, the
- * move is checked but the board is not modified.
- *-----------------------------------------------------------------------
- */
-
- apply(g,who,mn,flags,dest)
- struct game *g; /* game structure */
- int who; /* 0 = opponent, 1 = me */
- int mn; /* which element of mv array */
- int flags; /* A_* */
- int *dest; /* where to store destination point */
- {
- int i, j, blot;
- int op, np;
- int dir;
- char clr;
- struct mv *m;
- register struct point *b = g->board;
-
- dir = who ? g->mydir : g->opdir;
- clr = who ? g->mycolor : g->opcolor;
- blot = MVOK; /* no blot hit yet */
- m = who ? &g->mvs[mn] : &g->opmvs[mn];
- if (m->roll <= 0) /* sanity check */
- return(RJ_NOROLL); /* reject move */
- op = m->pt; /* starting point number */
- if (op < 0) /* this roll is unused */
- return(MVOK); /* and that's ok */
- if ( (op == 0) || (op == 25) ) /* moving off bar */
- op = BARPT(dir); /* use correct bar point */
- else { /* not moving off bar */
- j = BARPT(dir); /* make sure no pieces still on bar */
- if (b[j].qty > 0)
- return(RJ_ONBAR); /* can't move, pieces on bar */
- }
- np = op + m->roll*dir; /* move piece correct number of pts */
- if ( (np <= 0) || (np >= 25) ) {
- i = (dir > 0) ? 19 : 1;
- j = (dir > 0) ? 24 : 6;
- if (addpcs(b,clr,i,j)+b[OFFPT(dir)].qty < 15) /* all pcs not */
- return(RJ_NOOFF); /* in inner table, can't move off */
- if ( (np != 0) && (np != 25) ) {/* using bigger roll than needed */
- i = (dir > 0) ? 19 : op+1; /* check for pcs on higher pts */
- j = (dir > 0) ? op-1 : 6;
- if (addpcs(b,clr,i,j) > 0) /* there are some */
- return(RJ_EXACT); /* must use roll on them */
- }
- np = OFFPT(dir); /* this piece is moving off */
- }
- if (b[op].qty <= 0) /* no piece here to move */
- return(RJ_NOPIECE);
- if (b[op].color != clr) /* trying to move opponent's pieces? */
- return(RJ_NOTYOURS);
- if (b[np].qty == 0) /* moving to an empty point */
- b[np].color = b[op].color; /* copy color */
- if (b[np].color != b[op].color) { /* moving to occupied pt */
- if (b[np].qty == 1) { /* whacked a blot */
- blot = np; /* save point number for return */
- if ( (flags & A_CHKONLY) == 0) {
- b[np].qty = 0; /* bye bye */
- j = BARPT(REV(dir)); /* send it to opponents bar */
- b[j].color = b[np].color; /* copy color to bar pt */
- b[j].qty++; /* bump counter */
- if (flags & A_REDRAW) /* update screen */
- FeDrawPoint(b,j,0,g->flags & F_INVERT);
- b[np].color = b[op].color; /* my point now */
- }
- }
- else
- return(RJ_OCC); /* point is occupied */
- }
- if ( (flags & A_CHKONLY) == 0) {
- b[op].qty--; /* take piece from old pt */
- b[np].qty++; /* and put in on new pt */
- if (flags & A_REDRAW) {
- FeDrawPoint(b,op,0,g->flags & F_INVERT);/* update the screen */
- FeDrawPoint(b,np,0,g->flags & F_INVERT);
- }
- }
- if (dest != NULL) /* return new position */
- *dest = np;
- return(blot); /* succeeded, return MVOK or blot */
- }
-
-
- /*----------------------------------------------------------------------
- * addpcs -- add the number of pieces in a range of points
- *
- * This function returns the number of pieces of a certain color
- * that reside within a range of points.
- *----------------------------------------------------------------------
- */
-
- addpcs(b,clr,f,t)
- board b;
- char clr;
- int f, t;
- {
- int i, q;
-
- q = 0; /* quantity we have found so far */
- for (i = f; i <= t; i++)
- if (b[i].color == clr) /* found some */
- q += b[i].qty; /* count them */
- return(q); /* return quantity found */
- }
-