//**************************
// Filename: game.cpp
// Author: Aaron Rogers
// Updated: 09/04/02
// Purpose: Tic Tac Toe game
//**************************

// Library Includes
#include "game.h"
#include "ai.h"

// -- Graphics --
//  Backgrounds 
#include "gfx/ham_tut.map.c"	    // gfx2gba -fsrc -m -pham_tut.pal -t8 ham_tut.bmp
#include "gfx/ham_tut.pal.c"
#include "gfx/ham_tut.raw.c"
#include "gfx/tictactoe.map.c"	    // gfx2gba -fsrc -m -ptictactoe.pal -t8 tictactoe.bmp
#include "gfx/tictactoe.pal.c"
#include "gfx/tictactoe.raw.c"
#include "gfx/game_options.map.c"	    // gfx2gba -fsrc -m -pgame_options.pal -t8 game_options.bmp
#include "gfx/game_options.pal.c"
#include "gfx/game_options.raw.c"
#include "gfx/board_240_160.map.c"	// gfx2gba -fsrc -m -pboard_240_160.pal -t8 board_240_160.bmp
#include "gfx/board_240_160.pal.c"
#include "gfx/board_240_160.raw.c"
#include "gfx/fin_p1.map.c"	    // gfx2gba -fsrc -m -pfin_p1.pal -t8 fin_p1.bmp
#include "gfx/fin_p1.pal.c"
#include "gfx/fin_p1.raw.c"
#include "gfx/fin_p2.map.c"	    // gfx2gba -fsrc -m -pfin_p2.pal -t8 fin_p2.bmp
#include "gfx/fin_p2.pal.c"
#include "gfx/fin_p2.raw.c"
#include "gfx/fin_tie.map.c"	    // gfx2gba -fsrc -m -pfin_tie.pal -t8 fin_tie.bmp
#include "gfx/fin_tie.pal.c"
#include "gfx/fin_tie.raw.c"

//  Sprites 
#include "gfx/objects.pal.c" // Generated (separately) from all of the sprites
#include "gfx/red_O_32_32.raw.c" // gfx2gba -D -fsrc -t8 red_O_32_32.bmp
#include "gfx/red_X_32_32.raw.c"
#include "gfx/blue_O_32_32.raw.c" // gfx2gba -D -fsrc -t8 blue_O_32_32.bmp
#include "gfx/blue_X_32_32.raw.c"

#include "gfx/objects_ms.pal.c" // Generated (separately) from all of the sprites
#include "gfx/numbers.raw.c" // gfx2gba -D -fsrc -t8 numbers.bmp


//*********************************
// Function: TICTACTOE::TICTACTOE()
// Purpose: Default Constructor
//*********************************
TICTACTOE::TICTACTOE()
{
	// Set the game state to START
	game_state = START;

	// Initialize all of the spots
	// 0 = empty, 1 = Player 1, 2 = Player 2
	for (int i = 0; i < 9; ++i) {
		board[i] = 0; // Every space is empty at first
	}	

	// Set the number of players to 1
	players = 1;

	// Set the skill level to 3
	skill = 3;

	// Setup the mixer for sound
	mixer_freq = 26757;

}  // End of TICTACTOE::TICTACTOE()


//*****************************
// Function: TICTACTOE::init()
// Purpose: Initialize the game
//*****************************
void TICTACTOE::init()
{
	// Initialize HAMlib
	ham_Init();
	
	// Setup the background mode
	ham_SetBgMode(1);

	// Initalize the sound mixing
	ham_InitMixer(mixer_freq);

	// Set up the sounds
	mysample[0] =  ham_InitSample((u8*)_binary_clip_raw_start.data,
		_binary_clip_raw_start.size,
		_binary_clip_raw_start.freq>>10);
	mysample[1] =  ham_InitSample((u8*)_binary_dong_raw_start.data,
		_binary_dong_raw_start.size,
		_binary_dong_raw_start.freq>>10);

	return;
} // End of TICTACTOE::init()


