Files
claudePySnake/run_server.py
Vladyslav Doloman 84a58038f7 Implement stuck snake mechanics, persistent colors, and length display
Major gameplay changes:
- Snakes no longer die from collisions
- When blocked, snakes get "stuck" - head stays in place, tail shrinks by 1 per tick
- Snakes auto-unstick when obstacle clears (other snakes move/shrink away)
- Minimum snake length is 1 (head-only)
- Game runs continuously without rounds or game-over state

Color system:
- Each player gets a persistent color for their entire connection
- Colors assigned on join, rotate through available colors
- Color follows player even after disconnect/reconnect
- Works for both desktop and web clients

Display improvements:
- Show snake length instead of score
- Length accurately reflects current snake size
- Updates in real-time as snakes grow/shrink

Server fixes:
- Fixed HTTP server initialization issues
- Changed default host to 0.0.0.0 for network multiplayer
- Improved file serving with proper routing

Testing:
- Updated all collision tests for stuck mechanics
- Added tests for stuck/unstick behavior
- Added tests for color persistence
- All 12 tests passing

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-04 16:39:30 +03:00

99 lines
2.8 KiB
Python

"""Run the Snake game server."""
import asyncio
import argparse
from pathlib import Path
from src.server.game_server import GameServer
from src.server.http_server import HTTPServer
from src.shared.constants import DEFAULT_HOST, DEFAULT_PORT, DEFAULT_WS_PORT, DEFAULT_HTTP_PORT
async def main() -> None:
"""Run the server with command line arguments."""
parser = argparse.ArgumentParser(description="Run the Snake game server")
parser.add_argument(
"--host",
default=DEFAULT_HOST,
help=f"Host address to bind to (default: {DEFAULT_HOST})",
)
parser.add_argument(
"--port",
type=int,
default=DEFAULT_PORT,
help=f"TCP port number (default: {DEFAULT_PORT})",
)
parser.add_argument(
"--ws-port",
type=int,
default=DEFAULT_WS_PORT,
help=f"WebSocket port (default: {DEFAULT_WS_PORT}, 0 to disable)",
)
parser.add_argument(
"--http-port",
type=int,
default=DEFAULT_HTTP_PORT,
help=f"HTTP server port (default: {DEFAULT_HTTP_PORT}, 0 to disable)",
)
parser.add_argument(
"--web-dir",
default="web",
help="Directory containing web client files (default: web)",
)
parser.add_argument(
"--name",
default="Snake Server",
help="Server name for discovery (default: Snake Server)",
)
parser.add_argument(
"--no-discovery",
action="store_true",
help="Disable multicast discovery beacon",
)
parser.add_argument(
"--no-websocket",
action="store_true",
help="Disable WebSocket server",
)
parser.add_argument(
"--no-http",
action="store_true",
help="Disable HTTP server (for production with external web server)",
)
args = parser.parse_args()
# Determine WebSocket port
ws_port = None if args.no_websocket or args.ws_port == 0 else args.ws_port
# Create game server
server = GameServer(
host=args.host,
port=args.port,
server_name=args.name,
enable_discovery=not args.no_discovery,
ws_port=ws_port,
)
# Start HTTP server if enabled
http_server = None
if not args.no_http and args.http_port > 0:
web_dir = Path(args.web_dir)
if web_dir.exists():
# Use same host as game server for HTTP
http_host = args.host if args.host != "0.0.0.0" else "localhost"
http_server = HTTPServer(web_dir, args.http_port, http_host)
await http_server.start()
else:
print(f"Warning: Web directory '{web_dir}' not found. HTTP server disabled.")
# Start game server
try:
await server.start()
finally:
if http_server:
await http_server.stop()
if __name__ == "__main__":
asyncio.run(main())