Clue Simulator: The Code

Clue Simulator: The Code

My choice of a final project for Programming 1 was to create a game similar to the Hunger Games Simulator. If you’d like to learn more about the origins of the idea, click here. Instead of being based off of the Hunger Games, my program is based off of the board game, Clue, though the idea of each character being eliminated comes from the novel And Then There Were None by Agatha Christie. For those of you who don’t know what the Hunger Game Simulator is, basically you’re given a list of characters from the Hunger Games, or in my case, Clue. Once you click the proceed button, the characters are put into a list. Next to each character is a line of text saying what happened to them/what they did in that round. The rounds continue until all but one character is eliminated. If my description didn’t make much sense to you, you can click here and try the Hunger Games Simulator out, or you can click here to see a playthrough. Lastly, if you’d like a few more technicalities, click here.

————————————————————————————————————

To download the game, click here

————————————————————————————————————

from toolbox import get_number, get_integer, get_boolean, get_yes_no
def main():
    print_backstory()
    continue_game()
    print_instructions()
    continue_game()
    canvas = Canvas(width = 710, height = 520, bg = 'black')
    #
    # Packs the canvas into a frame/form.
    #
    canvas.pack(expand = YES, fill = BOTH)
    #
    # Loads the .gif image file.
    #
    mustard = PhotoImage(file = 'mustard.gif')
    green = PhotoImage(file = 'green.gif')
    plum = PhotoImage(file = 'plum.gif')
    azure = PhotoImage(file = 'azure.gif')
    rusty = PhotoImage(file = 'rusty.gif')
    white = PhotoImage(file = 'white.gif')
    scarlet = PhotoImage(file = 'scarlet.gif')
    peacock = PhotoImage(file = 'peacock.gif')
    meadowbrook = PhotoImage(file = 'meadowbrook.gif')
    lavender = PhotoImage(file = 'lavender.gif')
    #
    # Puts a gif image on the screen.
    #
    canvas.create_image(10, 10, image = rusty, anchor = NW)
    canvas.create_image(150, 10, image = lavender, anchor = NW)
    canvas.create_image(290, 10, image = azure, anchor = NW)
    canvas.create_image(430, 10, image = meadowbrook, anchor = NW)
    canvas.create_image(570, 10, image = plum, anchor = NW)
    canvas.create_image(10, 260, image = peacock, anchor = NW)
    canvas.create_image(150, 260, image = green, anchor = NW)
    canvas.create_image(290, 260, image = scarlet, anchor = NW)
    canvas.create_image(430, 260, image = mustard, anchor = NW)
    canvas.create_image(570, 260, image = white, anchor = NW)
    mainloop()
    textX = 210
    textY = 10
    textString = ''
    playAgain = True
    while playAgain:
        player, charactersAlive = give_team_options()
        begin() 
        charactersDead = []
        #
        # Makes sure nobody dies in the first round.
        #
        first_round(charactersAlive,charactersDead)
        continue_game()
        #
        # The murders begin.
        #
        while player not in charactersDead:
            charactersAlive, charactersDead = new_round(charactersAlive,charactersDead)
            continue_game()
            if player in charactersDead:
                print_loss()
            #
            # Character wins when 9 characters are dead and the player is alive.
            #
            if (len(charactersDead) == 9) and (player in charactersAlive):
                print_win()
                break
        playAgain = get_yes_no("Would you like to play again? ")
    cleanup()

import time
import random
import turtle
import tkinter
from tkinter import *

Above is my first section of code. This is what tells the computer to do and when to do it. This is also where it tells the computer to open the character images in a separate window. It begins with the backstory and instructions. Next, it opens the character images window, then goes into the actual game. After all of this, it tells you if you win or lose and asks if you’d like to play again.

def character(line): # do i need this?
    """Tells the computer that the lines in the file are characters."""
    data = line.split(',')
    character = data[0]
    return character

def give_team_options():
    """Gives the user options of teams."""
    print("""
================================================================
                           Guest List
================================================================""")
    time.sleep(.5)
    print("""1. Rusty Mayler
2. Lady Su Xian Lavender
3. Prince Philippe Azure
4. Mrs. Jane Meadow-Brook
5. Professor Peter Plum
6. Mrs. Patricia Peacock
7. Reverend John Green
8. Miss Josephine Scarlet
9. Colonel Michael Mustard
10. Mrs. Blanche White""")
    time.sleep(1)
    print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
    prompt = "Who do you think is the murderer [1-10]? "
    number = get_integer(prompt)-1
    #
    # Makes sure they pick a number in the list.
    #
    while number not in range(0,10):
        prompt = "Please pick a listed number [1-10]: "
        number = get_integer(prompt)-1
    ch1 = "Rusty"
    ch2 = "Lady Lavender"
    ch3 = "Prince Azure"
    ch4 = "Miss Meadow-Brook"
    ch5 = "Professor Plum"
    ch6 = "Mrs. Peacock"
    ch7 = "Mr. Green"
    ch8 = "Miss Scarlet"
    ch9 = "Colonel Mustard"
    ch10 = "Mrs. White"
    charactersAlive = [ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8, ch9, ch10]
    selectedCharacter = charactersAlive[number]
    print("    Character selected: "+selectedCharacter)
    return selectedCharacter, charactersAlive