//*****************************************
// Function: TICTACTOE::start_screen_init()
// Purpose: Initialize the start screen
//*****************************************
void TICTACTOE::start_screen_init()
{
	// Start the VBL counter at 0
	vbl_count = 0;

	// Start with the first start screen image
	start_screen_slide = 0;

	// Show the HAM Tutorial logo
	// Initialize the background palette
	ham_LoadBGPal((void *)ham_tut_Palette,256);

	// Setup the tileset for our image
	ham_bg[0].ti = ham_InitTileSet((void *)ham_tut_Tiles,
		SIZEOF_16BIT(ham_tut_Tiles),1,1);
	
	// Setup the map for our image
	ham_bg[0].mi = ham_InitMapEmptySet(3,0);
	bg_one = ham_InitMapFragment((void *)ham_tut_Map,30,20,0,0,30,20,0);
	ham_InsertMapFragment(bg_one,0,0,0);
	
	// Display the background
	ham_InitBg(0,1,0,0);

	return;
} // End of TICTACTOE::start_screen_init()


//***********************************************
// Function: TICTACTOE::start_screen_query_keys()
// Purpose: Gets input during start_screen()
//***********************************************
void TICTACTOE::start_screen_query_keys()
{
	// Increment the VBL counter every VBL
	++vbl_count;

	if ((vbl_count > 50) && (start_screen_slide == 0)) {
		vbl_count = 0;
		start_screen_slide = 1;

		// Deinitialize the background and sprites
		ham_DeInitBg(0);

		// Show the TICTACTOE screen

		// Initialize the background and sprites palettes
		ham_LoadBGPal((void *)tictactoe_Palette,256);

		// Setup the tileset for our image
		ham_bg[0].ti = ham_InitTileSet((void *)tictactoe_Tiles,
			SIZEOF_16BIT(tictactoe_Tiles),1,1);
	
		// Setup the map for our image
		ham_bg[0].mi = ham_InitMapEmptySet(3,0);
		bg_one = ham_InitMapFragment((void *)tictactoe_Map,30,20,0,0,30,20,0);
		ham_InsertMapFragment(bg_one,0,0,0);
	
		// Display the background
		ham_InitBg(0,1,0,0);
	}

	// After 50 VBLs, the next screen gets displayed
	if ((vbl_count > 50) && (start_screen_slide == 1)) {
		start_screen_slide = 2; // Just in case		

		// Change the game state
		game_state = MAIN;
	}

	return;
} // End of TICTACTOE::start_screen_query_keys()


//*******************************************
// Function: TICTACTOE::start_screen_deinit()
// Purpose: Deinitialize the start screen
//*******************************************
void TICTACTOE::start_screen_deinit()
{
	// Deinitialize the background
	ham_DeInitBg(0);

	return;
} // End of TICTACTOE::start_screen_deinit()


