//*****************************************
// Filename: ai.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
//*****************************************
#include "ai.h"
#include "stdlib.h"
//***************************************
// Function: ai_setup_passed_cards()
// Purpose: Determine three cards to pass
//***************************************
void ai_setup_passed_cards(HEARTS *game, u8 skill)
{
// Variables
u8 P2_one = 13, P2_two = 13, P2_thr = 13;
u8 P3_one = 13, P3_two = 13, P3_thr = 13;
u8 P4_one = 13, P4_two = 13, P4_thr = 13;
// The cards will be decided based on the AI's skill
if (skill == 1) {
bool is_done = false; // To get out of the while loop
// Get three different numbers from 0 to 12
while (!is_done) {
P2_one = rand()%13;
P2_two = rand()%13;
P2_thr = rand()%13;
if ((P2_one != P2_two) && (P2_two != P2_thr) && (P2_one != P2_thr)) {
P3_one = P2_one;
P3_two = P2_two;
P3_thr = P2_thr;
P4_one = P2_one;
P4_two = P2_two;
P4_thr = P2_thr;
is_done = true;
}
}
} else if (skill == 2 || skill == 3) {
// Variables
bool one_3 = false;
bool two_3 = false;
bool thr_3 = false;
Card one_card;
Card two_card;
Card thr_card;
u8 value[9]; // P2: 0-2, P3: 3-5, P4: 6-8
// Set the values to 13
for (u8 i = 0; i < 9; ++i) value[i] = 13;
// Start searching Player2's hands
for (u8 i = 0; i < 13; ++i) {
// Copy a card from player's hand to a temp card
one_card = game->get_card(2, i);
// See if it should be stored (and later passed)
if (card_value(game, 2, one_card) > 0) { // It's a (somewhat) valuable card
if (value[0] == 13) { // If the spot is empty...
value[0] = i; // ... store it ...
continue; // ... and start the for loop over again
} else if (value[1] == 13) {
value[1] = i;
continue;
} else if (value[2] == 13) {
value[2] = i;
continue;
}
// See if the current card is move valuable than a previously stored card
if (card_value(game, 2, one_card) > card_value(game, 2, game->get_card(2, value[0]))) {
value[0] = i;
continue;
} else if (card_value(game, 2, one_card) > card_value(game, 2, game->get_card(2, value[1]))) {
value[1] = i;
continue;
} else if (card_value(game, 2, one_card) > card_value(game, 2, game->get_card(2, value[2]))) {
value[2] = i;
continue;
}
}
} // End of for(...)
// Start searching Player3's hands
for (u8 i = 0; i < 13; ++i) {
// Copy a card from player's hand to a temp card
two_card = game->get_card(3, i);
// See if it should be stored (and later passed)
if (card_value(game, 3, two_card) > 0) { // It's a (somewhat) valuable card
if (value[3] == 13) { // If the spot is empty...
value[3] = i; // ... store it ...
continue; // ... and start the for loop over again
} else if (value[4] == 13) {
value[4] = i;
continue;
} else if (value[5] == 13) {
value[5] = i;
continue;
}
// See if the current card is move valuable than a previously stored card
if (card_value(game, 3, two_card) > card_value(game, 3, game->get_card(3, value[3]))) {
value[3] = i;
continue;
} else if (card_value(game, 3, two_card) > card_value(game, 3, game->get_card(3, value[4]))) {
value[4] = i;
continue;
} else if (card_value(game, 3, two_card) > card_value(game, 3, game->get_card(3, value[5]))) {
value[5] = i;
continue;
}
}
} // End of for(...)
// Start searching Player4's hands
for (u8 i = 0; i < 13; ++i) {
// Copy a card from player's hand to a temp card
thr_card = game->get_card(4, i);
// See if it should be stored (and later passed)
if (card_value(game, 4, thr_card) > 0) { // It's a (somewhat) valuable card
if (value[6] == 13) { // If the spot is empty...
value[6] = i; // ... store it ...
continue; // ... and start the for loop over again
} else if (value[7] == 13) {
value[7] = i;
continue;
} else if (value[8] == 13) {
value[8] = i;
continue;
}
// See if the current card is move valuable than a previously stored card
if (card_value(game, 4, thr_card) > card_value(game, 4, game->get_card(4, value[6]))) {
value[6] = i;
continue;
} else if (card_value(game, 4, thr_card) > card_value(game, 4, game->get_card(4, value[7]))) {
value[7] = i;
continue;
} else if (card_value(game, 4, thr_card) > card_value(game, 4, game->get_card(4, value[8]))) {
value[8] = i;
continue;
}
}
} // End of for(...)
// Copy over the good values
if (value[0] != 13) P2_one = value[0];
if (value[1] != 13) P2_two = value[1];
if (value[2] != 13) P2_thr = value[2];
if (value[3] != 13) P3_one = value[3];
if (value[4] != 13) P3_two = value[4];
if (value[5] != 13) P3_thr = value[5];
if (value[6] != 13) P4_one = value[6];
if (value[7] != 13) P4_two = value[7];
if (value[8] != 13) P4_thr = value[8];
// See if all of the values are filled in
if (value[0] != 13 && value[1] != 13 && value[2] != 13) one_3 = true;
if (value[3] != 13 && value[4] != 13 && value[5] != 13) two_3 = true;
if (value[6] != 13 && value[7] != 13 && value[8] != 13) thr_3 = true;
// If any of the values aren't good, we'll have to get more
if (!one_3 || !two_3 || !thr_3) {
// Setup some temp variables
bool p2_1 = false, p2_2 = false, p2_3 = false;
bool p3_1 = false, p3_2 = false, p3_3 = false;
bool p4_1 = false, p4_2 = false, p4_3 = false;
// If any of them have a good value, we won't change that later
if (value[0] != 13) p2_1 = true;
if (value[1] != 13) p2_2 = true;
if (value[2] != 13) p2_3 = true;
if (value[3] != 13) p3_1 = true;
if (value[4] != 13) p3_2 = true;
if (value[5] != 13) p3_3 = true;
if (value[6] != 13) p4_1 = true;
if (value[7] != 13) p4_2 = true;
if (value[8] != 13) p4_3 = true;
// Just in case each player hasn't selected 3 cards, randomly pick the rest
while (!one_3) {
// Get three different numbers from 0 to 12
if (!p2_1) P2_one = rand()%13;
if (!p2_2) P2_two = rand()%13;
if (!p2_3) P2_thr = rand()%13;
if ((P2_one != P2_two) && (P2_two != P2_thr) && (P2_one != P2_thr)) {
one_3 = true;
}
}
while (!two_3) {
// Get three different numbers from 0 to 12
if (!p3_1) P3_one = rand()%13;
if (!p3_2) P3_two = rand()%13;
if (!p3_3) P3_thr = rand()%13;
if ((P3_one != P3_two) && (P3_two != P3_thr) && (P3_one != P3_thr)) {
two_3 = true;
}
}
while (!thr_3) {
// Get three different numbers from 0 to 12
if (!p4_1) P4_one = rand()%13;
if (!p4_2) P4_two = rand()%13;
if (!p4_3) P4_thr = rand()%13;
if ((P4_one != P4_two) && (P4_two != P4_thr) && (P4_one != P4_thr)) {
thr_3 = true;
}
}
}
} // End of if (skill == x) ...
game->add_to_passed_cards(3, P2_one);
game->add_to_passed_cards(4, P2_two);
game->add_to_passed_cards(5, P2_thr);
game->add_to_passed_cards(6, P3_one);
game->add_to_passed_cards(7, P3_two);
game->add_to_passed_cards(8, P3_thr);
game->add_to_passed_cards(9, P4_one);
game->add_to_passed_cards(10, P4_two);
game->add_to_passed_cards(11, P4_thr);
return;
}
//*************************************************
// Function: ai_choose_card()
// Purpose: Determine which card the AI should play
//*************************************************
u8 ai_choose_card(HEARTS *game, u8 skill)
{
// Variables
u8 Chosen_Card = 13;
u8 curr_turn = game->gt(); // Current turn
u8 curr_lead = game->gl(); // Who lead
// Check if the computer has the 2 of Clubs
Chosen_Card = Two_of_Clubs(game, curr_turn);
if (Chosen_Card != 13) return Chosen_Card;
// Figure out the suit that was played
u8 suit_lead = game->gsl();
if (skill == 1) {
// Look through hand for card of that suit
for (u8 i = 0; i < 13; ++i) {
if ((game->player_number(curr_turn, i) != 0) &&
(game->player_suit(curr_turn, i) == suit_lead)) {
return i;
}
}
// Pick a random card
Chosen_Card = 0;
while (game->player_number(curr_turn, Chosen_Card) == 0) {
++Chosen_Card;
}
} else if (skill == 2 || skill == 3) {
// AI must throw the first card (but not 2 of Clubs)
if (curr_turn == curr_lead) {
// Throw the lowest card
Chosen_Card = lowest_card(game, curr_turn);
if (Chosen_Card != 13) return Chosen_Card;
// Pick a random card
for (Chosen_Card = 0; Chosen_Card < 13; ++Chosen_Card) {
if (game->player_number(curr_turn, Chosen_Card) != 0 && game->valid_move(curr_turn, Chosen_Card))
return Chosen_Card;
}
// AI does not have to throw the first card
} else {
// Check whether AI has to follow suit
if (has_suit(game, curr_turn, suit_lead)) {
// If Spades was led...
if (suit_lead == 0) {
// ... if the player can get rid of the Queen, play it
Chosen_Card = play_Qsp(game, curr_turn);
if (Chosen_Card != 13) return Chosen_Card;
// ... if the player can get rid of the A or K, play it
Chosen_Card = play_AKsp(game, curr_turn);
if (Chosen_Card != 13) return Chosen_Card;
}
// If Hearts or Spades was lead, play the lowest
if (suit_lead == 2 || suit_lead == 0) {
Chosen_Card = lowest_of_suit(game, curr_turn, suit_lead);
if (Chosen_Card != 13) return Chosen_Card;
}
// Figure out what the current highest of the suit lead is
u8 highest = get_high(game, suit_lead);
u8 gch = get_closest_high(game, curr_turn, suit_lead, highest);
u8 gcl = get_closest_low(game, curr_turn, suit_lead, highest);
// If only lower, play highest of low
if (gcl != 13 && gch == 13) return gcl;
// If only higher, play lowest of high...
// ... unless player is the last to play
if (gch != 13 && gcl == 13) {
if (game->gtc() == 3) {
Chosen_Card = highest_of_suit(game, curr_turn, suit_lead);
if (Chosen_Card != 13) return Chosen_Card;
} else {
return gch;
}
}
// Throw lowest card of the suit lead
Chosen_Card = lowest_of_suit(game, curr_turn, suit_lead);
if (Chosen_Card != 13) return Chosen_Card;
// Void in the suit lead
} else {
// If AI has the Queen of Spades, play it, except on the first trick
if (game->gtr() != 1) Chosen_Card = Queen_of_Spades(game, curr_turn);
if (Chosen_Card != 13) return Chosen_Card;
// If AI has the Ace of Spades, play it
Chosen_Card = has_card(game, curr_turn, 14, 0);
if (Chosen_Card != 13) return Chosen_Card;
// If AI has the King of Spades, play it
Chosen_Card = has_card(game, curr_turn, 13, 0);
if (Chosen_Card != 13) return Chosen_Card;
// If AI can void itself in a suit, do so
Chosen_Card = void_suit(game, curr_turn);
if (Chosen_Card != 13) return Chosen_Card;
// If AI has a Heart greater than the 10, play it
if (has_suit(game, curr_turn, 2)) {
Chosen_Card = highest_of_suit(game, curr_turn, 2);
if ((Chosen_Card != 13) && (game->player_number(curr_turn, Chosen_Card) > 10) &&
(game->valid_move(curr_turn, Chosen_Card))) {
return Chosen_Card;
}
}
// Throw the highest card
Chosen_Card = highest_card(game, curr_turn);
if (Chosen_Card != 13) return Chosen_Card;
} // End of if (has_suit(...))
}
}
return Chosen_Card;
} // End of ai_choose_card()
//******************************************
// Function: card_value()
// Purpose: Returns the card's passing value
//******************************************
u8 card_value(HEARTS *game, u8 player, Card cv_card)
{
// Variables
u8 number = cv_card.number;
u8 suit = cv_card.suit;
// If the player has more than 3 cards below
// the 8 of Spades, keep the A,K,Q of Spades
if (num_sp_below_eight(game, player) > 2) {
if (number == 12 && suit == 0) return 0;
if (number == 14 && suit == 0) return 0;
if (number == 13 && suit == 0) return 0;
} else {
if (number == 12 && suit == 0) return 10;
if (number == 14 && suit == 0) return 9;
if (number == 13 && suit == 0) return 9;
}
// Go through the rest of the deck
if (number == 14 && suit == 2) return 8;
if (number == 13 && suit == 2) return 8;
if (number == 12 && suit == 2) return 8;
if (number == 11 && suit == 2) return 7;
if (number == 14 && suit == 3) return 7;
if (number == 14 && suit == 1) return 7;
if (number == 13 && suit == 3) return 6;
if (number == 13 && suit == 1) return 6;
if (number == 12 && suit == 3) return 5;
if (number == 12 && suit == 1) return 5;
if (number == 11 && suit == 3) return 4;
if (number == 11 && suit == 1) return 4;
if (number == 11 && suit == 0) return 4;
if (number == 10) return 3;
if (number == 9) return 3;
if (number == 8) return 3;
if (number == 7) return 2;
if (number == 6) return 2;
if (number == 5) return 2;
if (number == 4) return 1;
if (number == 3) return 1;
if (number == 2) return 1;
return 0;
} // End of card_value()
//************************************
// Function: Two_of_Clubs()
// Purpose: Check whether has
// the 2 of Clubs
//************************************
u8 Two_of_Clubs(HEARTS *game, u8 player)
{
for (u8 i = 0; i < 13; ++i) {
if (game->player_number(player, i) == 2 && // It's a 2 ...
game->player_suit(player,i) == 1) { // ... of Clubs
return i;
}
}
// The calling function should make sure to
// check that the return value is != 13
return 13;
} // End of Two_of_Clubs()
//************************************
// Function: Queen_of_Spades()
// Purpose: Check whether has
// the Queen of Spades
//************************************
u8 Queen_of_Spades(HEARTS *game, u8 player)
{
for (u8 i = 0; i < 13; ++i) {
if (game->player_number(player, i) == 12 && // It's a Queen ...
game->player_suit(player,i) == 0) { // ... of Spades
return i;
}
}
// The calling function should make sure to
// check that the return value is != 13
return 13;
} // End of Queen_of_Spades()
//******************************************
// Function: has_card()
// Purpose: Returns the slot if has
// a card matching ,
// or returns 13 if not
//******************************************
u8 has_card(HEARTS *game, u8 player, u8 number, u8 suit)
{
// Variables
u8 h_c = 13;
// Loop through 's hand
for (u8 i = 0; i < 13; ++i) {
if (game->player_number(player, i) == number && game->player_suit(player, i) == suit) {
return i;
}
}
return h_c;
} // End of has_card()
//**************************************
// Function: has_suit()
// Purpose: Check whether has a
// card with suit
//**************************************
bool has_suit(HEARTS *game, u8 player, u8 suit)
{
for (u8 i = 0; i < 13; ++i) {
if ((game->player_number(player, i) != 0) && game->player_suit(player, i) == suit)
return true;
}
return false;
} // End of has_suit()
//*****************************************
// Function: get_high()
// Purpose: Returns the slot of the current
// highest card of
//*****************************************
u8 get_high(HEARTS *game, u8 suit)
{
// Variables
u8 curr_high = 4;
// Cycle through the tricks
for (u8 i = 0; i < 4; ++i) {
if (game->trick_suit(i) == suit) {
if (curr_high == 4) {
curr_high = i;
} else if (game->trick_number(i) > game->trick_number(curr_high)) {
curr_high = i;
}
}
}
// Make sure to check that the return value is != 4
return curr_high;
}
//**********************************************
// Function: get_closest_high()
// Purpose: Returns the slot of the next highest
// card, if any, in 's hand
// that is higher than . Returns
// 13 if only has lower cards
//**********************************************
u8 get_closest_high(HEARTS *game, u8 player, u8 suit, u8 high)
{
// No need to do any checks if is an Ace
if (high == 14) return 13;
// Variables
u8 closest_high = 13;
// Loop through 's hand
for (u8 i = 0; i < 13; ++i) {
// If the suit matches and the number is higher
if ((game->player_suit(player, i) == suit) && (game->player_number(player, i) > high)) {
// If this is the first card that's higher, store it
if (closest_high == 13) {
closest_high = i;
// Otherwise, check if this is lower than the current stored card
} else if ((game->player_number(player, i)) < (game->player_number(player, closest_high))) {
closest_high = i;
}
}
}
return closest_high;
} // End of closest_high()
//**********************************************
// Function: get_closest_low()
// Purpose: Returns the slot of the next lowest
// card, if any, in 's hand
// that is lower than . Returns
// 13 if only has higher cards
//**********************************************
u8 get_closest_low(HEARTS *game, u8 player, u8 suit, u8 low)
{
// No need to do any checks if is a 2
if (low == 2) return 13;
// Variables
u8 closest_low = 13;
// Loop through 's hand
for (u8 i = 0; i < 13; ++i) {
// If the suit matches and the number is lower
if ((game->player_suit(player, i) == suit) && (game->player_number(player, i) < low)) {
// If this is the first card that's lower, store it
if (closest_low == 13) {
closest_low = i;
// Otherwise, check if this is higher than the current stored card
} else if ((game->player_number(player, i)) > (game->player_number(player, closest_low))) {
closest_low = i;
}
}
}
return closest_low;
} // End of closest_low()
//*********************************************
// Function: lowest_of_suit()
// Purpose: Returns the slot of the lowest card
// of in 's hand or 13
// if they don't have it
//*********************************************
u8 lowest_of_suit(HEARTS *game, u8 player, u8 suit)
{
// Variables
u8 the_lowest = 13;
// If they don't have the suit, forget it
//if (!has_suit(game, player, suit)) return 13;
// Loop through 's cards of for the lowest one
for (u8 i = 0; i < 13; ++i) {
if (game->player_suit(player, i) == suit) {
if (the_lowest == 13) {
the_lowest = i;
} else if (game->player_number(player, the_lowest) > game->player_number(player, i)) {
the_lowest = i;
}
}
}
return the_lowest;
} // End of lowest_of_suit()
//**********************************************
// Function: highest_of_suit()
// Purpose: Returns the slot of the highest card
// of in 's hand or 13
// if they don't have it
//**********************************************
u8 highest_of_suit(HEARTS *game, u8 player, u8 suit)
{
// Variables
u8 the_highest = 13;
// If they don't have the suit, forget it
if (!has_suit(game, player, suit)) return 13;
// Loop through 's cards of for the lowest one
for (u8 i = 0; i < 13; ++i) {
if (game->player_suit(player, i) == suit) {
if (the_highest == 13) {
the_highest = i;
} else if (game->player_number(player, the_highest) < game->player_number(player, i)) {
the_highest = i;
}
}
}
return the_highest;
} // End of highest_of_suit()
//****************************************
// Function: lowest_card()
// Purpose: Returns the slot of the lowest
// card in 's hand
//****************************************
u8 lowest_card(HEARTS *game, u8 player)
{
// Variables
u8 low_card = 13;
// Start searching
for (u8 i = 0; i < 13; ++i) {
if (game->player_number(player, i) != 0) {
// Make sure if it's a Heart that Hearts are broken
if ((game->player_suit(player, i) != 2) ||
(game->player_suit(player, i) == 2 && (game->valid_move(player, i)))) {
// This is the first low card
if (low_card == 13) {
low_card = i;
// Current card is lower than the previous low card
} else if (game->player_number(player, i) < game->player_number(player, low_card)) {
low_card = i;
}
}
}
}
return low_card;
} // End of lowest_card()
//*****************************************
// Function: highest_card()
// Purpose: Returns the slot of the highest
// card in 's hand
//*****************************************
u8 highest_card(HEARTS *game, u8 player)
{
// Variables
u8 high_card = 13;
// Start searching
for (u8 i = 0; i < 13; ++i) {
if (game->player_number(player, i) != 0) {
if (high_card == 13) {
high_card = i;
} else if (game->player_number(player, i) > game->player_number(player, high_card)) {
// Make sure if it's a Heart that Hearts are broken
if ((game->player_suit(player, i) != 2) ||
((game->player_suit(player, i) == 2) && (game->valid_move(player, i)))) {
high_card = i;
}
}
}
}
return high_card;
} // End of highest_card()
//************************************
// Function: void_suit()
// Purpose: Would playing one card get
// rid of a suit for
//************************************
u8 void_suit(HEARTS *game, u8 player)
{
// Variables
u8 vs = 13; // The spot that will be returned
u8 num_suits[4]; // Stores the number of that suit
u8 loc_suits[4]; // Stores the location of that suit
u8 curr_suit = 4; // The current suit of a card in 's hand
// Set all of the current number of suits to 0
for (u8 i = 0; i < 4; ++i) num_suits[i] = 0;
// Now count them up
for (u8 i = 0; i < 13; ++i) {
if (game->player_number(player, i) != 0) {
curr_suit = game->player_suit(player, i);
if (curr_suit == 0) {
++num_suits[0];
loc_suits[0] = i;
} else if (curr_suit == 1) {
++num_suits[1];
loc_suits[1] = i;
} else if (curr_suit == 2) {
++num_suits[2];
loc_suits[2] = i;
} else if (curr_suit == 3) {
++num_suits[3];
loc_suits[3] = i;
}
}
}
// Figure out if any were only one
for (u8 i = 0; i < 13; ++i) {
if (num_suits[i] == 1) {
// Make sure if it's a Heart that Hearts are broken
if ((i != 2) || ((i == 2) && (game->valid_move(player, loc_suits[i])))) {
return loc_suits[i]; // And return that location
}
}
}
return vs;
} // End of void_suit()
//**************************************
// Function: number_of_suit()
// Purpose: Returns the number of
// in 's hand
//**************************************
u8 number_of_suit(HEARTS *game, u8 player, u8 suit)
{
// Variables
u8 num_suit = 0;
// Loop through 's cards
for (u8 i = 0; i < 13; ++i) {
if (game->player_number(player, i) != 0 && game->player_suit(player, i) == suit) ++num_suit;
}
return num_suit;
} // End of number_of_suit()
//****************************************
// Function: num_sp_below_eight()
// Purpose: Returns the number of Spades
// in 's hand below the 8
//****************************************
u8 num_sp_below_eight(HEARTS *game, u8 player)
{
// Variables
u8 num_suit = 0;
// Loop through 's cards
for (u8 i = 0; i < 13; ++i) {
if (game->player_number(player, i) < 8 && game->player_suit(player, i) == 0) ++num_suit;
}
return num_suit;
} // End of num_sp_below_eight()
//***********************************************
// Function: play_AKsp()
// Purpose: Determine if should play
// the Ace or King of Spades. Returns
// the slot of either if so or 13 if not
//***********************************************
u8 play_AKsp(HEARTS *game, u8 player)
{
// Variables
u8 Asp_slot = 13;
u8 Ksp_slot = 13;
u8 trick_cards = game->gtc();
u8 curr_numb = 0;
bool has_AKsp = false;
// The player must have the Ace or King of Spades
for (u8 i = 0; i < 13; ++i) {
if (game->player_suit(player, i) == 0) { // It's a Spade
curr_numb = game->player_number(player, i);
// If it's a King, store the King's spot
if (curr_numb == 13) {
has_AKsp = true; // Has one of them
Ksp_slot = i; // Store the spot
// If it's an Ace, store the Ace's spot
} else if (curr_numb == 14) {
has_AKsp = true; // Has one of them
Asp_slot = i; // Store the spot
}
}
}
// Doesn't have either, cya
if (!has_AKsp) return 13;
// Check if someone played the Ace of Spades, if so, play the King
for (u8 i = 0; i < 4; ++i) {
if (game->trick_number(i) == 14 && game->trick_suit(i) == 0) {
if (Ksp_slot != 13) {
return Ksp_slot;
}
}
}
// Check if someone played the Queen of Spades
for (u8 i = 0; i < 4; ++i) {
if (game->trick_number(i) == 12 && game->trick_suit(i) == 0) return 13;
}
// Check if the player has a lower Spade
if (lowest_of_suit(game, player, 0) != Ksp_slot) return 13;
// If three trick cards have been played, then discard either the Ace or King
if (trick_cards == 3) {
if (Asp_slot != 13) return Asp_slot;
if (Ksp_slot != 13) return Ksp_slot;
}
// If the player has the Queen of Spades, get rid of an Ace or King first
if (Queen_of_Spades(game, player) != 13) {
if (Asp_slot != 13) return Asp_slot;
if (Ksp_slot != 13) return Ksp_slot;
}
return 13;
}
//*******************************************
// Function: play_Qsp()
// Purpose: Determine if should play
// the Queen of Spades. Returns the
// slot if so or 13 if not.
//*******************************************
u8 play_Qsp(HEARTS *game, u8 player)
{
// Variables
bool Qsp = false;
u8 Qsp_slot = Queen_of_Spades(game, player);
// If they don't have it, they can't play it
if (Qsp_slot == 13) return 13;
// Otherwise, note if the Ace or King of Spades has been played
for (u8 i = 0; i < 4; ++i) {
if (game->trick_suit(i) == 0) { // Search the trick card for Spades
if (game->trick_number(i) == 13 || game->trick_number(i) == 14) { // And the Ace or King
Qsp = true; // A or K has been played, we can play the Queen
}
}
}
// If the Ace or King of Spades was played
if (Qsp) {
return Qsp_slot; // Then return the Queen's spot
} else {
return 13; // Otherwise, don't play the Queen
}
} // End of play_Qsp()