Spades Tutorial Part 4ΒΆ

For reference, here is the complete ruleset for Spades (without bidding):

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
DEF get_suit $card:
  RETURN TOKEN_GET_PROP $card 'suit';
END_DEF

# 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 follows_suit $card:
  RETURN EQUAL get_suit $card GET_PROP 'suit_led';
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;
  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

DEF set_up:
  SHUFFLE GET_CONTAINER 'draw_deck';
  ASSIGN 'i' 3;
  WHILE GREATER_OR_EQUAL $i 0:
    ASSIGN 'j' 12;
    WHILE GREATER_OR_EQUAL $j 0:
      ASSIGN 'tmp' POP GET_CONTAINER 'draw_deck' 0;
      APPEND GET_CONTAINER CONCAT CONCAT 'player_' STR $i '_hand' $tmp;
      ASSIGN 'j' PLUS $j -1;
    END_WHILE
    ASSIGN 'i' PLUS $i -1;
  END_WHILE
END_DEF

# play directives

RECEIVE play_card $dummy $card_name:
  IF NOT EQUAL $PLAYER_NAME GET_POSITION_ELT GET_PROP 'play_order' 0:
    REJECT CONCAT "not player turn: " $PLAYER_NAME;
  END_IF
  ASSIGN 'player_hand' GET_CONTAINER CONCAT $PLAYER_NAME "_hand";
  IF NOT CONTAINS_BY_NAME $player_hand $card_name:
    REJECT CONCAT "card not in player hand: " $card_name;
  END_IF
  # get the number of cards in player hand of the led suit
  ASSIGN 'ct' 0;
  ASSIGN 'i' PLUS SIZE $player_hand -1;
  WHILE GREATER_OR_EQUAL $i 0:
    IF follows_suit GET_BY_POSITION $player_hand $i:
      ASSIGN 'ct' PLUS $ct 1;
    END_IF
    ASSIGN 'i' PLUS $i -1;
  END_WHILE
  IF NOT
    OR
      OR
        IS_NULL GET_PROP 'suit_led'
        follows_suit GET_TOKEN $card_name
      EQUAL $ct 0:
    REJECT CONCAT "must follow suit: " $card_name;
  END_IF
  # ok to play card
  ASSIGN 'player_play' GET_CONTAINER CONCAT $PLAYER_NAME '_play';
  ASSIGN 'card_token' POP_BY_NAME $player_hand $card_name;
  IF IS_NULL $card_token:
    REJECT "Something went wrong";
  END_IF
  APPEND $player_play $card_token;
  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