CPSC 415 - Artificial Intelligence - Fall 2023

Program #5 — Logic-based adversarial agents

Possible experience: up to +100XP

Due: Sunday, Dec. 10th, midnight

Overview

In this final competitive throwdown, you'll be competing against 'bots, fellow players, and even your professor in the classic board game Clue®.

(Our) rules

If you don't know how to play Clue®, it's easy to learn. We're going to play a slightly-simplified version of the game anyway: no tokens, dice, or game board (those elements inflict needless random noise on what should be a pure intellectual contest).

Here are the basics:

The players

Our Clue® matches will always have exactly three players in them, even if some of them are dumb stand-ins like the random player provided in the assignment. The order of the players will be automatically shuffled by my simulator before playing.

The deck

  1. There are 21 cards in a standard Clue® deck, each one unique.
  2. Six of these cards represent possible murder suspects, whose names are scarlet, mustard, plum, white, green, and peacock.
  3. Six represent potential murder weapons: revolver (bang!), wrench (ow!), rope (gasp!), knife, candlestick, and leadpipe.
  4. The other nine represent rooms in a mansion, in which the murder might have taken place: hall, kitchen, library, billiardroom (these people are rich), study (and well read), diningroom (and well fed), lounge (and well rested), ballroom (and exercised), and conservatory (whatever that is).

The secret solution

Before the game begins, exactly one suspect card, one weapon card, and one room card are secretly removed from the deck and placed in an iron-clad solution vault. These three cards represent the "solution" to the game: the actual truth about who the murderer was, what weapon he/she used, and where the killing took place.

All the other cards are dealt out randomly to the players. Happily, if there are exactly three players, this comes out evenly (6 cards each).

The object of the game

The object of the game is to be the first player to figure out which three cards are in the hidden iron-clad vault. You do this by a process of logic, the very first baby step of which is: if you're holding a particular card, you know it's not part of the solution. That's because there's only one of each card in the deck. So you can immediately rule out six cards (the 6 you were dealt) without even being very smart.

Your move: "suggestions" vs "accusations"

Now this part is tricky so pay attention. Players alternate turns in round-robin fashion, and when it's your turn, you have two choices about what to do:

  1. You may "suggest" a solution to the next player in turn. This means you can name three cards (one suspect, one weapon, and one room) and ask the next player to secretly show you one of them if they have any. (The cards you name are normally cards you don't possess, but for strategic purposes it is by no means rare to name one or more that are actually in your hand.)

    So, if on your turn, you say "I'd like to suggest that scarlet was the murderer, with the knife, in the library," the next player will look at their cards to see whether they can rule out that hypothesis for you. If they can, they will secretly show you one of those three cards from their hand. All players hear the suggestion, and know whether or not a card was shown, even though they will not know which card was shown. If the next player does not have any of the three cards, they say "I cannot help you," in which case the burden rotates to the next player, who looks in their hand for one of the three cards, etc. If neither of the opponents have any of the named cards, the turn simply advances to the next player.
  2. Instead of "suggesting," you may instead "accuse" by also naming three cards. This is a one-time-only, spend-your-money, all-or-nothing move. It is the only way to win, and it is also a great way to lose. If the suspect, weapon, and room that you name are actually in the iron-clad box, you win the game. Otherwise, you are disqualified (DQ'd) and cannot win the game. (Note that DQ'd players still must show cards when other players "suggest," just as before; they simply do not take their own turn.)

In the rare but comical circumstance that all three players DQ, the game is declared a tie. Otherwise, whoever makes a winning accusation is the winner.

Supporting classes

The files clue.py and starting_CluePlayer.py, and from the class's github repo should be all you need to get started. I've also included a really dumb, random player called random_CluePlayer.py that you can practice beating up on.

(When you get to the point of running large multi-game contests, you'll also want clue_suite.py and clue_chunk.py.)

Running a single game

You can run clue.py with three player names to run a single game. Try it right now by running three random players against each other:

$ python3 clue.py random random random

This will print the winner, or the word "Tie". If you'd like to see narrative output of the game as its progressing, change the word CRITICAL in clue.py to "INFO" or even "DEBUG".

Running a suite of games

To run many games with the same three opponents, and see the results, run clue_suite.py as follows:

$ python3 clue_suite.py random random random 10000

This will run a suite of 10,000 games (using all your system cores) and print tabulated results.

The CluePlayer class

If you wanna be a playa, you'll need to create a subclass of the CluePlayer class. You should start by copying "starting_CluePlayer.py" to "yourUmwId_CluePlayer.py, and changing the word starting to your UMW ID wherever it appears in the file.

Then, read the documentation for each of the methods of this class. It's a total of 16 sentences. I worked really hard on those 16 sentences to make sure they're concise and explain everything you need to know. So be sure to read them, and to ask questions whenever you have them.

You will want to replace the "pass" with your own actual code for all of these methods.

Send email early and often with questions you have on absolutely anything!

It's just logical

Using the KB class that I wrote specifically for this assignment is likely to achieve much better results than you could otherwise. I do recommend that you get your feet wet first by experimenting with the random player, and making some smaller changes to it.

The PropKB.py and cnf.py files are already in the class code base (you're welcome), and the KB itself is described semi-exhaustively on the github page.

Grading

If your agent can consistently beat my random player (provided with the simulation code), it will earn at least +50XP.

If your agent can consistently beat my pretty sucky attempt at an actual thinking player (not provided), it will earn at least +75XP.

If your agent can consistently beat my not-as-sucky attempt (but not my real best, either), it will earn at least +100XP.

In December, we will have a three-at-a-time-bracket-style competition with everyone's best Clue player, plus mine. The runner-up in this "Clue® Challenge" will earn +110XP. The grand prize winner will earn a whopping +120XP, plus a weapon of their choice.

Turning it in

You will turn this assignment in by attaching your properly-named ClueAgent Python file to an email with subject line "CPSC 415 Program #5 turnin".

Getting help

Come to office hours, or send me email with subject line "CPSC 415 Program #5 help!!"