//*****************************************
// Filename: game.cpp
// Author: Aaron Rogers
// Updated: 11/04/02
// Purpose: Hearts game AI
//*****************************************
// This file is part of HAM Tutorial Hearts
// Copyright 2002 Aaron Rogers
// See README.txt for more information
//*****************************************


// Library Includes
#include "ai.h"
#include "game.h"
#include "splash.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/hearts.map.c" // gfx2gba -fsrc -m -phearts.pal -t8 hearts.bmp
#include "gfx/hearts.pal.c"
#include "gfx/hearts.raw.c"
#include "gfx/board.map.c" // gfx2gba -fsrc -m -pboard.pal -t8 board.bmp
#include "gfx/board.pal.c"
#include "gfx/board.raw.c"
#include "gfx/main_menu.pal.c" // Generated from all of the main_menu bitmaps
#include "gfx/main_menu_op.raw.c" // gfx2gba -D -fsrc -pmain_menu.pal -t1 -a34 *.bmp
#include "gfx/main_menu_qg.raw.c" // gfx2gba -D -fsrc -pmain_menu.pal -t1 -a34 *.bmp
#include "gfx/main_menu_rg.raw.c" // gfx2gba -D -fsrc -pmain_menu.pal -t1 -a34 *.bmp
#include "gfx/options.pal.c" // Generated from all of the options bitmaps
#include "gfx/options_sl.raw.c" // gfx2gba -a34 -D -fsrc -poptions.pal -t1 *.bmp
#include "gfx/options_so.raw.c" // gfx2gba -a34 -D -fsrc -poptions.pal -t1 *.bmp
#include "gfx/options_mu.raw.c" // gfx2gba -a34 -D -fsrc -poptions.pal -t1 *.bmp
#include "gfx/score.pal.c" // gfx2gba -a34 -fsrc -m -pscore.pal -t8 score.bmp
#include "gfx/score.map.c" // gfx2gba -a34 -fsrc -m -pscore.pal -t8 score.bmp
#include "gfx/score.raw.c" // gfx2gba -a34 -fsrc -m -pscore.pal -t8 score.bmp
#include "gfx/game_over.pal.c" // Generated from all of the game_over bitmaps
#include "gfx/game_over_p1.map.c" // gfx2gba -fsrc -m -t8 *.bmp
#include "gfx/game_over_p1.raw.c"
#include "gfx/game_over_p2.map.c" // gfx2gba -fsrc -m -t8 *.bmp
#include "gfx/game_over_p2.raw.c"
#include "gfx/game_over_p3.map.c" // gfx2gba -fsrc -m -t8 *.bmp
#include "gfx/game_over_p3.raw.c"
#include "gfx/game_over_p4.map.c" // gfx2gba -fsrc -m -t8 *.bmp
#include "gfx/game_over_p4.raw.c"
#include "gfx/game_over_tie.map.c" // gfx2gba -fsrc -m -t8 *.bmp
#include "gfx/game_over_tie.raw.c"


// Sprites
#include "gfx/in_game_objects.pal.c" // Generated (separately) from the following sprites
#include "gfx/card_back.raw.c" // gfx2gba -D -fsrc -pin_game_objects.pal -t8 *.bmp
#include "gfx/card_deck.raw.c" // gfx2gba -D -fsrc -pin_game_objects.pal -t8 *.bmp
#include "gfx/card_deck_64.raw.c" // gfx2gba -D -fsrc -pin_game_objects.pal -t8 *.bmp
#include "gfx/card_deck_grey.raw.c" // gfx2gba -D -fsrc -pin_game_objects.pal -t8 *.bmp
#include "gfx/card_deck_orange.raw.c" // gfx2gba -D -fsrc -pin_game_objects.pal -t8 *.bmp
#include "gfx/go.raw.c" // gfx2gba -D -fsrc -pin_game_objects.pal -t8 *.bmp
#include "gfx/pass_across.raw.c" // gfx2gba -D -fsrc -pin_game_objects.pal -t8 *.bmp
#include "gfx/pass_left.raw.c" // gfx2gba -D -fsrc -pin_game_objects.pal -t8 *.bmp
#include "gfx/pass_right.raw.c" // gfx2gba -D -fsrc -pin_game_objects.pal -t8 *.bmp

#include "gfx/options_sprites.pal.c" // Generated (separately) from the following sprites
#include "gfx/op_1.raw.c" // gfx2gba -D -fsrc -t8 op_1.bmp
#include "gfx/op_2.raw.c" // gfx2gba -D -fsrc -t8 op_2.bmp
#include "gfx/op_3.raw.c" // gfx2gba -D -fsrc -t8 op_3.bmp
#include "gfx/on.raw.c" // gfx2gba -D -fsrc -t8 on.bmp
#include "gfx/off.raw.c" // gfx2gba -D -fsrc -t8 off.bmp

#include "gfx/numbers_new.pal.c" // gfx2gba -D -fsrc -pnumbers_new.pal -t8 numbers_new.bmp
#include "gfx/numbers_new.raw.c" // gfx2gba -D -fsrc -pnumbers_new.pal -t8 numbers_new.bmp


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

  // Seed the random function only once
  seed = true;

} // End of HEARTS::HEARTS()


