mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-27 13:14:15 -08:00
MAINT: Apply pre-commit
Remove byte-order-marker pre-commit check as there would be many adjustments necessary
This commit is contained in:
@@ -2,7 +2,7 @@ import random
|
||||
|
||||
|
||||
def print_n_whitespaces(n: int):
|
||||
print(" "*n, end="")
|
||||
print(" " * n, end="")
|
||||
|
||||
|
||||
def print_n_newlines(n: int):
|
||||
@@ -75,10 +75,10 @@ if Z != "NO":
|
||||
["3", "HEAD", "1"],
|
||||
["4", "FEELERS", "2"],
|
||||
["5", "TAIL", "1"],
|
||||
["6", "LEGS", "6"]
|
||||
["6", "LEGS", "6"],
|
||||
]
|
||||
for row in table:
|
||||
print("{:<16}{:<16}{:<20}".format(row[0], row[1], row[2]))
|
||||
print(f"{row[0]:<16}{row[1]:<16}{row[2]:<20}")
|
||||
print_n_newlines(2)
|
||||
|
||||
A = 0
|
||||
@@ -299,4 +299,4 @@ while not (Y > 0):
|
||||
if Y != 0:
|
||||
break
|
||||
|
||||
print("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!")
|
||||
print("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!")
|
||||
|
||||
@@ -7,31 +7,35 @@ Demonstrates function-based Model View Controller pattern
|
||||
Ported by Peter Sharp
|
||||
"""
|
||||
|
||||
from random import randint
|
||||
from collections import namedtuple
|
||||
from random import randint
|
||||
|
||||
PAGE_WIDTH = 64
|
||||
|
||||
|
||||
def main(states, data):
|
||||
"""
|
||||
Starts the game loop using given states and data
|
||||
|
||||
|
||||
Uses a modified version of the MVC (Model View Controller) pattern that uses functions instead of objects
|
||||
|
||||
|
||||
each state in the game has one of each of the following:
|
||||
View, displays data
|
||||
Control, converts raw command from user into something the model understands
|
||||
Model, updates game data based on action received from controller
|
||||
"""
|
||||
|
||||
|
||||
while True:
|
||||
if 'exit' == data['state']: break
|
||||
view, control, model = states[data['state']]
|
||||
if "exit" == data["state"]:
|
||||
break
|
||||
view, control, model = states[data["state"]]
|
||||
cmd = view(data)
|
||||
action = control(cmd)
|
||||
data = model(data, action)
|
||||
|
||||
Bodypart = namedtuple('Bodypart', ['name', 'count', 'depends'])
|
||||
|
||||
|
||||
Bodypart = namedtuple("Bodypart", ["name", "count", "depends"])
|
||||
|
||||
|
||||
def print_start(_):
|
||||
"""
|
||||
@@ -47,19 +51,21 @@ def print_start(_):
|
||||
print()
|
||||
return input("DO YOU WANT INSTRUCTIONS? ")
|
||||
|
||||
|
||||
def control_start(cmd):
|
||||
"""
|
||||
Controls the start state
|
||||
"""
|
||||
if cmd.lower() in ('y', 'yes'):
|
||||
action = 'instructions'
|
||||
if cmd.lower() in ("y", "yes"):
|
||||
action = "instructions"
|
||||
else:
|
||||
action = 'game'
|
||||
action = "game"
|
||||
return action
|
||||
|
||||
|
||||
|
||||
def print_instructions(data):
|
||||
"""
|
||||
Prints game instructions
|
||||
Prints game instructions
|
||||
"""
|
||||
print("THE OBJECT OF BUG IS TO FINISH YOUR BUG BEFORE I FINISH")
|
||||
print("MINE. EACH NUMBER STANDS FOR A PART OF THE BUG BODY.")
|
||||
@@ -70,244 +76,263 @@ def print_instructions(data):
|
||||
print("IF THERE IS A CHANGE IN EITHER BUG I WILL GIVE YOU THE")
|
||||
print("OPTION OF SEEING THE PICTURES OF THE BUGS.")
|
||||
print("THE NUMBERS STAND FOR PARTS AS FOLLOWS:")
|
||||
|
||||
print_table([
|
||||
("NUMBER","PART","NUMBER OF PART NEEDED"),
|
||||
*[(i + 1, part.name, part.count) for i, part in enumerate(data['partTypes'])]
|
||||
])
|
||||
|
||||
print_table(
|
||||
[
|
||||
("NUMBER", "PART", "NUMBER OF PART NEEDED"),
|
||||
*[
|
||||
(i + 1, part.name, part.count)
|
||||
for i, part in enumerate(data["partTypes"])
|
||||
],
|
||||
]
|
||||
)
|
||||
print()
|
||||
print()
|
||||
return ''
|
||||
return ""
|
||||
|
||||
|
||||
def goto_game(_):
|
||||
"""
|
||||
Returns game
|
||||
Returns game
|
||||
"""
|
||||
return 'game'
|
||||
return "game"
|
||||
|
||||
|
||||
def update_state(data, action):
|
||||
"""
|
||||
sets game state to given player value
|
||||
"""
|
||||
return {**data, 'state': action}
|
||||
return {**data, "state": action}
|
||||
|
||||
|
||||
def update_game(data, action):
|
||||
"""
|
||||
Updates game data for player turns until one player successfully gets a body part
|
||||
Updates game data for player turns until one player successfully gets a body part
|
||||
"""
|
||||
# stores logs of what happened during a particular round
|
||||
logs = []
|
||||
|
||||
if 'pictures' == action:
|
||||
data['state'] = 'pictures'
|
||||
|
||||
if "pictures" == action:
|
||||
data["state"] = "pictures"
|
||||
else:
|
||||
partAdded = False
|
||||
while partAdded == False:
|
||||
for player, parts in data['players'].items():
|
||||
for player, parts in data["players"].items():
|
||||
# rolls the dice for a part
|
||||
newPartIdx = randint(1,6) - 1
|
||||
|
||||
newPartIdx = randint(1, 6) - 1
|
||||
|
||||
# gets information about the picked part
|
||||
partType = data['partTypes'][newPartIdx]
|
||||
|
||||
partType = data["partTypes"][newPartIdx]
|
||||
|
||||
# gets the number of existing parts of that type the player has
|
||||
partCount = parts[newPartIdx]
|
||||
|
||||
logs.append(('rolled', newPartIdx, player))
|
||||
|
||||
# a new part can only be added if the player has the parts
|
||||
|
||||
logs.append(("rolled", newPartIdx, player))
|
||||
|
||||
# a new part can only be added if the player has the parts
|
||||
# the new part depends on and doesn't have enough of the part already
|
||||
overMaxParts = partType.count < partCount + 1
|
||||
missingPartDep = partType.depends != None and parts[partType.depends] == 0
|
||||
|
||||
missingPartDep = (
|
||||
partType.depends != None and parts[partType.depends] == 0
|
||||
)
|
||||
|
||||
if not overMaxParts and not missingPartDep:
|
||||
# adds a new part
|
||||
# adds a new part
|
||||
partCount += 1
|
||||
logs.append(('added', newPartIdx, player))
|
||||
logs.append(("added", newPartIdx, player))
|
||||
partAdded = True
|
||||
elif missingPartDep:
|
||||
logs.append(('missingDep', newPartIdx, player, partType.depends))
|
||||
logs.append(("missingDep", newPartIdx, player, partType.depends))
|
||||
if overMaxParts:
|
||||
logs.append(('overMax', newPartIdx, player, partCount))
|
||||
|
||||
data['players'][player][newPartIdx] = partCount
|
||||
data['logs'] = logs
|
||||
|
||||
logs.append(("overMax", newPartIdx, player, partCount))
|
||||
|
||||
data["players"][player][newPartIdx] = partCount
|
||||
data["logs"] = logs
|
||||
|
||||
# checks if any players have finished their bug
|
||||
finished = get_finished(data)
|
||||
if len(finished) > 0:
|
||||
# and sets the state to 'won' if that's the case
|
||||
data['finished'] = finished
|
||||
data['state'] = 'won'
|
||||
data["finished"] = finished
|
||||
data["state"] = "won"
|
||||
return data
|
||||
|
||||
|
||||
def get_finished(data):
|
||||
"""
|
||||
Gets players who have finished their bugs
|
||||
"""
|
||||
totalParts = sum([partType.count for partType in data['partTypes']])
|
||||
totalParts = sum(partType.count for partType in data["partTypes"])
|
||||
finished = []
|
||||
for player, parts in data['players'].items():
|
||||
if(sum(parts) == totalParts): finished.append(player)
|
||||
for player, parts in data["players"].items():
|
||||
if sum(parts) == totalParts:
|
||||
finished.append(player)
|
||||
return finished
|
||||
|
||||
|
||||
def print_game(data):
|
||||
"""
|
||||
Displays the results of the game turn
|
||||
"""
|
||||
for log in data['logs']:
|
||||
for log in data["logs"]:
|
||||
code, partIdx, player, *logdata = log
|
||||
partType = data['partTypes'][partIdx]
|
||||
|
||||
if('rolled' == code):
|
||||
partType = data["partTypes"][partIdx]
|
||||
|
||||
if "rolled" == code:
|
||||
print()
|
||||
print(f"{player} ROLLED A {partIdx + 1}")
|
||||
print(f"{partIdx + 1}={partType.name}")
|
||||
|
||||
elif('added' == code):
|
||||
if 'YOU' == player:
|
||||
if partType.name in ['FEELERS', 'LEGS', 'TAIL']:
|
||||
|
||||
elif "added" == code:
|
||||
if "YOU" == player:
|
||||
if partType.name in ["FEELERS", "LEGS", "TAIL"]:
|
||||
print(f"I NOW GIVE YOU A {partType.name.replace('s', '')}.")
|
||||
else:
|
||||
print(f"YOU NOW HAVE A {partType.name}.")
|
||||
elif 'I' == player:
|
||||
if partType.name in ['BODY', 'NECK', 'TAIL']:
|
||||
elif "I" == player:
|
||||
if partType.name in ["BODY", "NECK", "TAIL"]:
|
||||
print(f"I NOW HAVE A {partType.name}.")
|
||||
elif partType.name == 'FEELERS':
|
||||
elif partType.name == "FEELERS":
|
||||
print("I GET A FEELER.")
|
||||
|
||||
|
||||
if partType.count > 2:
|
||||
print(f"{player} NOW HAVE {data['players'][player][partIdx]} {partType.name}")
|
||||
|
||||
elif 'missingDep' == code:
|
||||
depIdx, = logdata
|
||||
dep = data['partTypes'][depIdx]
|
||||
print(f"YOU DO NOT HAVE A {dep.name}" if 'YOU' == player else f"I NEEDED A {dep.name}")
|
||||
|
||||
elif 'overMax' == code:
|
||||
partCount, = logdata
|
||||
if(partCount > 1):
|
||||
num = 'TWO' if 2 == partCount else partCount
|
||||
print(
|
||||
f"{player} NOW HAVE {data['players'][player][partIdx]} {partType.name}"
|
||||
)
|
||||
|
||||
elif "missingDep" == code:
|
||||
(depIdx,) = logdata
|
||||
dep = data["partTypes"][depIdx]
|
||||
print(
|
||||
f"YOU DO NOT HAVE A {dep.name}"
|
||||
if "YOU" == player
|
||||
else f"I NEEDED A {dep.name}"
|
||||
)
|
||||
|
||||
elif "overMax" == code:
|
||||
(partCount,) = logdata
|
||||
if partCount > 1:
|
||||
num = "TWO" if 2 == partCount else partCount
|
||||
maxMsg = f"HAVE {num} {partType.name}S ALREADY"
|
||||
else:
|
||||
maxMsg = f"ALREADY HAVE A {partType.name}"
|
||||
print(f"{player} {maxMsg}")
|
||||
|
||||
return input("DO YOU WANT THE PICTURES? ") if len(data['logs']) else 'n'
|
||||
return input("DO YOU WANT THE PICTURES? ") if len(data["logs"]) else "n"
|
||||
|
||||
|
||||
def print_pictures(data):
|
||||
"""
|
||||
Displays what the bugs look like for each player
|
||||
"""
|
||||
typeIxs = { partType.name: idx for idx, partType in enumerate(data['partTypes']) }
|
||||
typeIxs = {partType.name: idx for idx, partType in enumerate(data["partTypes"])}
|
||||
PIC_WIDTH = 22
|
||||
for player, parts in data['players'].items():
|
||||
for player, parts in data["players"].items():
|
||||
print(f"*****{'YOUR' if 'YOU' == player else 'MY'} BUG*****")
|
||||
print()
|
||||
print()
|
||||
if(parts[typeIxs['BODY']] > 0):
|
||||
if(parts[typeIxs['FEELERS']] > 0):
|
||||
F = ' '.join(['F'] * parts[typeIxs['FEELERS']])
|
||||
if parts[typeIxs["BODY"]] > 0:
|
||||
if parts[typeIxs["FEELERS"]] > 0:
|
||||
F = " ".join(["F"] * parts[typeIxs["FEELERS"]])
|
||||
for _ in range(4):
|
||||
print(' ' * 9 + F)
|
||||
if(parts[typeIxs['HEAD']] > 0):
|
||||
print(" " * 9 + F)
|
||||
if parts[typeIxs["HEAD"]] > 0:
|
||||
print_centered("HHHHHHH", PIC_WIDTH)
|
||||
print_centered("H H", PIC_WIDTH)
|
||||
print_centered("H O O H", PIC_WIDTH)
|
||||
print_centered("H H", PIC_WIDTH)
|
||||
print_centered("H V H", PIC_WIDTH)
|
||||
print_centered("HHHHHHH", PIC_WIDTH)
|
||||
if(parts[typeIxs['NECK']] > 0):
|
||||
if parts[typeIxs["NECK"]] > 0:
|
||||
for _ in range(2):
|
||||
print_centered("N N", PIC_WIDTH)
|
||||
print_centered("BBBBBBBBBBBB", PIC_WIDTH)
|
||||
for _ in range(2):
|
||||
print_centered("B B", PIC_WIDTH)
|
||||
|
||||
if(parts[typeIxs['TAIL']] > 0):
|
||||
|
||||
if parts[typeIxs["TAIL"]] > 0:
|
||||
print("TTTTTB B")
|
||||
print_centered("BBBBBBBBBBBB", PIC_WIDTH)
|
||||
if(parts[typeIxs['LEGS']] > 0):
|
||||
L = 'L' * parts[typeIxs['LEGS']]
|
||||
if parts[typeIxs["LEGS"]] > 0:
|
||||
L = "L" * parts[typeIxs["LEGS"]]
|
||||
for _ in range(2):
|
||||
print(' '*5+L)
|
||||
print(" " * 5 + L)
|
||||
print()
|
||||
|
||||
|
||||
def control_game(cmd):
|
||||
"""
|
||||
returns state based on command
|
||||
"""
|
||||
if cmd.lower() in ('y', 'yes'):
|
||||
action = 'pictures'
|
||||
if cmd.lower() in ("y", "yes"):
|
||||
action = "pictures"
|
||||
else:
|
||||
action = 'game'
|
||||
action = "game"
|
||||
return action
|
||||
|
||||
|
||||
def print_winner(data):
|
||||
"""
|
||||
Displays the winning message
|
||||
"""
|
||||
for player in data['finished']:
|
||||
for player in data["finished"]:
|
||||
print(f"{'YOUR' if 'YOU' == player else 'MY'} BUG IS FINISHED.")
|
||||
print("I HOPE YOU ENJOYED THE GAME, PLAY IT AGAIN SOON!!")
|
||||
|
||||
|
||||
|
||||
def exit_game(_):
|
||||
"""
|
||||
Exists the game regardless of input
|
||||
"""
|
||||
return 'exit'
|
||||
|
||||
return "exit"
|
||||
|
||||
|
||||
def print_centered(msg, width=PAGE_WIDTH):
|
||||
"""
|
||||
Prints given message centered to given width
|
||||
"""
|
||||
spaces = " " * ((width - len(msg)) // 2)
|
||||
print(spaces + msg)
|
||||
|
||||
|
||||
|
||||
def print_table(rows):
|
||||
for row in rows:
|
||||
print(*row, sep="\t")
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
# The main states in the game
|
||||
states = {
|
||||
# Initial state of the game
|
||||
'start': (print_start, control_start, update_state),
|
||||
|
||||
"start": (print_start, control_start, update_state),
|
||||
# displays game instructions
|
||||
'instructions': (print_instructions, goto_game, update_state),
|
||||
|
||||
# the main game state
|
||||
'game': (print_game, control_game, update_game),
|
||||
|
||||
"instructions": (print_instructions, goto_game, update_state),
|
||||
# the main game state
|
||||
"game": (print_game, control_game, update_game),
|
||||
# displays pictures before returning to game
|
||||
'pictures': (print_pictures, goto_game, update_state),
|
||||
|
||||
"pictures": (print_pictures, goto_game, update_state),
|
||||
# Displays the winning players and message
|
||||
'won': (print_winner, exit_game, update_state)
|
||||
"won": (print_winner, exit_game, update_state),
|
||||
}
|
||||
|
||||
# body part types used by the game to work out whether a player's body part can be added
|
||||
partTypes = (
|
||||
Bodypart(name="BODY", count=1 , depends=None),
|
||||
Bodypart(name="NECK", count=1 , depends=0),
|
||||
Bodypart(name="HEAD", count=1 , depends=1),
|
||||
Bodypart(name="FEELERS", count=2 , depends=2),
|
||||
Bodypart(name="TAIL", count=1 , depends=0),
|
||||
Bodypart(name="LEGS", count=6 , depends=0)
|
||||
Bodypart(name="BODY", count=1, depends=None),
|
||||
Bodypart(name="NECK", count=1, depends=0),
|
||||
Bodypart(name="HEAD", count=1, depends=1),
|
||||
Bodypart(name="FEELERS", count=2, depends=2),
|
||||
Bodypart(name="TAIL", count=1, depends=0),
|
||||
Bodypart(name="LEGS", count=6, depends=0),
|
||||
)
|
||||
|
||||
# all the data used by the game
|
||||
data = {
|
||||
'state': 'start',
|
||||
'partNo': None,
|
||||
'players': {
|
||||
'YOU': [0] * len(partTypes),
|
||||
'I': [0] * len(partTypes)
|
||||
},
|
||||
'partTypes': partTypes,
|
||||
'finished': [],
|
||||
'logs': []
|
||||
"state": "start",
|
||||
"partNo": None,
|
||||
"players": {"YOU": [0] * len(partTypes), "I": [0] * len(partTypes)},
|
||||
"partTypes": partTypes,
|
||||
"finished": [],
|
||||
"logs": [],
|
||||
}
|
||||
main(states, data)
|
||||
main(states, data)
|
||||
|
||||
Reference in New Issue
Block a user