#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>
#include "wf.h"

#define WORMS 0
#define TEAMS 1
#define FULL 0
#define SEL 1
#define AVG 0
#define WINS 1

#ifdef __GO32
unsigned char *scr = (unsigned char *)0xe00a0000;
#define far
#else
unsigned char far *scr = (unsigned char far *)0xa0000000;
#define outportb outp
#endif

extern unsigned char big[];
extern unsigned char bar[];
extern unsigned char fnt[];
extern unsigned char pall[];
extern unsigned char sfont[];

void setup_screen (void);
int get_key (void);
void display (void);
void un_print (int y);
void load_graphics (void);
unsigned char font [80][9][9];
void load_font (void);
long readchar (int c, long ind);
void load_rankings(void);
void ch_mode (int i);
void pstring (int x, int y, char *st);
void sprint (int x, int y, char *st);
unsigned char blogo [161][320];

char wr[64][40];		       /* Worm rank strings */
char tr[2][16][40];		       /* Team rank strings */
static int max[2][2]={0,0,0,0};
static int pos[2]={0, 0};
int fmode=SEL;
int mode=WORMS;
int smode=AVG;

main()
{
    int key;
    int i;
    static char th[2][40]={
	"TEAM       P   W   F   A   D AVG",
	"TEAM       P   W   F   A   D W/P"};
    FILE *fp;
    
    load_font();
    load_rankings();
    ch_mode (0x13);
    load_graphics();
    setup_screen();
    key = -1;
    max[WORMS][FULL]=64;
    max[TEAMS][FULL]=16;
    pstring (0, 6, "   NAME             TEAM     PTS");
    display ();
    while (key != 27 && key != 'q' && key != 'Q' && key != 256+45)
    {
	key = get_key();
	if (key == 256+'H')
	{
	    if (pos[mode])
	    {
		pos[mode]--;
		display();
	    }
	}
	if (key == 256+'P')
	{
	    if (pos[mode]+10 < max[mode][fmode])
	    {
		pos[mode]++;
		display();
	    }
	}
	if (key == 256+73)
	{
	    if (pos[mode])
	    {
		pos[mode]-=10;
		if (pos[mode]<0)
		    pos[mode]=0;
		display();
	    }
	}
	if (key == 256+81)
	{
	    if (pos[mode]+10 < max[mode][fmode])
	    {
		for (i = 0; i < 10; i++)
		    un_print (i*13+25);
		pos[mode]+=10;
		if (pos[mode]+10 > max[mode][fmode])
		    pos[mode]=max[mode][fmode]-10;
		display();
	    }
	}
	if ((key == 'T' || key == 't') && mode==WORMS)
	{
	    un_print (6);
	    pstring (0, 6, th[smode]);
	    mode = TEAMS;
	    for (i = 0; i < 10; i++)
		un_print (i*13+25);
	    display();
	}
	if (key == 'P' || key == 'p')
	{
	    fp = fopen ("print.dat", "w");
            fprintf (fp, "   NAME             TEAM     PTS\n\n");
	    for (i = 0; i < max[WORMS][fmode]; i++)
		fprintf (fp, "%s\n", wr[i]);
	    fprintf (fp, "\n%s\n\n", th[smode]);
	    for (i = 0; i < max[TEAMS][fmode]; i++)
		fprintf (fp, "%s\n", tr[smode][i]);
	    fclose (fp);
	}
	if ((key == 'S' || key == 's') && mode==TEAMS)
	{
	    smode=1-smode;
	    un_print (6);
	    pstring (0, 6, th[smode]);
	    display();
	}
	if ((key == 'W' || key == 'w') && mode==TEAMS)
	{
	    un_print (6);
	    pstring (0, 6, "   NAME             TEAM     PTS");
	    mode = WORMS;
	    for (i = 0; i < 10; i++)
		un_print (i*13+25);
	    display();
	}
	if (key == 'F' || key == 'f')
	{
	    fmode=1-fmode;
	    if (pos[0]+10 > max[0][fmode])
		pos[0]=max[0][fmode]-10;
	    if (pos[0]<0)
		pos[0]=0;
	    if (pos[1]+10 > max[1][fmode])
		pos[1]=max[1][fmode]-10;
	    if (pos[1]<0)
		pos[1]=0;
	    if (mode==WORMS)
	    {
		un_print (6);
		pstring (0, 6, "   NAME             TEAM     PTS");
		mode = WORMS;
		for (i = 0; i < 10; i++)
		    un_print (i*13+25);
		display();
	    }
	    else
	    {
		un_print (6);
		pstring (0, 6, th[smode]);
		mode = TEAMS;
		for (i = 0; i < 10; i++)
		    un_print (i*13+25);
		display();
	    }
	}
    }
    ch_mode (2);
}

int get_key (void)
{
    union REGS regs;
    
    regs.h.ah = 0;
    int86 (0x16, &regs, &regs);
    if (!regs.h.al)
	return (regs.h.ah==3 ? 0 : regs.h.ah+256);
    else
	return regs.h.al;
}
    
