mirror of
https://github.com/GoodStartLabs/AI_Diplomacy.git
synced 2026-04-22 16:49:15 +00:00
First crack, mostly Claude, on running each agent as an individual connection to the server via WebSocket.
201 lines
6.6 KiB
Python
201 lines
6.6 KiB
Python
"""
|
|
Simple example demonstrating how to use the WebSocketDiplomacyClient.
|
|
|
|
This script shows basic operations like connecting, creating/joining games,
|
|
and interacting with a Diplomacy server via WebSocket.
|
|
"""
|
|
|
|
import asyncio
|
|
from loguru import logger
|
|
from websocket_diplomacy_client import connect_to_diplomacy_server
|
|
|
|
|
|
async def basic_client_example():
|
|
"""
|
|
Basic example showing how to connect and interact with a Diplomacy server.
|
|
"""
|
|
try:
|
|
# Connect to the server
|
|
logger.info("Connecting to Diplomacy server...")
|
|
client = await connect_to_diplomacy_server(
|
|
hostname="localhost",
|
|
port=8432,
|
|
username="test_player",
|
|
password="test_password",
|
|
)
|
|
logger.info("Connected successfully!")
|
|
|
|
# List available games
|
|
logger.info("Listing available games...")
|
|
games = await client.list_games()
|
|
logger.info(f"Found {len(games)} games:")
|
|
for game in games:
|
|
logger.info(
|
|
f" Game {game.get('game_id', 'unknown')}: {game.get('status', 'unknown')} "
|
|
f"({game.get('n_players', 0)}/{game.get('n_controls', 0)} players)"
|
|
)
|
|
|
|
# Get available maps
|
|
logger.info("Getting available maps...")
|
|
maps = await client.get_available_maps()
|
|
logger.info(f"Available maps: {list(maps.keys())}")
|
|
|
|
# Create a new game
|
|
logger.info("Creating a new game...")
|
|
game = await client.create_game(
|
|
map_name="standard",
|
|
rules=["NO_PRESS", "IGNORE_ERRORS", "POWER_CHOICE"],
|
|
power_name="FRANCE", # Control France
|
|
n_controls=1, # Only need 1 player to start (for testing)
|
|
deadline=None, # No time pressure
|
|
)
|
|
logger.info(f"Created game {client.game_id} as {client.power_name}")
|
|
|
|
# Get current game state
|
|
logger.info("Getting current game state...")
|
|
state = client.get_state()
|
|
logger.info(f"Current phase: {client.get_current_phase()}")
|
|
logger.info(f"France has {len(client.get_units('FRANCE'))} units")
|
|
|
|
# Get possible orders
|
|
logger.info("Getting possible orders for France...")
|
|
possible_orders = client.get_all_possible_orders()
|
|
france_orders = possible_orders.get("FRANCE", [])
|
|
logger.info(f"France can make {len(france_orders)} possible orders")
|
|
if france_orders:
|
|
logger.info(f"First few orders: {france_orders[:5]}")
|
|
|
|
# Submit some orders (example: hold all units)
|
|
logger.info("Submitting hold orders for all French units...")
|
|
units = client.get_units("FRANCE")
|
|
hold_orders = []
|
|
for unit in units:
|
|
# Format: "A PAR H" means Army in Paris holds
|
|
hold_orders.append(f"{unit} H")
|
|
|
|
if hold_orders:
|
|
await client.set_orders("FRANCE", hold_orders)
|
|
logger.info(f"Submitted orders: {hold_orders}")
|
|
|
|
# Try to process the game (might fail if we don't have admin rights)
|
|
logger.info("Attempting to process the game...")
|
|
try:
|
|
await client.process_game()
|
|
logger.info("Game processed successfully")
|
|
|
|
# Synchronize to get updated state
|
|
await client.synchronize()
|
|
logger.info(
|
|
f"After processing - Current phase: {client.get_current_phase()}"
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.warning(f"Could not process game (normal if not admin): {e}")
|
|
|
|
# Leave the game
|
|
logger.info("Leaving the game...")
|
|
await client.game.leave()
|
|
logger.info("Left the game successfully")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error in example: {e}", exc_info=True)
|
|
finally:
|
|
# Clean up
|
|
if "client" in locals():
|
|
await client.close()
|
|
logger.info("Example completed")
|
|
|
|
|
|
async def join_existing_game_example(game_id: str):
|
|
"""
|
|
Example showing how to join an existing game.
|
|
|
|
Args:
|
|
game_id: ID of the game to join
|
|
"""
|
|
try:
|
|
logger.info(f"Joining existing game {game_id}...")
|
|
client = await connect_to_diplomacy_server(
|
|
hostname="localhost",
|
|
port=8432,
|
|
username="test_player_2",
|
|
password="test_password",
|
|
)
|
|
|
|
# Join as an observer first
|
|
game = await client.join_game(game_id=game_id, power_name=None)
|
|
logger.info(f"Joined game {game_id} as observer")
|
|
|
|
# Get game state
|
|
state = client.get_state()
|
|
logger.info(f"Game phase: {client.get_current_phase()}")
|
|
logger.info(f"Game status: {game.status}")
|
|
|
|
# List powers and their status
|
|
for power_name, power in client.powers.items():
|
|
logger.info(
|
|
f"{power_name}: {len(power.centers)} centers, "
|
|
f"{len(power.units)} units, eliminated: {power.is_eliminated()}"
|
|
)
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error joining game: {e}", exc_info=True)
|
|
finally:
|
|
if "client" in locals():
|
|
await client.close()
|
|
|
|
|
|
async def message_sending_example():
|
|
"""
|
|
Example showing how to send diplomatic messages.
|
|
"""
|
|
try:
|
|
client = await connect_to_diplomacy_server()
|
|
|
|
# Create a game with PRESS allowed
|
|
game = await client.create_game(
|
|
rules=[
|
|
"IGNORE_ERRORS",
|
|
"POWER_CHOICE",
|
|
], # Remove NO_PRESS to allow messages
|
|
power_name="FRANCE",
|
|
n_controls=1,
|
|
)
|
|
|
|
# Send a public message
|
|
await client.send_message(
|
|
sender="FRANCE",
|
|
recipient="GLOBAL",
|
|
message="Greetings from France! Let's have a fair game.",
|
|
)
|
|
logger.info("Sent public message")
|
|
|
|
# Send a private message (would need another power to be present)
|
|
try:
|
|
await client.send_message(
|
|
sender="FRANCE",
|
|
recipient="ENGLAND",
|
|
message="Hello England, shall we discuss an alliance?",
|
|
)
|
|
logger.info("Sent private message to England")
|
|
except Exception as e:
|
|
logger.info(f"Could not send private message: {e}")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Error in messaging example: {e}", exc_info=True)
|
|
finally:
|
|
if "client" in locals():
|
|
await client.close()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
import sys
|
|
|
|
if len(sys.argv) > 1:
|
|
# Join existing game if game ID provided as argument
|
|
game_id = sys.argv[1]
|
|
asyncio.run(join_existing_game_example(game_id))
|
|
else:
|
|
# Run basic example
|
|
asyncio.run(basic_client_example())
|
|
|