King of the Cards

Code available here!

In this King of the Hill challenge, you must write a bot that can play Crazy Eights. This is a card game often played by children, in which the objective is to empty your hand.

How to Play

The game of Crazy Eights is deceptively simple. At the beginning of the game, each player gets dealt a hand of cards (in this case eight), with the remaining cards placed in the middle of the table as the draw pile. The top card is then placed face up and serves as the beginning of the discard pile. Then, each player can discard one card per turn if that card has a matching suit or rank with the top card on the discard pile. They may also play an 8, which allows them to change the effective suit of the 8 and therefore the suit the next player must follow. The played card then becomes the top card. If the player does not have any matching cards, they must draw from the draw pile until they get a matching card and play that. If they exhaust the draw pile, play passes to the next player. Players may draw at any time, even if they have playable cards (which does not count as a turn).

For example, if 6♣ is played, the next player:

• Can play a 6 of any suit
• Can play any club
• Can play an 8 (and then must declare a suit)
• Can draw and continue their turn.

If the draw pile runs out, then the discard pile (except for the top card) is shuffled and becomes the new draw pile.

The game ends once a player runs out of cards, in which case they are declared the winner. (This differs from normal Crazy Eights, and is included to make this game a bit simpler.)

Bots

Bots must be written in Python. Bots will have access to the kotc module, which supplies these classes:

• KOTCBot, which bots must extend
• Card, which represents a card
• Suit and Rank, enums representing the suit and value of a card

Bots must implement a play method, which takes as input a Card representing the top card on the discard pile. This method must return a Card within that bot's hand. If the returned Card is not in the bot's hand that bot is disqualified. (I will leave a comment on it with information about the state of the game when it happened.) However, if the Card is an Eight then only the rank will be checked against the bot's hand. If the bot has no playable cards in its hand, the play method will NOT be called and the controller will automatically draw cards on behalf of the bot and add them to its hand. The bot should NEVER modify its hand! This will be done by the controller. The play method may also return None or False, which will cause its turn to be skipped.

Bots will compete against each other in matches of two, in an elimination-style tournament bracket. The winner will advance onwards, and the loser will be executed eliminated.

API

KOTCBot

This class is the actual bot.

Methods and properties: (Do NOT override any of these in your bot)

• draw: When called, this function draws a card from the pile and adds it to the bot's hand. It also returns the card drawn.
• hand: This property is a list of Cards representing the bot's hand.
• arena: This property is the KOTCArena instance the bot is playing in.

KOTCArena

This class is accessible through the arena property of the Bot. It has three functions available to the bots:

• handSizes: Returns a list of the lengths of the hands of the other bots
• discardSize: Returns the size of the discard pile
• drawSize: Returns the size of the draw pile

Card

The Card class represents a card, and takes a Suit and Rank when constructed. This class must be returned by the bot's play method. Its suit and rank can be accessed through their respective properties.

• all: This classmethod takes no parameters and returns a 52-item list of all possible card combinations.

Note: All enumeration members are UPPERCASE.

Suit

Members of this enum:

• CLUBS
• DIAMONDS
• SPADES
• HEARTS

Rank

Members of this enum:

• ACE
• KING
• QUEEN
• JACK
• TWO through TEN

Example Bot

This bot just plays any available card, without using eights.

import kotc

class ExampleBot(kotc.KOTCBot):
for card in self.hand:
return card

• You could instead run bots in rounds of three or four at a time. I think a tournament bracket relies on a lot of luuck. May 17, 2022 at 20:08
• @emanresuA I intend to run each game multiple times to fix this. May 17, 2022 at 20:11
• "Players may draw at any time"; what will happen if we run out of cards, even discarded before? For example, I write while True: self.draw()?
– tsh
May 18, 2022 at 3:01
• Could you post the code for running a simulation of the KOTC? I would like to test things out on my own, as well as solve the ambiguities, such as the actual code of your enums. Finally, for convenience, could you add a function that returns a list of all 52 possible cards? May 19, 2022 at 0:39
• Is the simulation going to use an actual 52 card deck with 52 unique cards in it or does it just give me a random card whenever I draw one? May 19, 2022 at 13:47

BasicBot

import kotc
from random import shuffle
class BasicBot(kotc.KOTCBot):
shuffle(self.hand)
for card in self.hand:
if (card.rank == kotc.Rank.EIGHT):
playables = 0
for card2 in self.hand:
playables+=1
if playables<2:
return card2


• You want for card in shuffle(self.hand) or self.hand: if you want to shuffle your hand in the for statement. Or simply call shuffle(self.hand) in the line before for card in self.hand). May 17, 2022 at 22:09