void setup_screen(void)
{
    long i, j;
    unsigned char far *o, *s;
    memcpy (scr, blogo[0], sizeof (blogo));
    memcpy (scr+51520, bar, sizeof (bar));
    sprint (158, 171, "F: FULL MODE      S: SORT METHOD");
    sprint (158, 178, "T: TEAM LEAGUE  W: WORM RANKINGS");
    sprint (158, 185, "ARROWS/PGUP/PGDN: SCROLL LISTING");
    sprint (158, 192, "P: PRINT TO FILE         Q: QUIT");
}

void load_graphics (void)
{
    unsigned int i, j;
    unsigned char *buffer;
    long ind;
    
    ind=0;
    for (i = 0; i < 256; i++)
    {
	outportb (0x3c8, i);
	for (j = 0; j < 3; j++)
	    outportb (0x3c9, pall[i*3+j]/4);
    }
    
    buffer = malloc (287*161);
    
    for (i = 0; i < sizeof (big); i++)
    {
	if (big[i] != 10)
	    buffer[ind++]=big[i];
	else
	{
	    i++;
	    for (j = ind; j < ind+big[i]; j++)
		buffer[j]=10;
	    ind=j;
	}
    }   
    
    for (i = 0; i < 161; i++)
    {
	memset (blogo[i], 0, 320);
	memcpy (blogo[i]+16, buffer+i*287, 287);
    }
    free (buffer);
}

void display (void)
{
    int i;
    for (i = 0; i < 10; i++)
	if (i+pos[mode] < max[mode][fmode])
	    pstring (0, i*13+25,
		     (mode==WORMS ? wr[i+pos[mode]] : tr [smode][i+pos[mode]]));
}
    
void un_print (int y)
{
    memcpy (scr+(unsigned)y*320, blogo[y], 3200);
}

void ch_mode (int i)
{
    union REGS regs;
    
    regs.h.ah=0;
    regs.h.al=i;
    int86 (0x10, &regs, &regs);
}

void load_rankings(void)
{
    static struct worm {
	char name[20];
	long pf, pa, po;
    }worms[64];
    
    static struct team {
	char name[20];
	int p, w, f, a, d, av, wp;
	unsigned int point;
    }teams[16];
    
    FILE *fp;
    static unsigned char buffer[4204];
    int i, j, k, t, order[64];
    int off;
    int tm=0;			       /* #teams */
    int wm=0;			       /* #worms */
    
    fp = fopen ("worms.cfg", "rb");
    if (fp == NULL)
    {
	printf ("Can't find worms.cfg!\n");
	exit (1);
    }
    
    fread (buffer, 4204, 1, fp);
    fclose (fp);
    
    for (i = 0; i < 16; i++)
    {
	strcpy (teams[i].name, buffer+i*0xaa);
	teams[i].name[9]=0;
	teams[i].p = buffer[0xde8+i*24]+255*buffer[0xde9+i*24];
	teams[i].w = buffer[0xdec+i*24]+255*buffer[0xded+i*24];
	teams[i].f = buffer[0xdf4+i*24]+255*buffer[0xdf5+i*24];
	teams[i].a = buffer[0xdf8+i*24]+255*buffer[0xdf9+i*24];
	teams[i].d = teams[i].f-teams[i].a;
	if (teams[i].p)
	    teams[i].wp = (teams[i].w*100)/teams[i].p;
	else 
	    teams[i].wp = 0;
    }
    for (i = 0; i < 64; i++)
    {
	off = (i/4)*170;
	strcpy (worms[i].name, buffer+off+18+18*(i%4));
	worms[i].pf = buffer[off+94+4*(i%4)]+256*buffer[off+95+4*(i%4)];
	worms[i].pa = buffer[off+154+4*(i%4)]+256*buffer[off+155+4*(i%4)];
	if (worms[i].pa != 0)
	    worms[i].po = (1000*worms[i].pf)/worms[i].pa;
	else
	    worms[i].po = 0;
	order[i] = i;
    }
    for (i = 0; i < 63; i++)
	for (j = i+1; j < 64; j++)
	    if (worms[order[i]].po < worms[order[j]].po)
    {
	t = order[i];
	order [i]=order[j];
	order [j]=t;
    }
    
    for (i = 0; i < 64; i++)
    {
	sprintf (wr[i], "%2d %-.16s %.8s %3d",
		 i+1, worms[order[i]].name,
		 teams[(order[i])/4].name, (worms[order[i]].po)/10);
	if (worms[order[i]].pa)
	    wm++;
    }
    for (i = 0; i < 16; i++)
    {
	order[i]=i;
	t = 0;
	j=0;
	for (k = 0; k < 4; k++)
	    if (worms[i*4+k].pa)
	{
	    j++;
	    t+=worms[i*4+k].po;
	}
	if (j)
	    teams[i].av=t/j;
	else
	    teams[i].av=0;
    }
    for (i = 0; i < 15; i++)
	for (j = i+1; j < 16; j++)
	    if (teams[order[i]].av < teams[order[j]].av) 
    {
	t = order[i];
	order [i]=order[j];
	order [j]=t;
    }
    
    for (i = 0; i < 16; i++)
    {
	if (teams[order[i]].p)
	    tm++;
	
	sprintf (tr[AVG][i],"%.8s%4d%4d%4d%4d%+4d%4d", 
		 teams[order[i]].name, teams[order[i]].p,
		 teams[order[i]].w, teams[order[i]].f, 
		 teams[order[i]].a, teams[order[i]].d, 
		 teams[order[i]].av/10);
    }
    for (i = 0; i < 15; i++)
	for (j = i+1; j < 16; j++)
	    if (teams[order[i]].wp < teams[order[j]].wp)
    {
	t = order[i];
	order [i]=order[j];
	order [j]=t;
    }
    
    for (i = 0; i < 16; i++)
	sprintf (tr[WINS][i],"%.8s%4d%4d%4d%4d%+4d%4d", 
		 teams[order[i]].name, teams[order[i]].p,
		 teams[order[i]].w, teams[order[i]].f, 
		 teams[order[i]].a, teams[order[i]].d, 
		 teams[order[i]].wp);
    max[WORMS][SEL]=wm;
    max[TEAMS][SEL]=tm;
}

