16-is-dead/game.py

228 lines
6.2 KiB
Python

"""This is the main module of the game 16-is-dead.
Main functionality and calculations are handled here.
"""
__author__ = ""
__credits__ = ""
__email__ = ""
import random
import time
import sys
import user_interface as ui
import clean_input
def check_special_score(score, p):
"""
Checks if player or AI have a score of 9, 10 or >=16.
If a score is >=16, 'restart' gets returned and the game
is immediately over.
Otherwise the score is returned.
False == break for loop
True == do nothing
:param p: tuple with current player
:param score:
:return: bool, 'restart' or score
"""
if score == 9 and p[1]: # Player has score of 9.
return True, score
elif score == 10 and p[1]: # Player has score of 10.
print("Sie haben 10 erreicht. Noch ein letzter Wurf...")
time.sleep(1)
r = roll_dice()
ui.dice_animation()
ui.pling(r)
print(f"Sie würfeln {r}.")
if score + sum(r) == 16:
print(f"Sie haben insgesamt {score + sum(r)} gewürfelt und damit verloren.\n")
return False, "restart"
return True, score + sum(r)
elif score >= 16 and p[1]: # Player score is too high.
print(f"Sie haben insgesamt {score} gewürfelt und damit verloren.\n")
return False, "restart"
elif score == 9 and not p[1]: # AI has score of 9.
return True, score
elif score == 10 and not p[1]: # AI has score of 10.
print(f"{p[0]} hat insgesamt 10 gewürfelt und muss noch einmal würfeln.")
r = roll_dice()
print(f"{p[0]} würfelt {r}.")
if score + sum(r) == 16:
print(f"{p[0]} hat insgesamt {score + sum(r)} gewürfelt und damit verloren.\n")
return False, "restart"
return True, score + sum(r)
elif score >= 16 and not p[1]: # AI score is too high.
print(f"{p[0]} hat insgesamt {score} gewürfelt und damit verloren.\n")
return False, "restart"
else:
return False, score
def choose_loser(all_results):
"""
Determines the players with the lowest score
and prints them.
Then starts a new game.
:param all_results: list of dicts with players and final score.
:return: None
"""
loser_score = 15
losers = []
for r in all_results: # Get lowest score.
if r["final_score"] < loser_score:
loser_score = r["final_score"]
for r in all_results: # Check if there are multiple players with lowest score.
if r["final_score"] == loser_score:
losers.append(r["player"])
loser_string = "\nDie folgenden Spieler haben verloren: "
losers = ",".join(losers)
loser_string = loser_string + losers
print(loser_string)
ui.the_end()
clean_input.io_str("Wollen Sie noch eine Runde spielen? Drücken Sie 'r'"
" für eine neue Runde oder 'q' zum Beenden. ", [])
def roll_dice(number=1, faces=6, seed=3.8):
"""
Throws a certain number of dice with a certain number of faces.
:param number: Number of dice
:param faces: Number of faces of a die
:param seed: Number for random.seed() to reproduce randomness
:return: List of results
"""
if seed:
random.seed(seed)
results = []
for n in range(number):
result = random.randint(1, faces)
results.append(result)
return results
def sixteen_is_dead(players):
"""
Most important method.
Rotates over all players and keeps track of their score.
If the human player presses 'n', the die gets handed to the AI.
:param players: list of tuples
:return: None
"""
all_results = []
for p in players:
if p[1]: # human player
button = clean_input.io_str("Sie sind an der Reihe!", ["", "n"])
player_score = 0
while button != "n":
current_roll = roll_dice()
ui.dice_animation()
ui.pling(current_roll)
print("Sie haben " + str(current_roll) + " gewürfelt!")
player_score += sum(current_roll)
button, player_score = check_special_score(player_score, p)
if not button and player_score == "restart":
main()
print("Damit haben Sie insgesamt " + str(player_score) + " gewürfelt.")
if button:
break
button = clean_input.io_str("Wollen Sie weiterwürfeln? ", ["", "n"])
all_results.append({"player": p[0], "final_score": player_score})
else: # AI
print("Nächster Spieler...")
ai_score = 0
time.sleep(1.5)
while ai_score < 13: # Roll until score at least 12.
current_roll = roll_dice()
print(f"{p[0]} würfelt {current_roll}.")
time.sleep(1)
ai_score += sum(current_roll)
button, ai_score = check_special_score(ai_score, p)
if not button and ai_score == "restart":
main()
print(f"{p[0]} hat damit insgesamt {ai_score} gewürfelt.")
if button:
break
all_results.append({"player": p[0], "final_score": ai_score})
else:
choose_loser(all_results)
def main():
"""
Assigns human player name and number of players.
Construct list of tuples with players.
:return: None
"""
with open("player_welcome_message", "r", encoding="utf8") as f:
welcome = ""
for line in f.readlines():
welcome += line
eval(welcome)
name = ""
while not name:
name = input("Wie heißen Sie? ")
if name == 'r':
main()
elif name == 'q':
ui.the_end()
sys.exit()
else:
pass
print(f"Willkommen, {name}!")
player_number = 0
while not player_number:
player_number = clean_input.io_int("Gegen wie viele Personen wollen Sie spielen? ")
players = []
human = (name, True)
players.append(human)
for p in range(int(player_number)):
players.append(("P" + str(p), False))
sixteen_is_dead(players)
if __name__ == "__main__":
main()