Improved ui with game host controls

This commit is contained in:
Kyler Olsen 2025-04-24 23:00:43 -06:00
parent 0635ab50f9
commit f6888d6337
3 changed files with 84 additions and 24 deletions

View File

@ -45,7 +45,8 @@ class Game:
packet_id = network_utilities.unpack_varint(self.__server)
if packet_id == 1:
name = network_utilities.unpack_string(self.__server)
self.__player.player_joined(name)
admin = bool(network_utilities.unpack_varint(self.__server))
self.__player.player_joined(name, admin)
elif packet_id == 2:
text = network_utilities.unpack_string(self.__server)
self.__player.new_verse(text)
@ -74,6 +75,7 @@ class Player:
__score: int
__game: Game | None
__ui: UI
__admin: bool
def __init__(self, name: str, ui: UI):
self.__name = name
@ -81,6 +83,7 @@ class Player:
self.__score = 0
self.__game = None
self.__ui = ui
self.__admin = False
@property
def name(self) -> str: return self.__name
@ -91,6 +94,9 @@ class Player:
@property
def score(self) -> int: return self.__score
@property
def admin(self) -> bool: return self.__admin
def join_game(self, host: str = 'localhost', port: int = 7788):
conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
conn.connect((host, port))
@ -115,9 +121,10 @@ class Player:
if self.__game is not None:
self.__game.end_game()
def player_joined(self, name: str):
def player_joined(self, name: str, admin: bool):
if self.__game is not None:
self.__ui.player_joined(name)
if name == self.name: self.__admin = admin or self.__admin
self.__ui.player_joined(name, admin)
def new_verse(self, text: str):
if self.__game is not None:

View File

