const char *_VERSION="\0$VER: Flut-Server! 4.0a (23.03.96)";

#include	<dos/dos.h>
#include	"Flut.h"

#define gamespfad	0
#define scorepfad	1
#define newsdatpfad	2
#define halldatpfad	3

void user_points(UBYTE anforder);
void killgame(UBYTE welches);
void hall_add(UBYTE art, UBYTE pos, UBYTE anforder);
void pointeradd(void);
void events(void);
void save_hall(void);
void load_hall(void);
void save_news(void);
void load_news(void);
void save_games(void);
void load_games(void);
void save_scores(void);
void load_scores(void);
void news_add(void);
void scores_add(void);
void make_path(byte pathnr);

struct allstruct *all;
struct tm*datum_zeit;

ULONG	today;

FILE	*fp;

char	path[4][17]={	"flut.games",	"flut.scores",	"flut.news",	"flut.hall1"},
		pathstart[108],
		pathwork[108],

		line_c[200],*p3,
		line_d[200],*p4;

int		wertung_a,wertung_b;

BPTR	lock;

UBYTE	x,y,i,j,k;

BOOL	off,hall_yes;

UBYTE	tasks;

main()
{
	if (flutport=CreatePort(FLUT_PORT,0))
	{
		if(all=(struct allstruct *)AllocVec(sizeof(struct allstruct),MEMF_PUBLIC|MEMF_CLEAR))
		{
			lock=GetProgramDir();
			NameFromLock(lock,pathstart,108);

			load_games();
			load_scores();
			load_news();
			load_hall();

			while(!off)
			{
				WaitPort(flutport);
				while(ptr=(struct messagestruct *)GetMsg(flutport))
				{
					if(off)
					{
						Permit();
						off=FALSE;
					}

					events();

					if(tasks==0)
					{
						off=TRUE;
						Forbid();
					}
				}
			}
			FreeVec(all);
		}
		DeletePort(flutport);
		Permit();
	}
}

void make_path(byte pathnr)
{
	strcpy(pathwork,pathstart);
	AddPart(pathwork,path[pathnr],108);
}

void pointeradd(void)
{
	if(all->pointer==9)
	{
		all->pointer=0;
	}
	else
	{
		all->pointer++;
	}
	ptr->pointer=all->pointer;
}

void killgame(UBYTE welches)
{
	for(j=0;j<all->game[welches].y_size;j++)
	{
		for(i=0;i<all->game[welches].x_size;i++)
		{
			all->game[welches].farbe[i][j]=0;
			all->game[welches].fuellgrad[i][j]=0;
		}
	}
	for(i=0;i<6;i++)
	{
		all->game[welches].player[i].userid=0;
	}
	all->game[welches].anzahl=0;
	all->game[welches].x_size=0;
	all->game[welches].y_size=0;
}

void events(void)
{
	switch (ptr->com)
	{
		case MSG_GAME:
			ptr->result=FALSE;
			if(ptr->game_neu<0)
			{
				ptr->result=TRUE;
			}
			else
			{
				if(ptr->game_neu>49)
				{
					if(!all->game[ptr->game_neu].belegt || all->olg[ptr->game_neu-50].joined>0)
					{
						ptr->result=TRUE;
						all->game[ptr->game_neu].belegt=TRUE;
						if(all->olg[ptr->game_neu-50].joined>0)
						{
							all->olg[ptr->game_neu-50].joined++;
							ptr->olgpointer=all->olg[ptr->game_neu-50].pointer;
						}
					}
				}
				else
				{
					if(!all->game[ptr->game_neu].belegt)
					{
						ptr->result=TRUE;
						all->game[ptr->game_neu].belegt=TRUE;
					}
				}
			}
			if(ptr->result)
			{
				if(ptr->game_alt>49)
				{
					if(all->olg[ptr->game_alt-50].joined>0)
					{
						all->olg[ptr->game_alt-50].joined--;
					}
					if(all->olg[ptr->game_alt-50].joined==0)
					{
						all->game[ptr->game_alt].belegt=FALSE;
						killgame(ptr->game_alt);
					}
				}
				else
				{
					all->game[ptr->game_alt].belegt=FALSE;
				}
			}
			break;
		case MSG_SCORES:
			scores_add();
			break;
		case MSG_INIT:
			ptr->all=all;
			tasks++;
			sprintf(all->mails[all->pointer],"%s joined Flut!",ptr->pname);
			pointeradd();
			break;
		case MSG_QUIT:
			tasks--;

			if(tasks==0)
			{
				save_games();
				save_scores();
				save_news();
				save_hall();
			}
			else
			{
				if(ptr->timeleft==0)
				{
					sprintf(all->mails[all->pointer],"%s left the BBS because of CARRIER/TIME!",ptr->pname);
				}
				else
				{
					sprintf(all->mails[all->pointer],"%s left Flut!",ptr->pname);
				}
				pointeradd();
			}
			break;
		case MSG_MESS:
			sprintf(all->mails[all->pointer],"%s: %s",ptr->pname,ptr->mess);
			pointeradd();
			break;
	}
	ReplyMsg(ptr);
}

