/* XScrabble moves.c move validation and scoring routines By csuos@warwick.ac.uk */ #include "scrab.h" #include "globals.h" void convupper(char *str) { int conv = 0; while (str[conv] != '\0') { str[conv] = toupper((int)str[conv]); conv++; } } unsigned int emptyboard(char b[BOARDSIZE][BOARDSIZE]) { int x,y; int empty = 1; for (x = 0; x < BOARDSIZE; x++) for (y = 0; y < BOARDSIZE; y++) { if (b[x][y] != ' ') empty = 0; } return empty; } int validate(char newboard[BOARDSIZE][BOARDSIZE],int testing, int *goscore) { int checkx,checky; int sx,sy,ex,ey; int finish = 0; /* set finished flag to false */ int invalid = 0; /* set invalid flag to false */ int nothoriz = 1; /* set horizontal check to true */ int notvert = 1; /* set vertical check to true */ int oldpiece = 0; /* set old piece check to false */ int csx,csy,cex,cey,empty; empty = emptyboard(board); /* find first new letter */ checkx = checky = 0; while (!((board[checkx][checky] == ' ') && (newboard[checkx][checky] != ' ')) && (!finish)) { checkx++; if (checkx == BOARDSIZE) { checkx = 0; checky++; } if (checky == BOARDSIZE) finish = 1; /* set finished flag to true */ } if (finish) return HORLICKS; /* return invalid if new pieces are not added */ else { sx=checkx; sy=checky; } /* check for a horizontal word */ if ((checkx+1 < BOARDSIZE) && (newboard[checkx+1][checky] != ' ')) { /* find end of horizontal , including old pieces*/ while ((checkx+1 < BOARDSIZE) && (newboard[checkx+1][checky] != ' ')) { if (board[checkx+1][checky] == ' ') { nothoriz = 0; } checkx++; } if (!nothoriz) { ex = checkx; ey = checky; /* check for no extra pieces */ checkx++; if (checkx == BOARDSIZE) { checkx = 0 ; checky++; } while ((checky < BOARDSIZE) && (!invalid)) { if ((board[checkx][checky] == ' ') && (newboard[checkx][checky] != ' ')) invalid = 1; /* go is invalid */ else { checkx++; if (checkx == BOARDSIZE) { checkx = 0 ; checky++; } } } if (invalid) return HORLICKS; else { if (!empty) /* check to see if there is an old piece around word */ { csx = sx; cex = ex; if (sy > 0) csy = sy-1; else csy = sy; if (ey < BOARDSIZE-1) cey = ey+1; else cey = ey; for (checkx = csx; checkx <= cex; checkx++) for (checky = csy; checky <= cey; checky++) if (board[checkx][checky] != ' ') oldpiece = 1; if ((sx > 0)&&(board[sx-1][sy]!=' ')) oldpiece = 1; if ((ex < BOARDSIZE-1)&&(board[ex+1][ey]!=' ')) oldpiece = 1; if (oldpiece) return (checkwords(newboard,sx,sy,ex,ey,testing,goscore)); else return HORLICKS; } else return (checkwords(newboard,sx,sy,ex,ey,testing,goscore)); } } } checkx = sx; checky = sy; /* check for a vertical word */ if ((checky+1 < BOARDSIZE) && (newboard[checkx][checky+1] != ' ') && nothoriz) { /* check for no extra pieces before vertical word */ checky++; checkx = 0; while ((checkx < sx) && (!invalid)) { if ((board[checkx][checky] == ' ') && (newboard[checkx][checky] != ' ')) invalid = 1; /* extra piece, go is invalid */ else { checky++; if (checky == BOARDSIZE) { checky = sy+1; checkx++; } } } if (invalid) return HORLICKS; /* reset check variables */ checkx=sx; checky=sy; /* now find end of vertical word */ while ((checky+1 < BOARDSIZE) && (newboard[checkx][checky+1] != ' ')) { if (board[checkx][checky+1] == ' ') { notvert = 0; } checky++; } if (!notvert) { ex = checkx; ey = checky; /* check for no extra pieces after vertical word */ checky++; if (checky == BOARDSIZE) { checky = sy; checkx ++; } while ((checkx < BOARDSIZE) && (!invalid)) { if ((board[checkx][checky] == ' ') && (newboard[checkx][checky] != ' ')) invalid = 1; /* go is invalid */ else { checky++; if (checky == BOARDSIZE) { checky = sy ; checkx++; } } } if (invalid) return HORLICKS; else { if (!empty) { csy = sy; cey = ey; if (sx > 0) csx = sx-1; else csx = sx; if (ex < BOARDSIZE-1) cex = ex+1; else cex = ex; for (checkx = csx; checkx <= cex; checkx++) for (checky = csy; checky <= cey; checky++) if (board[checkx][checky] != ' ') oldpiece = 1; if ((sy > 0)&&(board[sx][sy-1]!=' ')) oldpiece = 1; if ((ey < BOARDSIZE-1)&&(board[ex][ey+1]!=' ')) oldpiece = 1; if (oldpiece) return (checkwords(newboard,sx,sy,ex,ey,testing,goscore)); else return HORLICKS; } else return (checkwords(newboard,sx,sy,ex,ey,testing,goscore)); } } } if (notvert && nothoriz) { /* one letter */ ex = sx; ey = sy; /* check for no extra letters */ checkx++; if (checkx == BOARDSIZE) { checkx = 0; checky++; } while ((checky < BOARDSIZE) && (!invalid)) { if ((board[checkx][checky] == ' ') && (newboard[checkx][checky] != ' ')) invalid = 1; /* go is invalid */ else { checkx++; if (checkx == BOARDSIZE) { checkx = 0; checky++; } } } if (invalid) return HORLICKS; else { /* check to see if there is at least one surrounding piece */ if (((sy > 0)&&(board[sx][sy-1]!=' '))|| ((sy < BOARDSIZE-1)&&(board[sx][sy+1]!=' '))|| ((sx > 0)&&(board[sx-1][sy]!=' '))|| ((sx < BOARDSIZE-1)&&(board[sx+1][sy]!=' '))) return (checkwords(newboard,sx,sy,ex,ey,testing,goscore)); else return HORLICKS; } } return HORLICKS; /* just in case */ } int checkwords(char nb[BOARDSIZE][BOARDSIZE],int sx,int sy,int ex,int ey,int testing,int *goscore) { int checkx,checky,lefttile,righttile,toptile,bottile; int indict,fillword; char checkword[16]; int correct = 1; int loneletter = 0; char wordsmade[BESTGOWORDSLEN] = ""; int wordpos = 0; /* initialise go score */ *goscore = 0; /* if first go check to see if it passes through centre */ if (emptyboard(board)) { /* if horizontal word */ if (ey-sy == 0) { if (!((sx <= 7) && (ex >= 7) && (sy == 7))) return NOTCENTRE; } else /* if vertical word */ { if (!((sy <= 7) && (ey >= 7) && (sx == 7))) return NOTCENTRE; } } /* check for horizontal word */ if (ey-sy == 0) { /* ####check left and right for complete word#### */ /* check left */ checkx = sx; while (((checkx-1) >= 0) && (board[checkx-1][sy] != ' ')) { checkx--; } lefttile = checkx; /* check right */ checkx = ex; while (((checkx+1) < BOARDSIZE) && (board[checkx+1][sy] != ' ')) { checkx++; } righttile = checkx; /* do not check if it is one letter */ if (!((lefttile == sx)&&(righttile == sx))) { /* construct word */ for (fillword=lefttile; fillword <= righttile; fillword++) { checkword[fillword-lefttile] = nb[fillword][sy]; } checkword[fillword-lefttile]='\0'; /* and check it */ convupper(checkword); if (!testing) indict = wordsearch(checkword); else indict = 1; correct = correct&&indict; if (indict) { *goscore += scoreword(lefttile,sy,righttile,sy,nb); if ((wordpos+strlen(checkword)+1)= 0) && (board[checkx][checky-1] != ' ')) { checky--; } toptile = checky; /* check down */ checky = sy; while (((checky+1) < BOARDSIZE) && (board[checkx][checky+1] != ' ')) { checky++; } bottile = checky; /* do not check if it is one letter */ if (!((toptile == sy)&&(bottile == sy))) { /* construct word */ for (fillword=toptile; fillword <= bottile; fillword++) { checkword[fillword-toptile] = nb[checkx][fillword]; } checkword[fillword-toptile]='\0'; /* and check it */ convupper(checkword); if (!testing) { indict = wordsearch(checkword); } else indict = 1; correct = correct&&indict; if (indict) { *goscore += scoreword(checkx,toptile,checkx,bottile,nb); if ((wordpos+strlen(checkword)+1)= 0) && (board[sx][checky-1] != ' ')) { checky--; } toptile = checky; /* check down */ checky = ey; while (((checky+1) < BOARDSIZE) && (board[sx][checky+1] != ' ')) { checky++; } bottile = checky; /* no need to check for lone letter, already checked */ /* construct word */ for (fillword=toptile; fillword <= bottile; fillword++) { checkword[fillword-toptile] = nb[sx][fillword]; } checkword[fillword-toptile]='\0'; /* and check it */ convupper(checkword); if (!testing) indict = wordsearch(checkword); else indict = 1; correct = correct && indict; if (indict) { *goscore += scoreword(sx,toptile,sx,bottile,nb); if ((wordpos+strlen(checkword)+1)= 0) && (board[checkx-1][checky] != ' ')) { checkx--; } lefttile = checkx; /* check right */ checkx = sx; while (((checkx+1) < BOARDSIZE) && (board[checkx+1][checky] != ' ')) { checkx++; } righttile = checkx; /* do not check if it is one letter */ if (!((lefttile == sx)&&(righttile == sx))) { /* construct word */ for (fillword=lefttile; fillword <= righttile; fillword++) { checkword[fillword-lefttile] = nb[fillword][checky]; } checkword[fillword-lefttile]='\0'; /* and check it */ convupper(checkword); if (!testing) indict = wordsearch(checkword); else indict = 1; correct = correct&&indict; if (indict) { *goscore += scoreword(lefttile,checky,righttile,checky,nb); if ((wordpos+strlen(checkword)+1)