home *** CD-ROM | disk | FTP | other *** search
- /* check.c 10/29/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"
-
- /*======================================================================
- * This file contains the functions that check for unused moves.
- *======================================================================
- */
-
-
- PRIVATE int maxused, hiused, nlegal;
-
- struct legal *rmlegal();
-
-
- legalmoves(g)
- struct game *g;
- {
- struct game tmp;
- int i;
- struct legal *l;
-
- tmp = *g; /* we don't want to change actual game */
- for (i = 0; i < 4; tmp.mvs[i++].pt = -1); /* mark all unused */
- maxused = -1; /* init to not all used */
- hiused = 0; /* init to 0 */
- nlegal = 0; /* init to no legal moves*/
- lhead = NULL;
- ltail = NULL;
- if (tmp.mvs[0].roll == tmp.mvs[1].roll)
- scanmvs(&tmp,0,3); /* there is only one ordering */
- else {
- scanmvs(&tmp,0,1); /* scan for one ordering */
- i = tmp.mvs[0].roll; /* reverse rolls */
- tmp.mvs[0].roll = tmp.mvs[1].roll;
- tmp.mvs[1].roll = i;
- for (i = 0; i < 4; tmp.mvs[i++].pt = -1); /* mark all unused */
- scanmvs(&tmp,0,1); /* scan for other ordering */
- }
- trimunused();
- trimlowused();
- trimequal();
- g->maxused = maxused;
- g->hiused = hiused;
- if (nlegal == 0) {
- if (g->dispmsg != NULL)
- free(g->dispmsg);
- g->dispmsg = save("You don't have any legal moves.");
- }
- else if (nlegal == 1) {
- if (g->dispmsg != NULL)
- free(g->dispmsg);
- g->dispmsg = save("You only have one legal move.");
- if (*rc.automove == 'y') {
- if ( (lhead->nmove==0) && (lhead->mvs[0].roll!=g->mvs[0].roll))
- g->mvs[1] = g->mvs[0];
- for (i = 0; i <= lhead->nmove; i++) {
- g->mvs[i] = lhead->mvs[i];
- apply(g,1,i,0,NULL);
- }
- }
- }
-
- /* we have no use for the legal moves list, so free it */
- /* maybe in the future we will have a use for it */
-
- for (l = lhead; l != NULL; l = l->next)
- free(l);
- lhead = NULL;
- ltail = NULL;
- }
-
-
- scanmvs(g,mn,max)
- struct game *g;
- {
- int i;
- board sv;
-
- copyboard(g->board,sv);
- for (i = 0; i <= 24; i++) {
- if (i == 0)
- g->mvs[mn].pt = BARPT(g->mydir);
- else
- g->mvs[mn].pt = i;
- if (apply(g,1,mn,0,NULL) < 0) /* can't move from this pt */
- continue;
- addlegal(mn,g->mvs[mn].roll,g->mvs[mn].pt);
- if (mn < max)
- scanmvs(g,mn+1,max);
- copyboard(sv,g->board);
- }
- }
-
-
- addlegal(mn,r,pt)
- int mn, r, pt;
- {
- int i;
- struct legal *n;
-
- if ( (n = (struct legal *) calloc(sizeof(struct legal),1)) == NULL) {
- FeFinishSession();
- TFinishSession();
- fprintf(stderr,"Out of memory!\n");
- exit(1);
- }
- clearmvs(n->mvs);
- if (ltail != NULL)
- for (i = 0; i < mn; i++) /* copy prefix from prev move */
- n->mvs[i] = ltail->mvs[i];
- n->mvs[mn].roll = r;
- n->mvs[mn].pt = pt;
- n->next = NULL;
- if (lhead == NULL) {
- n->prev = NULL;
- lhead = n;
- ltail = n;
- }
- else {
- n->prev = ltail;
- ltail->next = n;
- ltail = n;
- }
- n->himove = 0;
- for (i = 0; i <= mn; i++)
- if (n->mvs[i].roll > n->himove)
- n->himove = n->mvs[i].roll;
- if (mn > maxused) /* keep track of whether it is possible */
- maxused = mn; /* to use all of the rolls */
- nlegal++;
- n->nmove = mn;
- }
-
-
- trimunused()
- {
- struct legal *l;
-
- l = lhead;
- while (l != NULL) {
- if (l->nmove < maxused)
- l = rmlegal(l);
- else
- l = l->next;
- }
- }
-
-
- trimlowused()
- {
- struct legal *l;
-
- l = lhead;
- while (l != NULL) {
- if (l->himove < hiused)
- l = rmlegal(l);
- else
- l = l->next;
- }
- }
-
-
- trimequal()
- {
- struct legal *l, *p;
- struct mv m1[4], m2[4];
- int i, n;
-
- for (l = lhead; l != NULL; l = l->next) {
- extractmvs(l,m1);
- n = l->nmove;
- p = l->next;
- while (p != NULL) {
- if (p->nmove != n) {
- p = p->next;
- continue;
- }
- extractmvs(p,m2);
- for (i = 0; i <= n; i++)
- if ((m1[i].roll != m2[i].roll)||(m1[i].pt != m2[i].pt))
- break;
- if (i <= n)
- p = p->next;
- else
- p = rmlegal(p);
- }
- }
- }
-
-
- struct legal *rmlegal(l)
- struct legal *l;
- {
- struct legal *t;
-
- t = l;
- if (l == lhead) {
- lhead = l->next;
- l = lhead;
- }
- else {
- if ( (l->prev->next = l->next) != NULL)
- l->next->prev = l->prev;
- l = l->next;
- }
- free(t);
- nlegal--;
- return(l);
- }
-
-
- extractmvs(l,m)
- struct legal *l;
- struct mv *m;
- {
- int i, n, s;
- struct mv tmp;
-
- clearmvs(m);
- for (i = 0; i <= l->nmove; i++) /* extract the moves */
- m[i] = l->mvs[i];
- n = l->nmove;
- do { /* sort by increasing roll then increasing point */
- s = 0;
- for (i = 0; i < n; i++) { /* long live bubblesort */
- if (m[i].roll < m[i+1].roll)
- continue;
- else if ( (m[i].roll == m[i+1].roll) && (m[i].pt < m[i+1].pt) )
- continue;
- tmp = m[i];
- m[i] = m[i+1];
- m[i+1] = tmp;
- s = 1;
- }
- n--;
- } while (s);
- }
-
-
- checkused(g)
- struct game *g;
- {
- int h, i;
-
- h = 0;
- for (i = 0; i <= g->maxused; i++) {
- if (g->mvs[i].pt < 0) {
- FeMessage("You left a roll unused.");
- return(1);
- }
- if (h < g->mvs[i].roll)
- h = g->mvs[i].roll;
- }
- if (g->hiused > h) {
- FeMessage("You can use the higher roll.");
- return(1);
- }
- return(0);
- }
-