void save_hall(void)
{
	for(i=0;i<2;i++)
	{
		path[halldatpfad][9]=i+49;
		make_path(halldatpfad);
		if(fp=fopen(pathwork,"w"))
		{
			for(j=0;j<10;j++)
			{
				fputs(all->fame.hall[i][j],fp);
			}
			fclose(fp);
		}
	}
}

void load_hall(void)
{
	for(i=0;i<2;i++)
	{
		path[halldatpfad][9]=i+49;

		j=0;
		make_path(halldatpfad);
		if(fp=fopen(pathwork,"r"))
		{
			while (fgets(all->fame.hall[i][j],sizeof(all->fame.hall[i][0]),fp))
			{
				j++;
			}
			fclose(fp);
		}
	}
}

void save_news(void)
{
	make_path(newsdatpfad);
	if(fp=fopen(pathwork,"w"))
	{
		for(j=0;j<15;j++)
		{
			fputs(all->fame.news[j],fp);
		}
		fclose(fp);
	}
}

void load_news(void)
{
	i=0;
	make_path(newsdatpfad);
	if(fp=fopen(pathwork,"r"))
	{
		while (fgets(all->fame.news[i],sizeof(all->fame.news[0]),fp))
		{
			i++;
		}
		fclose(fp);
	}
}

void save_games(void)
{
	make_path(gamespfad);
	if (fp=fopen(pathwork,"w"))
	{
		for(x=0;x<50;x++)
		{
			if(all->game[x].anzahl>0)
			{
				sprintf(line_c,"%d;%2.2d*%2.2d;%d;%d\n",all->game[x].anzahl,all->game[x].x_size,all->game[x].y_size,all->game[x].status,all->game[x].border);
				fputs(line_c,fp);

				k=0;
				for(j=0;j<all->game[x].y_size;j++)
				{
					for(i=0;i<all->game[x].x_size;i++)
					{
						line_c[k]=all->game[x].farbe[i][j]+48;
						line_d[k]=all->game[x].fuellgrad[i][j]+48;
						k++;
					}
				}
				line_c[k]=10;
				line_d[k]=10;
				line_c[k+1]=0;
				line_d[k+1]=0;

				fputs(line_c,fp);
				fputs(line_d,fp);

				for(y=0;y<all->game[x].anzahl;y++)
				{
					sprintf(line_c,"%9.9d%c\n",all->game[x].player[y].userid,all->game[x].player[y].last_wall_lese);
					fputs(line_c,fp);
					sprintf(line_c,"%10.10d\n",all->game[x].player[y].last_move);
					fputs(line_c,fp);
				}
			}
			else
			{
				strcpy(line_c,"0\n");
				fputs(line_c,fp);
			}
		}
		fclose(fp);
	}
}


void load_games(void)
{
	x=0;
	make_path(gamespfad);
	if (fp=fopen(pathwork,"r"))
	{
		while (fgets(line_c,sizeof(line_c),fp))
		{
			all->game[x].anzahl=line_c[0]-48;
			if(all->game[x].anzahl>0)
			{
				all->game[x].x_size=atoi(line_c + 2);
				all->game[x].y_size=atoi(line_c + 5);
				all->game[x].status=atoi(line_c + 8);
				all->game[x].border=atoi(line_c + 10);
				fgets(line_c,sizeof(line_c),fp);
				fgets(line_d,sizeof(line_d),fp);
				k=0;
				for(j=0;j<all->game[x].y_size;j++)
				{
					for(i=0;i<all->game[x].x_size;i++)
					{
						all->game[x].farbe[i][j]=line_c[k]-48;
						all->game[x].fuellgrad[i][j]=line_d[k]-48;
						k++;
					}
				}
				y=0;
				while(y<all->game[x].anzahl)
				{
					fgets(line_c,sizeof(line_c),fp);
					all->game[x].player[y].userid=atoi(line_c);
					all->game[x].player[y].last_wall_lese=line_c[9];
					fgets(line_c,sizeof(line_c),fp);
					all->game[x].player[y].last_move=atol(line_c);
					y++;
				}
			}
			x++;
		}
		fclose(fp);
	}
}

void save_scores(void)
{
	make_path(scorepfad);
	if (fp=fopen(pathwork,"w"))
	{
		x=0;
		while(all->user[x].userid!=0)
		{
			if(all->user[x].points[0]<0)
			{
				sprintf(line_c,"%9.9d#%4.4d#%d\n",all->user[x].userid,all->user[x].points[0],all->user[x].points[1]);
			}
			else
			{
				sprintf(line_c,"%9.9d#%5.5d#%d\n",all->user[x].userid,all->user[x].points[0],all->user[x].points[1]);
			}
			fputs(line_c,fp);
			x++;
		}
		fclose(fp);
	}
}


void load_scores(void)
{
	make_path(scorepfad);
	if (fp=fopen(pathwork,"r"))
	{
		x=0;
		while (fgets(line_c,sizeof(line_c),fp))
		{
			all->user[x].userid=atoi(line_c);
			all->user[x].points[0]=atoi(line_c+10);
			all->user[x].points[1]=atoi(line_c+16);
			x++;
		}
		fclose(fp);
	}
}

