#pragma output REGISTER_SP = 0xa000

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>

#include "ansi.h"

#define BOARD_WIDTH 40
#define BOARD_HEIGHT 20
#define BOT_COUNT 10

char board[BOARD_HEIGHT][BOARD_WIDTH];
int posX, posY;
int robotX[BOT_COUNT];
int robotY[BOT_COUNT];
unsigned int robotCount;
short seed;
unsigned char color = 0;

void displayStatus(char *text) {
	gotoxy(5, 22);
	clrline();
	printf("%s", text);
}

void drawBoard() {
	int i;
	int j;
	
	for (i=0;i<BOARD_HEIGHT;i++) {
		for(j=0;j<BOARD_WIDTH;j++) {
			gotoxy(j + 5, i + 1);
			switch(board[i][j]) {
				case 'X':
					if (color) {
						printf("\033[1;36mX\033[0m");
					} else {
						printf("X");
					}
					break;
				case '*':
					if (color) {
						printf("\033[1;32m*\033[0m");
					} else {
						printf("*");
					}
					break;
				case '+':
					if (color) {
						printf("\033[1;33m+\033[0m");
					} else {
						printf("+");
					}
					break;
				case ' ':
					printf(" ");
					break;
			}
		}
	}
}

void setupBoard() {
	int i;
	int j;
	
	robotCount = BOT_COUNT;
	
	for (i=0;i<BOARD_HEIGHT;i++) {
		for (j=0;j<BOARD_WIDTH;j++) {
			if (rand() % 20 == 5) {
				board[i][j] = 'X';
			} else {
				board[i][j] = ' ';
			}
		}
	}
	
	for (i=0;i<BOARD_HEIGHT;i++) {
		board[i][0] = 'X';
		board[i][BOARD_WIDTH-1] = 'X';
	}
	for (i=0;i<BOARD_WIDTH;i++) {
		board[0][i] = 'X';
		board[BOARD_HEIGHT-1][i] = 'X';
	}
	
	// add player
	
	do {
		posX = rand() % (BOARD_WIDTH - 2) + 1;
		posY = rand() % (BOARD_HEIGHT - 2) + 1;
	} while (board[posY][posX] == 'X');
	
	board[posY][posX] = '*';
	
	// add robots
	
	for (i=0;i<BOT_COUNT;i++) {
		do {
			robotX[i] = rand() %  (BOARD_WIDTH - 2)  + 1;
			robotY[i] = rand() %  (BOARD_HEIGHT - 2)  + 1;
		} while (board[robotY[i]][robotX[i]] != ' ');
		
		board[robotY[i]][robotX[i]] = '+';
	}
}

int robotMove() {
	int i;
	int j;
	
	int newX;
	int newY;
	
	for (i=0;i<BOT_COUNT;i++) {
		if (robotX[i] == -1 && robotY[i] == -1) continue;
		if (robotX[i] - posX > 0) {
			newX = robotX[i]-1;
		} else if (robotX[i] - posX < 0) {
			newX = robotX[i]+ 1;
		} else {
			newX = robotX[i];
		}
		
		if (robotY[i] - posY > 0) {
			newY = robotY[i]-1;
		} else if (robotY[i] - posY < 0) {
			newY = robotY[i]+ 1;
		} else {
			newY = robotY[i];
		}
		
		if (board[newY][newX] == 'X') {
			robotCount--;
			gotoxy(robotX[i] + 5, robotY[i] + 1);
			printf(" ");
			board[robotY[i]][robotX[i]] = ' ';
			robotY[i] = -1;
			robotX[i] = -1;
		} else if (board[newY][newX] == '+') {
			// destroy both robots;
			for (j=0;j<BOT_COUNT;j++) {
				if (robotX[j] == newX && robotY[j] == newY) {
					robotX[j] = -1;
					robotY[j] = -1;
				}
			}
			gotoxy(robotX[i] + 5, robotY[i] + 1);
			printf(" ");
			board[robotY[i]][robotX[i]] = ' ';
			robotX[i] = -1;
			robotY[i] = -1;
			robotCount -= 2;
			board[newY][newX] = ' ';
			gotoxy(newX + 5, newY + 1);
			printf(" ");
		} else if (board[newY][newX] == '*') {
			// uh oh
			gotoxy(robotX[i] + 5, robotY[i] + 1);
			printf(" ");
			gotoxy(newX + 5, newY + 1);
			if (color) {
				printf("\033[1;33m+\033[0m");
			} else {
				printf("+");
			}			
			displayStatus("Executed by a Robot! You're Dead. Press a key to Exit");
			return 1;
		} else {
			board[robotY[i]][robotX[i]] = ' ';
			board[newY][newX] = '+';
			gotoxy(robotX[i] + 5, robotY[i] + 1);
			printf(" ");
			gotoxy(newX + 5, newY + 1);
			if (color) {
				printf("\033[1;33m+\033[0m");
			} else {
				printf("+");
			}
			
			robotY[i] = newY;
			robotX[i] = newX;
		}
	}
	if (robotCount == 0) {
		displayStatus("You win! Press a key to Exit");
		return 1;
	}
	return 0;
}

