From 96de231f91f825bba2a6ce9926aa12fd7722523a Mon Sep 17 00:00:00 2001 From: Zachary Vance Date: Mon, 8 Feb 2021 23:08:16 -0800 Subject: [PATCH] Stupid russia program --- archive/lootboxes.md | 2 +- archive/stupid_russia.md | 2 +- archive/stupid_russia.py | 82 ++++++++++++++++++++++++++++++++++++++++ mygames.md | 2 +- 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 archive/stupid_russia.py diff --git a/archive/lootboxes.md b/archive/lootboxes.md index 634a0b7..2da7c38 100644 --- a/archive/lootboxes.md +++ b/archive/lootboxes.md @@ -1,7 +1,7 @@ # Loot Boxes Written 2021-02-08 by Zachary Vance -A short storytelling game for 2-6 players. Play as long as you want, 10-60 minutes. +A short storytelling game for 2-4 players, better with fewer. Play as long as you want, 10-60 minutes. - Each player describes their character in one or two sentences. They also have a starting inventory of any three items they want. - One player starts out as GM. The GM describes a challenging situation. For example the player's driver's license has expired but they need to get to the airport to pick up Rhianna. diff --git a/archive/stupid_russia.md b/archive/stupid_russia.md index 75f4a65..3d07949 100644 --- a/archive/stupid_russia.md +++ b/archive/stupid_russia.md @@ -1,7 +1,7 @@ # Stupid Russia By Zachary Vance and an anonymous friend, in 2017. Revised and playtested 2021-01-15. -**Playtesting notes**: I don't recommend this game. The rules are too hard to understand, and there is not enough feedback for players. The Inspector is very busy and doesn't get to play. We played in Discord with about 5 "rooms" with various caps on the number of players in that voice channel. The "rooms" worked well, I suggest this system for any party game that should have a bit of eavesdropping and private conversation. We played for an hour with 10 people--this was about right, maybe even long. We should have used less codenames. Two people dropped out partway, which didn't cause major issues. +**Playtesting notes**: I don't recommend this game. The rules are too hard to understand, and there is not enough feedback for players. The Inspector is very busy and doesn't get to play. We played in Discord with about 5 "rooms" with various caps on the number of players in that voice channel. The "rooms" worked well, I suggest this system for any party game that should have a bit of eavesdropping and private conversation. We played for an hour with 10 people--this was about right, maybe even long. We should have used less codenames. Two people dropped out partway, which didn't cause major issues. [Python program](/archive/stupid_russia.py) A party game of making and breaking alliances for 8-20 players. One player is the Inspector (this could be done by a computer), and the other players are Stupid KGB Directors. The Directors all have a list of spies loyal to them. They try to report as many names as possible, but if too many Directors report a name, the agent is killed and all Directors who reported that agent lose some points. Everyone is encouraged to adopt a stupid persona and a bad Russian accent. diff --git a/archive/stupid_russia.py b/archive/stupid_russia.py new file mode 100644 index 0000000..b1d67e9 --- /dev/null +++ b/archive/stupid_russia.py @@ -0,0 +1,82 @@ +import collections, math, os, random, string + +players = ["Alice", "Bob", "Carol", "Dave", "Edna", "Frank", "Gertie", "Harold", "Ian", "Jenny"] +code_names_per_player = 3 +operatives_per_player = 5 + +LETTERS = string.ascii_uppercase +FIRST_NAMES = sorted("Dmitry Alexander Maksim Ivan Anna Sofia Maria Anastasia Vlad Grigori".split()) # 10 +LAST_NAMES = sorted("Ivanov Smirnov Petrov Sidorov Popov Orlov Makarov Andreev Volkov Titov".split()) # 10 +CODE_NAMES = sorted("Dacha Ruble Sputnik Kopeck Commissar Babushka Kulak Matryoshka Ukase Zek Muzhik Knout Namestnik Rasputitsa Golubsty Kasha Kissel Knish Kulich Kholodets Kvas Medovukha Okroshka Oladyi Paskha Pelmeni Pirog Pirozhki Rassolnik Sbiten Vodka Shchi Solyanka Ukha Vatrushka Borscht Syrniki Nyet Stolichnaya Da".split()) + +random.shuffle(players) +directors = LETTERS[:len(players)] +code_names = sorted(random.sample(CODE_NAMES, code_names_per_player*len(players))) + +names = ["{} {}".format(first, last) for first in FIRST_NAMES for last in LAST_NAMES] +real_names = {} +for code_name, real_name in zip(code_names, random.sample(names, len(code_names))): + real_names[code_name] = real_name + +half = len(players) // 2 +retirement = math.floor(len(code_names)*2*0.75) +longest_code_name = max(len(x) for x in code_names) +longest_real_name = max(len(x) for x in real_names.values()) + +ok = False +while not ok: + start_directors = collections.defaultdict(list) + operatives = dict() + for director in directors: + operatives[director] = sorted(random.sample(code_names, operatives_per_player)) + for code_name in operatives[director]: + start_directors[code_name].append(director) + ok = True + for code_name in code_names: + #if len(start_directors[code_name]) >= half+1: + # ok = False + if len(start_directors[code_name]) == 0: + ok = False + +for fn in list(LETTERS) + ["GM"]: + try: + os.remove("{}.txt".format(fn)) + except OSError: + pass +for director, player in zip(directors, players): + with open("{}.txt".format(director), "w") as f: + f.write("{}, you are Junior Director {director} (out of {min}-{max}). Keep your director letter secret.\n".format(player, director=director, min=directors[0], max=directors[-1])) + f.write("The following {} codenames work for you. You MAY tell other players this secret information.\n".format(operatives_per_player)) + for code_name in operatives[director]: + f.write(" {}, birth name {}\n".format(code_name.upper().rjust(longest_code_name), real_names[code_name])) + f.write("\n") + f.write("The {} codenames are:\n".format(len(code_names))) + f.write(" {}\n".format(" ".join([cn.upper() for cn in code_names]))) + f.write("The {} possible first real names are:\n".format(len(FIRST_NAMES))) + f.write(" {}\n".format(" ".join(FIRST_NAMES))) + f.write("The {} possible last real names are:\n".format(len(LAST_NAMES))) + f.write(" {}\n".format(" ".join(LAST_NAMES))) + f.write("\n") + f.write("You may submit one report to the inspector by PM, for each codename.\n") + f.write("- Submissions are one line each\n") + f.write("- Your director letter MUST be the first thing on the line\n") + f.write("- All reports are announced by your real name. Only the contents are secret\n") + f.write("- ( 0 points) Report an incorrect real name\n") + f.write("- (+2 points) Each honest (reported by {} or less directors) codename submitted with a correct real name\n".format(half)) + f.write("- ( 0 points) Each traitor (reported by {} or more directors) codename submitted with a correct real name\n".format(half+1)) + f.write("- (-1 points) Each honest codename you submitted, later found to be a traitor (reported by {} directors)\n".format(half+1)) + f.write("- ( 0 points) You can submit the word 'FAKE' instead of a report\n") + f.write("\n") + f.write("You don't know your point total. If you reach {} points, your retirement will be announced. Retired players can only submit FAKE reports.\n".format(retirement)) + f.write("The game ends if: one hour passes, all players but one retire, or at the inspector's discretion if things get boring.\n") + f.write("The player with the most points at the end of the game wins.\n") + f.write("\n") + +with open("GM.txt", "w") as f: + f.write("Directors\n") + for director, player in zip(directors, players): + f.write("{} - {}\n\n".format(director, player)) + f.write("\n") + f.write("Operatives\n") + for code_name in code_names: + f.write("{}: {} -- {}\n".format(code_name.upper().rjust(longest_code_name) , real_names[code_name].ljust(longest_real_name), "".join(start_directors[code_name]))) diff --git a/mygames.md b/mygames.md index 757f7f5..b8dfb3b 100644 --- a/mygames.md +++ b/mygames.md @@ -4,7 +4,7 @@ Sometimes I made games. I make board games, card games, storytelling games, and | Game | Date | Type | Complexity | Players | Tested? | Recommended? | Description | |--------------------------------------------------------------------------|------------|----------------------|------------|--------------|----------|---------------|-------------| -| [Loot Boxes](/archive/lootboxes.md) | 2021-02-08 | Storytelling | Low | 2-6 | No | Yes | Players have an inventory of random items. They must use the items to solve a series of challenges. +| [Loot Boxes](/archive/lootboxes.md) | 2021-02-08 | Storytelling | Low | 2-4 | No | Yes | Players have an inventory of random items. They must use the items to solve a series of challenges. | ["No, this cannot be! I AM INVINCIBLE!](/archive/invincible.md) v2 | 2021-02-08 | Storytelling | Medium | 2-8 | No | Maybe | Villains send wave after harder wave of enemies at the Heros, until they kill the Villains. | [Ultimate Archwizards vs the Dark Lord](/archive/ultimate_archwizard.md) | 2021-02-03 | Storytelling | Low | 3-5, plus GM | No | Yes | One-page storytelling game about the final episode in a fight anime. | ["No, this cannot be! I AM INVINCIBLE!](/archive/invincible1.md) v1 | 2021-02-07 | Storytelling | Medium | 2-8 | Yes | No | Villains send wave after harder wave of enemies at the Heros, until they kill the Villains. -- 2.47.3