TowerHcraft Environment
Simple environment with tower-structured constructor rules to evaluate polynomial sub-behaviors reusability.
The goal of the environment is to get the item on top of the tower.
The tower has 'height' layers and 'width' items per layer, plus the final item on top of the last layer.
Each item in the tower requires all the items of the previous layer to be built. Items of the floor layer require nothing and can be built from the start.
Example
For example here is a tower of height 2 and width 3:
6 | ||
---|---|---|
3 | 4 | 5 |
0 | 1 | 2 |
The goal here is to get the item 6. Item 6 requires the items {3, 4, 5}. Each of the items 3, 4 and 5 requires items {0, 1, 2}. Each of the items 0, 1 and 2 requires nothing and can be crafted from the start.
Requirements graph for H2-W3:
1"""# TowerHcraft Environment 2 3Simple environment with tower-structured constructor rules 4to evaluate polynomial sub-behaviors reusability. 5 6The goal of the environment is to get the item on top of the tower. 7 8The tower has 'height' layers and 'width' items per layer, 9plus the final item on top of the last layer. 10 11Each item in the tower requires all the items of the previous layer to be built. 12Items of the floor layer require nothing and can be built from the start. 13 14## Example 15 16For example here is a tower of height 2 and width 3: 17 18| | 6 | | 19|:-:|:-:|:-:| 20| 3 | 4 | 5 | 21| 0 | 1 | 2 | 22 23The goal here is to get the item 6. 24Item 6 requires the items {3, 4, 5}. 25Each of the items 3, 4 and 5 requires items {0, 1, 2}. 26Each of the items 0, 1 and 2 requires nothing and can be crafted from the start. 27 28Requirements graph for H2-W3: 29<div class="graph"> 30.. include:: ../../../docs/images/requirements_graphs/TowerHcraft-H2-W3.html 31</div> 32 33""" 34 35from typing import List 36 37from hcraft.elements import Item 38from hcraft.env import HcraftEnv 39from hcraft.transformation import Transformation, Use, Yield, PLAYER 40from hcraft.world import world_from_transformations 41from hcraft.task import GetItemTask 42 43try: 44 import gymnasium as gym 45 46 gym.register( 47 id="TowerHcraft-v1", 48 entry_point="hcraft.examples.tower:TowerHcraftEnv", 49 ) 50 51except ImportError: 52 pass 53 54 55class TowerHcraftEnv(HcraftEnv): 56 """Tower, a tower-structured hierarchical Environment. 57 58 Item of given layer requires all items of the previous. 59 The goal is to obtain the last item on top of the tower. 60 61 """ 62 63 def __init__(self, height: int = 2, width: int = 3, **kwargs): 64 """ 65 Args: 66 height (int): Number of layers of the tower (ignoring goal item). 67 width (int): Number of items per layer. 68 """ 69 self.height = height 70 self.width = width 71 n_items = self.height * self.width + 1 72 self.items = [Item(str(i)) for i in range(n_items)] 73 name = f"TowerHcraft-H{self.height}-W{self.width}" 74 if not isinstance(kwargs.get("max_step"), int): 75 if self.width == 1: 76 kwargs["max_step"] = 1 + int(self.width * (self.height + 1)) 77 else: 78 # 1 + w + w**2 + ... + w**h 79 kwargs["max_step"] = 1 + int( 80 (1 - self.width ** (self.height + 1)) / (1 - self.width) 81 ) 82 transformations = self.build_transformations(self.items) 83 world = world_from_transformations(transformations) 84 if "purpose" not in kwargs: 85 kwargs["purpose"] = GetItemTask(self.items[-1]) 86 super().__init__(world, name=name, **kwargs) 87 88 def build_transformations(self, items: List[Item]) -> List[Transformation]: 89 """Build transformations to make every item accessible. 90 91 Args: 92 items: List of items. 93 94 Returns: 95 List of craft recipes as transformations. 96 97 """ 98 transformations = [] 99 100 # First layer recipes 101 for first_layer_id in range(self.width): 102 item = items[first_layer_id] 103 new_recipe = Transformation(inventory_changes=[Yield(PLAYER, item)]) 104 transformations.append(new_recipe) 105 106 # Tower recipes 107 for layer in range(1, self.height): 108 for item_layer_id in range(self.width): 109 item_id = layer * self.width + item_layer_id 110 item = items[item_id] 111 112 inventory_changes = [Yield(PLAYER, item)] 113 114 prev_layer_id = (layer - 1) * self.width 115 for prev_item_id in range(self.width): 116 required_item = items[prev_layer_id + prev_item_id] 117 inventory_changes.append(Use(PLAYER, required_item, consume=1)) 118 119 new_recipe = Transformation(inventory_changes=inventory_changes) 120 transformations.append(new_recipe) 121 122 # Last item recipe 123 last_item = items[-1] 124 inventory_changes = [Yield(PLAYER, last_item)] 125 last_layer_id = (self.height - 1) * self.width 126 for prev_item_id in range(self.width): 127 required_item = items[last_layer_id + prev_item_id] 128 inventory_changes.append(Use(PLAYER, required_item, consume=1)) 129 130 new_recipe = Transformation(inventory_changes=inventory_changes) 131 transformations.append(new_recipe) 132 133 return transformations
API Documentation
56class TowerHcraftEnv(HcraftEnv): 57 """Tower, a tower-structured hierarchical Environment. 58 59 Item of given layer requires all items of the previous. 60 The goal is to obtain the last item on top of the tower. 61 62 """ 63 64 def __init__(self, height: int = 2, width: int = 3, **kwargs): 65 """ 66 Args: 67 height (int): Number of layers of the tower (ignoring goal item). 68 width (int): Number of items per layer. 69 """ 70 self.height = height 71 self.width = width 72 n_items = self.height * self.width + 1 73 self.items = [Item(str(i)) for i in range(n_items)] 74 name = f"TowerHcraft-H{self.height}-W{self.width}" 75 if not isinstance(kwargs.get("max_step"), int): 76 if self.width == 1: 77 kwargs["max_step"] = 1 + int(self.width * (self.height + 1)) 78 else: 79 # 1 + w + w**2 + ... + w**h 80 kwargs["max_step"] = 1 + int( 81 (1 - self.width ** (self.height + 1)) / (1 - self.width) 82 ) 83 transformations = self.build_transformations(self.items) 84 world = world_from_transformations(transformations) 85 if "purpose" not in kwargs: 86 kwargs["purpose"] = GetItemTask(self.items[-1]) 87 super().__init__(world, name=name, **kwargs) 88 89 def build_transformations(self, items: List[Item]) -> List[Transformation]: 90 """Build transformations to make every item accessible. 91 92 Args: 93 items: List of items. 94 95 Returns: 96 List of craft recipes as transformations. 97 98 """ 99 transformations = [] 100 101 # First layer recipes 102 for first_layer_id in range(self.width): 103 item = items[first_layer_id] 104 new_recipe = Transformation(inventory_changes=[Yield(PLAYER, item)]) 105 transformations.append(new_recipe) 106 107 # Tower recipes 108 for layer in range(1, self.height): 109 for item_layer_id in range(self.width): 110 item_id = layer * self.width + item_layer_id 111 item = items[item_id] 112 113 inventory_changes = [Yield(PLAYER, item)] 114 115 prev_layer_id = (layer - 1) * self.width 116 for prev_item_id in range(self.width): 117 required_item = items[prev_layer_id + prev_item_id] 118 inventory_changes.append(Use(PLAYER, required_item, consume=1)) 119 120 new_recipe = Transformation(inventory_changes=inventory_changes) 121 transformations.append(new_recipe) 122 123 # Last item recipe 124 last_item = items[-1] 125 inventory_changes = [Yield(PLAYER, last_item)] 126 last_layer_id = (self.height - 1) * self.width 127 for prev_item_id in range(self.width): 128 required_item = items[last_layer_id + prev_item_id] 129 inventory_changes.append(Use(PLAYER, required_item, consume=1)) 130 131 new_recipe = Transformation(inventory_changes=inventory_changes) 132 transformations.append(new_recipe) 133 134 return transformations
Tower, a tower-structured hierarchical Environment.
Item of given layer requires all items of the previous. The goal is to obtain the last item on top of the tower.
64 def __init__(self, height: int = 2, width: int = 3, **kwargs): 65 """ 66 Args: 67 height (int): Number of layers of the tower (ignoring goal item). 68 width (int): Number of items per layer. 69 """ 70 self.height = height 71 self.width = width 72 n_items = self.height * self.width + 1 73 self.items = [Item(str(i)) for i in range(n_items)] 74 name = f"TowerHcraft-H{self.height}-W{self.width}" 75 if not isinstance(kwargs.get("max_step"), int): 76 if self.width == 1: 77 kwargs["max_step"] = 1 + int(self.width * (self.height + 1)) 78 else: 79 # 1 + w + w**2 + ... + w**h 80 kwargs["max_step"] = 1 + int( 81 (1 - self.width ** (self.height + 1)) / (1 - self.width) 82 ) 83 transformations = self.build_transformations(self.items) 84 world = world_from_transformations(transformations) 85 if "purpose" not in kwargs: 86 kwargs["purpose"] = GetItemTask(self.items[-1]) 87 super().__init__(world, name=name, **kwargs)
Arguments:
- height (int): Number of layers of the tower (ignoring goal item).
- width (int): Number of items per layer.
89 def build_transformations(self, items: List[Item]) -> List[Transformation]: 90 """Build transformations to make every item accessible. 91 92 Args: 93 items: List of items. 94 95 Returns: 96 List of craft recipes as transformations. 97 98 """ 99 transformations = [] 100 101 # First layer recipes 102 for first_layer_id in range(self.width): 103 item = items[first_layer_id] 104 new_recipe = Transformation(inventory_changes=[Yield(PLAYER, item)]) 105 transformations.append(new_recipe) 106 107 # Tower recipes 108 for layer in range(1, self.height): 109 for item_layer_id in range(self.width): 110 item_id = layer * self.width + item_layer_id 111 item = items[item_id] 112 113 inventory_changes = [Yield(PLAYER, item)] 114 115 prev_layer_id = (layer - 1) * self.width 116 for prev_item_id in range(self.width): 117 required_item = items[prev_layer_id + prev_item_id] 118 inventory_changes.append(Use(PLAYER, required_item, consume=1)) 119 120 new_recipe = Transformation(inventory_changes=inventory_changes) 121 transformations.append(new_recipe) 122 123 # Last item recipe 124 last_item = items[-1] 125 inventory_changes = [Yield(PLAYER, last_item)] 126 last_layer_id = (self.height - 1) * self.width 127 for prev_item_id in range(self.width): 128 required_item = items[last_layer_id + prev_item_id] 129 inventory_changes.append(Use(PLAYER, required_item, consume=1)) 130 131 new_recipe = Transformation(inventory_changes=inventory_changes) 132 transformations.append(new_recipe) 133 134 return transformations
Build transformations to make every item accessible.
Arguments:
- items: List of items.
Returns:
List of craft recipes as transformations.
Inherited Members
- hcraft.env.HcraftEnv
- world
- invalid_reward
- max_step
- name
- render_window
- render_mode
- state
- current_step
- current_score
- cumulated_score
- episodes
- task_successes
- terminal_successes
- purpose
- metadata
- truncated
- observation_space
- action_space
- action_masks
- step
- render
- reset
- close
- all_behaviors
- solving_behavior
- planning_problem
- infos
- gymnasium.core.Env
- spec
- unwrapped
- np_random_seed
- np_random
- has_wrapper_attr
- get_wrapper_attr
- set_wrapper_attr