/******************************************************************************
*									      *
*	(C) 1993 by K. Ballueder					      *
*									      *
*	See README and COPYING for details.				      *
*									      *
*	Please feel free to contact me:					      *
*		kballued@charon.physik.uni-osnabrueck.de		      *
*		kballued@jupiter.rz.uni-osnabrueck.de			      *
*									      *
******************************************************************************/


#ifdef OS_DOS
#	include <bios.h>
#	include <dos.h>
#else
#	include <stdio.h>
#	include <unistd.h>
#endif

#include "scores.h"
#include "bdash.h"
#include "graphic.h"
#include "react.h"
#include "communic.h"
#include "movers.h"
#include "sound.h"
#include "game.h"

#include "io.h"

#ifdef OS_DOS
#	define CURSOR_LEFT  	0x4b00
#	define CURSOR_RIGHT 	0x4d00
#	define CURSOR_UP    	0x4800
#	define CURSOR_DOWN  	0x5000
#	define ESC          	0x011b
#	define PAUSE_KEY	'p'
#	define CHEAT_NEXTLEVEL	'n'
#	define CHEAT_ENTER	'c'
#else
#	define CURSOR_LEFT	'4'
#	define CURSOR_RIGHT	'6'
#	define CURSOR_UP	'8'	
#	define CURSOR_DOWN	'2'
#	define PAUSE_KEY	'p'
#	define ESC		'q'
#	define CHEAT_NEXTLEVEL	'n'
#	define CHEAT_ENTER	'c'
#endif

static int can_enter(int x, int y, int player)
{
	register int feld = (int) level_table[y][x];

	if(feld == FELD_ERDE || feld == FELD_LEER || feld == FELD_WATER)
		return 1;
	if(feld >= FELD_DIAMANT_1 && feld <= FELD_DIAMANT_4)
		return 1;
	if(feld >= FELD_KEY_1 && feld <= FELD_KEY_4)
		return 1;
	if(feld >= FELD_TOR_1 && feld <= FELD_TOR_4)
		return keys[player][feld-FELD_TOR_1];
	return 0;
}


static int drowned = 0;

static void betritt_feld(int x, int y, int player)
{
	register int feld = (int) level_table[y][x];

	if(player == 0)
	{	if(feld >= FELD_DIAMANT_1 &&
		   feld <= FELD_DIAMANT_4)
			{	increment_score(2);
				soundeffect(SND_PING);
			}
		else if(feld >= FELD_KEY_1 &&
			feld <= FELD_KEY_4)
				keys[player][feld-FELD_KEY_1] ++;
		else if(feld >= FELD_TOR_1 &&
			feld <= FELD_TOR_4)
			{	keys[player][feld-FELD_TOR_1] --;
				soundeffect(SND_DOOR);
			}
		else if(feld == FELD_WATER)
			{	soundeffect(SND_WATER);
				sleep(SHORT_BREAK);
				tod();
				drowned = 1;
				return;
			}
	}
	level_table[y][x] = player+1;
	draw_spieler(x,y,player);
}

static
int rechts_moeglich(int x, int y,int player)  /* kann Feld betreten werden? */
{
	unsigned char object;

	if(x == 99)
	return 0;

	object = level_table[y][x+1];
	if(can_enter(x+1,y,player))
	return 1;
	else
	if(object < FELD_EXPLODE)
	{ 	if(x == 98)
			return 0;
		if(level_table[y][x+2] == FELD_LEER)
		{ 	move_object(x+1,y,x+2,y,object);
			if(y > 0)
			{ 	bearbeite_feld(x+1,y-1); /* kommt was von oben? */
				bearbeite_feld(x+2,y); /* faellt es runter? */
			}
		return 1;
		}
	}
	return 0;
}

static
int links_moeglich(int x, int y, int player)  /* kann Feld betreten werden? */
{
	unsigned char object;

	if(x == 0)
		return 0;

	object = level_table[y][x-1];
	if(can_enter(x-1,y,player))
		return 1;
	else if(object < FELD_EXPLODE)
	{ 	if(x  < 2)
			return 0;
		if(level_table[y][x-2] == FELD_LEER)
		{	if(object == FELD_STEIN) object = FELD_STEIN_2;
			if(object == FELD_BOMBE) object = FELD_BOMBE_2;
			move_object(x-1,y,x-2,y,object);
			if(y > 0)
			{ 	bearbeite_feld(x-1,y-1);
				bearbeite_feld(x-2,y);
			}
			return 1;
		}
	}
	return 0;
}

static
int hoch_moeglich(int x, int y, int player)  /* kann Feld betreten werden? */
{
	if(y == 0)
		return 0;

	if(can_enter(x,y-1,player))
		return 1;
	else
		return 0;
}