void sprint (int x, int y, char *st)
{
    unsigned char far *s, far *o, far *c;
    static unsigned char mask [5]={16, 8, 4, 2, 1};
    unsigned int z, a, b;
    
    s = scr+320*(unsigned)y+(unsigned)x;
    for (z =0; z < strlen (st); z++)
    {
	if (st[z]=='/')
	    st[z]=65+36;
	if (st[z]=='+')
	    st[z]=65+38;
	if (st[z]=='-')
	    st[z]=65+39;
	if (st[z]=='*')
	    st[z]=65+40;
	if (st[z]==':')
	    st[z]=65+41;
	if (st[z]<65 || st[z]>106)
	    st[z]=' ';
	c = sfont+(st[z]-65)*5;
	if (st[z] != ' ')
	{
	    for (b = 0; b < 6; b++)
	    {
		o = s+320*b+z*5;
		for (a = 0; a < 5; a++)
		    if (c[a] != 6 && (c[a] || c[a-211]!=5))
			o[a]=c[a];
		c+=210;
	    }
	}
    }
}
		    
void pstring (int x, int y, char *st)
{
    unsigned char far *s, far *o;
    int z, a, b;
    
    s = scr+320*(unsigned)y+(unsigned)x;

    for (b = 8; b >=0; b--)
    {	
	o = s+320*(unsigned)b;
	for (z = 0; z < strlen (st); z++)
	    for (a = 8; a >= 0; a--)
	    {
		if (font[st[z]-32][b][a]) {
		    o[z*10+a]=font[st[z]-32][b][a];
		    if (a == 8 || b == 8 || !font[st[z]-32][b+1][a+1])
			o[z*10+a+321]=0;
		}
		else
		{
		    o[z*10+a]=blogo[y+b][x+a+z*10];
		    if (a == 8 || b == 8)
			o[z*10+a+321]=blogo[y+b+1][x+a+z*10+1];
		}
	    }
	
    }
}
    
void load_font (void)
{
    int i,j,k;
    long ind;
    
    ind=0;
    for (i = 0; i < 80; i++)
	for (j=0; j < 9; j++)
	    for (k = 0; k < 9; k++)
		font[i][j][k]=0;
    for (i = 0; i <= 9; i++)
	ind=readchar (i+16, ind);
    for (i = 'A'; i <= 'Z'; i++)
	ind=readchar (i-32, ind);
    ind=readchar ('@'-32, ind);
    ind=readchar (':'-32, ind);
    ind=readchar ('-'-32, ind);
    ind=readchar ('.'-32, ind);
    ind=readchar ('='-32, ind);
    ind=readchar ('+'-32, ind);
    ind=readchar ('/'-32, ind);
    ind=readchar ('*'-32, ind);
}

long readchar (int c, long ind)
{
    int j;
    unsigned char gg;
    int k;

    for (j = 0; j < 20; j++)
    {
	gg = fnt[ind++];
	k = gg & 3;
	font[c][(j*4)/9][(j*4)%9]=k;
	k = (gg>>2) & 3;
	font[c][(j*4+1)/9][(j*4+1)%9]=k;
	k = (gg>>4) & 3;
	font[c][(j*4+2)/9][(j*4+2)%9]=k;
	k = (gg>>6) & 3;
	font[c][(j*4+3)/9][(j*4+3)%9]=k;
    }
    gg = fnt[ind++];
    k = gg&3;
    font[c][8][8]=k;
    return ind;
}

