/* XScrabble misc.c various functions By csuos@warwick.ac.uk */ #include "scrab.h" #include "globals.h" #include "zlib.h" #include "bzlib.h" /* set up letter frequency array */ extern int freq[NUMCHAR_MAX]; void loaddict() { void *fp; int n; int mode; int count; int nextlen = 3; int error; char buf[256]; char *ptr; fp = (void *)fopen(app_data.dictfile,"r"); mode = 0; if (fp==NULL) { sprintf(buf,"%s.gz",app_data.dictfile); fp = (void *)gzopen(buf,"r"); mode = 1; } if (fp==NULL) { sprintf(buf,"%s.bz2",app_data.dictfile); fp = (void *)BZ2_bzopen(buf,"r"); mode = 2; } if (fp==NULL) { fprintf(stderr,"Couldn't open dictionary %s or %s.\n", app_data.dictfile, app_data.dictfile); exit(1); } /*printf("Loading dictionary...\n"); */ count = 0; word_pos[0] = count; dict = NULL; readstuff: if (mode==0) { ptr = fgets(buf, 20, (FILE *)fp); buf[19] = '\0'; n = strlen(buf); if (buf[n-1]=='\n') { --n; buf[n] = '\0'; } } else if (mode==1) { ptr = gzgets((gzFile *)fp, buf, 20); buf[19] = '\0'; n = strlen(buf); if (buf[n-1]=='\n') { --n; buf[n] = '\0'; } } else if (mode==2) { n = 0; while(ptr=(char *)BZ2_bzRead(&error, (BZFILE *)fp, buf+n, 1)) { if (buf[n]=='\n' || n>=19) break; n++; } buf[n] = '\0'; if (!ptr && n>0) ptr = (char *)1; } if (!ptr) goto terminate; if (isspace(*buf)) goto readstuff; dict = (char **)realloc(dict, (count+1)*sizeof(char *)); if (!dict) { fprintf(stderr,"Memory allocation error.\n"); exit(1); } dict[count] = strdup(buf); if (!dict[count]) { fprintf(stderr,"Memory allocation error.\n"); exit(1); } if (n == nextlen) { word_pos[nextlen-2] = count; /* word length borders = word length - 2 */ nextlen++; } count++; goto readstuff; terminate: word_pos[nextlen-2] = count-1; if (mode==0) fclose((FILE *)fp); if (mode==1) gzclose((gzFile *)fp); if (mode==2) BZ2_bzclose((BZFILE *)fp); } void savegame() { FILE *fp; char homedir[MAXPATHLEN]; char fullpath[MAXPATHLEN]; int sx,sy,np,cn; int checksum = 0; strcpy(homedir,getenv("HOME")); strcpy(&fullpath[0],homedir); strcat(fullpath,SAVENAME); fp = fopen(fullpath,"w"); if (fp==NULL) { fprintf(stderr,"Couldn't save position to file : %s",fullpath); } else { for (sx = 0;sx < BOARDSIZE; sx++) for (sy = 0;sy < BOARDSIZE; sy++) { fprintf(fp,"%c",board[sx][sy]); checksum+=board[sx][sy]*sx*sy; } fprintf(fp,"\n"); fprintf(fp,"%i\n",num_players); checksum+=num_players; for (np = 0;np < num_players;np++) { fprintf(fp,"%i\n%s\n%s\n%i\n",player[np].score, player[np].name,player[np].bar, type[np]); for(cn=0;player[np].name[cn] != '\0';cn++) checksum+=player[np].name[cn]*cn; for(cn=0;player[np].bar[cn] != '\0';cn++) checksum+=player[np].bar[cn]*cn; checksum+=player[np].score*np; checksum+=type[np]*np; } if (bagptr == -1) /* if bag is empty */ fprintf(fp,"%i\n%s\n",bagptr,PROMPT[EMPTY]); else fprintf(fp,"%i\n%s\n",bagptr,bag); checksum+=bagptr; if (bagptr > -1) for(cn=0;bag[cn]!= '\0';cn++) checksum+=bag[cn]; fprintf(fp,"%i\n",num_passed); checksum+=num_passed; fprintf(fp,"%i\n",curr_player); checksum+=curr_player; fprintf(fp,"%i\n",checksum%MAGNUM); fclose(fp); } } void loadgame() { FILE *fp; char homedir[MAXPATHLEN]; char fullpath[MAXPATHLEN]; int sx,sy,np,cn; int checksum = 0; int filechecksum; strcpy(homedir,getenv("HOME")); strcpy(&fullpath[0],homedir); strcat(fullpath,SAVENAME); fp = fopen(fullpath,"r"); if (fp==NULL) { fprintf(stderr,"Couldn't find save position file : %s",fullpath); } else { for (sx = 0;sx < BOARDSIZE; sx++) for (sy = 0;sy < BOARDSIZE; sy++) { fscanf(fp,"%c",&board[sx][sy]); checksum+=board[sx][sy]*sx*sy; cboard[sx][sy]=board[sx][sy]; } fscanf(fp,"\n"); fscanf(fp,"%i\n",&num_players); checksum+=num_players; for (np = 0;np < num_players;np++) { fscanf(fp,"%i\n%[^\n]\n%[^\n]\n%i\n",&player[np].score, player[np].name,player[np].bar, &type[np]); for(cn=0;player[np].name[cn] != '\0';cn++) checksum+=player[np].name[cn]*cn; for(cn=0;player[np].bar[cn] != '\0';cn++) checksum+=player[np].bar[cn]*cn; checksum+=player[np].score*np; checksum+=type[np]*np; } fscanf(fp,"%i\n%[^\n]\n",&bagptr,bag); checksum+=bagptr; if (bagptr > -1) for(cn=0;bag[cn]!= '\0';cn++) checksum+=bag[cn]; fscanf(fp,"%i\n",&num_passed); checksum+=num_passed; fscanf(fp,"%i\n",&curr_player); checksum+=curr_player; fscanf(fp,"%i\n",&filechecksum); fclose(fp); checksum=checksum%MAGNUM; if (checksum != filechecksum) { fprintf(stderr,"Checksum error in save file."); exit(1); } } } void savescores() { FILE *fp; int nplayers,numscores,cgoscores; fp = fopen(app_data.scorefile,"w"); if (fp==NULL) { fprintf(stderr,"Couldn't save high scores to file\n"); } else { for (nplayers = 0;nplayers < 4;nplayers++) for (numscores = 0;numscores < NUMHIGHSCORES;numscores++) { fprintf(fp,"%s\n",highscores[nplayers][numscores].name); fprintf(fp,"%i\n",highscores[nplayers][numscores].score); fprintf(fp,"%li\n",highscores[nplayers][numscores].date); } for (cgoscores = 0;cgoscores < NUMGOSCORES; cgoscores++) { fprintf(fp,"%s\n",bestgos[cgoscores].name); fprintf(fp,"%i\n",bestgos[cgoscores].score); fprintf(fp,"%li\n",bestgos[cgoscores].date); fprintf(fp,"%s\n",bestgos[cgoscores].words); } fclose(fp); } } void loadscores() { FILE *fp; int nplayers,numscores,cgoscores; fp = fopen(app_data.scorefile,"r"); if (fp==NULL) { fprintf(stderr,"Couldn't open high scores to file\n"); fprintf(stderr,"%s\n",app_data.scorefile); } else { for (nplayers = 0;nplayers < 4;nplayers++) for (numscores = 0;numscores < NUMHIGHSCORES;numscores++) { fscanf(fp,"%[^\n]\n",highscores[nplayers][numscores].name); fscanf(fp,"%i\n",&highscores[nplayers][numscores].score); fscanf(fp,"%li\n",&highscores[nplayers][numscores].date); } for (cgoscores = 0;cgoscores < NUMGOSCORES; cgoscores++) { fscanf(fp,"%[^\n]\n",bestgos[cgoscores].name); fscanf(fp,"%i\n",&bestgos[cgoscores].score); fscanf(fp,"%li\n",&bestgos[cgoscores].date); fscanf(fp,"%[^\n]\n",bestgos[cgoscores].words); } fclose(fp); } } void alterscores() { int playercount,checkhi,placed; int slip; time_t t; for (playercount = 0; playercount < num_players;playercount++) { if (type[playercount] > 0) continue; placed = 0; checkhi = 0; while ((checkhi < NUMHIGHSCORES)&&(!placed)) { if (highscores[num_players-1][checkhi].score < player[playercount].score) { placed = 1; slip = NUMHIGHSCORES-1; while (slip > checkhi) { highscores[num_players-1][slip].score = highscores[num_players-1][slip-1].score; strcpy(highscores[num_players-1][slip].name, highscores[num_players-1][slip-1].name); highscores[num_players-1][slip].date = highscores[num_players-1][slip-1].date; slip--; } highscores[num_players-1][checkhi].score = player[playercount].score; strcpy(highscores[num_players-1][checkhi].name, player[playercount].name); t = time((time_t *)NULL); highscores[num_players-1][checkhi].date = t; } checkhi++; } } } void alterbestgo(int goscore,char *wordsmade) { int placed,checkhi,slip; time_t t; if ((num_players == 1)||(type[curr_player] > 0)) return; placed = 0; checkhi = 0; while ((checkhi < NUMGOSCORES)&&(!placed)) { if (bestgos[checkhi].score < goscore) { placed = 1; slip = NUMGOSCORES-1; while (slip > checkhi) { bestgos[slip].score = bestgos[slip-1].score; strcpy(bestgos[slip].name, bestgos[slip-1].name); bestgos[slip].date = bestgos[slip-1].date; strcpy(bestgos[slip].words, bestgos[slip-1].words); slip--; } bestgos[checkhi].score = goscore; strcpy(bestgos[checkhi].name, player[curr_player].name); t = time((time_t *)NULL); bestgos[checkhi].date = t; strcpy(bestgos[checkhi].words, wordsmade); } checkhi++; } if (placed) { savescores(); UpdateBestgo(); } } void showscores(int numplay,char outstring[256]) { int hicount,rep; char histr[80]; char timestr[80]; outstring[0] = '\0'; for (hicount = 0;hicount < NUMHIGHSCORES;hicount++) { strcat(outstring,highscores[numplay-1][hicount].name); sprintf(histr,"%i",highscores[numplay-1][hicount].score); for (rep=0; rep<(int)(16-strlen(highscores[numplay-1][hicount].name)-strlen(histr)); rep++) strcat(outstring,"."); strcat(outstring,histr); timestr[0]='\0'; if (highscores[numplay-1][hicount].date == 0) strcpy(timestr,PROMPT[EMPTY_PAR]); else sprintf(timestr,"%.24s",ctime(&highscores[numplay-1][hicount].date)); for (rep=0; rep<(int)(26-strlen(timestr));rep++) strcat(outstring,"."); strcat(outstring,timestr); if (hicount < NUMHIGHSCORES-1) strcat(outstring,"\n"); } } void showgoscores(char *outstring) { int hicount,rep; char histr[80]; char timestr[80]; outstring[0] = '\0'; for (hicount = 0;hicount < NUMGOSCORES;hicount++) { strcat(outstring,bestgos[hicount].name); sprintf(histr,"%i",bestgos[hicount].score); for (rep=0; rep<(int)(16-strlen(bestgos[hicount].name)-strlen(histr)); rep++) strcat(outstring,"."); strcat(outstring,histr); timestr[0]='\0'; if (bestgos[hicount].date == 0) strcpy(timestr,PROMPT[EMPTY_PAR]); else sprintf(timestr,"%.24s",ctime(&bestgos[hicount].date)); for (rep=0; rep<(int)(26-strlen(timestr));rep++) strcat(outstring,"."); strcat(outstring,timestr); for (rep=0; rep<(int)(35-strlen(bestgos[hicount].words));rep++) strcat(outstring,"."); strcat(outstring," "); strcat(outstring,bestgos[hicount].words); if (hicount < NUMGOSCORES-1) strcat(outstring,"\n"); } } unsigned int wordsearch(char *word) { int start,end; int found = 0; int compare,wordlength; int lastmid = -1; int middle = -2; wordlength=strlen(word); if (wordlength < 2) return found; switch(wordlength) { case 2 : { start = word_pos[0] ; end = word_pos[1] ; break; } case 3 : { start = word_pos[1] ; end = word_pos[2] ; break; } case 4 : { start = word_pos[2] ; end = word_pos[3] ; break; } case 5 : { start = word_pos[3] ; end = word_pos[4] ; break; } case 6 : { start = word_pos[4] ; end = word_pos[5] ; break; } case 7 : { start = word_pos[5] ; end = word_pos[6] ; break; } case 8 : { start = word_pos[6] ; end = word_pos[7] ; break; } case 9 : { start = word_pos[7] ; end = word_pos[8] ; break; } case 10 : { start = word_pos[8] ; end = word_pos[9] ; break; } case 11 : { start = word_pos[9] ; end = word_pos[10] ; break; } case 12 : { start = word_pos[10] ; end = word_pos[11] ; break; } case 13 : { start = word_pos[11] ; end = word_pos[12] ; break; } case 14 : { start = word_pos[12] ; end = word_pos[13] ; break; } default : { start = word_pos[13] ; end = word_pos[14]+1 ; break; } } while ((lastmid != middle) && (!found)) { lastmid = middle; middle = ((end - start)/2)+start; compare = strcmp(word,dict[middle]); if (!compare) found = 1; else if (compare > 0) { start = middle; } else end = middle; } return found; } void clearboard(char b[BOARDSIZE][BOARDSIZE]) { int x,y; /* place blank spaces in board */ for(y=0; y < BOARDSIZE; y++) for(x=0; x < BOARDSIZE; x++) b[x][y]=' '; } void makebag() { int fillbagptr = 0, posf=0, poss=0; int ind, i, ls, fq; NUMBLANKS=(strlen(PROMPT[BLANKTILES])+1)/2; for (ind = 0; ind <= NUMBLANKS; ind++) { blanktiles[ind]=PROMPT[BLANKTILES][2*ind]; } NUMLETTERS=(strlen(PROMPT[LETTERSEQ])-1)/2; for (ind = 0; ind <= NUMLETTERS; ind++) { letterchar[ind] = PROMPT[LETTERSEQ][2*ind]; fq = 0; while ((PROMPT[FREQSEQ][posf]>='0') && (PROMPT[FREQSEQ][posf]<='9')) { fq = 10*fq + PROMPT[FREQSEQ][posf] - '0'; posf++; } posf++; ls = 0; while ((PROMPT[SCORESEQ][poss]>='0') && (PROMPT[SCORESEQ][poss]<='9')) { ls = 10*ls+PROMPT[SCORESEQ][poss]-'0'; poss++; } poss++; freq[letterchar[ind]] = fq; letterscore[letterchar[ind]] = ls; /* place the correct number of each letter in the bag */ for (i=1; i <= fq; i++) { bag[fillbagptr++] = letterchar[ind]; } } bagptr=fillbagptr-1; } void shufflebag() { /* create a new bag into which the random letters will go */ char newbag[BAGSIZE_MAX]; int shuffleptr,currentlett; int newbagptr= 0; /* generate new random number sequence based on the time */ srand((unsigned int)time((time_t *)NULL)); /* take all but one of the letters one at a time */ for (shuffleptr=(bagptr+1); shuffleptr > 1; shuffleptr--) { /* pick a random letter from the old bag */ currentlett = rand()%shuffleptr; /* put it in the new bag */ newbag[newbagptr++] = bag[currentlett]; /* fill its gap with the last letter in the bag */ bag[currentlett] = bag[shuffleptr-1]; } /* put the last letter in the new bag */ newbag[newbagptr]=bag[0]; /* put all the random letters bag in the old bag */ for (shuffleptr=0; shuffleptr < (bagptr+1); shuffleptr++) bag[shuffleptr] = newbag[shuffleptr]; } void addtobag(char *letts) { /* routine for adjusting bag when letters are changed */ strcat(bag,letts); bagptr += strlen(letts); shufflebag(); } void fillbar(int playernum) { int bn; for (bn=0; bn < BARLEN; bn++) { if (player[playernum].bar[bn] == ' ') { if (bagptr != -1) player[playernum].bar[bn] = bag[bagptr--]; } } bag[bagptr+1] = '\0'; } int bartotal(int playernum) { int bcount,total = 0; for (bcount = 0;bcount < BARLEN; bcount++) { if (isupper(player[playernum].bar[bcount])) { total+=letterscore[player[playernum].bar[bcount]]; } } return total; } void takeletters(int numletters,char *letters) { int count; /* take a number of letters from the front of the bag */ for (count=0; count < numletters; count++) letters[count]=bag[bagptr--]; bag[bagptr+1] = '\0'; } /* debug routines */ void showbag() { int check; /* show the bag */ for(check=0; check < bagptr+1; check++) printf("%c",bag[check]); printf("\n"); } void showboard(char b[BOARDSIZE][BOARDSIZE]) { int x,y; /* show the board */ printf("-----------------\n"); printf("|"); for(y=0; y < BOARDSIZE; y++) for(x=0; x < BOARDSIZE; x++) { printf("%c",b[x][y]); if ((x == BOARDSIZE-1)&& (y != BOARDSIZE-1)) printf("|\n|"); else if (x == BOARDSIZE-1) printf("|\n"); } printf("-----------------\n"); } void showstats() { int count; /* display player data */ for (count=0; count < num_players; count++) { printf("%s %i :-\n%s : %s\n%s : %i\n%s : %s\n\n",PROMPT[PLAYER],count+1,PROMPT[NAME],player[count].name,PROMPT[SCORE],player[count].score,PROMPT[BAR],player[count].bar); } } /* end of debug routines */