mirror of
https://github.com/GoodStartLabs/AI_Diplomacy.git
synced 2026-04-19 12:58:09 +00:00
89 lines
3.9 KiB
Python
89 lines
3.9 KiB
Python
import logging
|
|
import concurrent.futures
|
|
from typing import Dict
|
|
|
|
from .game_history import GameHistory
|
|
from .agent import DiplomacyAgent
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
async def planning_phase(
|
|
game,
|
|
agents: Dict[str, DiplomacyAgent],
|
|
game_history: GameHistory,
|
|
model_error_stats,
|
|
log_file_path: str,
|
|
):
|
|
"""
|
|
Lets each power generate a strategic plan using their DiplomacyAgent.
|
|
"""
|
|
logger.info(f"Starting planning phase for {game.current_short_phase}...")
|
|
active_powers = [p_name for p_name, p_obj in game.powers.items() if not p_obj.is_eliminated()]
|
|
eliminated_powers = [p_name for p_name, p_obj in game.powers.items() if p_obj.is_eliminated()]
|
|
|
|
logger.info(f"Active powers for planning: {active_powers}")
|
|
if eliminated_powers:
|
|
logger.info(f"Eliminated powers (skipped): {eliminated_powers}")
|
|
else:
|
|
logger.info("No eliminated powers yet.")
|
|
|
|
board_state = game.get_state()
|
|
|
|
with concurrent.futures.ThreadPoolExecutor(max_workers=len(active_powers)) as executor:
|
|
futures = {}
|
|
for power_name in active_powers:
|
|
if power_name not in agents:
|
|
logger.warning(f"Agent for {power_name} not found in planning phase. Skipping.")
|
|
continue
|
|
agent = agents[power_name]
|
|
client = agent.client
|
|
|
|
future = executor.submit(
|
|
client.get_plan,
|
|
game,
|
|
board_state,
|
|
power_name,
|
|
gather_possible_orders(game, power_name),
|
|
game_history,
|
|
agent_goals=agent.goals,
|
|
agent_relationships=agent.relationships,
|
|
log_file_path=log_file_path,
|
|
agent_private_diary_str=agent.format_private_diary_for_prompt(),
|
|
)
|
|
futures[future] = power_name
|
|
logger.debug(f"Submitted get_plan task for {power_name}.")
|
|
|
|
logger.info(f"Waiting for {len(futures)} planning results...")
|
|
for future in concurrent.futures.as_completed(futures):
|
|
power_name = futures[future]
|
|
try:
|
|
plan_result = future.result()
|
|
logger.info(f"Received planning result from {power_name}.")
|
|
|
|
if plan_result.startswith("Error:"):
|
|
logger.warning(f"Agent {power_name} reported an error during planning: {plan_result}")
|
|
if power_name in model_error_stats:
|
|
model_error_stats[power_name].setdefault("planning_generation_errors", 0)
|
|
model_error_stats[power_name]["planning_generation_errors"] += 1
|
|
else:
|
|
model_error_stats.setdefault(f"{power_name}_planning_generation_errors", 0)
|
|
model_error_stats[f"{power_name}_planning_generation_errors"] += 1
|
|
elif plan_result:
|
|
agent.add_journal_entry(f"Generated plan for {game.current_short_phase}: {plan_result[:100]}...")
|
|
game_history.add_plan(game.current_short_phase, power_name, plan_result)
|
|
logger.debug(f"Added plan for {power_name} to history.")
|
|
else:
|
|
logger.warning(f"Agent {power_name} returned an empty plan.")
|
|
|
|
except Exception as e:
|
|
logger.error(f"Exception during planning result processing for {power_name}: {e}")
|
|
if power_name in model_error_stats:
|
|
model_error_stats[power_name].setdefault("planning_execution_errors", 0)
|
|
model_error_stats[power_name]["planning_execution_errors"] += 1
|
|
else:
|
|
model_error_stats.setdefault(f"{power_name}_planning_execution_errors", 0)
|
|
model_error_stats[f"{power_name}_planning_execution_errors"] += 1
|
|
|
|
logger.info("Planning phase processing complete.")
|
|
return game_history
|