int playerMove() {
	char key;
	int newX;
	int newY;
	
	int done = 0;

	while (!done) {
		key = fgetc(stdin);
		done = 1;
		switch (tolower(key)) {
			case '7':
				newX = posX - 1;
				newY = posY - 1;
				break;
			case '8':
				newY = posY - 1;
				newX = posX;
				break;
			case '9':
				newY = posY - 1;
				newX = posX + 1;
				break;
			case '4':
				newX = posX - 1;
				newY = posY;
				break;
			case '6':
				newX = posX + 1;
				newY = posY;
				break;
			case '1':
				newX = posX - 1;
				newY = posY + 1;
				break;
			case '2':
				newY = posY + 1;
				newX = posX;
				break;
			case '3':
				newY = posY + 1;
				newX = posX + 1;
				break;
			case '0':
				return 0;
			case 'j':
				newX = rand() % (BOARD_WIDTH -2) + 1;
				newY = rand() % (BOARD_HEIGHT -2) + 1;
				break;
			case 'q':
				exit(0);
				break;
			default:
				done = 0;
				break;
		}
	}
	if (board[newY][newX] == ' ') {
		// safe move
		board[newY][newX] = '*';
		board[posY][posX] = ' ';
		gotoxy(posX + 5, posY + 1);
		printf(" ");
		gotoxy(newX + 5, newY + 1);
		if (color) {
			printf("\033[1;32m*\033[0m");
		} else {
			printf("*");
		}
		posY = newY;
		posX = newX;
		return 0;
	}
	else {
		if (board[newY][newX] == 'X') {
			// electrocuted
			displayStatus("High Voltage! ZAPP!! You're Dead. Press a key to Exit");
		} else {
			// robot got you!
			displayStatus("Executed by a Robot! You're Dead. Press a key to Exit");
		}
		return 1;
	}	
}

