//---------------------------------------------------------------------------------------------
#include <stdio.h>
#include <system.h>
#include <io.h>
//---------------------------------------------------------------------------------------------
#define IOWR_VGA(base,offset,data) IOWR_16DIRECT(base,(offset)*2,data)
#define IORD_VGA(base,offset) IORD_16DIRECT(base,(offset)*2)
#define PAC_V 1

#define INITIAL_GAME_SPEED 5000
#define INITIAL_PACX 14
#define INITIAL_PACY 23
#define INITIAL_PAC_LIFE 3
#define PAC_MOUTH_SPEED 21
#define TOTAL_PACDOT_NUM 240
//---------------------------------------------------------------------------------------------
int gameSpeed = INITIAL_GAME_SPEED;
int pacX = INITIAL_PACX;
int pacY = INITIAL_PACY;
int pacImgX = 203 + 9 * INITIAL_PACX;
int pacImgY = 105 + 9 * INITIAL_PACY;
int pacLife = INITIAL_PAC_LIFE;
int pacMove = 1;
int pacMouth = 0;
int pacDot = TOTAL_PACDOT_NUM;
unsigned char keyBoardCode = 0;
unsigned char pacOperation = 0;
//---------------------------------------------------------------------------------------------
void startPac() {
	printf("PacMan is running!\n");
	while(!IORD_8DIRECT(KEYBOARD_BASE,0));
	while(pacLife >= 0)
	{
		while(!IORD_8DIRECT(KEYBOARD_BASE,0)){
			int i;
			for(i = 0; i < gameSpeed; i++);
			movePac();
		}
		keyBoardCode = IORD_8DIRECT(KEYBOARD_BASE,1);
		movePac();
	}
}
//---------------------------------------------------------------------------------------------
void paintPac(int x, int y) {
	IOWR_VGA(VGA_BASE, 0, x);
	IOWR_VGA(VGA_BASE, 1, y);
	if(pacMouth < PAC_MOUTH_SPEED / 3) {
		switch(pacMove) {
		case 1:
			IOWR_VGA(VGA_BASE, 2, 1);
			break;
		case 2:
			IOWR_VGA(VGA_BASE, 2, 3);
			break;
		case 3:
			IOWR_VGA(VGA_BASE, 2, 5);
			break;
		case 4:
			IOWR_VGA(VGA_BASE, 2, 7);
			break;
		default:
			break;
		}
	}
	if(pacMouth < 2 * PAC_MOUTH_SPEED / 3) {
		switch(pacMove) {
		case 1:
			IOWR_VGA(VGA_BASE, 2, 2);
			break;
		case 2:
			IOWR_VGA(VGA_BASE, 2, 4);
			break;
		case 3:
			IOWR_VGA(VGA_BASE, 2, 6);
			break;
		case 4:
			IOWR_VGA(VGA_BASE, 2, 8);
			break;
		default:
			break;
		}
	}
	else
		IOWR_VGA(VGA_BASE, 2, 0);
	pacMouth = (pacMouth + 1) % PAC_MOUTH_SPEED;
}

//---------------------------------------------------------------------------------------------
void movePac() {
	int nextPacX;
	int nextPacY;
	unsigned nextContent;
	switch(keyBoardCode)
	{
	case 117:	//up
		nextPacY = (pacImgY - PAC_V - 105) / 9;
		IOWR_VGA(VGA_BASE, 15, nextPacY * 28 + pacX + 1);
		nextContent = IORD_VGA(VGA_BASE, 0);
		if(nextContent == 26 || nextContent == 27 || nextContent == 28) {
			pacImgY -= PAC_V;
			pacMove = 4;
		}
		else if(pacMove != 4)
			pacOperation = 117;
		break;
	case 116:	//right
		nextPacX = (pacImgX + PAC_V - 203) / 9;
		IOWR_VGA(VGA_BASE, 15, pacY * 28 + nextPacX + 1);
		nextContent = IORD_VGA(VGA_BASE, 0);
		if(nextContent == 26 || nextContent == 27 || nextContent == 28) {
			pacImgX += PAC_V;
			pacMove = 1;
		}
		else if(pacMove != 1)
			pacOperation = 116;
		break;
	case 114:	//down
		nextPacY = (pacImgY + PAC_V - 105) / 9;
		IOWR_VGA(VGA_BASE, 15, nextPacY * 28 + pacX + 1);
		nextContent = IORD_VGA(VGA_BASE, 0);
		if(nextContent == 26 || nextContent == 27 || nextContent == 28) {
			pacImgY += PAC_V;
			pacMove = 2;
		}
		else if(pacMove != 2)
			pacOperation = 114;
		break;
	case 107:	//left
		nextPacX = (pacImgX - PAC_V - 203) / 9;
		IOWR_VGA(VGA_BASE, 15, pacY * 28 + nextPacX + 1);
		nextContent = IORD_VGA(VGA_BASE, 0);
		if(nextContent == 26 || nextContent == 27 || nextContent == 28) {
			pacImgX -= PAC_V;
			pacMove = 3;
		}
		else if(pacMove != 3)
			pacOperation = 107;
		break;
	default:
		break;
	}
	paintPac(pacImgX, pacImgY);
	pacX = (pacImgX - 203) / 9;
	pacY = (pacImgY - 105) / 9;

	unsigned mazeContent;
	IOWR_VGA(VGA_BASE, 15, pacY * 28 + pacX + 1);
	mazeContent = IORD_VGA(VGA_BASE, 0);
	printf("pacX = %d, pacY = %d, key=%d\n", pacX, pacY, mazeContent);
	if(mazeContent == 26) { 	//pacDot
		//pacMan eats a pacDot
		IOWR_VGA(VGA_BASE, 12, pacY * 28 + pacX + 1);
		IOWR_VGA(VGA_BASE, 13, 28);
		pacDot--;
	}

	if(pacDot == 0)
		printf("Stage Clear!\n");
}
//---------------------------------------------------------------------------------------------
int main() {
	startPac();
	return 0;
}