void hall_add(UBYTE art, UBYTE pos, UBYTE anforder)
{
	datum_zeit=localtime(&today);
	strftime(line_c,10,"%d-%b-%y",datum_zeit);
	for(x=9;x>0;x--)
	{
		strcpy(all->fame.hall[art][x],all->fame.hall[art][x-1]);
	}
	sprintf(all->fame.hall[art][0],"[%dC%s %s\n",pos,line_c,ptr->name[anforder]);
}

void news_add(void)
{
	datum_zeit=localtime(&today);
	strftime(line_c,10,"%d-%b-%y",datum_zeit);
	for(x=14;x>0;x--)
	{
		strcpy(all->fame.news[x],all->fame.news[x-1]);
	}
	if(ptr->game_neu>49)
	{
		sprintf(all->fame.news[0],"C3%s  OLG ---/--- C%1x%-8.8s C%1x%-8.8s C%1x%-8.8s C%1x%-8.8s C%1x%-8.8s C%1x%-8.8s\n",line_c,ptr->status[0],ptr->name[0],ptr->status[1],ptr->name[1],ptr->status[2],ptr->name[2],ptr->status[3],ptr->name[3],ptr->status[4],ptr->name[4],ptr->status[5],ptr->name[5]);
	}
	else
	{
		sprintf(all->fame.news[0],"C3%s   %2.2d %3.3d/%2.2d C%1x%-8.8s C%1x%-8.8s C%1x%-8.8s C%1x%-8.8s C%1x%-8.8s C%1x%-8.8s\n",line_c,ptr->game_neu+1,wertung_a,wertung_b,ptr->status[0],ptr->name[0],ptr->status[1],ptr->name[1],ptr->status[2],ptr->name[2],ptr->status[3],ptr->name[3],ptr->status[4],ptr->name[4],ptr->status[5],ptr->name[5]);
	}
}

void user_points(UBYTE anforder)
{
	x=0;
	while(all->user[x].userid!=all->game[ptr->game_neu].player[anforder].userid && all->user[x].userid!=0)
	{
		x++;
	}
	all->user[x].userid=all->game[ptr->game_neu].player[anforder].userid;

	if(ptr->status[anforder]==1)
	{
		all->user[x].points[0]+=wertung_a;
	}
	if(ptr->status[anforder]==2)
	{
		all->user[x].points[0]+=wertung_b;
	}
	if(anforder==ptr->akt_user-1)
	{
		if(ptr->game_neu>49)
		{
			all->user[x].points[1]+=ptr->punkte;
		}
		else
		{
			all->user[x].points[0]+=ptr->punkte;
		}
	}

	if(all->user[x].points[0] > 999)
	{
		hall_add(0,7,anforder);
		hall_yes=TRUE;
	}
	if(all->user[x].points[1] > 999)
	{
		hall_add(1,43,anforder);
		hall_yes=TRUE;
	}
}

void scores_add(void)
{
	ptr->result=FALSE;
	if(ptr->game_neu>49)
	{
		for(y=0;y<all->game[ptr->game_neu].anzahl;y++)
		{
			ptr->all->olg[ptr->game_neu-50].status[y]=ptr->status[y];
		}
	}

	time(&today);

	hall_yes=FALSE;

	if(ptr->game_neu>49)
	{
		wertung_a=0;
		wertung_b=0;
	}
	else
	{
		wertung_a=all->game[ptr->game_neu].x_size*ptr->all->game[ptr->game_neu].y_size*ptr->all->game[ptr->game_neu].anzahl/6;
		wertung_b=all->game[ptr->game_neu].x_size*ptr->all->game[ptr->game_neu].y_size/(-6);
	}

	if(ptr->status[y]==0)
	{
		user_points(ptr->akt_user-1);
	}
	else
	{
		for(y=0;y<all->game[ptr->game_neu].anzahl;y++)
		{
			user_points(y);
		}
	}

	if(ptr->status[0]>0)
	{
		news_add();
	}

	if(hall_yes)
	{
		i=0;
		j=0;
		while(all->user[j].userid>0)
		{
			if(ptr->game_neu>49)
			{
				all->user[j].points[1]=0;
			}
			else
			{
				all->user[j].points[0]=0;
			}

			if(all->user[j].points[0]==0 && all->user[j].points[1]==0)
			{
				all->user[j].userid=0;
			}

			if(all->user[i].userid==0 && all->user[j].userid!=0)
			{
				all->user[i].userid=all->user[j].userid;
				all->user[i].points[0]=all->user[j].points[0];
				all->user[i].points[1]=all->user[j].points[1];
				all->user[j].userid=0;
				all->user[j].points[0]=0;
				all->user[j].points[1]=0;
			}

			if(all->user[i].userid!=0)
			{
				i++;
			}

			j++;
		}
		ptr->result=TRUE;
	}
	else
	{
		ptr->result=FALSE;
	}
}