//****************************************
// Function: TICTACTOE::main_screen_init()
// Purpose: Initialize the main screen
//****************************************
void TICTACTOE::main_screen_init()
{
	// "Players" option is "in focus"
	which = 0;

	// Set the object to visible
	visible = 1;

	// Start the VBL counter at 0
	vbl_count = 0;

	// Prompt the user for the number of players

	// Initialize the background and sprites palettes
	ham_LoadBGPal((void *)game_options_Palette,256);
	ham_LoadObjPal((void *)objects_ms_Palette,256);

	// Setup the tileset for our image
	ham_bg[0].ti = ham_InitTileSet((void *)game_options_Tiles,
		SIZEOF_16BIT(game_options_Tiles),1,1);
	
	// Setup the map for our image
	ham_bg[0].mi = ham_InitMapEmptySet(3,0);
	bg_one = ham_InitMapFragment((void *)game_options_Map,30,20,0,0,30,20,0);
	ham_InsertMapFragment(bg_one,0,0,0);
	
	// Display the background
	ham_InitBg(0,1,0,0);

	// Setup the Players pointer, it can be "1" or "2"
	num_play_pnt.x_pos = 155;
	num_play_pnt.y_pos = 30;
	switch (players) {
	case 1:
		num_play_pnt.image = ham_CreateObj((void *)&numbers_Bitmap[0],0,2,OBJ_MODE_NORMAL,
			1,0,0,0,0,0,0,num_play_pnt.x_pos,num_play_pnt.y_pos);
		break;
	case 2:
		num_play_pnt.image = ham_CreateObj((void *)&numbers_Bitmap[1024],0,2,OBJ_MODE_NORMAL,
			1,0,0,0,0,0,0,num_play_pnt.x_pos,num_play_pnt.y_pos);
		break;
	default: // This shouldn't happen
		num_play_pnt.image = ham_CreateObj((void *)&numbers_Bitmap[0],0,2,OBJ_MODE_NORMAL,
			1,0,0,0,0,0,0,num_play_pnt.x_pos,num_play_pnt.y_pos);
		break;
	}


	// Setup the Skill pointer initially as "1", it can be "1" or "2"
	skill_pnt.x_pos = 155;
	skill_pnt.y_pos = 95;
	switch (skill) {
	case 1:
		skill_pnt.image = ham_CreateObj((void *)&numbers_Bitmap[0],0,2,OBJ_MODE_NORMAL,
			1,0,0,0,0,0,0,skill_pnt.x_pos,skill_pnt.y_pos);
		break;
	case 2:
		skill_pnt.image = ham_CreateObj((void *)&numbers_Bitmap[1024],0,2,OBJ_MODE_NORMAL,
			1,0,0,0,0,0,0,skill_pnt.x_pos,skill_pnt.y_pos);
		break;
	case 3:
		skill_pnt.image = ham_CreateObj((void *)&numbers_Bitmap[2048],0,2,OBJ_MODE_NORMAL,
			1,0,0,0,0,0,0,skill_pnt.x_pos,skill_pnt.y_pos);
		break;
	case 4:
		skill_pnt.image = ham_CreateObj((void *)&numbers_Bitmap[3072],0,2,OBJ_MODE_NORMAL,
			1,0,0,0,0,0,0,skill_pnt.x_pos,skill_pnt.y_pos);
		break;
	case 5:
		skill_pnt.image = ham_CreateObj((void *)&numbers_Bitmap[4096],0,2,OBJ_MODE_NORMAL,
			1,0,0,0,0,0,0,skill_pnt.x_pos,skill_pnt.y_pos);
		break;
	default: // This shouldn't happen
		skill_pnt.image = ham_CreateObj((void *)&numbers_Bitmap[0],0,2,OBJ_MODE_NORMAL,
			1,0,0,0,0,0,0,skill_pnt.x_pos,skill_pnt.y_pos);
		break;
	}

	return;
} // End of TICTACTOE::main_screen_init()