int main()
{
	int done = 0;
	int quit = 0;
	seed = 9374;
	
	srand(seed);

	while (!quit) {
		clrscr();
		
		if (!color) {
			printf(" ___     _         _      ___ _                 \n");
 			printf("| _ \\___| |__  ___| |_   / __| |_  __ _ ___ ___ \n");
 			printf("|   / _ \\ '_ \\/ _ \\  _| | (__| ' \\/ _` (_-</ -_)\n");
 			printf("|_|_\\___/_.__/\\___/\\__|  \\___|_||_\\__,_/__/\\___|\n");
			printf("\nBased on the game \"CHASE\" appearing in the book\n");
			printf("    \"More BASIC Computer Games\" by David Ahl\n\n");

			printf("P - Play\n");
			printf("I - Print Instructions\n");
			printf("C - ANSI Color (off)\n");
        	printf("S - Enter Random Seed (%u)\n", seed);
        	printf("Q - Quit\n");
		} else {
			printf("\033[1;35m ___     _         _      ___ _                 \n");
 			printf("| _ \\___| |__  ___| |_   / __| |_  __ _ ___ ___ \n");
 			printf("|   / _ \\ '_ \\/ _ \\  _| | (__| ' \\/ _` (_-</ -_)\n");
 			printf("|_|_\\___/_.__/\\___/\\__|  \\___|_||_\\__,_/__/\\___|\n");
			printf("\n\033[1;32mBased on the game \"CHASE\" appearing in the book\n");
			printf("    \"More BASIC Computer Games\" by David Ahl\n\n");
			printf("\033[1;36mP \033[1;37m- Play\n");
			printf("\033[1;36mI \033[1;37m- Print Instructions\n");
			printf("\033[1;36mC \033[1;37m- ANSI Color (\033[1;32mon\033[1;37m)\n");
			printf("\033[1;36mS \033[1;37m- Enter Random Seed (\033[1;32m%u\033[1;37m)\n", seed);
        	printf("\033[1;36mQ \033[1;37m- Quit\n");
		}

		switch(tolower(fgetc(stdin))) {
			case 'p':
				done = 0;
				clrscr();
				setupBoard();

				if (!color) {
					printf("                                                          R O B O T\n");
					printf("                                                          C H A S E\n");                                              
					printf("\n");
					printf("                                                       Turn NUM LOCK on!\n");       
					printf("\n");                                                     
					printf("                                                      7   8   9  J - Jump\n");     
					printf("                                                        \\ | /    0 - Pass\n");      
					printf("                                                      4 - * - 6\n");                
					printf("                                                        / | \\\n");                  
					printf("                                                      1   2   3  Q - Quit\n");
					printf("\n");                                                               
					printf("                                                      * - You\n");                  
					printf("                                                      X - High Voltage Line\n");    
					printf("                                                      + - Killer Robot\n");
				} else {
					printf("                                                          \033[1;35mR O B O T\033[0m\n");
					printf("                                                          \033[1;35mC H A S E\033[0m\n");                                              
					printf("\n");
					printf("                                                       \033[1;31mTurn NUM LOCK on!\033[0m\n");       
					printf("\n");                                                     
					printf("                                                      \033[1;37m7   8   9  J - Jump\033[0m\n");     
					printf("                                                        \033[1;37m\\ | /    0 - Pass\033[0m\n");      
					printf("                                                      \033[1;37m4 - * - 6\n");                
					printf("                                                        \033[1;37m/ | \\\n");                  
					printf("                                                      \033[1;37m1   2   3  Q - Quit\033[0m\n");
					printf("\n");                                                               
					printf("                                                      \033[1;32m* \033[1;37m- You\033[0m\n");                  
					printf("                                                      \033[1;36mX \033[1;37m- High Voltage Line\033[0m\n");    
					printf("                                                      \033[1;33m+ \033[1;37m- Killer Robot\033[0m\n");
				}
				drawBoard();
				while (!done) {
					gotoxy(79, 23);
					if (playerMove()) break;
					done = robotMove();
				}
				fgetc(stdin);
				break;
			case 'i':
				clrscr();
				if (color) {
					printf("\033[0m");
				}

				printf("You are trapped in a maze of high voltage power\n");
				printf("fences and posts. There are also killer robots\n");
				printf("trying to destroy you.\n\n");
																
				printf("Your only hope is to lure the robots into a fence\n");
				printf("or each other to destroy them.\n\n");
																
				printf("If things get hopeless, you can do a mega jump,\n");
				printf("but you could end up anywhere, including on top\n");
				printf("of a power fence or a robot!\n");

				if (color) {
					printf("\033[1;37m");
				}
				printf("\nPress a key to continue!\n");
				fgetc(stdin);
				break;
			case 'c':
				color = !color;
				break;
			case 's':
				printf("Please enter a seed: ");
				scanf("%u", &seed);
				srand(seed);
				break;
			case 'q':
				if (color) {
					printf("\033[0m");
				}
				quit = 1;
				break;
		}
	}
	clrscr();
	printf("Thanks for playing Robot Chase!\n");
	return 0;
}