This second section is what prints out the list of characters on the screen and allows you to pick which one you believe is the murderer. Throughout the game, the computer remembers this character, which allows it to tell you if you won or lost in the end.

def new_round(charactersAlive,charactersDead):
    """Starts a new round."""
    randomDeath = random.randrange(0,len(charactersAlive))
    #
    # charactersDead.append(random character death) first because
    # it's accessed through the charactersAlive list.
    #
    dead = charactersAlive[randomDeath]
    deathScenarios = open('./weapons.csv', 'r')
    counter = 1
    lineNumber = random.randrange(1, 11)
    for line in deathScenarios:
        if lineNumber == counter:
            deathScenario = line
        counter = counter + 1
    deathScenarios.close
    #
    # Selects a new random death scenario from new file called "death scenarios"
    #
    whatHappens = f'{dead} {deathScenario}'
    print(whatHappens)
    print()
    scenarioFile = open('./scenarios.csv', 'r')
    scenarioList = scenarioFile.readlines()
    scenarioFile.close
    scenariosUsed = []
    charactersDead.append(dead)
    charactersAlive.remove(dead)
    for index in charactersAlive:
        characterName = character(index)
        scenario, lineNumber, scenarioList = scenarios(scenarioList)
        whatHappens = f'{characterName} {scenario}'
        print(whatHappens)
        #
        # if updating scenario, update the number in following if statement
        #
        if lineNumber == 11:
            charactersAlive.remove(characterName)
            charactersDead.append(characterName)
    #print(charactersAlive)
    #print(charactersDead)
    characters_dead(charactersDead)
    return charactersAlive, charactersDead

def first_round(charactersAlive,charactersDead):
    """Plays the first round. No one dies here."""
    for index in charactersAlive:
        characterName = character(index)
        scenario, lineNumber = first_round_scenarios()
        whatHappens = f'{characterName} {scenario}'
        print(whatHappens)
    return charactersAlive, charactersDead

The third section is what plays the actual game. It goes into a file that has a list of different things each character could do in each round and selects one randomly. After selecting one, it prints out a list of the characters, along with what they do in that round. The first round has a different set of things they could do, since it’s supposed to represent them traveling to the Boddy Manor. None of the characters die during the first round, as well.

def scenarios(scenarioList):
    """Gets scenarios from a file."""
    #
    # Selects a scenario from the second half of the file.
    #
    scenarioNumber = random.randrange(11, len(scenarioList))
    scenario = scenarioList[scenarioNumber]
    scenarioList.remove(scenario)
    scenarioNumber += 1
    return scenario, scenarioNumber, scenarioList

def first_round_scenarios():
    """Gets scenarios from a file for the first round (no deaths)."""
    scenarioFile = open('./scenarios.csv', 'r')
    counter = 1
    lineNumber = random.randrange(1, 11)
    for line in scenarioFile:
        if lineNumber == counter:
            scenario = line
        counter = counter + 1
    scenarioFile.close
    return scenario, lineNumber

This section kind of goes along with the one before it. Simply stated, this is what tells the computer to open the file that contains what each character does. Along with this, it tells the computer what in that file is considered to be a scenario and where each begins and ends.

def characters_dead(charactersDead):
    """Notifies user what characters are dead."""
    print("Characters dead: ")
    if len(charactersDead) == 0:
        print("    none")
    else:
        for character in charactersDead:
            print("   -" + character)

There isn’t much to say about this next section, except that it tells you which characters dies every round. A list of eliminated characters is also given at the bottom of each round.

def print_win():
    """Tells the user they won."""
    slow_print("Great job investigator!")
    time.sleep(1)
    slow_print("You found the murderer!")
    time.sleep(1)
    slow_print("Sadly, everyone is still dead.")
    print()

def print_loss():
    """Tells the user they lost."""
    slow_print("Looks like the guest you chose was not the murderer.")
    time.sleep(1)
    slow_print("As punishment, you will never know the truth.")
    print()

This fourth section is pretty self-explanatory. It tells you if you won or lost and prints out a bit of text afterwards.

