Skip to content

Instantly share code, notes, and snippets.

@jamesbraza
Created July 1, 2021 06:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jamesbraza/67668705d092e768160b0236a7684fa8 to your computer and use it in GitHub Desktop.
Save jamesbraza/67668705d092e768160b0236a7684fa8 to your computer and use it in GitHub Desktop.
War simulator that limits the number of rounds
"""
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