415 lines
15 KiB
Python
415 lines
15 KiB
Python
# File: Game.py
|
|
# Description: Game class and three game classes
|
|
# Author: Yirui Guo
|
|
# Student ID: 2218040201
|
|
# This is my own work as defined by
|
|
# the University's Academic Misconduct Policy.
|
|
#
|
|
from Dice import Dice
|
|
from Player import Player
|
|
|
|
|
|
class Game:
|
|
players = {}
|
|
bids = {}
|
|
|
|
def __init__(self):
|
|
self.prompt = "> "
|
|
self.__valid_inputs = ['n', 'c', 's', 'p', 'q']
|
|
self.__helpMsg = '\nWhat would you like to do?\n(n) register a new player\n(c) show your coins\n(s) show the leader board\n(p) play a game\n(q) quit'
|
|
|
|
def handle_game(self, comm):
|
|
if comm == 'n':
|
|
print("What is the name of the new player?")
|
|
name = input(self.prompt)
|
|
if name in self.players:
|
|
print("Sorry, the name is already taken.")
|
|
else:
|
|
self.players[name] = Player(name)
|
|
print("Welcome, ", name)
|
|
elif comm == 'c':
|
|
try:
|
|
if len(self.players) == 0:
|
|
raise AttributeError
|
|
print("--------Coins--------")
|
|
for key in self.players:
|
|
print(key, self.players[key].get_coins())
|
|
except AttributeError:
|
|
print("You have no player now!")
|
|
elif comm == 's':
|
|
try:
|
|
if len(self.players) == 0:
|
|
raise AttributeError
|
|
print("================================")
|
|
print("Name\t\tPlayed\tWon\tCoins")
|
|
print("================================")
|
|
lb = {}
|
|
for key in self.players:
|
|
lb[key] = self.players[key].get_coins()
|
|
top = sorted(lb.items(), key=lambda k: k[1], reverse=True)
|
|
for key in top:
|
|
print(f"{key[0]}\t\t{self.players[key[0]].total_round}\t{self.players[key[0]].win_round}\t{key[1]}")
|
|
print("================================")
|
|
except AttributeError:
|
|
print("You have no player now!")
|
|
elif comm == 'p':
|
|
print('Which game would you like to play?\n(e) Even-or-Odd\n(m) Minz\n(b) Bunco')
|
|
user_input = input(self.prompt)
|
|
if user_input not in ['e', 'm', 'b']:
|
|
print("Please choose from e, m, b!")
|
|
else:
|
|
self.call_game(user_input)
|
|
else:
|
|
raise ValueError
|
|
|
|
def set_persons(self, l, r):
|
|
print(f"How many players ({l}-{r})?")
|
|
try:
|
|
user_input = int(input(self.prompt))
|
|
if user_input < l or user_input > r:
|
|
raise ValueError
|
|
self.__persons = int(user_input)
|
|
for i in range(self.__persons):
|
|
while True:
|
|
print(f"What is the name of player #{i + 1}?")
|
|
user_input = input(self.prompt)
|
|
if user_input not in self.players.keys():
|
|
print(f'There is no player named {user_input}.')
|
|
elif user_input in self.bids.keys():
|
|
print(f'{user_input} is already in the game.')
|
|
else:
|
|
while True:
|
|
print(
|
|
f"How many coins would you bid {user_input} (1-{self.players[user_input].get_coins()})?")
|
|
try:
|
|
input_coin = int(input(self.prompt))
|
|
if input_coin > self.players[user_input].get_coins() or input_coin < 1:
|
|
raise ValueError
|
|
else:
|
|
self.bids[user_input] = input_coin
|
|
break
|
|
except ValueError:
|
|
print("Invalid number of coins.")
|
|
break
|
|
except ValueError:
|
|
print(f"Please input a number between {l} and {r}!")
|
|
self.set_persons(l, r)
|
|
|
|
def play_game(self):
|
|
while True:
|
|
print(self.__helpMsg)
|
|
user_input = input(self.prompt)
|
|
try:
|
|
self.handle_game(user_input)
|
|
except ValueError:
|
|
print("Sorry! Please retry with a valid command.")
|
|
|
|
def call_game(self, comm: str) -> None:
|
|
"""
|
|
Choose game
|
|
:param comm:
|
|
"""
|
|
if comm == 'e':
|
|
game = EvenOrOdd(self.players)
|
|
game.play_game()
|
|
elif comm == 'm':
|
|
game = Minz(self.players)
|
|
game.play_game()
|
|
elif comm == 'b':
|
|
game = Bunco(self.players)
|
|
game.play_game()
|
|
|
|
|
|
class Minz(Game):
|
|
points = {}
|
|
additional_turns_players = []
|
|
|
|
def __init__(self, players):
|
|
super().__init__()
|
|
self.__persons = 0
|
|
self.players = players
|
|
|
|
def play_game(self):
|
|
if len(self.players) < 3:
|
|
print("No enough players to play EvenOrOdd!")
|
|
return
|
|
print("Let the game begin!")
|
|
self.set_persons(3,5)
|
|
self.the_first_turn()
|
|
if len(self.additional_turns_players):
|
|
self.the_second_turn()
|
|
sorted(self.points.items(), key=lambda d: d[1])
|
|
print("-----RESULT-----")
|
|
for point in self.points:
|
|
print(point, self.points[point])
|
|
print("")
|
|
winner = max(self.points.items(), key=lambda d: d[1])
|
|
winner = winner[0]
|
|
for key in self.points:
|
|
if key == winner:
|
|
self.players[key].win(self.bids[key])
|
|
self.players[key].win_round += 1
|
|
self.players[key].total_round += 1
|
|
else:
|
|
self.players[key].lose(self.bids[key])
|
|
self.players[key].total_round += 1
|
|
print(f"Congratulations, {winner}! You win!")
|
|
|
|
def the_first_turn(self):
|
|
flipped = {}
|
|
self.turn(self.bids)
|
|
for key, value in self.points.items():
|
|
if value not in flipped:
|
|
flipped[value] = [key]
|
|
else:
|
|
flipped[value].append(key)
|
|
flipped = sorted(flipped)
|
|
for key in flipped:
|
|
if len(flipped[key]) > 1:
|
|
self.additional_turns_players = flipped[max(flipped, key=lambda k: k[1])]
|
|
break
|
|
|
|
def the_second_turn(self):
|
|
self.turn(self.additional_turns_players)
|
|
|
|
def turn(self, players):
|
|
dice = Dice()
|
|
for key in players:
|
|
choice = ''
|
|
self.power = ''
|
|
print(f"It's {key}'s turn.")
|
|
self.points[key] = 0
|
|
while True:
|
|
print("How strong will you throw (0-5)?")
|
|
try:
|
|
self.power = int(input(self.prompt))
|
|
if self.power > 5 or self.power < 0:
|
|
raise ValueError
|
|
else:
|
|
break
|
|
except ValueError:
|
|
print("Invalid choice.")
|
|
for i in range(2):
|
|
point = dice.get_point_of_dice(self.power)
|
|
print(point[1], end=" ")
|
|
self.points[key] += point[0]
|
|
print("")
|
|
|
|
|
|
class EvenOrOdd(Game):
|
|
def __init__(self, players):
|
|
super().__init__()
|
|
self.__persons = 0
|
|
self.players = players
|
|
self.player = ""
|
|
|
|
def play_game(self):
|
|
if len(self.players) < 1:
|
|
print("No enough players to play EvenOrOdd!")
|
|
return
|
|
dice = Dice()
|
|
print("Let's play the game of EvenOrOdd!")
|
|
while True:
|
|
print("What is the name of player?")
|
|
self.player = input(self.prompt)
|
|
if self.player not in self.players:
|
|
print(f'There is no player named {self.player}.')
|
|
else:
|
|
while True:
|
|
print(
|
|
f"How many coins would you bid {self.player} (1-{self.players[self.player].get_coins()})?")
|
|
try:
|
|
input_coin = int(input(self.prompt))
|
|
if input_coin > self.players[self.player].get_coins() or input_coin < 1:
|
|
raise ValueError
|
|
else:
|
|
self.bids[self.player] = input_coin
|
|
break
|
|
except ValueError:
|
|
print("Invalid number of coins.")
|
|
break
|
|
choice = ''
|
|
self.power = ''
|
|
print(f"Hey {self.player}, Even (e) or Odd (o)?")
|
|
while True:
|
|
choice = input(self.prompt)
|
|
if choice not in ('e', 'o'):
|
|
print("Invalid choice.")
|
|
print("Even (e) or Odd (o)?")
|
|
else:
|
|
break
|
|
while True:
|
|
print("How strong will you throw (0-5)?")
|
|
try:
|
|
self.power = int(input(self.prompt))
|
|
if self.power > 5 or self.power < 0:
|
|
raise ValueError
|
|
else:
|
|
break
|
|
except ValueError:
|
|
print("Invalid choice.")
|
|
point = dice.get_point_of_dice(self.power)
|
|
result = self.get_result(choice, point[0])
|
|
print(point[1])
|
|
if result:
|
|
print(f"Congratulations, {self.player}! You win!")
|
|
self.players[self.player].win(self.bids[self.player])
|
|
self.players[self.player].win_round += 1
|
|
self.players[self.player].total_round += 1
|
|
else:
|
|
print(f"Sorry, {self.player}! You lose!")
|
|
self.players[self.player].lose(self.bids[self.player])
|
|
self.players[self.player].total_round += 1
|
|
|
|
def get_result(self, choice: str, point: int) -> bool:
|
|
is_even = not (point % 2)
|
|
print(is_even)
|
|
if choice == 'e' and is_even:
|
|
return True
|
|
elif choice == 'o' and is_even:
|
|
return False
|
|
elif choice == 'e' and not is_even:
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
|
|
class Bunco(Game):
|
|
def __init__(self, players: dict):
|
|
super().__init__()
|
|
self.current_player = None
|
|
self.__persons = 0
|
|
self.players = players
|
|
self.set_persons(2, 4)
|
|
self.num_players = len(self.bids)
|
|
self.player_names = [i for i in self.players]
|
|
self.scores = {}
|
|
self.round_winners = []
|
|
for _ in self.bids:
|
|
self.scores[_] = []
|
|
self.buncos = {}
|
|
for _ in self.bids:
|
|
self.buncos[_] = 0
|
|
|
|
def play_game(self):
|
|
if len(self.players) < 2:
|
|
print("No enough players to play EvenOrOdd!")
|
|
return
|
|
print("Let's play the game of Bunco!")
|
|
starting_player = self.player_names[0]
|
|
for round_number in range(1, 7):
|
|
self.play_round(round_number, starting_player)
|
|
self.print_results()
|
|
|
|
def play_round(self, round_number, starting_player):
|
|
print(f"<Round {round_number}>")
|
|
self.current_player = starting_player
|
|
round_scores = {}
|
|
while True:
|
|
for player in self.player_names:
|
|
current_total = 0
|
|
self.scores[player].append(0)
|
|
print(f"It's {player}'s turn.")
|
|
roll = self.roll_dice()
|
|
points = self.calc_score(roll, round_number)
|
|
current_total += points
|
|
print(f"You earned {points} points, {current_total} points in total.")
|
|
while points > 0:
|
|
self.scores[player][round_number - 1] += points
|
|
current_total += points
|
|
if self.scores[player][round_number - 1] >= 21:
|
|
round_scores[player] = current_total
|
|
break
|
|
print(f"Keep playing {player}.")
|
|
roll = self.roll_dice()
|
|
points = self.calc_score(roll, round_number)
|
|
current_total += points
|
|
print(f"You earned {points} points, {current_total} points in total.")
|
|
round_scores[player] = current_total
|
|
round_winner = (max(round_scores.items(), key=lambda k: k[1]))[0]
|
|
print(f"{round_winner} is the winner in round {round_number}!\n")
|
|
self.round_winners.append(round_winner)
|
|
return
|
|
|
|
def roll_dice(self) -> list:
|
|
dice = Dice()
|
|
self.power = 0
|
|
while True:
|
|
print("How strong will you throw (0-5)?")
|
|
try:
|
|
self.power = int(input(self.prompt))
|
|
if self.power > 5 or self.power < 0:
|
|
raise ValueError
|
|
else:
|
|
break
|
|
except ValueError:
|
|
print("Invalid choice.")
|
|
points = []
|
|
for i in range(3):
|
|
point = dice.get_point_of_dice(self.power)
|
|
print(point[1], end=" ")
|
|
points.append(point[0])
|
|
print("")
|
|
return points
|
|
|
|
def print_results(self):
|
|
print("======================================")
|
|
print("Round", end='\t')
|
|
for i in range(self.num_players):
|
|
print(self.player_names[i], end='\t')
|
|
print("")
|
|
round_number = 1
|
|
for i in range(6):
|
|
print(f"\t{round_number}\t", end="")
|
|
for key in self.scores:
|
|
print(f"{self.scores[key][round_number - 1]}\t", end="")
|
|
print("")
|
|
round_number += 1
|
|
print("======================================")
|
|
print("Total\t", end="")
|
|
for key in self.player_names:
|
|
print(f"{sum(self.scores[key])}\t", end="")
|
|
print("")
|
|
print("======================================")
|
|
print("Bunco\t", end="")
|
|
for key in self.player_names:
|
|
print(f'{self.buncos[key]}\t', end="")
|
|
print("")
|
|
round_wins = {}
|
|
for i in self.player_names:
|
|
round_wins[i] = 0
|
|
for i in self.round_winners:
|
|
round_wins[i] += 1
|
|
winner = max(round_wins.items(), key=lambda k: k[1])[0]
|
|
print(
|
|
f'{winner} won {round_wins[winner]} rounds, scoring {sum(self.scores[winner])} points, with {self.buncos[winner]} Buncos')
|
|
print(f'Congratrulations, {winner}! You win!')
|
|
for i in self.player_names:
|
|
if i == winner:
|
|
self.players[i].win(self.bids[i])
|
|
self.players[i].win_round += 1
|
|
self.players[i].total_round += 1
|
|
else:
|
|
self.players[i].lose(self.bids[i])
|
|
self.players[i].total_round += 1
|
|
|
|
|
|
def calc_score(self, roll: list[int], round_number):
|
|
score = 0
|
|
point = roll[0]
|
|
if roll[0] == roll[1] == roll[2]:
|
|
if point == round_number:
|
|
score += 21
|
|
self.buncos[self.current_player] += 1
|
|
else:
|
|
score += 5
|
|
for point in roll:
|
|
if point == round_number:
|
|
score += 1
|
|
return score
|
|
|
|
|
|
if __name__ == '__main__':
|
|
game = Bunco({'a': Player('a'), 'b': Player('b')})
|
|
game.play_game()
|