def print_backstory():
    """Prints a backstory/plot for the game."""
    print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
    slow_print2("Hampshire, England                                  March, 1954")
    print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
    time.sleep(1)
    slow_print2("Dear guest,")
    time.sleep(1)
    slow_print2("""    It has been requested that you attend a dinner party at the
Boddy Manor. Noting the manor's secluded location, I
recommended you pack for a week's stay. A carriage will be
waiting for you at early morning tomorrow.

Sincerely,
""")
    time.sleep(1)
    slow_print("Wadsworth")
    time.sleep(1)
    continue_game()
    print()
    slow_print("""Ten strangers received this invintation, all on the night of
March 18th, 1954. The Boddy Manor is an elegant English country
house located in the woods of southwest Hampshire. The manor
includes the typical ballroom, library, billiard room, and the
like, though rumor has it that it even has its own set of
secret corridors that link the building's four corners
together.
""")
    time.sleep(1)
    slow_print("""They soon discovered that Wadsworth is one of Mr. Boddy's
butlers. Upon arrival of the carriage, he informed them that
Mr. Boddy was planning to blackmail his guests because each
was suspected of committing a crime.
""")
    time.sleep(1)
    slow_print("""Upon arrival, Mr. Boddy, after somehow getting word of what
his butler revealed, threatened to expose all of them if he
was arrested. He supplied each guest with a weapon, demanding
that someone kill Wadsworth.
""")
    time.sleep(1)
    slow_print("""After turning out the lights, a gunshot rang out. The lights
were switched back on only to reveal Mr. Boddy's corpse.
""")
    time.sleep(1)
    slow_print("But one question remained...")
    time.sleep(1)
    slow_print("Who was next?")
    print()
    time.sleep(1)

def print_instructions():
    """Gives the user instructions on how to play the game."""
    slow_print("""
================================================================
~~~~~~~~~~~~~~~~~And Then... There Was A Clue~~~~~~~~~~~~~~~~~~~
================================================================""")
    slow_print("""Welcome! This is a simulator based off of a combination of the
board game Clue and the novel And Then There Were None. You will
first be given a list of 10 characters to choose from. Choose
the one you believe is the murderer. Once the character is
chosen, the game will begin. There will be up to 10 rounds where
the characters are printed in a list with a description of what
they did during that round. You will be notified after each
round if a character died. If your character dies, you were
obviously incorect.
Good luck, my esteemed investigator.

Mr. John Boddy
================================================================
""")

This section is what prints out the backstory and instructions for the game. It takes a little while, due to the slow printing, but I feel it’s important to know a bit of information about the game before you play. It gives it a storyline and makes it feel a little more realistic. Not only this, but I didn’t know the backstory of the Clue board game until making this program, so hopefully I could teach a couple people what I learned.

def begin():
    """Lets the user decide when to begin the game."""
    print()
    prompt = "Type 'b' to begin: "
    begin = input(prompt)
    while begin not in ['b']:
        begin = input(prompt)
    if begin == 'b':
        print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
        pass
    else:
        print("***ERROR***")
        begin = input(prompt)

def continue_game():
    """Lets the user say when they'd like to continue."""
    print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
    prompt = "Type 'c' to continue: "
    nextRound = input(prompt)
    while nextRound not in ['c']:
        nextRound = input(prompt)
    if nextRound == 'c':
        print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
        pass
    else:
        print("***ERROR***")
        nextRound = input(prompt)

These two methods allow you to continue the game whenever you’d like by typing a ‘b’ or ‘c’ and pressing enter. I felt this was a good addition, since there was a lot of text beforehand and this allows you time to read it all.

def slow_print(string,pauseTime=0.01,newLine=True):
    """print characters one at a time."""
    for character in string:
        print(character,end="")
        if character == '.':
            time.sleep(0)
        else:
            time.sleep(pauseTime+0)
    if newLine == True:
        print()

def slow_print2(string,pauseTime=0.01,newLine=True):
    """Customized slow_print for the backstory section."""
    for character in string:
        print(character,end="")
        if character == '.':
            time.sleep(.5)
        else:
            time.sleep(pauseTime+0)
    if newLine == True:
        print()

These two methods are simply to tell the computer what slow printing is to make the backstory and instructions look a little neater. Slow printing is when the text is printed out letter after letter instead of appearing on the screen all at once. This can be a little frustrating, especially since I don’t have a skip button yet, but it gives you a little more time to read the instructions and backstory.

def cleanup():
    print("Goodbye investigator.")

All this last little section does is tells you goodbye once you leave the program. After going through the game, you’re asked if you’d like to play again. If you say yes, the game repeats. If you say no, on the other hand, this text appears.

This is a picture of my friend, Janna, trying out my program 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *