Created
July 1, 2021 06:29
-
-
Save jamesbraza/67668705d092e768160b0236a7684fa8 to your computer and use it in GitHub Desktop.
War simulator that limits the number of rounds
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
War simulator that limits the number of rounds. | |
"Fork": https://lethain.com/war-card-game-in-python/ | |
I expanded the code to plot the probability the game of War finishes within | |
a limit on the rounds. This was part of an extra credit problem in a CS class. | |
""" | |
import random | |
import numpy as np | |
import matplotlib.pyplot as plt | |
DEBUG_PRINT = False | |
def generate_deck(suites=4, type_cards=13): | |
"""Generate a randomized deck of cards.""" | |
cards = [] | |
for suite in range(suites): | |
for type_card in range(1, type_cards + 1): | |
cards.append(type_card) | |
random.shuffle(cards) | |
return cards | |
def play_war(deck, max_rounds: int): | |
half_deck = int(len(deck) / 2) | |
a_cards = deck[:half_deck] | |
b_cards = deck[half_deck:] | |
a_stash = [] | |
b_stash = [] | |
round_ = 1 | |
while round_ < max_rounds and a_cards and b_cards: | |
# by using pop, we're playing from the end forward | |
a_card = a_cards.pop() | |
b_card = b_cards.pop() | |
if a_card == b_card: | |
a_stash.extend([a_card] + a_cards[-3:]) | |
a_cards = a_cards[:-3] | |
a_cards.append(a_stash.pop()) | |
b_stash.extend([b_card] + b_cards[-3:]) | |
b_cards = b_cards[:-3] | |
b_cards.append(b_stash.pop()) | |
elif a_card > b_card: | |
# ordering of a_stash and b_stash is undefined by game rules | |
a_cards = [a_card, b_card] + a_stash + b_stash + a_cards | |
a_stash = [] | |
b_stash = [] | |
elif b_card > a_card: | |
# ordering of a_stash and b_stash is undefined by game rules | |
b_cards = [b_card, a_card] + b_stash + a_stash + b_cards | |
a_stash = [] | |
b_stash = [] | |
if DEBUG_PRINT: | |
print( | |
"round %s: a_cards: %s, a_stash %s, b_cards %s, b_stash %s" | |
% (round_, len(a_cards), len(a_stash), len(b_cards), len(b_stash)) | |
) | |
round_ += 1 | |
return round_ < max_rounds | |
def main(ntrials: int = 5000) -> None: | |
def sim_one_round(max_rounds: int) -> bool: | |
""" | |
Simulate one game of War. | |
:param max_rounds: Max number of rounds for the game to finish. | |
:return: True if the game finished within the max rounds, otherwise False. | |
""" | |
return play_war(generate_deck(), max_rounds) | |
x = np.arange(start=0, stop=2000, step=10) | |
y = np.array([np.mean([sim_one_round(i) for _ in range(ntrials)]) for i in x]) | |
plt.plot(x, y) | |
plt.xlabel("num rounds") | |
plt.ylabel("P(game terminates)") | |
plt.title("Relating Number of War Rounds to to P(game terminates)") | |
plt.savefig("images/q16_plot.png") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment