The Gymnasium definition for the observation space. At the root is a Dict space with the following keys: ['game', 'rules', 'map', 'player', 'city', 'tech', 'unit', 'options', 'dipl', 'gov', 'client']. We describe the important state spaces below.
Click on the source code below to show the space definition.
Map State
Source code in src/civrealm/freeciv/map/map_state.py
defget_observation_space(self):city_space=gymnasium.spaces.Dict({# Common city fields'id':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'owner':gymnasium.spaces.Box(low=0,high=255,shape=(1,),dtype=np.uint8),'size':gymnasium.spaces.Box(low=0,high=255,shape=(1,),dtype=np.uint8),# TODO: may change this to actual map size'x':gymnasium.spaces.Box(low=0,high=255,shape=(1,),dtype=np.uint8),'y':gymnasium.spaces.Box(low=0,high=255,shape=(1,),dtype=np.uint8),'name':gymnasium.spaces.Text(max_length=100),# My city fields'food_stock':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'granary_size':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'granary_turns':gymnasium.spaces.Box(low=-32768,high=32767,shape=(1,),dtype=np.int16),'production_kind':gymnasium.spaces.Box(low=-1,high=127,shape=(1,),dtype=np.int8),'production_value':gymnasium.spaces.Box(low=-1,high=127,shape=(1,),dtype=np.int8),'city_radius_sq':gymnasium.spaces.Box(low=-1,high=127,shape=(1,),dtype=np.int8),'buy_cost':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'shield_stock':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'disbanded_shields':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'caravan_shields':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'last_turns_shield_surplus':gymnasium.spaces.Box(low=-32768,high=32767,shape=(1,),dtype=np.int16),'luxury':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'science':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'prod_food':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'surplus_food':gymnasium.spaces.Box(low=-32768,high=32767,shape=(1,),dtype=np.int16),'prod_gold':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'surplus_gold':gymnasium.spaces.Box(low=-32768,high=32767,shape=(1,),dtype=np.int16),'prod_shield':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'surplus_shield':gymnasium.spaces.Box(low=-32768,high=32767,shape=(1,),dtype=np.int16),'prod_trade':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'surplus_trade':gymnasium.spaces.Box(low=-32768,high=32767,shape=(1,),dtype=np.int16),'bulbs':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'city_waste':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'city_corruption':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'city_pollution':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),# -1: None, 1: Disorder, 2: Peace, 3: Celebrating'state':gymnasium.spaces.Box(low=-1,high=3,shape=(1,),dtype=np.int8),'growth_in':gymnasium.spaces.Text(max_length=100),'turns_to_prod_complete':gymnasium.spaces.Box(low=-32768,high=32767,shape=(1,),dtype=np.int16),'prod_process':gymnasium.spaces.Box(low=-32768,high=32767,shape=(1,),dtype=np.int16),'ppl_angry':gymnasium.spaces.Box(low=-1,high=127,shape=(1,),dtype=np.int8),'ppl_unhappy':gymnasium.spaces.Box(low=-1,high=127,shape=(1,),dtype=np.int8),'ppl_content':gymnasium.spaces.Box(low=-1,high=127,shape=(1,),dtype=np.int8),'ppl_happy':gymnasium.spaces.Box(low=-1,high=127,shape=(1,),dtype=np.int8),# Boolean vector'can_build_unit':gymnasium.spaces.Box(low=0,high=1,shape=(self.rule_ctrl.ruleset_control['num_unit_types'],),dtype=np.int8),# Boolean vector'improvements':gymnasium.spaces.Box(low=0,high=1,shape=(self.rule_ctrl.ruleset_control['num_impr_types'],),dtype=np.int8),'turn_last_built':gymnasium.spaces.Box(low=1,high=32767,shape=(1,),dtype=np.int16),})returngymnasium.spaces.Dict({city_id:city_spaceforcity_idinself.city_dict.keys()})
Unit State
Source code in src/civrealm/freeciv/units/unit_state.py
defget_observation_space(self):unit_space=gymnasium.spaces.Dict({# Common unit fields'owner':gymnasium.spaces.Box(low=0,high=255,shape=(1,),dtype=np.uint8),'health':gymnasium.spaces.Box(low=0,high=100,shape=(1,),dtype=np.uint8),'veteran':gymnasium.spaces.Box(low=0,high=1,shape=(1,),dtype=np.uint8),# TODO: may change this to actual map size'x':gymnasium.spaces.Box(low=0,high=255,shape=(1,),dtype=np.uint8),'y':gymnasium.spaces.Box(low=0,high=255,shape=(1,),dtype=np.uint8),# Unit type fields'type_rule_name':gymnasium.spaces.Box(low=0,high=len(self.rule_ctrl.unit_types)-1,shape=(1,),dtype=np.uint8),'type_attack_strength':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=np.uint16),'type_defense_strength':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=np.uint16),'type_firepower':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=np.uint16),'type_build_cost':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=np.uint16),'type_convert_time':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=np.uint16),'type_converted_to':gymnasium.spaces.Box(low=0,high=len(self.rule_ctrl.unit_types)-1,shape=(1,),dtype=np.uint8),'type_obsoleted_by':gymnasium.spaces.Box(low=0,high=len(self.rule_ctrl.unit_types)-1,shape=(1,),dtype=np.uint8),'type_hp':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=np.uint16),'type_move_rate':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=np.uint16),'type_vision_radius_sq':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=np.uint16),'type_worker':gymnasium.spaces.Discrete(1),# Boolean'type_can_transport':gymnasium.spaces.Discrete(1),# Boolean# My unit specific fields'home_city':gymnasium.spaces.Box(low=-1,high=len(self.city_ctrl.cities)-1,shape=(1,),dtype=np.int16),'moves_left':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'upkeep_food':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'upkeep_shield':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),'upkeep_gold':gymnasium.spaces.Box(low=-1,high=32767,shape=(1,),dtype=np.int16),})returngymnasium.spaces.Dict({unit_id:unit_spaceforunit_idinself.unit_ctrl.units.keys()})
Tech State
Get observation space.
Returns:
Type
Description
gymnasium.space.Dict(
"tech_status": Box,
"current_tech": Box
)
"tech_status": Box of shape (reqtree_size,)
list status of all techs, with values of each entry:
-1: obtained,
0: under research,
1: can be researched,
2: need other prerequest tech(s),
defget_observation_space(self)->Dict:""" Get observation space. Returns ------- gymnasium.space.Dict( "tech_status": Box, "current_tech": Box ) "tech_status": Box of shape (reqtree_size,) list status of all techs, with values of each entry: -1: obtained, 0: under research, 1: can be researched, 2: need other prerequest tech(s), "current_tech": Box(tech_id: Int, current_bulbs_on_it: Int) """returnDict({"tech_status":Box(np.ones(self.reqtree_size)*(-1),np.ones(self.reqtree_size)*self.UPPER_TECH_STATUS,dtype=int),"current_tech":Tuple(Discrete(self.reqtree_size),Discrete(self.UPPER_BULB_BOUND),Box(0,self.UPPER_BULB_BOUND,dtype=float))})
Player State
Source code in src/civrealm/freeciv/players/player_state.py
defget_observation_space(self):player_space=gymnasium.spaces.Dict({**{# Common player fields'player_id':gymnasium.spaces.Box(low=0,high=255,shape=(1,),dtype=int),'name':gymnasium.spaces.Text(max_length=100),'score':gymnasium.spaces.Box(low=-1,high=65535,shape=(1,),dtype=int),'team':gymnasium.spaces.Box(low=0,high=255,shape=(1,),dtype=int),'is_alive':gymnasium.spaces.Discrete(2),# Boolean'nation':gymnasium.spaces.Box(low=0,high=list(self.rule_ctrl.nations.keys())[-1],shape=(1,),dtype=int),'turns_alive':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=int),'government':gymnasium.spaces.Box(low=0,high=len(self.rule_ctrl.governments)-1,shape=(1,),dtype=int),'target_government':gymnasium.spaces.Box(low=0,high=len(self.rule_ctrl.governments)-1,shape=(1,),dtype=int),'government_name':gymnasium.spaces.Text(max_length=100),'researching':gymnasium.spaces.Box(low=0,high=len(self.rule_ctrl.techs)-1,shape=(1,),dtype=int),'research_name':gymnasium.spaces.Text(max_length=100),# Tax, science, luxury are percentages, should sum to 100'tax':gymnasium.spaces.Box(low=0,high=100,shape=(1,),dtype=int),'science':gymnasium.spaces.Box(low=0,high=100,shape=(1,),dtype=int),'luxury':gymnasium.spaces.Box(low=0,high=100,shape=(1,),dtype=int),# My player fields'gold':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=int),'culture':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=int),# mood_type, values are MOOD_PEACEFUL and MOOD_COMBAT'mood':gymnasium.spaces.Discrete(2),# The turn when the revolution finishes'revolution_finishes':gymnasium.spaces.Box(low=-1,high=65535,shape=(1,),dtype=int),'science_cost':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=int),'bulbs_researched':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=int),'researching_cost':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=int),'tech_goal':gymnasium.spaces.Box(low=0,high=len(self.rule_ctrl.techs)-1,shape=(1,),dtype=int),'tech_upkeep':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=int),'techs_researched':gymnasium.spaces.Box(low=0,high=len(self.rule_ctrl.techs)-1,shape=(1,),dtype=int),'total_bulbs_prod':gymnasium.spaces.Box(low=0,high=65535,shape=(1,),dtype=int),'embassy_txt':gymnasium.spaces.Text(max_length=100),# Other player fields# Possible values are player_const.ATTITUDE_TXT'love':gymnasium.spaces.Text(max_length=100),},**{f'tech_{tech_id}':gymnasium.spaces.Discrete(2)fortech_idinself.rule_ctrl.techs.keys()}})returngymnasium.spaces.Dict({player_id:player_spaceforplayer_idinself.player_ctrl.players.keys()})
Diplomatic state
Source code in src/civrealm/freeciv/players/diplomacy_state_ctrl.py
defget_observation_space(self):diplomacy_space=gymnasium.spaces.Dict({'diplomatic_state':gymnasium.spaces.Discrete(player_const.DS_LAST),# TODO: to be specified'diplomacy_clause_map':gymnasium.spaces.Sequence(gymnasium.spaces.Dict()),'meeting_initializers':gymnasium.spaces.Discrete(255),})returngymnasium.spaces.Dict({player_id:diplomacy_spaceforplayer_idinself.diplomatic_state.keys()})