//*****************************
// Function: HEARTS::init()
// Purpose: Initialize the game
//*****************************
void HEARTS::init()
{
  // Initialize HAMlib
  ham_Init();

  // Setup the background mode
  ham_SetBgMode(1);

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

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

  // Turn the sound off at first
  sound = 0;

  // Turn the music off at first
  music = 0;

  // Setup the 64 pixel card pointer
  big_card = false;

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


//*****************************************
// Function: HEARTS::start_screen_init()
// Purpose: Initialize the start screen
//*****************************************
void HEARTS::start_screen_init()
{
  // Set the tileset for the 'HAM Tutorial' screen
  ham_bg[0].ti = ham_InitTileSet((void *)ham_tut_Tiles,
   SIZEOF_16BIT(ham_tut_Tiles),1,1);
  ham_bg[0].mi = ham_InitMapSet((void *)ham_tut_Map,1024,0,0);

  // Display the background
  ham_InitBg(0,1,0,0);

  // Used for the fading backgrounds
  CSplash *ham_tut_Splash = new CSplash;

  // Fade in the 'HAM Tutorial' screen
  ham_tut_Splash->Init();
  //ham_tut_Splash->SetTexture((u8*)ham_tut_Bitmap);
  ham_tut_Splash->SetPalette((u16*)ham_tut_Palette);
  ham_tut_Splash->SetFadeSpeed(3);
  ham_tut_Splash->FadeIn();
  ham_tut_Splash->WaitFrames(100*64);
  ham_tut_Splash->FadeOut();
  ham_tut_Splash->WaitFrames(100*16);

  // Deinitialize the background
  ham_DeInitBg(0);

  // Set the tileset for the 'Hearts' screen
  ham_bg[0].ti = ham_InitTileSet((void *)hearts_Tiles,
   SIZEOF_16BIT(hearts_Tiles),1,1);
  ham_bg[0].mi = ham_InitMapSet((void *)hearts_Map,1024,0,0);

  // Display the background
  ham_InitBg(0,1,0,0);

  // Used for the fading backgrounds
  CSplash *hearts_Splash = new CSplash;

  // Fade in 'Hearts' screen
  hearts_Splash->Init();
  //hearts_Splash->SetTexture((u8*)hearts_Bitmap);
  hearts_Splash->SetPalette((u16*)hearts_Palette);
  hearts_Splash->SetFadeSpeed(3);
  hearts_Splash->FadeIn();
  hearts_Splash->WaitFrames(100*64);
  hearts_Splash->FadeOut();
  hearts_Splash->WaitFrames(100*16);

  // Change the game state
  game_state = MAIN; // *** should be main ***

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


//********************************************
// Function: HEARTS::start_screen_query_keys()
// Purpose: Gets input during start_screen()
//********************************************
void HEARTS::start_screen_query_keys()
{
  return;
} // End of HEARTS::start_screen_query_keys()


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

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


//****************************************
// Function: HEARTS::main_screen_init()
// Purpose: Initialize the main screen
//****************************************
void HEARTS::main_screen_init()
{
  // Setup the background mode
  ham_SetBgMode(4);

  // Setup variables to keep track of screens
  curr_screen = 0;
  last_screen = 0;

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

  // Set the round to zero
  round = 0; // *** increment at the end of a game ***

  // Set everyone's score to 0
  for (u8 i = 0; i < 4; ++i) Total_Score[i] = 0;

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

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

  // Display the image
  TOOL_DMA1_SET(&main_menu_qg_Bitmap,
   MEM_BG_PTR,SIZEOF_32BIT(main_menu_qg_Bitmap),
   DMA_TRANSFER_32BIT,
   DMA_STARTAT_NOW);

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


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

  // START or A button
  if (vbl_count > 10 && (F_CTRLINPUT_START_PRESSED || F_CTRLINPUT_A_PRESSED)) {
   // See if we seeded the random function or not
   if (!seed) {
   // Keep calling random to keep things random
   flash_count = rand()%1000;
   } else {
   // No need to seed anymore
   seed = false;

   // Seed the random function
   srand(vbl_count);
   }

   // Make sure to do this after seeding the random function
   vbl_count = 0;

   // Change the game state
   if (curr_screen == 0) { // Quick Game
game_state = PLAY;
   // Reset everything
   ham_Init();
   } else if (curr_screen == 1) { // Regular Game
   } else if (curr_screen == 2) { // Options screen
   game_state = OPTIONS;
   }
  }

  // UP
  if (vbl_count > 10 && F_CTRLINPUT_UP_PRESSED) {
   vbl_count = 0;
   last_screen = curr_screen;
   if (curr_screen == 0) {
   curr_screen = 2;
   } else {
   --curr_screen;
   }
  }

  // DOWN
  if (vbl_count > 10 && F_CTRLINPUT_DOWN_PRESSED) {
   vbl_count = 0;
   last_screen = curr_screen;
   if (curr_screen == 2) {
   curr_screen = 0;
   } else {
   ++curr_screen;
   }
  }

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


//************************************************
// Function: HEARTS::main_screen_redraw()
// Purpose: Redraw the screen during main_screen()
//************************************************
void HEARTS::main_screen_redraw()
{
  // See if changes were made
  if (last_screen != curr_screen) {
   if (curr_screen == 0) {
   // Display the image
   TOOL_DMA1_SET(&main_menu_qg_Bitmap,
   MEM_BG_PTR,SIZEOF_32BIT(main_menu_qg_Bitmap),
   DMA_TRANSFER_32BIT,
   DMA_STARTAT_NOW);
   } else if (curr_screen == 1) {
   // Display the image
   TOOL_DMA1_SET(&main_menu_rg_Bitmap,
   MEM_BG_PTR,SIZEOF_32BIT(main_menu_rg_Bitmap),
   DMA_TRANSFER_32BIT,
   DMA_STARTAT_NOW);
   } else if (curr_screen == 2) {
   // Display the image
   TOOL_DMA1_SET(&main_menu_op_Bitmap,
   MEM_BG_PTR,SIZEOF_32BIT(main_menu_op_Bitmap),
   DMA_TRANSFER_32BIT,
   DMA_STARTAT_NOW);
   }
   last_screen = curr_screen; // Set them equal - this means there was no input change
  }

  return;
} // End of HEARTS::main_screen_redraw()


//******************************************
// Function: HEARTS::main_screen_deinit()
// Purpose: Deinitialize the main screen
//******************************************
void HEARTS::main_screen_deinit()
{

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


//************************************
// Function: HEARTS::in_game_init()
// Purpose: Initialize game playing
//************************************
void HEARTS::in_game_init()
{
  // Setup the background mode
  ham_SetBgMode(1);

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

  // Used to cycle through the deck
  deck_spot = 0;

  // Start the pointer on the first card
  my_pnt_card = 0;

  // In round 3, no cards need to be selected to pass
  if (round != 3) {
   pass_three = 0;
  } else {
   pass_three = 5;
  }

  // If it's not the fourth ruond, the first stage
  // of a trick is passing three cards
  if (round != 3) {
   choose_three = true;
  } else {
   choose_three = false;
  }

  // Setup the first trick
  first_trick = true;

  // This is false until a Heart is played
  hearts_broken = false;

  // There are no cards played yet
  trick_cards = 0;

  // Start off on the first trick
  tricks = 1;

  // Setup the four trick cards locations
  T[0].x_pos = 100; // Player 1
  T[0].y_pos = 82;
  T[1].x_pos = 65; // Player 2
  T[1].y_pos = 62;
  T[2].x_pos = 100; // Player 3
  T[2].y_pos = 42;
  T[3].x_pos = 136; // Player 4
  T[3].y_pos = 62;

  // Setup the locations for the 'pass xxx'/'go' sprites
  pass_xxx[0].x_pos = 87;
  pass_xxx[0].y_pos = 47;

  // Create the 'pass_xxx'/'go' sprite right away
  create_pass_xxx = true;
  delete_go = false;
  flash_pass_xxx = 0; // Flashing off
  flash_go = 0; // Flashing off

  // Set all the cards to blank
  for (u8 i = 0; i < 4; ++i) {
   Trick[i].number = 0;
   Trick[i].suit = 0;
  }

  // Set everyone's hand score to 0
  for (u8 i = 0; i < 4; ++i) {
   Hand_Score[i] = 0;
  }

  // Make sure Passed_Cards[] is empty
  for (u8 i = 0; i < 12; ++i) {
   Passed_Cards[i] = 13;
  }

  // Setup the deck of cards
  // Go through and initialize the deck to empty
  for (u8 i = 0; i < 52; ++i) {
   Deck[i].number = 0;
   Deck[i].suit = 0;
  }

  // Setup a temporary deck
  Card Temp_Deck[52];

  // Fill in the temporary deck first
  u8 n = 2; // Number (2 - 14)
  u8 s = 0; // Suit (0 - 3)
  for (u8 i = 0; i < 52; ++i) {
   Temp_Deck[i].number = n;
   Temp_Deck[i].suit = s;
   ++n;
   if (n == 15) {
   n = 2; // Cards must be 2 - 14
   ++s; // After the Ace, increment the suit
   }
   //if (s == 4) s = 0; // The suit must be 0 - 3
  }
  // Randomly move the cards into the actual deck
  u8 spot;
  for (u8 i = 0; i < 52; ++i) {
   // Get a random spot in the deck
   spot = rand()%52;
   // Make sure the spot is open
   while (Deck[spot].number != 0) {
   ++spot; // Otherwise move to the next spot
   if (spot == 52) spot = 0;
   }

   // Copy the card to the open spot
   Deck[spot].number = Temp_Deck[i].number;
   Deck[spot].suit = Temp_Deck[i].suit;
  }

  // Setup the hand for each player
  for (u8 i = 0; i < 13; ++i) {
   Player1[i].number = Deck[i].number; // The card number (2-14)
   Player1[i].suit = Deck[i].suit; // The card suit (0-3)
   Player2[i].number = Deck[(i+13)].number;
   Player2[i].suit = Deck[(i+13)].suit;
   Player3[i].number = Deck[(i+26)].number;
   Player3[i].suit = Deck[(i+26)].suit;
   Player4[i].number = Deck[(i+39)].number;
   Player4[i].suit = Deck[(i+39)].suit;
  }

  // Sort the hands
  hand_sort(1);
  hand_sort(2);
  hand_sort(3);
  hand_sort(4);

  // Get computer players ready to pass cards
  if (players == 1 && round != 3) {
   ai_setup_passed_cards(this, skill);
  }

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

  // Setup the tileset for our image
  ham_bg[0].ti = ham_InitTileSet((void *)board_Tiles,
   SIZEOF_16BIT(board_Tiles),1,1);

  // Setup the map for our image
  ham_bg[0].mi = ham_InitMapEmptySet(3,0);
  bg_one = ham_InitMapFragment((void *)board_Map,30,20,0,0,30,20,0);
  ham_InsertMapFragment(bg_one,0,0,0);

  // Display the background
  ham_InitBg(0,1,3,0);

  // Larger version of the card used as a pointer
  Card_64[0].x_pos = 40; // 209
  Card_64[0].y_pos = 140; // 134
  graphic_spot = convert_card_64(Player1[0].number, Player1[0].suit);
  Card_64[0].slot = ham_CreateObj((void *)&card_deck_64_Bitmap[graphic_spot],0,3,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,Card_64[0].x_pos,Card_64[0].y_pos);
  // Hide it if necessary
  if (!big_card) {
   ham_SetObjVisible(Card_64[0].slot, 0);
  }

  // Setup the graphics for all four players' cards
  for (u8 i = 0; i < 13; ++i) {
   P1[i].x_pos = 40 + (i)*10;
   P1[i].y_pos = 121;

   graphic_spot = convert_card(Player1[i].number, Player1[i].suit);
   P1[i].slot = ham_CreateObj((void *)&card_deck_Bitmap[graphic_spot],0,2,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,P1[i].x_pos,P1[i].y_pos);
   // Swap the sprite priorities
   if (i > 0) {
   ham_SetObjBefore(P1[i].slot, P1[i-1].slot);
   }

   P2[i].x_pos = 5;
   P2[i].y_pos = 2 + (i)*10;

   P3[i].x_pos = 40 + (i)*10;
   P3[i].y_pos = 2;

   P4[i].x_pos = 200;
   P4[i].y_pos = 2 + (i)*10;

   if (i == 0) {
   P2[0].slot = ham_CreateObj((void *)&card_back_Bitmap[0],0,2,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,P2[0].x_pos,P2[0].y_pos);
   P3[0].slot = ham_CreateObj((void *)&card_back_Bitmap[0],0,2,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,P3[0].x_pos,P3[0].y_pos);
   P4[0].slot = ham_CreateObj((void *)&card_back_Bitmap[0],0,2,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,P4[0].x_pos,P4[0].y_pos);
   } else {
   P2[i].slot = ham_CloneObj(P2[0].slot,P2[i].x_pos,P2[i].y_pos);
   P3[i].slot = ham_CloneObj(P2[0].slot,P3[i].x_pos,P3[i].y_pos);
   P4[i].slot = ham_CloneObj(P2[0].slot,P4[i].x_pos,P4[i].y_pos);

   // Swap the sprite priorities
   ham_SetObjBefore(P4[i].slot, P4[i-1].slot);
   }
  }

  // Swap the image of the first card (to make it grey)
  graphic_spot = convert_card(Player1[0].number, Player1[0].suit);
  ham_UpdateObjGfx(P1[0].slot,(void *)&card_deck_grey_Bitmap[graphic_spot]);

  // In the fourth round no cards are passed so we need to
  // figure out who goes first ahead of time
  if (round == 3) {
   setup_leader();
   turn = leader;
  }

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


//******************************************
// Function: HEARTS::in_game_query_keys()
// Purpose: Gets input during in_game()
//******************************************
void HEARTS::in_game_query_keys()
{
  // Increment the VBL counter every VBL
  ++vbl_count;

  // Increment the counter to flash sprites
  if (flash_pass_xxx != 0 || flash_go != 0) ++flash_count;

  // Create the 'pass_xxx' sprite
  // Pass left
  if ((round == 0) && (pass_three < 3) && (create_pass_xxx)) {
   create_pass_xxx = false;
   flash_pass_xxx = 1; // Start flashing
   pass_xxx[0].slot = ham_CreateObj((void *)&pass_left_Bitmap[0],0,3,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,pass_xxx[0].x_pos,pass_xxx[0].y_pos);
  } else if ((round == 0) && (pass_three == 3)) {
   //ham_SetObjVisible(pass_xxx[0].slot, 1);
   ham_DeleteObj(pass_xxx[0].slot); // Delete the 'pass_xxx' sprite
   flash_pass_xxx = 0; // Stop flashing
  // Pass right
  } else if ((round == 1) && (pass_three < 3) && (create_pass_xxx)) {
   create_pass_xxx = false;
   flash_pass_xxx = 1; // Start flashing
   pass_xxx[0].slot = ham_CreateObj((void *)&pass_right_Bitmap[0],0,3,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,pass_xxx[0].x_pos,pass_xxx[0].y_pos);
  } else if ((round == 1) && (pass_three == 3)) {
   //ham_SetObjVisible(pass_xxx[0].slot, 1);
   ham_DeleteObj(pass_xxx[0].slot); // Delete the 'pass_xxx' sprite
   flash_pass_xxx = 0; // Stop flashing
  // Pass Across
  } else if ((round == 2) && (pass_three < 3) && (create_pass_xxx)) {
   create_pass_xxx = false;
   flash_pass_xxx = 1; // Start flashing
   pass_xxx[0].slot = ham_CreateObj((void *)&pass_across_Bitmap[0],0,3,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,pass_xxx[0].x_pos,pass_xxx[0].y_pos);
  } else if ((round == 2) && (pass_three == 3)) {
   // ham_SetObjVisible(pass_xxx[0].slot, 1);
   ham_DeleteObj(pass_xxx[0].slot); // Delete the 'pass_xxx' sprite
   flash_pass_xxx = 0; // Stop flashing
  }

  // Flash the 'pass_xxx' srite on or off
  if ((flash_count%20 == 0) && (flash_pass_xxx != 0)) { // Every 20 frames
   if (flash_pass_xxx == 1) { // Flash on
   flash_pass_xxx = 2; // Flash off next time
   ham_SetObjVisible(pass_xxx[0].slot, 1);
   } else if (flash_pass_xxx == 2) { // Flash off
   flash_pass_xxx = 1; // Flash on next time
   ham_SetObjVisible(pass_xxx[0].slot, 0);
   }
  }

  // If it's the fourth round and Player 1 has the 2 of Clubs, create the 'Go!' sprite
  if (round == 3 && first_trick && trick_cards == 0 && leader == 1 && !delete_go) {
   flash_go = 1;
   delete_go = true;
   pass_xxx[0].slot = ham_CreateObj((void *)&go_Bitmap[0],0,3,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,pass_xxx[0].x_pos,pass_xxx[0].y_pos);
  }

  // Flash the 'Go!' srite on or off
  if ((flash_count%20 == 0) && (flash_go != 0)) { // Every 20 frames
   if (flash_go == 1) { // Flash on
   flash_go = 2; // Flash off next time
   ham_SetObjVisible(pass_xxx[0].slot, 1);
   } else if (flash_go == 2) { // Flash off
   flash_go = 1; // Flash on next time
   ham_SetObjVisible(pass_xxx[0].slot, 0);
   }
  }

  // SELECT
  if (vbl_count > 5 && F_CTRLINPUT_SELECT_PRESSED) {
   vbl_count = 0;
   game_state = START; // Restart the entire HEARTS game
   return;
  }

  // One player version of input check
  if (choose_three || pass_three == 4 || turn == 1) {

   // START
   if (vbl_count > 10 && F_CTRLINPUT_START_PRESSED) {
   vbl_count = 0;
   if (first_trick && pass_three == 3) {
   // Pass the cards
   pass_cards();
   // Save the card that came into the spots that you passed out
   Card temp_passed[3];
   temp_passed[0].number = Player1[Passed_Cards[0]].number;
   temp_passed[0].suit = Player1[Passed_Cards[0]].suit;
   temp_passed[1].number = Player1[Passed_Cards[1]].number;
   temp_passed[1].suit = Player1[Passed_Cards[1]].suit;
   temp_passed[2].number = Player1[Passed_Cards[2]].number;
   temp_passed[2].suit = Player1[Passed_Cards[2]].suit;
   // Sort the hand
   hand_sort(1);
   // Update the graphic for the card in the corner
   graphic_spot = convert_card_64(Player1[0].number, Player1[0].suit);
   ham_UpdateObjGfx(Card_64[0].slot,(void *)&card_deck_64_Bitmap[graphic_spot]);
   Card_64[0].x_pos = P1[0].x_pos;
   ham_SetObjX(Card_64[0].slot, Card_64[0].x_pos);
   // Find the cards in their new spots
   for (u8 i = 0; i < 13; ++i) {
   // Move all of the cards down at first
   P1[i].y_pos = 121;
   ham_SetObjY(P1[i].slot,P1[i].y_pos);
   // Update the graphics for every card
   graphic_spot = convert_card(Player1[i].number, Player1[i].suit);
   ham_UpdateObjGfx(P1[i].slot,(void *)&card_deck_Bitmap[graphic_spot]);
   if (Player1[i].number == temp_passed[0].number && Player1[i].suit == temp_passed[0].suit) {
   // Move the card up if it matches
   P1[i].y_pos = 110;
   ham_SetObjY(P1[i].slot,P1[i].y_pos);
   } else if (Player1[i].number == temp_passed[1].number && Player1[i].suit == temp_passed[1].suit) {
   // Move the card up if it matches
   P1[i].y_pos = 110;
   ham_SetObjY(P1[i].slot,P1[i].y_pos);
   } else if (Player1[i].number == temp_passed[2].number && Player1[i].suit == temp_passed[2].suit) {
   // Move the card up if it matches
   P1[i].y_pos = 110;
   ham_SetObjY(P1[i].slot,P1[i].y_pos);
   }
   }
   // Done choosing three cards
   choose_three = false;
   // Using pass_three as a temp variable
   ++pass_three;
   } else if (first_trick && pass_three == 4) {
   // Update the graphics for all of the cards
   for (u8 i = 0; i < 13; ++i) {
   // Make sure all of the cards are moved down
   P1[i].y_pos = 121;
   ham_SetObjY(P1[i].slot,P1[i].y_pos);
   }
   // Move my_pnt_card back to the first spot
   my_pnt_card = 0;
   // Swap the image of the first card (to make it grey)
   graphic_spot = convert_card(Player1[0].number, Player1[0].suit);
   ham_UpdateObjGfx(P1[0].slot,(void *)&card_deck_grey_Bitmap[graphic_spot]);
   // Decide who leads first
   setup_leader();
   // Create the 'go' sprite
   if (first_trick && leader == 1) {
   flash_go = 1;
   delete_go = true;
   pass_xxx[0].slot = ham_CreateObj((void *)&go_Bitmap[0],0,3,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,pass_xxx[0].x_pos,pass_xxx[0].y_pos);
   }
   // To start the trick, turn = leader
   turn = leader;
   // Increment pass_three so it will no longer be processed
   ++pass_three;
   }
   }

   // RIGHT only
   if(vbl_count > 5 && F_CTRLINPUT_RIGHT_PRESSED && pass_three != 4) {
   vbl_count = 0;
   if (Player1[my_pnt_card].number != 0) {
   // Change the current card to white
   graphic_spot = convert_card(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(P1[my_pnt_card].slot,(void *)&card_deck_Bitmap[graphic_spot]);
   // Then move the card one to the right
   if (my_pnt_card != 12) {
   ++my_pnt_card;
   } else {
   my_pnt_card = 0;
   }
   }
   // Move the pointer to a valid spot
   while (Player1[my_pnt_card].number == 0) {
   if (my_pnt_card != 12) {
   ++my_pnt_card;
   } else {
   my_pnt_card = 0;
   }
   }
   // Change the new card to grey
   graphic_spot = convert_card(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(P1[my_pnt_card].slot,(void *)&card_deck_grey_Bitmap[graphic_spot]);
   // Update the graphic for the card in the corner
   Card_64[0].x_pos = P1[my_pnt_card].x_pos;
   ham_SetObjX(Card_64[0].slot, P1[my_pnt_card].x_pos);
   graphic_spot = convert_card_64(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(Card_64[0].slot,(void *)&card_deck_64_Bitmap[graphic_spot]);
   }

   // LEFT only
   if(vbl_count > 5 && F_CTRLINPUT_LEFT_PRESSED && pass_three != 4) {
   vbl_count = 0;
   if (Player1[my_pnt_card].number != 0) {
   // Change the current card to white
   graphic_spot = convert_card(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(P1[my_pnt_card].slot,(void *)&card_deck_Bitmap[graphic_spot]);
   // Then move the card one to the left
   if (my_pnt_card != 0) {
   --my_pnt_card;
   } else {
   my_pnt_card = 12;
   }
   }
   // Move the pointer to a valid spot
   while (Player1[my_pnt_card].number == 0) {
   if (my_pnt_card != 0) {
   --my_pnt_card;
   } else {
   my_pnt_card = 12;
   }
   }
   // Change the new card to grey
   graphic_spot = convert_card(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(P1[my_pnt_card].slot,(void *)&card_deck_grey_Bitmap[graphic_spot]);
   // Update the graphic for the card in the corner
   Card_64[0].x_pos = P1[my_pnt_card].x_pos;
   ham_SetObjX(Card_64[0].slot, P1[my_pnt_card].x_pos);
   graphic_spot = convert_card_64(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(Card_64[0].slot,(void *)&card_deck_64_Bitmap[graphic_spot]);
   }

   // A Button
   if (vbl_count > 10 && F_CTRLINPUT_A_PRESSED) {
   vbl_count = 0;
   // Check whether it's the first phase of a trick - passing three cards
   if (choose_three) {
   // Move the card up & get it ready to pass
   if ((P1[my_pnt_card].y_pos == 121) && (pass_three < 3)) {
   P1[my_pnt_card].y_pos = 110; // Move up
   Passed_Cards[pass_three] = my_pnt_card;
   ++pass_three; // Increment the 'cards chosen' counter
   // Move the card down, don't pass that card
   } else if (P1[my_pnt_card].y_pos == 110) {
   P1[my_pnt_card].y_pos = 121; // Move down
   --pass_three; // Decrement the 'cards chosen' counter
   for (u8 i = 0; i < 3; ++i) {
   if (Passed_Cards[i] == my_pnt_card) {
   u8 j = i;
   while (j != 2) {
   Passed_Cards[j] = Passed_Cards[j+1];
   ++j;
   }
   Passed_Cards[2] = 13;
   }
   }
   }
   ham_SetObjY(P1[my_pnt_card].slot,P1[my_pnt_card].y_pos);
   } else { // Otherwise, try to play the card
   if (turn == 1 && trick_cards != 4) {
   // Move that card into the trick
   if (!first_trick || trick_cards != 0 ||
   (first_trick && Player1[my_pnt_card].number == 2 // 2 of Clubs
   && Player1[my_pnt_card].suit == 1)) {
   // Add the card to Trick[] if it is a valid card
   if ((Player1[my_pnt_card].number != 0) && valid_move(1, my_pnt_card)) {
   // Delete the 'go' sprite
   if (delete_go) {
   flash_go = 0; // Don't flash 'go' sprite anymore
   delete_go = false; // Don't try to delete 'go' sprite anymore
   ham_DeleteObj(pass_xxx[0].slot); // Delete the 'go' sprite
   }
   // Move the card into the trick
   add_card_to_trick(my_pnt_card);
   // If it is a Heart, make sure we know Hearts have been broken
   if ((!hearts_broken) && (Trick[0].suit == 2)) hearts_broken = true;
   // Move the card up
   graphic_spot = convert_card(Trick[0].number, Trick[0].suit);
   if (Trick[0].suit == 2 || (Trick[0].number == 12 && Trick[0].suit == 0)) {
T[0].slot = ham_CreateObj((void *)&card_deck_orange_Bitmap[graphic_spot],0,2,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,T[0].x_pos,T[0].y_pos);
   } else {
   T[0].slot = ham_CreateObj((void *)&card_deck_Bitmap[graphic_spot],0,2,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,T[0].x_pos,T[0].y_pos);
   }
   // Hide the old card location
   ham_DeleteObj(P1[my_pnt_card].slot);
   // Remove the old card's info
   remove_card(1, my_pnt_card);
   // If Player 1 lead, setup suit_lead
   if (leader == 1) {
   suit_lead = Trick[0].suit;
   }
   // Increment turn
   if (turn == 4) {
   turn = 1;
   } else {
   ++turn;
   }
   // Increment trick_cards
   ++trick_cards;
   // Move the card to a new spot
   if (tricks != 13) {
   if (my_pnt_card == 12) {
   my_pnt_card = 0;
   } else {
   ++my_pnt_card;
   }
   // If it's empty, keep it moving
   while (Player1[my_pnt_card].number == 0) {
   if (my_pnt_card == 12) {
   my_pnt_card = 0;
   } else {
   ++my_pnt_card;
   }
   }
   // Change the new card to grey
   graphic_spot = convert_card(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(P1[my_pnt_card].slot,(void *)&card_deck_grey_Bitmap[graphic_spot]);
   // Update the graphic for the card in the corner
   Card_64[0].x_pos = P1[my_pnt_card].x_pos;
   ham_SetObjX(Card_64[0].slot, P1[my_pnt_card].x_pos);
   graphic_spot = convert_card_64(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(Card_64[0].slot,(void *)&card_deck_64_Bitmap[graphic_spot]);
   }
   }
   }
   }
   }
   } // End of A Button

   // B Button
   if (vbl_count > 10 && F_CTRLINPUT_B_PRESSED) {
   vbl_count = 0;
   if (!big_card) {
   // Update the graphic for the card in the corner
   Card_64[0].x_pos = P1[my_pnt_card].x_pos;
   ham_SetObjX(Card_64[0].slot, P1[my_pnt_card].x_pos);
   graphic_spot = convert_card_64(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(Card_64[0].slot,(void *)&card_deck_64_Bitmap[graphic_spot]);
   ham_SetObjVisible(Card_64[0].slot, 1);
   big_card = true;
   } else if (big_card) {
   ham_SetObjVisible(Card_64[0].slot, 0);
   big_card = false;
   }
   }
  } else if (turn != 1 && trick_cards != 4) {
   // Have the computer pick a card to play
   ai_card = ai_choose_card(this, skill);
   // Move that card into the trick
   add_card_to_trick(ai_card);
   // Hide the old card location // *** not sure about this ***
   if (turn == 2) {
   ham_DeleteObj(P2[ai_card].slot);
   }
   if (turn == 3) {
   ham_DeleteObj(P3[ai_card].slot);
   }
   if (turn == 4) {
   ham_DeleteObj(P4[ai_card].slot);
   }
   // Update sprites
   ham_CopyObjToOAM();
   // If it is a Heart, make sure we know Hearts have been broken
   if ((!hearts_broken) && (Trick[turn-1].suit == 2)) hearts_broken = true;
   // Move the card up
   graphic_spot = convert_card(Trick[turn-1].number, Trick[turn-1].suit);
   if (Trick[turn-1].suit == 2 || (Trick[turn-1].number == 12 && Trick[turn-1].suit == 0)) {
   T[turn-1].slot = ham_CreateObj((void *)&card_deck_orange_Bitmap[graphic_spot],0,2,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,T[turn-1].x_pos,T[turn-1].y_pos);
   } else {
   T[turn-1].slot = ham_CreateObj((void *)&card_deck_Bitmap[graphic_spot],0,2,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,T[turn-1].x_pos,T[turn-1].y_pos);
   }
   // Remove that card from players hand
   remove_card(turn, ai_card);
   // Setup suit_lead to match the first card lead
   if (leader == turn) {
   suit_lead = Trick[turn-1].suit;
   }
   // Increment turn
   if (turn == 4 && trick_cards != 3) {
   turn = 1;
   } else {
   ++turn;
   }
   // Increment trick_cards
   ++trick_cards;
   // Move Player1's pointer to a card that is of the same suit as suit lead
   if (trick_cards == 1 && Player1[my_pnt_card].suit != suit_lead) {
   u8 suit_slot = 0;
   // Loop through Player1's cards
   while (suit_slot != 13) {
   // Player1 has the suit, stop looking
   if ((Player1[suit_slot].number != 0) && (Player1[suit_slot].suit == suit_lead)) {
   break;
   }
   // Otherwise move to the next card
   ++suit_slot;
   }
   // If suit_slot is not 13, then they have the suit
   if (suit_slot != 13) {
   // Change the current card to white
   graphic_spot = convert_card(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(P1[my_pnt_card].slot,(void *)&card_deck_Bitmap[graphic_spot]);
   // Move the pointer
   my_pnt_card = suit_slot;
   // Change the new card to grey
   graphic_spot = convert_card(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(P1[my_pnt_card].slot,(void *)&card_deck_grey_Bitmap[graphic_spot]);
   // Update the graphic for the card in the corner
   Card_64[0].x_pos = P1[my_pnt_card].x_pos;
   ham_SetObjX(Card_64[0].slot, P1[my_pnt_card].x_pos);
   graphic_spot = convert_card_64(Player1[my_pnt_card].number, Player1[my_pnt_card].suit);
   ham_UpdateObjGfx(Card_64[0].slot,(void *)&card_deck_64_Bitmap[graphic_spot]);
   }
   }
  } else if (vbl_count > 35 && trick_cards == 4) {
   vbl_count = 0;
   // Update variables
   turn = trick_winner();
   leader = turn;
   // Score the trick (based on who the new leader is)
   score_trick();
   // Hide the old trick
   for (u8 i = 0; i < 4; ++i) {
   ham_DeleteObj(T[i].slot);
   // Clear out the old trick
   Trick[i].number = 0;
   Trick[i].suit = 0;
   }
   // No longer the first trick
   if (first_trick) first_trick = false;
   // Reset trick cards
   trick_cards = 0;
   // Update the number of tricks
   ++tricks;
   // Check if the round is over
   if (tricks == 14) {
   // Increment the round
   if (round == 3) {
   round = 0;
   } else {
   ++round;
   }
   // Change the gamestate
   game_state = SCORE;
   return;
   }

  }// End of if (players == 1 && turn == 1)

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


//********************************************
// Function: HEARTS::in_game_redraw()
// Purpose: Redraw the screen during in_game()
//********************************************
void HEARTS::in_game_redraw()
{

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


//**************************************
// Function: HEARTS::in_game_deinit()
// Purpose: Deinitialize game playing
//**************************************
void HEARTS::in_game_deinit()
{
  // Deinitialize the background
  ham_DeInitBg(0);

  // *** brute force delete ***
  for (u8 i = 0; i < 128; ++i) {
   ham_DeleteObj(i);
  }

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

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


//*************************************
// Function: HEARTS::score_init()
// Purpose: Initialize the score screen
//*************************************
void HEARTS::score_init()
{
  // Start the VBL counter at 0
  vbl_count = 0;

  // Start with the first start screen image
  curr_screen = 1;

  // Show the Hand Scores screen
  // Initialize the background palette
  ham_LoadBGPal((void *)score_Palette,256);
  ham_LoadObjPal((void *)numbers_new_Palette,256);

  /*
  // Set the tileset for the 'Hearts' screen
  ham_bg[0].ti = ham_InitTileSet((void *)score_Tiles,
   SIZEOF_16BIT(score_Tiles),1,1);
  ham_bg[0].mi = ham_InitMapSet((void *)score_Map,256,0,0);

  // Display the background
  ham_InitBg(0,1,0,0);
  */

  // Setup the tileset for our image
  ham_bg[0].ti = ham_InitTileSet((void *)score_Tiles,
   SIZEOF_16BIT(score_Tiles),1,1);

  // Setup the map for our image
  ham_bg[0].mi = ham_InitMapEmptySet(3,0);
  bg_one = ham_InitMapFragment((void *)score_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 Hand Score pointers
  HSh[0].x_pos = 129; HSh[0].y_pos = 48;
  HSt[0].x_pos = 139; HSt[0].y_pos = 48;
  HSo[0].x_pos = 149; HSo[0].y_pos = 48;
  HSh[1].x_pos = 129; HSh[1].y_pos = 76;
  HSt[1].x_pos = 139; HSt[1].y_pos = 76;
  HSo[1].x_pos = 149; HSo[1].y_pos = 76;
  HSh[2].x_pos = 129; HSh[2].y_pos = 104;
  HSt[2].x_pos = 139; HSt[2].y_pos = 104;
  HSo[2].x_pos = 149; HSo[2].y_pos = 104;
  HSh[3].x_pos = 129; HSh[3].y_pos = 132;
  HSt[3].x_pos = 139; HSt[3].y_pos = 132;
  HSo[3].x_pos = 149; HSo[3].y_pos = 132;

  // Setup the Total Score pointers
  TSh[0].x_pos = 184; TSh[0].y_pos = 48;
  TSt[0].x_pos = 194; TSt[0].y_pos = 48;
  TSo[0].x_pos = 204; TSo[0].y_pos = 48;
  TSh[1].x_pos = 184; TSh[1].y_pos = 76;
  TSt[1].x_pos = 194; TSt[1].y_pos = 76;
  TSo[1].x_pos = 204; TSo[1].y_pos = 76;
  TSh[2].x_pos = 184; TSh[2].y_pos = 104;
  TSt[2].x_pos = 194; TSt[2].y_pos = 104;
  TSo[2].x_pos = 204; TSo[2].y_pos = 104;
  TSh[3].x_pos = 184; TSh[3].y_pos = 132;
  TSt[3].x_pos = 194; TSt[3].y_pos = 132;
  TSo[3].x_pos = 204; TSo[3].y_pos = 132;

  // See if anyone 'shot the moon'
  if (Hand_Score[0] == 26) {
   Hand_Score[0] = 0;
   Hand_Score[1] = 26;
   Hand_Score[2] = 26;
   Hand_Score[3] = 26;
  } else if (Hand_Score[1] == 26) {
   Hand_Score[0] = 26;
   Hand_Score[1] = 0;
   Hand_Score[2] = 26;
   Hand_Score[3] = 26;
  } else if (Hand_Score[2] == 26) {
   Hand_Score[0] = 26;
   Hand_Score[1] = 26;
   Hand_Score[2] = 0;
   Hand_Score[3] = 26;
  } else if (Hand_Score[3] == 26) {
   Hand_Score[0] = 26;
   Hand_Score[1] = 26;
   Hand_Score[2] = 26;
   Hand_Score[3] = 0;
  }

  // Add the hand scores to the total scores
  for (u8 i = 0; i < 4; ++i) {
   Total_Score[i] += Hand_Score[i];
  }

  // Setup the Hand Score values
  graphic_spot = convert_number(Hand_Score[0]/10);
  HSt[0].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,HSt[0].x_pos,HSt[0].y_pos);
  graphic_spot = convert_number(Hand_Score[0]%10);
  HSo[0].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,HSo[0].x_pos,HSo[0].y_pos);
  graphic_spot = convert_number(Hand_Score[1]/10);
  HSt[1].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,HSt[1].x_pos,HSt[1].y_pos);
  graphic_spot = convert_number(Hand_Score[1]%10);
  HSo[1].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,HSo[1].x_pos,HSo[1].y_pos);
  graphic_spot = convert_number(Hand_Score[2]/10);
  HSt[2].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,HSt[2].x_pos,HSt[2].y_pos);
  graphic_spot = convert_number(Hand_Score[2]%10);
  HSo[2].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,HSo[2].x_pos,HSo[2].y_pos);
  graphic_spot = convert_number(Hand_Score[3]/10);
  HSt[3].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,HSt[3].x_pos,HSt[3].y_pos);
  graphic_spot = convert_number(Hand_Score[3]%10);
  HSo[3].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,HSo[3].x_pos,HSo[3].y_pos);

  // Setup the graphics for each score
  // Check whether they have gone over 100
  u8 hundreds = 0;
  if (Total_Score[0]/100 > 0) {
   // Setup the 'hundreds'
   hundreds = Total_Score[0]/100;
   graphic_spot = convert_number(hundreds);
   TSh[0].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSh[0].x_pos,TSh[0].y_pos);
   // Setup the 'tens'
   graphic_spot = convert_number((Total_Score[0]/10)-hundreds*10);
   TSt[0].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSt[0].x_pos,TSt[0].y_pos);
  } else {
   // Setup the 'tens'
   graphic_spot = convert_number(Total_Score[0]/10);
   TSt[0].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSt[0].x_pos,TSt[0].y_pos);
  }
  if (Total_Score[1]/100 > 0) {
   // Setup the 'hundreds'
   hundreds = Total_Score[1]/100;
   graphic_spot = convert_number(hundreds);
   TSh[1].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSh[1].x_pos,TSh[1].y_pos);
   // Setup the 'tens'
   graphic_spot = convert_number((Total_Score[1]/10)-hundreds*10);
   TSt[1].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSt[1].x_pos,TSt[1].y_pos);
  } else {
   // Setup the 'tens'
   graphic_spot = convert_number(Total_Score[1]/10);
   TSt[1].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSt[1].x_pos,TSt[1].y_pos);
  }
  if (Total_Score[2]/100 > 0) {
   // Setup the 'hundreds'
   hundreds = Total_Score[2]/100;
   graphic_spot = convert_number(hundreds);
   TSh[2].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSh[2].x_pos,TSh[2].y_pos);
   // Setup the 'tens'
   graphic_spot = convert_number((Total_Score[2]/10)-hundreds*10);
   TSt[2].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSt[2].x_pos,TSt[2].y_pos);
  } else {
   // Setup the 'tens'
   graphic_spot = convert_number(Total_Score[2]/10);
   TSt[2].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSt[2].x_pos,TSt[2].y_pos);
  }
  if (Total_Score[3]/100 > 0) {
   // Setup the 'hundreds'
   hundreds = Total_Score[3]/100;
   graphic_spot = convert_number(hundreds);
   TSh[3].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSh[3].x_pos,TSh[3].y_pos);
   // Setup the 'tens'
   graphic_spot = convert_number((Total_Score[3]/10)-hundreds*10);
   TSt[3].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSt[3].x_pos,TSt[3].y_pos);
  } else {
   // Setup the 'tens'
   graphic_spot = convert_number(Total_Score[3]/10);
   TSt[3].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSt[3].x_pos,TSt[3].y_pos);
  }

  // Figure out the 'ones'
  graphic_spot = convert_number(Total_Score[0]%10);
  TSo[0].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSo[0].x_pos,TSo[0].y_pos);
  graphic_spot = convert_number(Total_Score[1]%10);
  TSo[1].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSo[1].x_pos,TSo[1].y_pos);
  graphic_spot = convert_number(Total_Score[2]%10);
  TSo[2].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSo[2].x_pos,TSo[2].y_pos);
  graphic_spot = convert_number(Total_Score[3]%10);
  TSo[3].slot = ham_CreateObj((void *)&numbers_new_Bitmap[graphic_spot],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,TSo[3].x_pos,TSo[3].y_pos);

  return;
} // End of score_init()