//**********************************************
// Function: TICTACTOE::main_screen_query_keys()
// Purpose: Gets input during main_screen()
//**********************************************
void TICTACTOE::main_screen_query_keys()
{
	// Increment the VBL counter every VBL
	++vbl_count;

	// This is used to make the sprites "blink"
	if (vbl_count%5 == 0) { // Every five frames
		if (which == 0 && visible) {  // If it's visible...
			ham_SetObjVisible(num_play_pnt.image, 0); // ... hide it
			visible = 0;
		} else if (which == 1 && visible) { // If it's invisible...
			ham_SetObjVisible(skill_pnt.image, 0); // ... show it
			visible = 0;
		} else if (which == 0 && !visible) { // Same here...
			ham_SetObjVisible(num_play_pnt.image, 1);
			visible = 1;
		} else if (which == 1 && !visible) {
			ham_SetObjVisible(skill_pnt.image, 1);
			visible = 1;
		}
	}

	// UP or DOWN
	if (vbl_count > 10 && (F_CTRLINPUT_UP_PRESSED || F_CTRLINPUT_DOWN_PRESSED)) {
		if (which == 0) {
			if (!visible) ham_SetObjVisible(num_play_pnt.image, 1);
			which = 1;
		} else if (which == 1) {
			if (!visible) ham_SetObjVisible(skill_pnt.image, 1);
			which = 0;
		}
		return;
	}
	
	// Here we check for the user changing the number of players or the skill level
	if (which == 0) { // Changing "Players" option
		// LEFT or RIGHT or SELECT
		if (vbl_count > 10 && (F_CTRLINPUT_RIGHT_PRESSED || F_CTRLINPUT_LEFT_PRESSED 
			|| F_CTRLINPUT_SELECT_PRESSED)) {
			vbl_count = 0;
			if (players == 1) {
				players = 2;
				ham_UpdateObjGfx(num_play_pnt.image,(void *)&numbers_Bitmap[1024]);
			} else if (players == 2) {
				players = 1;
				ham_UpdateObjGfx(num_play_pnt.image,(void *)&numbers_Bitmap[0]);
			}
		}
	} else if (which == 1) { // Changing "Skill" option
		// RIGHT
		if (vbl_count > 10 && (F_CTRLINPUT_RIGHT_PRESSED)) {
			vbl_count = 0;
			// Figure out what the current skill is & and what the next should be
			switch (skill) {
			case 1:
				skill = 2;
				ham_UpdateObjGfx(skill_pnt.image,(void *)&numbers_Bitmap[1024]);
				break;
			case 2:
				skill = 3;
				ham_UpdateObjGfx(skill_pnt.image,(void *)&numbers_Bitmap[2048]);
				break;
			case 3:
				skill = 4;
				ham_UpdateObjGfx(skill_pnt.image,(void *)&numbers_Bitmap[3072]);
				break;
			case 4:
				skill = 5;
				ham_UpdateObjGfx(skill_pnt.image,(void *)&numbers_Bitmap[4096]);
				break;
			case 5:
				skill = 1;
				ham_UpdateObjGfx(skill_pnt.image,(void *)&numbers_Bitmap[0]);
				break;
			default:
				break;
			}
		}

		// LEFT
		if (vbl_count > 10 && (F_CTRLINPUT_LEFT_PRESSED)) {
			vbl_count = 0;
			// Figure out what the current skill is & and what the next should be
			switch (skill) {
			case 1:
				skill = 5;
				ham_UpdateObjGfx(skill_pnt.image,(void *)&numbers_Bitmap[4096]);
				break;
			case 2:
				skill = 1;
				ham_UpdateObjGfx(skill_pnt.image,(void *)&numbers_Bitmap[0]);
				break;
			case 3:
				skill = 2;
				ham_UpdateObjGfx(skill_pnt.image,(void *)&numbers_Bitmap[1024]);
				break;
			case 4:
				skill = 3;
				ham_UpdateObjGfx(skill_pnt.image,(void *)&numbers_Bitmap[2048]);
				break;
			case 5:
				skill = 4;
				ham_UpdateObjGfx(skill_pnt.image,(void *)&numbers_Bitmap[3072]);
				break;
			default:
				break;
			}
		}
	}

	// A or B or START
	if (vbl_count > 10 && (F_CTRLINPUT_A_PRESSED || F_CTRLINPUT_B_PRESSED 
		|| F_CTRLINPUT_START_PRESSED)) {
		// Time to start playing the game
		game_state = PLAY;
		return;
	}

	return;
} // End of TICTACTOE::main_screen_query_keys()


//******************************************
// Function: TICTACTOE::main_screen_deinit()
// Purpose: Deinitialize the main screen
//******************************************
void TICTACTOE::main_screen_deinit()
{
	// Deinitialize the background and sprites
	ham_DeInitBg(0);
	ham_DeleteObj(num_play_pnt.image);
	ham_DeleteObj(skill_pnt.image);
	
	// This must be called to actually delete the sprites
	ham_CopyObjToOAM();

	return;
} // End of TICTACTOE::main_screen_deinit()


