Spades Tutorial Part 3¶
There is one last thing to do: after all four players have played a card, it’s time to figure out who took the trick, clear the play area, and reset any relevant PROP s
Declaring a winner at the end of a trick¶
The winner is the player who played
- the highest card in the leading suit, if no spades (trumps) were played
- the highest spade, if a spade was played
It’s a bit of a pain to write this logic as explained this way. Instead, we’ll do this:
- each card in the deck has a numerical value from 1-13 for Ace-King
- for each card that was played, assign it a point value according to what was played - if the card is the led suit, assign the card’s numerical value (but make sure that Aces are high, not low) - if the card is a spade, assign the card’s numerical value plus some value that makes sure that the lower spade beats any led suit - if the card is any other suit, just assign 0. It’s not possible for that card to win.
- sort the players according to the point value of the card they played. The player with the highest point card wins
We’ll define a couple helper functions here, too:
# aces high
DEF get_value $card:
ASSIGN 'tmp' INT TOKEN_GET_PROP $card 'value';
IF EQUAL $tmp 1:
ASSIGN 'tmp' 14;
END_IF
RETURN $tmp;
END_DEF
DEF spades_value $card:
IF EQUAL get_suit $card 's':
RETURN PLUS get_value $card 100;
END_IF
IF EQUAL get_suit $card GET_PROP 'suit_led':
RETURN PLUS get_value $card 50;
END_IF
RETURN 0;
END_DEF
DEF tuple_helper $player_name:
ASSIGN 'play_container' GET_CONTAINER CONCAT $player_name '_play';
ASSIGN 'played_card' POP $play_container 0;
RETURN TUPLE2 $player_name spades_value $played_card;
END_DEF
# figure out winner for the trick and clean up trick accounting props
DEF clean_up_trick:
ASSIGN 'trick_values' MAP GET_PROP 'play_order' 'tuple_helper';
DEBUG $trick_values;
REVERSE SORT_TUPLE $trick_values;
DEBUG $trick_values;
ASSIGN 'winner' GET_POSITION_ELT GET_POSITION_ELT $trick_values 0 0;
DEBUG $winner;
END_DEF
- We defined
tuple_helper
so that we can take advantage of theMAP
andSORT_TUPLE
primitives. tuple_helper
takes a given player, removes their last played card from their_play
container (which clears their play area), and puts together a tuple consisting of (player name, point value of the card they played)MAP
applies this function to all the players, creating a list of these tuplesSORT_TUPLE
sorts this list based on the second element of the tuple (so, based on the point value)- As
SORT_TUPLE
sorts in ascending order, we applyREVERSE
to make the order descending - Then, the first element of the list should be the winner
Misc other book keeping¶
There are just a few things left to do:
- set
suit_led
for the first card played in a trick - increment
current_trick_count
every time a card is played, to know when the end of the trick happens - pass play to the next player by invoking
ROTATE_PLAY_ORDER
- actually call
clean_up_trick
at the end of a trick clean_up_trick
already clears the play area, but we should reset other registers too such assuit_led
orcurrent_trick_count
- at the end of the trick, change the play order so that the winner leads the next trick
To do the above, we add the following code to their respective functions:
DEF clean_up_trick:
...
SET_ELT GET_PROP 'player_scores' $winner PLUS GET_ELT GET_PROP 'player_scores' $winner 1;
SET_PROP 'current_trick_count' 0;
SET_PROP 'current_trick_num' PLUS GET_PROP 'current_trick_num' 1;
SET_PROP 'suit_led' NULL;
ASSIGN 'ct' 0;
WHILE AND
NOT EQUAL GET_POSITION_ELT GET_PROP 'play_order' 0 $winner
LESS $ct 5:
ROTATE_PLAY_ORDER;
ASSIGN 'ct' PLUS $ct 1;
END_WHILE
END_DEF
RECEIVE play_card $dummy $card_name:
...
SET_PROP 'current_trick_count' PLUS GET_PROP 'current_trick_count' 1;
IF IS_NULL GET_PROP 'suit_led':
SET_PROP 'suit_led' get_suit $card_token;
END_IF
ROTATE_PLAY_ORDER;
IF EQUAL GET_PROP 'current_trick_count' 4:
clean_up_trick;
END_IF
ACCEPT;
END_RECEIVE