static
int runter_moeglich(int x, int y, int player)  /* kann Feld betreten werden? */
{
	if(y == 99)
		return 0;

	return can_enter(x,y+1,player);
}





/* the following procedures handle all reactions to user actions and call
 * the controlling functions for other object's behaviour
 * (real ritchie-english)
 */

void switch_scancode(int scancode, int player)
{
	int lastx[2], lasty[2];

	lastx[player]=player_x[player];
	lasty[player]=player_y[player];
	switch(scancode)
	{	case CURSOR_RIGHT:
			if(rechts_moeglich(player_x[player],player_y[player],player))
			{	level_table[player_y[player]][player_x[player]] = FELD_LEER;
				draw_leer(player_x[player],player_y[player]);
				if(player_y[player] > 0)
					bearbeite_feld(player_x[player],player_y[player]-1);
				if(player_x[player] > 0)
					bearbeite_feld(player_x[player]-1,player_y[player]);
				if(player == 0)
					scroll_left(player_x[player]);
				betritt_feld(++player_x[player],player_y[player],player);
			}
		break;
		case CURSOR_LEFT:
			if(links_moeglich(player_x[player],player_y[player], player))
			{ 	level_table[player_y[player]][player_x[player]] = FELD_LEER;
				draw_leer(player_x[player],player_y[player]);
				if(player == 0)
					scroll_right(player_x[player]);
				if(player_y[player] > 0)
					bearbeite_feld(player_x[player],player_y[player]-1);
				if(player_x[player] < 99)
					bearbeite_feld(player_x[player]+1,player_y[player]);
				betritt_feld(--player_x[player],player_y[player],player);
				}
		break;
		case CURSOR_UP:
			if(hoch_moeglich(player_x[player],player_y[player],player))
			{ 	level_table[player_y[player]][player_x[player]] = FELD_LEER;
				draw_leer(player_x[player],player_y[player]);
				if(player == 0)
					scroll_down(player_y[player]);
				bearbeite_feld(player_x[player],player_y[player]);
				betritt_feld(player_x[player],--player_y[player],player);
			}
		break;
		case CURSOR_DOWN:
			if(runter_moeglich(player_x[player],player_y[player],player))
			{ 	level_table[player_y[player]][player_x[player]] = FELD_LEER;
				draw_leer(player_x[player],player_y[player]);
				if(player == 0)
					scroll_up(player_y[player]);
				if(player_y[player] > 0)
					bearbeite_feld(player_x[player],player_y[player]-1);
				bearbeite_feld(player_x[player],player_y[player]);
				betritt_feld(player_x[player],++player_y[player],player);
			}
		break;
		case PAUSE_KEY:
			while(getch() != PAUSE_KEY)
				;
		break;
#ifdef ENABLE_CHEATING
		case CHEAT_NEXTLEVEL:
			do
				increment_score(1);
			while(get_score() < points_required);	/* dirty trick */
		break;			
		case CHEAT_ENTER:
			lives = 100;
			globale_flags.cheating = 1;
		break;
#endif		
	}
	if(drowned)	/* restore old position */
	{	drowned = 0;
		player_x[player] = lastx[player];
		player_y[player] = lasty[player];
		draw_spieler(player_x[player],player_y[player],player);
	}
	update_graphics();
}

/*
 * controlling():	main loop, keyboard polling, the game itself
 */

int controlling(void)
{
	int scancode = 0, player, pl;
	int num_of_players = globale_flags.twoplayer ? 2 : 1;

	debug_printf("entering controlling()\n");

	do
	for(pl=0;pl < num_of_players;pl++)
	{	if((globale_flags.twoplayer)&&(globale_flags.slavemode != 0))
			player = 1-pl;
		else
			player = pl;
		if(player == 0 && scancode != ESC)
		{
#ifdef OS_DOS
#	ifdef DEBUG
			scancode = bioskey(0);
#	else
			if(bioskey(1))
				scancode = bioskey(0);
			else
				scancode = 0;  /* nix los */
#	endif
#else
			scancode = getchar();
#endif
			if(globale_flags.twoplayer)
				Send_Taste(scancode);
		}
		else
			scancode = Receive_Taste();
		switch_scancode(scancode,player);

		debug_printf("calling move_objects:\n");
		move_objects(); /* Viechers bewegen */
		update_graphics();
		react(); /* mal sehen, ob's klappt */
	}
	while(scancode != ESC && !globale_flags.dead &&
		get_score() < points_required);

	debug_printf("leaving controlling() after get_score()\n");

	return !(get_score() < points_required);
}
