Spaces:
Runtime error
Runtime error
| from __future__ import annotations | |
| from typing import Literal | |
| from pydantic import BaseModel, Field, model_validator | |
| from openenv.core.env_server.types import Action, Observation, State | |
| class UnitSummary(BaseModel): | |
| unit_id: int = Field(..., description="Freeciv unit id") | |
| unit_type: str = Field(..., description="Ruleset unit type name") | |
| health: int = Field(0, description="Current health") | |
| moves_left: int = Field(0, description="Movement points remaining") | |
| home_city_id: int | None = Field(None, description="Home city id, if any") | |
| veteran_level: int = Field(0, description="Veteran level") | |
| can_build_city: bool = Field(False, description="Whether the unit can found a city now") | |
| move_directions: list[int] = Field(default_factory=list, description="Legal move direction indexes") | |
| class CitySummary(BaseModel): | |
| city_id: int = Field(..., description="Freeciv city id") | |
| size: int = Field(..., description="Population size") | |
| prod_food: int = Field(0, description="Gross food output") | |
| prod_shield: int = Field(0, description="Gross shield output") | |
| prod_trade: int = Field(0, description="Gross trade output") | |
| surplus_food: int = Field(0, description="Net food surplus") | |
| surplus_shield: int = Field(0, description="Net shield surplus") | |
| surplus_trade: int = Field(0, description="Net trade surplus") | |
| production_kind: int | None = Field(None, description="Current production kind enum from Freeciv") | |
| production_value: int | None = Field(None, description="Current production value id from Freeciv") | |
| turns_to_complete: float | None = Field(None, description="Turns until current production completes") | |
| production_options: list[str] = Field(default_factory=list, description="Legal production targets") | |
| class LegalAction(BaseModel): | |
| action_type: Literal[ | |
| "end_turn", | |
| "move_unit", | |
| "build_city", | |
| "set_city_production", | |
| "set_research", | |
| ] | |
| label: str = Field(..., description="Human-readable action label") | |
| unit_id: int | None = Field(None, description="Target unit id") | |
| city_id: int | None = Field(None, description="Target city id") | |
| direction: int | None = Field(None, description="Freeciv direction index 0..7") | |
| target: str | None = Field(None, description="Production or tech target name") | |
| raw_action_key: str | None = Field(None, description="Underlying freeciv-bot action key") | |
| class FreecivAction(Action): | |
| action_type: Literal[ | |
| "end_turn", | |
| "move_unit", | |
| "build_city", | |
| "set_city_production", | |
| "set_research", | |
| ] | |
| unit_id: int | None = None | |
| city_id: int | None = None | |
| direction: int | None = None | |
| target: str | None = None | |
| def validate_shape(self) -> "FreecivAction": | |
| if self.action_type == "end_turn": | |
| return self | |
| if self.action_type == "move_unit": | |
| if self.unit_id is None or self.direction is None: | |
| raise ValueError("move_unit requires unit_id and direction") | |
| return self | |
| if self.action_type == "build_city": | |
| if self.unit_id is None: | |
| raise ValueError("build_city requires unit_id") | |
| return self | |
| if self.action_type == "set_city_production": | |
| if self.city_id is None or not self.target: | |
| raise ValueError("set_city_production requires city_id and target") | |
| return self | |
| if self.action_type == "set_research": | |
| if not self.target: | |
| raise ValueError("set_research requires target") | |
| return self | |
| raise ValueError(f"unsupported action_type: {self.action_type}") | |
| class FreecivObservation(Observation): | |
| turn: int = Field(..., description="Current game turn") | |
| score: float = Field(..., description="Current player score") | |
| known_tiles: int = Field(..., description="Tiles known to the player") | |
| visible_tiles: int = Field(..., description="Tiles currently visible to the player") | |
| city_count: int = Field(..., description="Number of owned cities") | |
| unit_count: int = Field(..., description="Number of owned units") | |
| techs_researched: int = Field(..., description="Number of researched techs") | |
| status: str = Field("ok", description="High-level environment status") | |
| summary: str = Field(..., description="Compact text summary for LLMs") | |
| units: list[UnitSummary] = Field(default_factory=list, description="Compact unit summaries") | |
| cities: list[CitySummary] = Field(default_factory=list, description="Compact city summaries") | |
| legal_actions: list[LegalAction] = Field(default_factory=list, description="Legal actions exposed by the environment") | |
| reward: float = Field(0.0, description="Reward from the last action") | |
| done: bool = Field(False, description="Whether the episode is done") | |
| class FreecivState(State): | |
| turn: int = Field(0, description="Current game turn") | |
| score: float = Field(0.0, description="Current player score") | |
| known_tiles: int = Field(0, description="Known tiles") | |
| visible_tiles: int = Field(0, description="Visible tiles") | |
| city_count: int = Field(0, description="Owned city count") | |
| unit_count: int = Field(0, description="Owned unit count") | |
| techs_researched: int = Field(0, description="Researched tech count") | |