From 97d6df18969de6a5281ee22508321d310ae68939 Mon Sep 17 00:00:00 2001 From: Vladyslav Doloman Date: Sat, 4 Oct 2025 17:21:53 +0300 Subject: [PATCH] Add player names to snake display MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Show human-readable player names instead of player IDs in both desktop and web clients. Player names are now stored in the Snake model and synchronized across all clients. Changes: - Added player_name field to Snake model - Updated create_snake() to accept player_name parameter - Desktop client shows "YOU:" or "PlayerName:" - Web client shows "You (Name)" or "Name" šŸ¤– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- .claude/settings.local.json | 5 ++++- src/client/renderer.py | 2 +- src/server/game_logic.py | 5 +++-- src/server/game_server.py | 5 +++-- src/shared/models.py | 3 +++ web/game.js | 4 ++-- 6 files changed, 16 insertions(+), 8 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index 7ce2cf8..fbcffa3 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -6,7 +6,10 @@ "Bash(python:*)", "Bash(pip install:*)", "Bash(git log:*)", - "Bash(git add:*)" + "Bash(git add:*)", + "Bash(git commit -m \"$(cat <<''EOF''\nImplement stuck snake mechanics, persistent colors, and length display\n\nMajor gameplay changes:\n- Snakes no longer die from collisions\n- When blocked, snakes get \"stuck\" - head stays in place, tail shrinks by 1 per tick\n- Snakes auto-unstick when obstacle clears (other snakes move/shrink away)\n- Minimum snake length is 1 (head-only)\n- Game runs continuously without rounds or game-over state\n\nColor system:\n- Each player gets a persistent color for their entire connection\n- Colors assigned on join, rotate through available colors\n- Color follows player even after disconnect/reconnect\n- Works for both desktop and web clients\n\nDisplay improvements:\n- Show snake length instead of score\n- Length accurately reflects current snake size\n- Updates in real-time as snakes grow/shrink\n\nServer fixes:\n- Fixed HTTP server initialization issues\n- Changed default host to 0.0.0.0 for network multiplayer\n- Improved file serving with proper routing\n\nTesting:\n- Updated all collision tests for stuck mechanics\n- Added tests for stuck/unstick behavior\n- Added tests for color persistence\n- All 12 tests passing\n\nšŸ¤– Generated with [Claude Code](https://claude.com/claude-code)\n\nCo-Authored-By: Claude \nEOF\n)\")", + "Bash(git push:*)", + "Bash(git commit:*)" ], "deny": [], "ask": [] diff --git a/src/client/renderer.py b/src/client/renderer.py index 04ef300..57b9dd5 100644 --- a/src/client/renderer.py +++ b/src/client/renderer.py @@ -109,7 +109,7 @@ class Renderer: color = COLOR_SNAKES[snake.color_index % len(COLOR_SNAKES)] # Prepare length text - prefix = "YOU: " if snake.player_id == player_id else f"Player: " + prefix = "YOU: " if snake.player_id == player_id else f"{snake.player_name}: " status = "" if snake.alive else " (DEAD)" text = f"{prefix}Length {len(snake.body)}{status}" diff --git a/src/server/game_logic.py b/src/server/game_logic.py index f96506d..cae8347 100644 --- a/src/server/game_logic.py +++ b/src/server/game_logic.py @@ -21,12 +21,13 @@ class GameLogic: """Initialize game logic.""" self.state = GameState() - def create_snake(self, player_id: str, color_index: int = 0) -> Snake: + def create_snake(self, player_id: str, color_index: int = 0, player_name: str = "") -> Snake: """Create a new snake for a player. Args: player_id: Unique identifier for the player color_index: Index in COLOR_SNAKES array for this snake's color + player_name: Human-readable name for the player Returns: New Snake instance @@ -41,7 +42,7 @@ class GameLogic: for i in range(INITIAL_SNAKE_LENGTH) ] - snake = Snake(player_id=player_id, body=body, direction=RIGHT, color_index=color_index) + snake = Snake(player_id=player_id, body=body, direction=RIGHT, color_index=color_index, player_name=player_name) return snake def spawn_food(self) -> Food: diff --git a/src/server/game_server.py b/src/server/game_server.py index 1d0af2a..86b1098 100644 --- a/src/server/game_server.py +++ b/src/server/game_server.py @@ -169,7 +169,7 @@ class GameServer: # Add snake to game if game is running if self.game_logic.state.game_running: color_index = self.player_colors[player_id] - snake = self.game_logic.create_snake(player_id, color_index) + snake = self.game_logic.create_snake(player_id, color_index, player_name) self.game_logic.state.snakes.append(snake) print(f"Player {player_name} ({player_id}) joined via {client_type.value}. Total players: {len(self.clients)}") @@ -193,7 +193,8 @@ class GameServer: self.game_logic.state.snakes = [] for player_id in self.clients.keys(): color_index = self.player_colors.get(player_id, 0) - snake = self.game_logic.create_snake(player_id, color_index) + player_name = self.player_names.get(player_id, f"Player_{player_id[:8]}") + snake = self.game_logic.create_snake(player_id, color_index, player_name) self.game_logic.state.snakes.append(snake) # Spawn initial food diff --git a/src/shared/models.py b/src/shared/models.py index 4e6ce3e..4a2f9d2 100644 --- a/src/shared/models.py +++ b/src/shared/models.py @@ -34,6 +34,7 @@ class Snake: score: int = 0 stuck: bool = False # True when snake is blocked and shrinking color_index: int = 0 # Index in COLOR_SNAKES array for persistent color + player_name: str = "" # Human-readable player name def get_head(self) -> Position: """Get the head position of the snake.""" @@ -49,6 +50,7 @@ class Snake: "score": self.score, "stuck": self.stuck, "color_index": self.color_index, + "player_name": self.player_name, } @classmethod @@ -61,6 +63,7 @@ class Snake: snake.score = data["score"] snake.stuck = data.get("stuck", False) # Default to False for backward compatibility snake.color_index = data.get("color_index", 0) # Default to 0 for backward compatibility + snake.player_name = data.get("player_name", "") # Default to empty string for backward compatibility return snake diff --git a/web/game.js b/web/game.js index 619c235..7a95e13 100644 --- a/web/game.js +++ b/web/game.js @@ -322,8 +322,8 @@ class GameClient { const nameSpan = document.createElement('span'); nameSpan.className = 'player-name'; nameSpan.textContent = snake.player_id === this.playerId ? - `You (${snake.player_id.substring(0, 8)})` : - snake.player_id.substring(0, 8); + `You (${snake.player_name})` : + snake.player_name; const scoreSpan = document.createElement('span'); scoreSpan.className = 'player-score';