/*********************************************/
/* you just keep on pushing my luck over the */
/*          BOULDER        DASH              */
/*                                           */
/*     Jeroen Houttuin, ETH Zurich, 1990     */
/*                                           */
/*                                           */
/*	  PC-VGA version from :				*/
/*                                           */
/*		Herve SOULARD, Paris, 1990		*/
/*                                           */
/*********************************************/

#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <sys\types.h>
#include <sys\stat.h>
#include <malloc.h>
#include <string.h>
#include <memory.h>
#include <conio.h>
#include <ctype.h>
#include <dos.h>
#include <graph.h>

#include "xbd.h"


char	*getenv();
void (interrupt far *oldVect)();

int count = 0;
Bool startCount = FALSE;
Bool newLevel = FALSE;

Bool noSound = FALSE;


void far interrupt newClock()
{
	if (startCount && count)
		count--;
	_chain_intr(oldVect);
}


Bool kbdHit(void)
{ 
	if (*kbdPtrRead == *kbdPtrWrite)
		return(FALSE);
	else
		return(TRUE);
}

void getKbd(byte *TT,byte *T)
{ 
	*T = *(kbdBuffer + *kbdPtrRead);
	if (*T == 0x00 || *T == 0xE0) {
		*T = *(kbdBuffer + *kbdPtrRead + 1);
		*TT = 'F';
	}
	else
		*TT = 'T';
	*kbdPtrRead += 2;
	if (*kbdPtrRead == 0x3E)
		*kbdPtrRead = 0x1E;
}


void init_vars()
{
	blobbreak = 100;
	critical = 100;
	blobcells = 0;
	curorder = STAND;
	gamestop = TRUE;
	scoreobs = TRUE;
	stoplevel = FALSE;
	levelnum = 1;
	speed = 1;
	lives = 4;
	xin = 0;
	yin = 0;
	players = 1;
}


void adapt_timer()
{
	if (speed <= 0)
		speed = 1;
	count = 34 / speed;
}



/* Handle a key stroke by the user. */
void handle_key(byte keytype, byte keyhit)
{
	if (players <= 0) {
		init_level(levelnum);
		adapt_timer();
		stoplevel = FALSE;
		draw_field(TRUE);
		gamestop = TRUE;
		players = 1;
		return;
	}
	if (keytype == 'T') {
		switch (keyhit) {
			case K_SPACE:
				gamestop = !gamestop;
				break;
		}
	}
	else {
		switch (keyhit) {
			case K_LEFT:
				steal = FALSE;
				curorder = LEFT;
				gamestop = FALSE;
				break;
			case K_UP:
				steal = FALSE;
				curorder = UP;
				gamestop = FALSE;
				break;
			case K_DOWN:
				steal = FALSE;
				curorder = DOWN;
				gamestop = FALSE;
				break;
			case K_RIGHT:
				steal = FALSE;
				curorder = RIGHT;
				gamestop = FALSE;
				break;
			case K_CTL_LEFT:
				steal = TRUE;
				curorder = LEFT;
				gamestop = FALSE;
				break;
			case K_CTL_UP:
				steal = TRUE;
				curorder = UP;
				gamestop = FALSE;
				break;
			case K_CTL_DOWN:
				steal = TRUE;
				curorder = DOWN;
				gamestop = FALSE;
				break;
			case K_CTL_RIGHT:
				steal = TRUE;
				curorder = RIGHT;
				gamestop = FALSE;
				break;
		}
	}
}


/* Function which is called whenever the timer signal goes off */
void ticker()
{
	startCount = FALSE;
	if (curtime)
		curtime--;
	if (tinkact)
		tinkdur--;
	if (curtime % 10 == 1)
		scoreobs = TRUE;

	if (!gamestop) {
		if (newLevel) {
			newLevel = FALSE;
			_clearscreen(_GCLEARSCREEN);
		}
		calculate_field();
		draw_field(0);
	}
	if (stoplevel) {
		init_level(levelnum);
		adapt_timer();
		gamestop = TRUE;
		stoplevel = FALSE;
		newLevel = TRUE;
	}
	adapt_timer();
	startCount = TRUE;
}




void main(argc, argv)
int argc;
char **argv;
{
	long		period;
	char		buf[50];
	int		i;
	char		*tmp;
	char		aux[200];
	char		soundName[255];

	byte	keyhit;
	byte	keytype;
	
	
	if (tmp = getenv("XBDLIB"))
		strcpy(aux, tmp);
	else
		strcpy(aux, LIB);

	init_vars();

	/* scan the command line for executing parameters and flags */
	for (i = 1; i < argc; ++i) {
		if (argv[i][0] == '-') {
			switch (argv[i][1]) {
				case 'l' :
					if (argv[i][2] == '\0' && i + 1 < argc) {
						sscanf(argv[i + 1], "%d", &levelnum);
						i++;	
					}
					else
						sscanf(argv[i] + 2, "%d", &levelnum);
					break;
				case 's' :
					noSound = TRUE;
					soundDone = FALSE;
					break;
			}
		}
		else {
			printf("usage: xbd [-l <level>] [-s] \n");
			printf("                              \n");
			printf("       -l = starting level    \n");
			printf("       -s = no digitized sound\n");
			exit(1);
		}
	}

	levelstart = levelnum;
	init_level(levelnum);

	if (!noSound) {
		strcpy(soundName,aux);
		strcat(soundName,"\\explode");
		readSound(soundName, &sndExplode);

		strcpy(soundName,aux);
		strcat(soundName,"\\whizz");
		readSound(soundName, &sndWhizz);

		strcpy(soundName,aux);
		strcat(soundName,"\\gameover");
		readSound(soundName, &sndOver);

		strcpy(soundName,aux);
		strcat(soundName,"\\yahoo");
		readSound(soundName, &sndYahoo);
	}

	oldVect = _dos_getvect(0x1C);
	xstart();

	load();
	
	make_gcs();
	_clearscreen(_GCLEARSCREEN);
	draw_field(TRUE);
	draw_score();

	/* initialize timer structure according to speed */
	adapt_timer();

	startCount = FALSE;
	_dos_setvect(0x1C,newClock);
	
	while (lives > 0) {		/* MAIN LOOP */
		if (!count) 
			ticker();
		if (kbdHit()) {
			getKbd(&keytype,&keyhit);
			if (keytype == 'T') {
				switch (keyhit) {
					case K_ESC:
						if (!noSound) {
							playSound(sndOver);
							while (!soundDone);
						}
						xend();
						_dos_setvect(0x1C,oldVect);
						add_score();
						if (!noSound) {
							closeSound(&sndExplode);
							closeSound(&sndWhizz);
							closeSound(&sndOver);
							closeSound(&sndYahoo);
						}
						exit(-1);
						break;
					case K_D:
					case K_d:
						curorder = KILL;
						break;
					case K_R:
					case	K_r:
						_clearscreen(_GCLEARSCREEN);
						draw_field(TRUE);
						break;
					default:
						handle_key(keytype,keyhit);
						break;
				}
			}
			else
				handle_key(keytype,keyhit);
		}
		if (!gamestop)
			startCount = TRUE;
	}

	if (!noSound) {
		playSound(sndOver);
		while (!soundDone);
	}

	xend();
	_dos_setvect(0x1C,oldVect);
	add_score();

	if (!noSound) {
		closeSound(&sndExplode);
		closeSound(&sndWhizz);
		closeSound(&sndOver);
		closeSound(&sndYahoo);
	}
	exit(-1);
}