//************************************
// Function: TICTACTOE::in_game_init()
// Purpose: Initialize game playing
//************************************
void TICTACTOE::in_game_init()
{
	// 1 = Player 1, 2 = Player 2
	turn = 1; 

	// Of course, no one wins right away
	winner = 0; 

	// Start the VBL counter at 0
	vbl_count = 0;

	// How many open squares left
	open_squares = 9;

	// Initialize the background and sprites palettes
	ham_LoadBGPal((void *)board_240_160_Palette,256);
	ham_LoadObjPal((void *)objects_Palette,256);

	// Setup the tileset for our image
	ham_bg[0].ti = ham_InitTileSet((void *)board_240_160_Tiles,
		SIZEOF_16BIT(board_240_160_Tiles),1,1);
	
	// Setup the map for our image
	ham_bg[0].mi = ham_InitMapEmptySet(3,0);
	bg_one = ham_InitMapFragment((void *)board_240_160_Map,30,20,0,0,30,20,0);
	ham_InsertMapFragment(bg_one,0,0,0);
	
	// Display the background
	ham_InitBg(0,1,3,0);
	
	// Setup the "mouse" pointer
	my_pointer.x_pos = 63;
	my_pointer.y_pos = 63;
	my_pointer.image = ham_CreateObj((void *)&red_X_32_32_Bitmap,0,2,OBJ_MODE_NORMAL,
			1,0,0,0,0,0,0,my_pointer.x_pos,my_pointer.y_pos);
	
	// Every square in the board is unoccupied at first
	for (int i = 0; i < 9; ++i) {
		board[i] = 0;
	}

	// Setup all of the spots on the board
	spots[0].x_pos = 8;   spots[0].y_pos = 8;
	spots[1].x_pos = 63;  spots[1].y_pos = 8;
	spots[2].x_pos = 119; spots[2].y_pos = 8;
	spots[3].x_pos = 8;   spots[3].y_pos = 63;
	spots[4].x_pos = 63;  spots[4].y_pos = 63;
	spots[5].x_pos = 119; spots[5].y_pos = 63;
	spots[6].x_pos = 8;   spots[6].y_pos = 119;
	spots[7].x_pos = 63;  spots[7].y_pos = 119;
	spots[8].x_pos = 119; spots[8].y_pos = 119;

	return;
} // End of TICTACTOE::in_game_init()


