/*      XLeScrabble
        misc.c
        various functions
        By csuos@warwick.ac.uk
*/

#include "scrab.h"
#include "globals.h"

void loaddict()
{
	FILE *fp;
	int count;
	int nextlen = 3;
	char sys[255];
	char unname[255] = "";

	fp = fopen(app_data.dictfile,"r");
	if (fp==NULL)
	{
	    sprintf(sys,"%s.gz",app_data.dictfile);
	    fp = fopen(sys,"r");
	    if (fp==NULL)
	    {
		fprintf(stderr,"Couldn't open dictionary %s or %s\n",
			app_data.dictfile,sys);
        	exit(1);
	    }

	    sprintf(unname,"/tmp/.ScrabDict%d",getpid());
	    sprintf(sys,"gzip -cd %s > %s",app_data.dictfile,unname);
	    system(sys);

	    fp = fopen(unname,"r");
	    if (fp==NULL)
	    {
		fprintf(stderr,"Error during unzip of dictionary\n");
        	exit(1);
	    }
	}

	/*printf("Loading dictionary...\n");	*/
	count = 0;
	word_pos[0] = count;
	while (!feof(fp))
	{
		fscanf(fp, "%s\n",dict[count]);
		if (strlen(dict[count]) == nextlen)
		{
			word_pos[nextlen-2] = count;
			/* word length borders = word length - 2 */
			nextlen++;
		}
		count++;
		if (count >= DICTSIZE)
		{
			fprintf(stderr,"dictionary exceeds maximum size.\n");
			exit(1);
		}
	}
	word_pos[nextlen-2] = count-1;
	fclose(fp);

	if (unname[0] != '\0')
	    unlink(unname);
}

void loadperms()
{
	FILE *fp;
	int perm,nperms,values;
	
	fp = fopen(app_data.permfile,"r");
	if (fp==NULL)
	{
		fprintf(stderr,"Couldn't open permutations file\n");
		exit(1);
	}
	/*printf("Loading permutations...\n");*/
	for (nperms = 0;nperms < 7;nperms++)
	{
		fscanf(fp,"%i\n",&numperms[nperms]);
	}
	for (perm = 0;perm < 7;perm++)
		for (nperms = 0; nperms < numperms[perm];nperms++)
		{
			for (values = 0; values < perm+1;values++)
			{
				perms[perm][nperms][values] = getc(fp);
			}
			fscanf(fp,"\n");
		}
	fclose(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\nEMPTY\n",bagptr);
		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");
	}
	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,"(empty)");
		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,"(empty)");
		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()
{
	/* set up letter frequency array */
	int freq[NUMLETTERS] =	LETTER_FREQUENCY_TABLE;
	/* start filling bag from 2nd position as blanks are first two */
	int fillbagptr = 2;
	int makeptr,letter;

	/* cycle through frequency table */
	for (makeptr = 0; makeptr < NUMLETTERS; makeptr++)
		/* place the correct number of each letter in the bag */
		for (letter=1; letter <= freq[makeptr]; letter++)
			{
				bag[fillbagptr++] = 'A'+makeptr;
			}
	/* finally inserts the blanks in the bag */
	bag[0]=bag[1]='*';	
}

void shufflebag()
{
	/* create a new bag into which the random letters will go */
	char newbag[BAGSIZE];
	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]-'A'];
		}
	}
	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';
}

void playersetup(char playername[MAXPLAYERS][NAMELEN])
{
	int playercount;

	/* fill player data into player structure */
	for (playercount = 0; playercount < num_players; playercount++)
		{
			strcpy(player[playercount].name,playername[playercount]);
			player[playercount].score=0;
			takeletters(BARLEN,player[playercount].bar);
		}
}

/* 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("Player %i :-\nName : %s\nScore : %i\nBar : %s\n\n",count+1,player[count].name,player[count].score,player[count].bar);
		}
}

/* end of debug routines */