//****************************************
// Function: HEARTS::score_query_keys()
// Purpose: Gets input during score screen
//****************************************
void HEARTS::score_query_keys()
{
  // Increment the VBL counter every VBL
  ++vbl_count;

  // A, B or START button
  if (vbl_count > 10 && (F_CTRLINPUT_A_PRESSED || F_CTRLINPUT_B_PRESSED || F_CTRLINPUT_START_PRESSED)) {
   // Get back into the game
   if (is_winner()) {
   game_state = FINISH;
   } else {
   game_state = PLAY;
   }
  }

  return;
} // End of score_query_keys


//****************************************
// Function: HEARTS::score_redraw()
// Purpose: Redraw the screen during score
//****************************************
void HEARTS::score_redraw()
{
  return;
} // End of score_redraw()


//***************************************
// Function: HEARTS::score_deinit()
// Purpose: Deinitialize the score screen
//***************************************
void HEARTS::score_deinit()
{
  // Deinitialize the background
  ham_DeInitBg(0);

  // *** brute force delete ***
  for (u8 i = 0; i < 128; ++i) {
   ham_DeleteObj(i);
  }

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

  return;
} // End of score_deinit()


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

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

  // Choose which background to load based on the winner
  if (winner == 0) { // Player1
   // Setup the tileset for our image
   ham_bg[0].ti = ham_InitTileSet((void *)game_over_p1_Tiles,
   SIZEOF_16BIT(game_over_p1_Tiles),1,1);
   // Setup the map for our image
   ham_bg[0].mi = ham_InitMapEmptySet(3,0);
   bg_one = ham_InitMapFragment((void *)game_over_p1_Map,30,20,0,0,30,20,0);
   ham_InsertMapFragment(bg_one,0,0,0);
  } else if (winner == 1) { // Player2
   // Setup the tileset for our image
   ham_bg[0].ti = ham_InitTileSet((void *)game_over_p2_Tiles,
   SIZEOF_16BIT(game_over_p2_Tiles),1,1);
   // Setup the map for our image
   ham_bg[0].mi = ham_InitMapEmptySet(3,0);
   bg_one = ham_InitMapFragment((void *)game_over_p2_Map,30,20,0,0,30,20,0);
   ham_InsertMapFragment(bg_one,0,0,0);
  } else if (winner == 2) { // Player3
   // Setup the tileset for our image
   ham_bg[0].ti = ham_InitTileSet((void *)game_over_p3_Tiles,
   SIZEOF_16BIT(game_over_p3_Tiles),1,1);
   // Setup the map for our image
   ham_bg[0].mi = ham_InitMapEmptySet(3,0);
   bg_one = ham_InitMapFragment((void *)game_over_p3_Map,30,20,0,0,30,20,0);
   ham_InsertMapFragment(bg_one,0,0,0);
  } else if (winner == 3) { // Player4
   // Setup the tileset for our image
   ham_bg[0].ti = ham_InitTileSet((void *)game_over_p4_Tiles,
   SIZEOF_16BIT(game_over_p4_Tiles),1,1);
   // Setup the map for our image
   ham_bg[0].mi = ham_InitMapEmptySet(3,0);
   bg_one = ham_InitMapFragment((void *)game_over_p4_Map,30,20,0,0,30,20,0);
   ham_InsertMapFragment(bg_one,0,0,0);
  } else if (winner == 4) { // Tie Game
   // Setup the tileset for our image
   ham_bg[0].ti = ham_InitTileSet((void *)game_over_tie_Tiles,
   SIZEOF_16BIT(game_over_tie_Tiles),1,1);
   // Setup the map for our image
   ham_bg[0].mi = ham_InitMapEmptySet(3,0);
   bg_one = ham_InitMapFragment((void *)game_over_tie_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 HEARTS::finish_init()


//*********************************************
// Function: HEARTS::finish_query_keys()
// Purpose: Gets input during the finish screen
//*********************************************
void HEARTS::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: HEARTS::finish_deinit()
// Purpose: Deinitialize finish()
//*************************************
void HEARTS::finish_deinit()
{
  // Deinitialize the background and sprites
  ham_DeInitBg(0);

  // *** brute force delete ***
  for (u8 i = 0; i < 128; ++i) {
   ham_DeleteObj(i);
  }

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

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


//*************************************
// Function: HEARTS::options_init()
// Purpose: Displays the options screen
//*************************************
void HEARTS::options_init()
{
  // Start the VBL counter at 0
  vbl_count = 0;

  // Setup variables to keep track of screens
  curr_screen = 0;
  last_screen = 0;

  // Initialize the palettes
  ham_LoadBGPal((void *)options_Palette,256);
  ham_LoadObjPal((void *)options_sprites_Palette,256);

  // Display the image
  TOOL_DMA1_SET(&options_sl_Bitmap,
   MEM_BG_PTR,SIZEOF_32BIT(options_sl_Bitmap),
   DMA_TRANSFER_32BIT,
   DMA_STARTAT_NOW);

  // Setup the options sprites
  opts[0].x_pos = 173;
  opts[0].y_pos = 41;
  opts[1].x_pos = 160;
  opts[1].y_pos = 76;
  opts[2].x_pos = 160;
  opts[2].y_pos = 119;

  // Create the three options sprites
  opts[0].slot = ham_CreateObj((void *)&op_2_Bitmap[0],0,1,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,opts[0].x_pos,opts[0].y_pos);
  opts[1].slot = ham_CreateObj((void *)&off_Bitmap[0],0,2,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,opts[1].x_pos,opts[1].y_pos);
  opts[2].slot = ham_CreateObj((void *)&off_Bitmap[0],0,2,
   OBJ_MODE_NORMAL,1,0,0,0,0,0,0,opts[2].x_pos,opts[2].y_pos);

  return;
} // End of options_init()


//**********************************************
// Function: HEARTS::options_query_keys()
// Purpose: Gets input during the options screen
//**********************************************
void HEARTS::options_query_keys()
{
  // Increment the VBL counter every VBL
  ++vbl_count;

  // START or A button
  if (vbl_count > 10 && (F_CTRLINPUT_START_PRESSED || F_CTRLINPUT_A_PRESSED)) {
   // Go back to the main screen
   game_state = MAIN;
  }

  // UP
  if (vbl_count > 10 && F_CTRLINPUT_UP_PRESSED) {
   vbl_count = 0;
   last_screen = curr_screen;
   if (curr_screen == 0) {
   curr_screen = 2;
   } else {
   --curr_screen;
   }
  }

  // DOWN
  if (vbl_count > 10 && F_CTRLINPUT_DOWN_PRESSED) {
   vbl_count = 0;
   last_screen = curr_screen;
   if (curr_screen == 2) {
   curr_screen = 0;
   } else {
   ++curr_screen;
   }
  }

  // RIGHT
  if (vbl_count > 10 && F_CTRLINPUT_RIGHT_PRESSED) {
   vbl_count = 0;
   // Skill Level
   if (curr_screen == 0) {
   if (skill == 1) {
   skill = 2;
   } else if (skill == 2) {
   skill = 3;
   } else if (skill == 3) {
   skill = 1;
   }
   // Sound
   } else if (curr_screen == 1) {
   // Off
   if (sound == 0) {
   sound = 1; // On
   // On
   } else if (sound == 1) {
   sound = 0; // Off
   }
   // Music
   } else if (curr_screen == 2) {
   // Off
   if (music == 0) {
   music = 1; // On
   // On
   } else if (music == 1) {
   music = 0; // Off
   }
   }
  }

  // LEFT
  if (vbl_count > 10 && F_CTRLINPUT_LEFT_PRESSED) {
   vbl_count = 0;
   // Skill Level
   if (curr_screen == 0) {
   if (skill == 3) {
   skill = 2;
   } else if (skill == 2) {
   skill = 1;
   } else if (skill == 1) {
   skill = 3;
   }
   // Sound
   } else if (curr_screen == 1) {
   // Off
   if (sound == 0) {
   sound = 1; // On
   // On
   } else if (sound == 1) {
   sound = 0; // Off
   }
   // Music
   } else if (curr_screen == 2) {
   // Off
   if (music == 0) {
   music = 1; // On
   // On
   } else if (music == 1) {
   music = 0; // Off
   }
   }
  }

  return;
} // End of options_query_keys()


//********************************************
// Function: HEARTS::options_redraw()
// Purpose: Redraw the screen during options()
//********************************************
void HEARTS::options_redraw()
{
  // See if changes were made
  if (last_screen != curr_screen) {
   if (curr_screen == 0) {
   // Display the image
   TOOL_DMA1_SET(&options_sl_Bitmap,
   MEM_BG_PTR,SIZEOF_32BIT(options_sl_Bitmap),
   DMA_TRANSFER_32BIT,
   DMA_STARTAT_NOW);
   } else if (curr_screen == 1) {
   // Display the image
   TOOL_DMA1_SET(&options_so_Bitmap,
   MEM_BG_PTR,SIZEOF_32BIT(options_so_Bitmap),
   DMA_TRANSFER_32BIT,
   DMA_STARTAT_NOW);
   } else if (curr_screen == 2) {
   // Display the image
   TOOL_DMA1_SET(&options_mu_Bitmap,
   MEM_BG_PTR,SIZEOF_32BIT(options_mu_Bitmap),
   DMA_TRANSFER_32BIT,
   DMA_STARTAT_NOW);
   }
   last_screen = curr_screen; // Set them equal - this means there was no input change
  }

  // Update the sprites
  // Skill Level
  if (skill == 1) {
   ham_UpdateObjGfx(opts[0].slot,(void *)&op_1_Bitmap[0]);
  } else if (skill == 2) {
   ham_UpdateObjGfx(opts[0].slot,(void *)&op_2_Bitmap[0]);
  } else if (skill == 3) {
   ham_UpdateObjGfx(opts[0].slot,(void *)&op_3_Bitmap[0]);
  
  }
  // Sound
  if (sound == 0) {
   ham_UpdateObjGfx(opts[1].slot,(void *)&off_Bitmap[0]);
  } else if (sound == 1) {
   ham_UpdateObjGfx(opts[1].slot,(void *)&on_Bitmap[0]);
  }
  // Music
  if (music == 0) {
   ham_UpdateObjGfx(opts[2].slot,(void *)&off_Bitmap[0]);
  } else if (music == 1) {
   ham_UpdateObjGfx(opts[2].slot,(void *)&on_Bitmap[0]);
  }

  return;
} // End of options_redraw()


//*************************************
// Function: HEARTS::options_deinit()
// Purpose: Deinitialize options()
//*************************************
void HEARTS::options_deinit()
{
  // Delete the sprites
  ham_DeleteObj(opts[0].slot);
  ham_DeleteObj(opts[1].slot);
  ham_DeleteObj(opts[2].slot);

  return;
} // End of options_deinit()


//*********************************************
// Function: HEARTS::is_winner()
// Purpose: Checks to see if there was a winner
//*********************************************
bool HEARTS::is_winner()
{
  // Varables
  bool win = false;
  bool tie = false;

  // Make sure that no one is the winner yet
  winner = 4;

  // Cycle through the total scores
  for (u8 i = 0; i < 4; ++i) {
   // See if anyone has over 100
   if (Total_Score[i] >= 100) {
   // If no one scored over a hundred yet
   if (!win) {
   // Make sure we know that someone has won
   win = true;
   // If the stored score is empty
   if (winner == 4) {
   winner = i; // Store this one for now
   }
   }
   // Otherwise, check if the score is less than 100
   } else {
   // If the stored score is empty
   if (winner == 4) {
   winner = i; // Store this one
   // Otherwise, compare this score with the stored one
   } else {
   // Current score is less than stored score
   if (Total_Score[i] < Total_Score[winner]) {
   winner = i;
   tie = false;
   // Current store equals stored score, TIE!
   } else if (Total_Score[i] == Total_Score[winner]) {
   tie = true;
   }
   }
   }
  }

  // Check if there is a tie
  if (tie) winner = 4;

  return win;
} // End of HEARTS::is_winner()


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


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


//***************************
// Function: HEARTS::gsl()
// Purpose: Returns suit_lead
//***************************
u8 HEARTS::gsl()
{
  return suit_lead;
} // End of HEARTS::gsl()


//************************
// Function: HEARTS::gl()
// Purpose: Returns leader
//************************
u8 HEARTS::gl()
{
  return leader;
} // End of HEARTS::gl()


//************************
// Function: HEARTS::gtc()
// Purpose: Returns leader
//************************
u8 HEARTS::gtc()
{
  return trick_cards;
} // End of HEARTS::gtc()


//************************
// Function: HEARTS::gtr()
// Purpose: Returns tricks
//************************
u8 HEARTS::gtr()
{
  return tricks;
} // End of HEARTS::gtr()


//********************************************
// Function: HEARTS::trick_number()
// Purpose: Returns card number in Trick[slot]
//********************************************
u8 HEARTS::trick_number(u8 slot)
{
  return Trick[slot].number;
} // End of trick_number()


//******************************************
// Function: HEARTS::trick_suit()
// Purpose: Returns card suit in Trick[slot]
//******************************************
u8 HEARTS::trick_suit(u8 slot)
{
  return Trick[slot].suit;
} // End of trick_suit()


//********************************************
// Function: HEARTS::player_number()
// Purpose: Returns card suit of PlayerX[slot]
//********************************************
u8 HEARTS::player_number(u8 player, u8 slot)
{
  if (player == 1) {
   return Player1[slot].number;
  } else if (player == 2) {
   return Player2[slot].number;
  } else if (player == 3) {
   return Player3[slot].number;
  } else if (player == 4) {
   return Player4[slot].number;
  }

  return 0; // *** should never happen ***
} // End of player_number()


//********************************************
// Function: HEARTS::player_suit()
// Purpose: Returns card suit of PlayerX[slot]
//********************************************
u8 HEARTS::player_suit(u8 player, u8 slot)
{
  if (player == 1) {
   return Player1[slot].suit;
  } else if (player == 2) {
   return Player2[slot].suit;
  } else if (player == 3) {
   return Player3[slot].suit;
  } else if (player == 4) {
   return Player4[slot].suit;
  }

  return 0; // *** should never happen ***
} // End of player_suit()


//*********************************************
// Function: HEARTS::convert_card()
// Purpose: Returns the passed card info's spot
// in the card_deck graphics array
//*********************************************
u32 HEARTS::convert_card(u8 number, u8 suit)
{
  return (((number - 2) * 4096) + (suit * 1024));

} // End of HEARTS::convert_card()


//*********************************************
// Function: HEARTS::convert_card_64()
// Purpose: Returns the passed card info's spot
// in the card_deck_64 graphics array
//*********************************************
u32 HEARTS::convert_card_64(u8 number, u8 suit)
{
  return (((number - 2) * 16384) + (suit * 4096));

} // End of HEARTS::convert_card_64()


//******************************************
// Function: HEARTS::convert_number()
// Purpose: Returns the passed number's spot
// in the number graphics array
//******************************************
u32 HEARTS::convert_number(u8 number)
{
  return (number * 256);

} // End of HEARTS::convert_number()


//*************************************
// Function: HEARTS::hand_sort()
// Purpose: Sorts a hand: C,D,S,H : 2-A
//*************************************
void HEARTS::hand_sort(u8 player)
{
  if (player == 1) {
   for (u8 i = 0; i < 12; ++i) {
   for (u8 j = 0; j < 12; ++j) {
   u8 one = sort_card_value(Player1[j].number,Player1[j].suit);
   u8 two = sort_card_value(Player1[j+1].number,Player1[j+1].suit);
   if (two < one) {
   u8 temp_numb = Player1[j].number;
   u8 temp_suit = Player1[j].suit;
   Player1[j].number = Player1[j+1].number;
   Player1[j].suit = Player1[j+1].suit;
   Player1[j+1].number = temp_numb;
   Player1[j+1].suit = temp_suit;
   }
   }
   }
  } else if (player == 2) {
   for (u8 i = 0; i < 12; ++i) {
   for (u8 j = 0; j < 12; ++j) {
   u8 one = sort_card_value(Player2[j].number,Player2[j].suit);
   u8 two = sort_card_value(Player2[j+1].number,Player2[j+1].suit);
   if (two < one) {
   u8 temp_numb = Player2[j].number;
   u8 temp_suit = Player2[j].suit;
   Player2[j].number = Player2[j+1].number;
   Player2[j].suit = Player2[j+1].suit;
   Player2[j+1].number = temp_numb;
   Player2[j+1].suit = temp_suit;
   }
   }
   }
  } else if (player == 3) {
   for (u8 i = 0; i < 12; ++i) {
   for (u8 j = 0; j < 12; ++j) {
   u8 one = sort_card_value(Player3[j].number,Player3[j].suit);
   u8 two = sort_card_value(Player3[j+1].number,Player3[j+1].suit);
   if (two < one) {
   u8 temp_numb = Player3[j].number;
   u8 temp_suit = Player3[j].suit;
   Player3[j].number = Player3[j+1].number;
   Player3[j].suit = Player3[j+1].suit;
   Player3[j+1].number = temp_numb;
   Player3[j+1].suit = temp_suit;
   }
   }
   }
  } else if (player == 4) {
   for (u8 i = 0; i < 12; ++i) {
   for (u8 j = 0; j < 12; ++j) {
   u8 one = sort_card_value(Player4[j].number,Player4[j].suit);
   u8 two = sort_card_value(Player4[j+1].number,Player4[j+1].suit);
   if (two < one) {
   u8 temp_numb = Player4[j].number;
   u8 temp_suit = Player4[j].suit;
   Player4[j].number = Player4[j+1].number;
   Player4[j].suit = Player4[j+1].suit;
   Player4[j+1].number = temp_numb;
   Player4[j+1].suit = temp_suit;
   }
   }
   }
  }

  return;
} // End of HEARTS::hand_sort


//*******************************************************
// Function: HEARTS::sort_card_value()
// Purpose: Used during sort to figure out a card's value
//*******************************************************
u8 HEARTS::sort_card_value(u8 number, u8 suit)
{
  if (suit == 0) {
   suit = 2;
  } else if (suit == 1) {
   suit = 0;
  } else if (suit == 2) {
   suit = 3;
  } else if (suit == 3) {
   suit = 1;
  }

  return ((suit * 13) + (number - 2));
} // End of HEARTS::sort_card_value()


//*******************************************
// Function: setup_leader()
// Purpose: Figure out who has the 2 of Clubs
//*******************************************
void HEARTS::setup_leader()
{
  // Cycle through each hand looking for the 2 of Clubs
  for (u8 i = 0; i < 13; ++i) {
   if (Player1[i].number == 2 && Player1[i].suit == 1) {
   leader = 1;
   return;
   }
   if (Player2[i].number == 2 && Player2[i].suit == 1) {
   leader = 2;
   return;
   }
   if (Player3[i].number == 2 && Player3[i].suit == 1) {
   leader = 3;
   return;
   }
   if (Player4[i].number == 2 && Player4[i].suit == 1) {
   leader = 4;
   return;
   }
  }

  return;
} // End of setup_leader()


//**************************************
// Function: trick_winner()
// Purpose: Figure out who won the trick
//**************************************
u8 HEARTS::trick_winner()
{
  u8 check[4];
  check[0] = 0;
  check[1] = 0;
  check[2] = 0;
  check[3] = 0;

  // Determine which trick cards will be compared
  for (u8 i = 0; i < 4; ++i) {
   if (Trick[i].suit == suit_lead) {
   check[i] = Trick[i].number;
   }
  }

  if ((check[0] > check[1]) && (check[0] > check[2]) && (check[0] > check[3])) {
   return 1;
  } else if ((check[1] > check[0]) && (check[1] > check[2]) && (check[1] > check[3])) {
   return 2;
  } else if ((check[2] > check[0]) && (check[2] > check[1]) && (check[2] > check[3])) {
   return 3;
  } else if ((check[3] > check[0]) && (check[3] > check[1]) && (check[3] > check[2])) {
   return 4;
  } else {
   return 1;
  }

} // End of trick_winner()


//********************************************
// Function: score_trick()
// Purpose: Figure out the score of each trick
//********************************************
void HEARTS::score_trick()
{
  // Setup a pointer
  u8 *Trick_Winner = NULL;

  if (leader == 1) {
   Trick_Winner = &Hand_Score[0];
  } else if (leader == 2) {
   Trick_Winner = &Hand_Score[1];
  } else if (leader == 3) {
   Trick_Winner = &Hand_Score[2];
  } else if (leader == 4) {
   Trick_Winner = &Hand_Score[3];
  }

  // Add one point for a Heart
  if (Trick[0].suit == 2) *Trick_Winner += 1;
  if (Trick[1].suit == 2) *Trick_Winner += 1;
  if (Trick[2].suit == 2) *Trick_Winner += 1;
  if (Trick[3].suit == 2) *Trick_Winner += 1;

  // Add 13 points for a Queen of Spades
  if (Trick[0].number == 12 && Trick[0].suit == 0) *Trick_Winner += 13;
  if (Trick[1].number == 12 && Trick[1].suit == 0) *Trick_Winner += 13;
  if (Trick[2].number == 12 && Trick[2].suit == 0) *Trick_Winner += 13;
  if (Trick[3].number == 12 && Trick[3].suit == 0) *Trick_Winner += 13;

  return;
}


//***************************************
// Function: valid_move()
// Purpose: Check whether the card passed
// is valid to play
//***************************************
bool HEARTS::valid_move(u8 player, u8 slot)
{
  // Variables
  Card *Player = NULL;

  // Make the pointer point to the correct Card array
  if (player == 1) {
   Player = Player1;
  } else if (player == 2) {
   Player = Player2;
  } else if (player == 3) {
   Player = Player3;
  } else if (player == 4) {
   Player = Player4;
  }

  // *** there is already a check that the first card is the 2 of Clubs ***

  // Cannot play Queen of Spades on first trick
  if (first_trick && (Player[slot].number == 12 && Player[slot].suit == 0)) return false;

  // Cannot play a Heart on the first trick, unless the player has only Hearts
  if (first_trick && (Player[slot].suit == 2)) {
   for (u8 i = 0; i < 13; ++i) {
   if ((Player[i].number != 0) && (Player[i].suit != 2)) return false;
   }
   return true;
  }

  // Cannot lead a Heart until Hearts are broken, unless the player has only Hearts
  if ((leader == player) && (!hearts_broken) && (Player[slot].suit == 2)) {
   // Cycle through the hand to make sure the player has only Hearts
   for (u8 i = 0; i < 13; ++i) {
   if ((Player[i].number != 0) && (Player[i].suit != 2)) return false;
   }
   return true;
  }

  // Make sure the player plays the suit lead if they have it
  if ((leader != player) && (Player[slot].suit != suit_lead)) {
   // Cycle through the hand to make sure they don't have the suit
   for (u8 i = 0; i < 13; ++i) {
   if ((Player[i].number != 0) && (Player[i].suit == suit_lead)) return false;
   }
   return true;
  }

  return true;
} // End of valid_move()


void HEARTS::pass_cards()
{
  // Variables
  Card temp_cards[3];

  // Pass the cards
  if (round == 0) {
   // Backup Player 1's cards
   temp_cards[0].number = Player1[Passed_Cards[0]].number;
   temp_cards[0].suit = Player1[Passed_Cards[0]].suit;
   temp_cards[1].number = Player1[Passed_Cards[1]].number;
   temp_cards[1].suit = Player1[Passed_Cards[1]].suit;
   temp_cards[2].number = Player1[Passed_Cards[2]].number;
   temp_cards[2].suit = Player1[Passed_Cards[2]].suit;
   // Swap from Player 4 to Player 1
   Player1[Passed_Cards[0]].number = Player4[Passed_Cards[9]].number;
   Player1[Passed_Cards[0]].suit = Player4[Passed_Cards[9]].suit;
   Player1[Passed_Cards[1]].number = Player4[Passed_Cards[10]].number;
   Player1[Passed_Cards[1]].suit = Player4[Passed_Cards[10]].suit;
   Player1[Passed_Cards[2]].number = Player4[Passed_Cards[11]].number;
   Player1[Passed_Cards[2]].suit = Player4[Passed_Cards[11]].suit;
   // Swap from Player 3 to Player 4
   Player4[Passed_Cards[9]].number = Player3[Passed_Cards[6]].number;
   Player4[Passed_Cards[9]].suit = Player3[Passed_Cards[6]].suit;
   Player4[Passed_Cards[10]].number = Player3[Passed_Cards[7]].number;
   Player4[Passed_Cards[10]].suit = Player3[Passed_Cards[7]].suit;
   Player4[Passed_Cards[11]].number = Player3[Passed_Cards[8]].number;
   Player4[Passed_Cards[11]].suit = Player3[Passed_Cards[8]].suit;
   // Swap from Player 2 to Player 3
   Player3[Passed_Cards[6]].number = Player2[Passed_Cards[3]].number;
   Player3[Passed_Cards[6]].suit = Player2[Passed_Cards[3]].suit;
   Player3[Passed_Cards[7]].number = Player2[Passed_Cards[4]].number;
   Player3[Passed_Cards[7]].suit = Player2[Passed_Cards[4]].suit;
   Player3[Passed_Cards[8]].number = Player2[Passed_Cards[5]].number;
   Player3[Passed_Cards[8]].suit = Player2[Passed_Cards[5]].suit;
   // Swap from Player 1 to Player 2
   Player2[Passed_Cards[3]].number = temp_cards[0].number;
   Player2[Passed_Cards[3]].suit = temp_cards[0].suit;
   Player2[Passed_Cards[4]].number = temp_cards[1].number;
   Player2[Passed_Cards[4]].suit = temp_cards[1].suit;
   Player2[Passed_Cards[5]].number = temp_cards[2].number;
   Player2[Passed_Cards[5]].suit = temp_cards[2].suit;
  } else if (round == 1) {
   // Backup Player 1's cards
   temp_cards[0].number = Player1[Passed_Cards[0]].number;
   temp_cards[0].suit = Player1[Passed_Cards[0]].suit;
   temp_cards[1].number = Player1[Passed_Cards[1]].number;
   temp_cards[1].suit = Player1[Passed_Cards[1]].suit;
   temp_cards[2].number = Player1[Passed_Cards[2]].number;
   temp_cards[2].suit = Player1[Passed_Cards[2]].suit;
   // Swap from Player 2 to Player 1
   Player1[Passed_Cards[0]].number = Player2[Passed_Cards[3]].number;
   Player1[Passed_Cards[0]].suit = Player2[Passed_Cards[3]].suit;
   Player1[Passed_Cards[1]].number = Player2[Passed_Cards[4]].number;
   Player1[Passed_Cards[1]].suit = Player2[Passed_Cards[4]].suit;
   Player1[Passed_Cards[2]].number = Player2[Passed_Cards[5]].number;
   Player1[Passed_Cards[2]].suit = Player2[Passed_Cards[5]].suit;
   // Swap from Player 3 to Player 2
   Player2[Passed_Cards[3]].number = Player3[Passed_Cards[6]].number;
   Player2[Passed_Cards[3]].suit = Player3[Passed_Cards[6]].suit;
   Player2[Passed_Cards[4]].number = Player3[Passed_Cards[7]].number;
   Player2[Passed_Cards[4]].suit = Player3[Passed_Cards[7]].suit;
   Player2[Passed_Cards[5]].number = Player3[Passed_Cards[8]].number;
   Player2[Passed_Cards[5]].suit = Player3[Passed_Cards[8]].suit;
   // Swap from Player 4 to Player 3
   Player3[Passed_Cards[6]].number = Player4[Passed_Cards[9]].number;
   Player3[Passed_Cards[6]].suit = Player4[Passed_Cards[9]].suit;
   Player3[Passed_Cards[7]].number = Player4[Passed_Cards[10]].number;
   Player3[Passed_Cards[7]].suit = Player4[Passed_Cards[10]].suit;
   Player3[Passed_Cards[8]].number = Player4[Passed_Cards[11]].number;
   Player3[Passed_Cards[8]].suit = Player4[Passed_Cards[11]].suit;
   // Swap from Player 1 to Player 4
   Player4[Passed_Cards[9]].number = temp_cards[0].number;
   Player4[Passed_Cards[9]].suit = temp_cards[0].suit;
   Player4[Passed_Cards[10]].number = temp_cards[1].number;
   Player4[Passed_Cards[10]].suit = temp_cards[1].suit;
   Player4[Passed_Cards[11]].number = temp_cards[2].number;
   Player4[Passed_Cards[11]].suit = temp_cards[2].suit;
  } else if (round == 2) {
   // Backup Player 1's cards
   temp_cards[0].number = Player1[Passed_Cards[0]].number;
   temp_cards[0].suit = Player1[Passed_Cards[0]].suit;
   temp_cards[1].number = Player1[Passed_Cards[1]].number;
   temp_cards[1].suit = Player1[Passed_Cards[1]].suit;
   temp_cards[2].number = Player1[Passed_Cards[2]].number;
   temp_cards[2].suit = Player1[Passed_Cards[2]].suit;
   // Swap from Player 3 to Player 1
   Player1[Passed_Cards[0]].number = Player3[Passed_Cards[6]].number;
   Player1[Passed_Cards[0]].suit = Player3[Passed_Cards[6]].suit;
   Player1[Passed_Cards[1]].number = Player3[Passed_Cards[7]].number;
   Player1[Passed_Cards[1]].suit = Player3[Passed_Cards[7]].suit;
   Player1[Passed_Cards[2]].number = Player3[Passed_Cards[8]].number;
   Player1[Passed_Cards[2]].suit = Player3[Passed_Cards[8]].suit;
   // Swap from Player 1 to Player 3
   Player3[Passed_Cards[6]].number = temp_cards[0].number;
   Player3[Passed_Cards[6]].suit = temp_cards[0].suit;
   Player3[Passed_Cards[7]].number = temp_cards[1].number;
   Player3[Passed_Cards[7]].suit = temp_cards[1].suit;
   Player3[Passed_Cards[8]].number = temp_cards[2].number;
   Player3[Passed_Cards[8]].suit = temp_cards[2].suit;
   // Backup Player 2's cards
   temp_cards[0].number = Player2[Passed_Cards[3]].number;
   temp_cards[0].suit = Player2[Passed_Cards[3]].suit;
   temp_cards[1].number = Player2[Passed_Cards[4]].number;
   temp_cards[1].suit = Player2[Passed_Cards[4]].suit;
   temp_cards[2].number = Player2[Passed_Cards[5]].number;
   temp_cards[2].suit = Player2[Passed_Cards[5]].suit;
   // Swap from Player 4 to Player 2
   Player2[Passed_Cards[3]].number = Player4[Passed_Cards[9]].number;
   Player2[Passed_Cards[3]].suit = Player4[Passed_Cards[9]].suit;
   Player2[Passed_Cards[4]].number = Player4[Passed_Cards[10]].number;
   Player2[Passed_Cards[4]].suit = Player4[Passed_Cards[10]].suit;
   Player2[Passed_Cards[5]].number = Player4[Passed_Cards[11]].number;
   Player2[Passed_Cards[5]].suit = Player4[Passed_Cards[11]].suit;
   // Swap from Player 2 to Player 4
   Player4[Passed_Cards[9]].number = temp_cards[0].number;
   Player4[Passed_Cards[9]].suit = temp_cards[0].suit;
   Player4[Passed_Cards[10]].number = temp_cards[1].number;
   Player4[Passed_Cards[10]].suit = temp_cards[1].suit;
   Player4[Passed_Cards[11]].number = temp_cards[2].number;
   Player4[Passed_Cards[11]].suit = temp_cards[2].suit;
  }

  return;
} // End of pass_cards()


//*****************************************
// Function: add_to_passed_cards()
// Purpose: Add PlayerX[slot]'s card[value]
// to Passed_Cards[]
//*****************************************
void HEARTS::add_to_passed_cards(u8 slot, u8 value)
{
  // Make sure the slot is valid
  Passed_Cards[slot] = value;

  return;
} // End of add_to_passed_cards()


void HEARTS::add_card(u8 player, u8 slot, u8 number, u8 suit)
{
  switch (player)
  {
  case 1:
   Player1[slot].number = number;
   Player1[slot].suit = suit;
   break;
  case 2:
   Player2[slot].number = number;
   Player2[slot].suit = suit;
   break;
  case 3:
   Player3[slot].number = number;
   Player3[slot].suit = suit;
   break;
  case 4:
   Player4[slot].number = number;
   Player4[slot].suit = suit;
   break;
  }

  return;
} // End of add_card()


//**********************************************
// Function: add_card_to_trick()
// Purpose: Add card to Trick[slot] from PlayerX
//**********************************************
void HEARTS::add_card_to_trick(u8 slot)
{
  // Figure out who's turn it is
  if (turn == 1) {
   Trick[0].number = Player1[slot].number;
   Trick[0].suit = Player1[slot].suit;
  } else if (turn == 2) {
   Trick[1].number = Player2[slot].number;
   Trick[1].suit = Player2[slot].suit;
  } else if (turn == 3) {
   Trick[2].number = Player3[slot].number;
   Trick[2].suit = Player3[slot].suit;
  } else if (turn == 4) {
   Trick[3].number = Player4[slot].number;
   Trick[3].suit = Player4[slot].suit;
  }

  return;
} // End of add_card_to_trick()


//*******************************************
// Function: remove_card()
// Purpose: Zero out a card in PlayerX's hand
//*******************************************
void HEARTS::remove_card(u8 player, u8 slot)
{
  if (player == 1) {
   Player1[slot].number = 0;
   Player1[slot].suit = 4;
  } else if (player == 2) {
   Player2[slot].number = 0;
   Player2[slot].suit = 4;
  } else if (player == 3) {
   Player3[slot].number = 0;
   Player3[slot].suit = 4;
  } else if (player == 4) {
   Player4[slot].number = 0;
   Player4[slot].suit = 4;
  }

  return;
} // End of remove_card()


//****************************************************
// Function: get_card()
// Purpose: Returns the card at Player[]
//****************************************************
Card HEARTS::get_card(u8 player, u8 slot)
{
  // Variables
  Card temp;
  temp.number = 0;
  temp.suit = 0;

  Card *Player = NULL;

  // Make the pointer point to the correct Card array
  if (player == 1) {
   Player = Player1;
  } else if (player == 2) {
   Player = Player2;
  } else if (player == 3) {
   Player = Player3;
  } else if (player == 4) {
   Player = Player4;
  }

  temp.number = Player[slot].number;
  temp.suit = Player[slot].suit;

  return temp;
} // End of get_card()


bool HEARTS::is_first_trick()
{
  return first_trick;
} // End of is_first_trick()


//************************************
// 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()