//******************************************
// Function: TICTACTOE::in_game_query_keys()
// Purpose: Gets input during in_game()
//******************************************
void TICTACTOE::in_game_query_keys()
{
	// *** May not need this because of check at the end ***
	// Check to see if there was a winner
	if (is_winner()) {
		game_state = FINISH;
		return;
	}

	// *** May be able to move this to the A button check ***
	// Make sure there is an open square, else quit
	if (gos() < 1) {
		game_state = FINISH;
		return;
	}

	// Increment the VBL counter every VBL
	++vbl_count;

	// Two player version of input check
	if (players == 2 || (players == 1 && turn == 1)) {

		// SELECT
		if (F_CTRLINPUT_SELECT_PRESSED) {
			game_state = START; // Restart the entire TICTACTOE game
			return;
		}

		// UP-RIGHT
		if(vbl_count > 10 && F_CTRLINPUT_UP_PRESSED && F_CTRLINPUT_RIGHT_PRESSED) {
			if (my_pointer.y_pos != 8 && my_pointer.x_pos != 119) {
				vbl_count = 0;
				if (my_pointer.y_pos == 63) {
					my_pointer.y_pos = 8;
				} else {
					my_pointer.y_pos = 63;
				}
				if (my_pointer.x_pos == 63) {
					my_pointer.x_pos = 119;
				} else {
					my_pointer.x_pos = 63;
				}
			}
		}

		// DOWN-RIGHT
		if(vbl_count > 10 && F_CTRLINPUT_DOWN_PRESSED && F_CTRLINPUT_RIGHT_PRESSED) {
			if (my_pointer.y_pos != 119 && my_pointer.x_pos != 119) {
				vbl_count = 0;
				if (my_pointer.y_pos == 63) {
					my_pointer.y_pos = 119;
				} else {
					my_pointer.y_pos = 63;
				}
				if (my_pointer.x_pos == 63) {
					my_pointer.x_pos = 119;
				} else {
					my_pointer.x_pos = 63;
				}
			}
		}
	
		// DOWN-LEFT
		if(vbl_count > 10 && F_CTRLINPUT_DOWN_PRESSED && F_CTRLINPUT_LEFT_PRESSED) {
			if (my_pointer.y_pos != 119 && my_pointer.x_pos != 8) {
				vbl_count = 0;
				if (my_pointer.y_pos == 63) {
					my_pointer.y_pos = 119;
				} else {
					my_pointer.y_pos = 63;
				}
				if (my_pointer.x_pos == 63) {
					my_pointer.x_pos = 8;
				} else {
					my_pointer.x_pos = 63;
				}
			}
		}
	
		// UP-LEFT
		if(vbl_count > 10 && F_CTRLINPUT_UP_PRESSED && F_CTRLINPUT_LEFT_PRESSED) {
			if (my_pointer.y_pos != 8 && my_pointer.x_pos != 8) {
				vbl_count = 0;
				if (my_pointer.y_pos == 63) {
					my_pointer.y_pos = 8;
				} else {
					my_pointer.y_pos = 63;
				}
				if (my_pointer.x_pos == 63) {
					my_pointer.x_pos = 8;
				} else {
					my_pointer.x_pos = 63;
				}
			}
		}
	
		// UP only
		if(vbl_count > 10 && F_CTRLINPUT_UP_PRESSED && my_pointer.y_pos != 8) {
			vbl_count = 0;
			if (my_pointer.y_pos == 63) {
				my_pointer.y_pos = 8;
			} else {
				my_pointer.y_pos = 63;
			}
		}
		
		// RIGHT only
		if(vbl_count > 10 && F_CTRLINPUT_RIGHT_PRESSED && my_pointer.x_pos != 119) {
			vbl_count = 0;
			if (my_pointer.x_pos == 63) {
				my_pointer.x_pos = 119;
			} else {
				my_pointer.x_pos = 63;
			}
		}
		
		// DOWN only
		if(vbl_count > 10 && F_CTRLINPUT_DOWN_PRESSED && my_pointer.y_pos != 119) {
			vbl_count = 0;
			if (my_pointer.y_pos == 63) {
				my_pointer.y_pos = 119;
			} else {
				my_pointer.y_pos = 63;
			}
		}
	
		// LEFT only
		if(vbl_count > 10 && F_CTRLINPUT_LEFT_PRESSED && my_pointer.x_pos != 8) {
			vbl_count = 0;
			if (my_pointer.x_pos == 63) {
				my_pointer.x_pos = 8;
			} else {
				my_pointer.x_pos = 63;
			}
		}
	
		// A Button
		if (vbl_count > 10 && F_CTRLINPUT_A_PRESSED) {
			if (who(square(my_pointer.x_pos, my_pointer.y_pos)) == 0) {
				us = square(my_pointer.x_pos, my_pointer.y_pos);
				board[us] = turn; // Set the player occupying the spot
				--open_squares; // Decrement the number of open squares
				// Setup the image for the spot just taken
				if (turn == 1) {
					spots[us].image = ham_CreateObj((void *)&blue_X_32_32_Bitmap,0,2,OBJ_MODE_NORMAL,1,0,0,0,0,0,0,spots[us].x_pos,spots[us].y_pos);
					turn = 2;
				} else if (turn == 2) {
					spots[us].image = ham_CreateObj((void *)&blue_O_32_32_Bitmap,0,2,OBJ_MODE_NORMAL,1,0,0,0,0,0,0,spots[us].x_pos,spots[us].y_pos);
					turn = 1;
				}
			
				// If someone won or the board is full...
				if((is_winner()) || (gos() < 1)) {
					game_state = FINISH; // ... end the game
				}
			}
		}

		// B Button
		if (F_CTRLINPUT_B_PRESSED) {

		}
	// One player version of input check
	} else if (players == 1 && turn == 2) { 
		us = ai_move(this, skill); // Get a move from the AI handler
		board[us] = turn; // Set the player occupying the spot
		--open_squares; // Decrement the number of open squares
		// Setup the image for the spot just taken
		if (turn == 1) {
			spots[us].image = ham_CreateObj((void *)&blue_X_32_32_Bitmap,0,2,OBJ_MODE_NORMAL,1,0,0,0,0,0,0,spots[us].x_pos,spots[us].y_pos);
			turn = 2; // Change turns
		} else if (turn == 2) {
			spots[us].image = ham_CreateObj((void *)&blue_O_32_32_Bitmap,0,2,OBJ_MODE_NORMAL,1,0,0,0,0,0,0,spots[us].x_pos,spots[us].y_pos);
			turn = 1; // Change turns
		}
		
		// If someone won or the board is full...
		if((is_winner()) || (gos() < 1)) {
			game_state = FINISH; // ... end the game
		}
	} // End of if (players == x)

	return;
} // End of TICTACTOE::in_game_query_keys()


