Spaces:
Runtime error
Runtime error
File size: 5,372 Bytes
8dc7642 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | 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
@model_validator(mode="after")
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")
|