@ -3,7 +3,7 @@
# Apr 2025
from __future__ import annotations
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, ClassVar
import select
import datetime
import network_utilities
@ -15,6 +15,8 @@ if TYPE_CHECKING:
class Game:
FINAL_SCORE_LIST: ClassVar[int] = 50
__library: Library
__current_url: str
__current_url_parts: list[str]
@ -24,6 +26,7 @@ class Game:
__active: bool
__finished: bool
__created: datetime.datetime
__difficulty: int
def __init__(self, library: Library):
self.__library = library
@ -35,6 +38,7 @@ class Game:
self.__active = False
self.__finished = False
self.__created = datetime.datetime.now()
self.__difficulty = 0
@property
def active(self) -> bool: return self.__active
@ -45,18 +49,24 @@ class Game:
def add_player(self, name: str, conn: socket):
if not self.__active:
new_player = Player(name, self, conn)
for player in self.__clients:
new_player.player_joined(player.name)
self.__clients.append(new_player)
self.__total_scores.append(0)
for player in self.__clients:
player.player_joined(name)
if self.__clients:
for player in self.__clients:
new_player.player_joined(player.name, False)
self.__clients.append(new_player)
self.__total_scores.append(0)
for player in self.__clients:
player.player_joined(name, False)
else:
new_player.player_joined(new_player.name, True)
self.__clients.append(new_player)
self.__total_scores.append(0)
def start_game(self):
self.__active = True
def start_round(self, difficulty: int):
if self.__active and not self.__finished:
self.__difficulty = difficulty
self.__round_points = [0] * len(self.__clients)
self.__library.get_verse(difficulty, self)
@ -70,12 +80,11 @@ class Game:
if self.__active and not self.__finished:
if url == self.__current_url:
player.guess_correct()
self.__round_points[self.__clients.index(player)] = 4
self.__round_points[self.__clients.index(player)] = 4 + self.__difficulty
for i, points in enumerate(self.__round_points):
self.__total_scores[i] += points
self.__clients[i].verse_guessed(
points, self.__current_url, player.name)
self.end_game()
else:
partially_correct = []
for player_url, current_url in zip(url.strip('/').split('/'), self.__current_url_parts):
@ -88,9 +97,24 @@ class Game:
def end_game(self):
self.__finished = True
items = sorted(
[(i.name, j) for i, j in zip(self.__clients, self.__total_scores)],
reverse=True,
key=lambda o: o[1]
)
players = [i for i, _ in items]
scores = [i for _, i in items]
for player in self.__clients:
player.game_over(
[i.name for i in self.__clients], self.__total_scores)
if player.name in players[:Game.FINAL_SCORE_LIST]:
player.game_over(
players[:Game.FINAL_SCORE_LIST],
scores[:Game.FINAL_SCORE_LIST]
)
else:
player.game_over(
players[:Game.FINAL_SCORE_LIST] + [player.name],
scores[:Game.FINAL_SCORE_LIST] + [scores[players.index(player.name)]]
)
def update(self):
if not self.__active and (
@ -121,10 +145,11 @@ class Player:
@property
def name(self) -> str: return self.__name
def player_joined(self, name: str):
print(f">> (1, {self.name}) player_joined({name})")
def player_joined(self, name: str, admin: bool):
print(f">> (1, {self.name}) player_joined({name}, {admin})")
data = network_utilities.pack_varint(1)
data += network_utilities.pack_string(name)
data += network_utilities.pack_varint(admin)
self.__client.send(data)
def new_verse(self, text: str):
@ -145,7 +170,7 @@ class Player:
self.__client.send(data)
def guess_correct(self):
print(">> (4, {self.name}) guess_correct()")
print(f">> (4, {self.name}) guess_correct()")
data = network_utilities.pack_varint(4)
self.__client.send(data)
@ -180,7 +205,7 @@ class Player:
self.__game.start_round(difficulty)
elif packet_id == 4:
url = network_utilities.unpack_string(self.__client)
print(f"<< (4, {self.name}) guess_reference({url}, {self.name})")
print(f"<< (4, {self.name}) guess_reference({url})")
self.__game.guess_reference(url, self)
elif packet_id == 5:
print(f"<< (5, {self.name}) end_game()")

40
ui.py
View File

@ -10,6 +10,7 @@ class UI:
__player: Player
__verse: str
__in_game: bool
__in_between_rounds: bool
__game_over: bool
__term: Terminal
__buffer: str
@ -19,6 +20,7 @@ class UI:
self.__player.join_game(host, port)
self.__verse = ""
self.__in_game = False
self.__in_between_rounds = False
self.__game_over = False
self.__term = Terminal()
self.__buffer = ""
@ -50,10 +52,25 @@ class UI:
while not self.__game_over:
self.__player.update()
if text := self.get_line():
if self.__in_game: self.__guess_ref(text)
elif text == 'Start Game': self.__start_game()
if self.__in_between_rounds and self.__player.admin:
self.__next_round(text)
elif self.__in_between_rounds:
print("Waiting for the next round to start...")
elif self.__in_game: self.__guess_ref(text)
elif self.__player.admin: self.__start_game(text)
else:
print("Waiting for the game to start...")
sleep(0.1)
def __next_round(self, text: str):
if text.isdigit() and 0 <= int(text) <= 10:
print(f"Starting round with difficulty: {text}")
self.__player.new_round(int(text))
elif text.lower() == 'e':
self.__player.end_game()
else:
print("Invalid input!\nPlease enter a difficulty level between 1 and 10.")
def __guess_ref(self, text: str):
try:
url, possible = convert_reference(text)
@ -83,17 +100,25 @@ class UI:
)
print(self.__verse)
def __start_game(self, difficulty: int = 1):
def __start_game(self, text: str = "1"):
print("Starting game...")
self.__in_between_rounds = True
self.__player.start_game()
self.__player.new_round(difficulty)
self.__next_round(text)
def player_joined(self, name: str):
if name == self.__player.name: print(f"* {name} Joined the Game *")
def player_joined(self, name: str, admin: bool):
if name == self.__player.name:
if admin:
print("You are the game host.")
print("Please enter the difficulty for the first round to start the game.")
print("(Difficulty Range: 1 Easy - 10 Hard)")
print(f"* {name} Joined the Game *")
else: print(f"{name} Joined the Game")
def new_verse(self, text: str):
self.__reset()
self.__in_game = True
self.__in_between_rounds = False
self.__verse = text
print(self.__verse)
@ -118,6 +143,9 @@ class UI:
f"The reference is {ref}.\n"
f"You have been awarded {points} points for your guess."
)
self.__in_between_rounds = True
if self.__player.admin:
print("Please enter the difficulty for the next round (1-10) or 'e' to end the game.")
def game_over(self, players: list[str], scores: list[int]):
self.__game_over = True