//********************************************
// Function: TICTACTOE::in_game_redraw()
// Purpose: Redraw the screen during in_game()
//********************************************
void TICTACTOE::in_game_redraw()
{
	// Only update if the game state didn't change during play
	if (game_state == PLAY) {
		// Change the "mouse" pointer's image
		if (turn == 1) {
			ham_UpdateObjGfx(my_pointer.image,(void *)&red_X_32_32_Bitmap);
		} else if (turn == 2) {
			ham_UpdateObjGfx(my_pointer.image,(void *)&red_O_32_32_Bitmap);
		}
		// Reset the "mouse" pointer's position if it just go moved
		ham_SetObjX(my_pointer.image,my_pointer.x_pos);
		ham_SetObjY(my_pointer.image,my_pointer.y_pos);
	}

	return;
} // End of TICTACTOE::in_game_redraw()


//**************************************
// Function: TICTACTOE::in_game_deinit()
// Purpose: Deinitialize game playing
//**************************************
void TICTACTOE::in_game_deinit()
{
	// Deinitialize the background and sprites
	ham_DeInitBg(0);
	ham_DeleteObj(my_pointer.image);
	
	// ... including each spot on the board
	for (int i = 0; i < 9; ++i) {
		ham_DeleteObj(spots[i].image);
	}

	// This must be called to actually delete the sprites
	ham_CopyObjToOAM();

	return;
} // End of TICTACTOE::in_game_deinit()


//***********************************
// Function: TICTACTOE::finish_init()
// Purpose: Displays the screen 
//          after tie, win or quit
//***********************************
void TICTACTOE::finish_init()
{
	// Start the VBL counter at 0
	vbl_count = 0;

	// Initialize the background palette
	ham_LoadBGPal((void *)fin_p1_Palette,256);

	// Choose which background to load based on the winner
	if (winner == 0) { // Tie Game
		// Setup the tileset for our image
		ham_bg[0].ti = ham_InitTileSet((void *)fin_tie_Tiles,
			SIZEOF_16BIT(fin_tie_Tiles),1,1);
		// Setup the map for our image
		ham_bg[0].mi = ham_InitMapEmptySet(3,0);
		bg_one = ham_InitMapFragment((void *)fin_tie_Map,30,20,0,0,30,20,0);
		ham_InsertMapFragment(bg_one,0,0,0);
	} else if (winner == 1) { // Player 1 won
		// Setup the tileset for our image
		ham_bg[0].ti = ham_InitTileSet((void *)fin_p1_Tiles,
			SIZEOF_16BIT(fin_p1_Tiles),1,1);
		// Setup the map for our image
		ham_bg[0].mi = ham_InitMapEmptySet(3,0);
		bg_one = ham_InitMapFragment((void *)fin_p1_Map,30,20,0,0,30,20,0);
		ham_InsertMapFragment(bg_one,0,0,0);
	} else if (winner == 2) { // Player 2 won
		// Setup the tileset for our image
		ham_bg[0].ti = ham_InitTileSet((void *)fin_p2_Tiles,
			SIZEOF_16BIT(fin_p2_Tiles),1,1);
		// Setup the map for our image
		ham_bg[0].mi = ham_InitMapEmptySet(3,0);
		bg_one = ham_InitMapFragment((void *)fin_p2_Map,30,20,0,0,30,20,0);
		ham_InsertMapFragment(bg_one,0,0,0);
	}
	
	// Display the background
	ham_InitBg(0,1,0,0);

	return;
} // End of TICTACTOE::finish_init()


//*********************************************
// Function: TICTACTOE::finish_query_keys()
// Purpose: Gets input during the finish screen
//*********************************************
void TICTACTOE::finish_query_keys()
{
	// Increment the VBL counter every VBL
	++vbl_count;

	// Wait for the user to press a key
	if (vbl_count > 10 && anykey()) {
		game_state = MAIN;
	}

	return;
} // End of finish_query_keys()


//*************************************
// Function: TICTACTOE::finish_deinit()
// Purpose: Deinitialize finish()
//*************************************
void TICTACTOE::finish_deinit()
{
	// Deinitialize the background and sprites
	ham_DeInitBg(0);

	return;
} // End of TICTACTOE::finish_deinit()


//********************************************
// Function: TICTACTOE::square()
// Purpose: Converts co-ords to board[] number
//********************************************
u8 TICTACTOE::square(u8 x, u8 y)
{
	if (x == 8 && y == 8) return 0;
	if (x == 63 && y == 8) return 1;
	if (x == 119 && y == 8) return 2;
	if (x == 8 && y == 63) return 3;
	if (x == 63 && y == 63) return 4;
	if (x == 119 && y == 63) return 5;
	if (x == 8 && y == 119) return 6;
	if (x == 63 && y == 119) return 7;
	if (x == 119 && y == 119) return 8;

	return 9; // Passed a bad number (or two)
} // End of TICTACTOE::square()


//***************************************************
// Function: TICTACTOE::who()
// Purpose: Returns 0 = unocc, 1 = P1, 2 = P2
//***************************************************
u8 TICTACTOE::who(u8 square)
{
	return board[square];

} // End of TICTACTOE::who()


//*********************************************
// Function: TICTACTOE::is_winner()
// Purpose: Checks to see if there was a winner
//*********************************************
bool TICTACTOE::is_winner()
{
	if (board[0] != 0 && board[0] == board[1] && board[0] == board[2]) {
		winner = board[0];
		return true;
	} else if (board[3] != 0 && board[3] == board[4] && board[3] == board[5]) {
		winner = board[3];
		return true;
	} else if (board[6] != 0 && board[6] == board[7] && board[6] == board[8]) {
		winner = board[6];
		return true;
	} else if (board[0] != 0 && board[0] == board[3] && board[0] == board[6]) {
		winner = board[0];
		return true;
	} else if (board[1] != 0 && board[1] == board[4] && board[1] == board[7]) {
		winner = board[1];
		return true;
	} else if (board[2] != 0 && board[2] == board[5] && board[2] == board[8]) {
		winner = board[2];
		return true;
	} else if (board[0] != 0 && board[0] == board[4] && board[0] == board[8]) {
		winner = board[0];
		return true;
	} else if (board[2] != 0 && board[2] == board[4] && board[2] == board[6]) {
		winner = board[2];
		return true;
	}

	return false;
} // End of TICTACTOE::is_winner()


//****************************
// Function: TICTACTOE::gs()
// Purpose: Returns game_state
//****************************
TICTACTOE::states TICTACTOE::gs()
{
	return game_state;
} // End of TICTACTOE::gs()


//**************************
// Function: TICTACTOE::gt()
// Purpose: Returns turn
//**************************
u8 TICTACTOE::gt()
{
	return turn;
} // End of TICTACTOE::gt()


//******************************
// Function: TICTACTOE::gos()
// Purpose: Returns open_squares
//******************************
u8 TICTACTOE::gos() 
{
	return open_squares;
} // End of TICTACTOE::gos()


//**************************
// Function: TICTACTOE::gw()
// Purpose: Returns winner
//**************************
u8 TICTACTOE::gw()
{
	return winner;
} // End of TICTACTOE::gw()


//************************************************
// Function: TICTACTOE::check_samples()
// Purpose: Make sure the correct music is playing
//************************************************
void TICTACTOE::check_samples()
{
	if ((game_state == START) && (start_screen_slide == 0)) {
		if(!mysample[1]->playing) ham_PlaySample(mysample[1]);
	} else if (game_state == MAIN || game_state == PLAY || game_state == FINISH) {
		if(!mysample[0]->playing) ham_PlaySample(mysample[0]);
	}

	return;
} // End of TICTACTOE::check_samples()


//************************************
// Function: anykey()
// Purpose: True if any key is pressed
//************************************
bool anykey()
{
	return (F_CTRLINPUT_DOWN_PRESSED || F_CTRLINPUT_LEFT_PRESSED || F_CTRLINPUT_A_PRESSED ||
		F_CTRLINPUT_UP_PRESSED || F_CTRLINPUT_RIGHT_PRESSED || F_CTRLINPUT_B_PRESSED ||
		F_CTRLINPUT_START_PRESSED || F_CTRLINPUT_SELECT_PRESSED);
} // End of anykey()