HierarchyCraft environement examples.

Here is the list of available HierarchyCraft environments examples.

If you built one of your own, send us a pull request so we can add it to the list!

Minecraft inspired

See hcraft.examples.minecraft for more details. [CLI keyword: minecraft]

Gym name Task description
MineHcraft-NoReward-v1 No task (Sandbox)
MineHcraft-Stone-v1 Get the cobblestone item mining it with a wooden pickaxe
MineHcraft-Iron-v1 Get the iron-ingot item smelting raw ore gathered with a stone pickage
MineHcraft-Diamond-v1 Get the diamond item mining it with an iron pickaxe
MineHcraft-EnchantingTable-v1 Craft the enchanting table from a book, obsidian and diamonds
MineHcraft-Dragon-v1 Get the ender-dragon-head by killing it in the ender
MineHcraft-[name]-v1 Get one of the Item of given name where Item is in env.world.items
MineHcraft-v1 Get all items at least once

Minigrid inspired

[CLI keyword: minicraft]

Gym name Documentation reference
MiniHCraftEmpty-v1 hcraft.examples.minicraft.empty
MiniHCraftFourRooms-v1 hcraft.examples.minicraft.fourrooms
MiniHCraftMultiRoom-v1 hcraft.examples.minicraft.multiroom
MiniHCraftCrossing-v1 hcraft.examples.minicraft.crossing
MiniHCraftKeyCorridor-v1 hcraft.examples.minicraft.keycorridor
MiniHCraftDoorKey-v1 hcraft.examples.minicraft.doorkey
MiniHCraftUnlock-v1 hcraft.examples.minicraft.unlock
MiniHCraftUnlockPickup-v1 hcraft.examples.minicraft.unlockpickup
MiniHCraftBlockedUnlockPickup-v1 hcraft.examples.minicraft.unlockpickupblocked

Parametrised toy structures

Gym name CLI name Reference
TowerHcraft-v1 tower hcraft.examples.tower
RecursiveHcraft-v1 recursive hcraft.examples.recursive
LightRecursiveHcraft-v1 light-recursive hcraft.examples.light_recursive

Stochastic parametrised toy structures

Gym name CLI name Reference
RandomHcraft-v1 random hcraft.examples.random_simple

Other examples

Gym name CLI name Reference
Treasure-v1 treasure hcraft.examples.treasure
  1"""#HierarchyCraft environement examples.
  2
  3Here is the list of available HierarchyCraft environments examples.
  4
  5If you built one of your own, send us a pull request so we can add it to the list!
  6
  7##Minecraft inspired
  8
  9See `hcraft.examples.minecraft` for more details.
 10[CLI keyword: `minecraft`]
 11
 12| Gym name                         | Task description                                                       |
 13|:---------------------------------|:-----------------------------------------------------------------------|
 14| MineHcraft-NoReward-v1           | No task (Sandbox)                                                      |
 15| MineHcraft-Stone-v1              | Get the cobblestone item mining it with a wooden pickaxe               |
 16| MineHcraft-Iron-v1               | Get the iron-ingot item smelting raw ore gathered with a stone pickage |
 17| MineHcraft-Diamond-v1            | Get the diamond item mining it with an iron pickaxe                    |
 18| MineHcraft-EnchantingTable-v1    | Craft the enchanting table from a book, obsidian and diamonds          |
 19| MineHcraft-Dragon-v1             | Get the ender-dragon-head by killing it in the ender                   |
 20| MineHcraft-[name]-v1             | Get one of the Item of given `name` where Item is in env.world.items   |
 21| MineHcraft-v1                    | Get all items at least once                                            |
 22
 23
 24##Minigrid inspired
 25
 26[CLI keyword: `minicraft`]
 27
 28| Gym name                         | Documentation reference                         |
 29|:---------------------------------|:------------------------------------------------|
 30| MiniHCraftEmpty-v1               | `hcraft.examples.minicraft.empty`               |
 31| MiniHCraftFourRooms-v1           | `hcraft.examples.minicraft.fourrooms`           |
 32| MiniHCraftMultiRoom-v1           | `hcraft.examples.minicraft.multiroom`           |
 33| MiniHCraftCrossing-v1            | `hcraft.examples.minicraft.crossing`            |
 34| MiniHCraftKeyCorridor-v1         | `hcraft.examples.minicraft.keycorridor`         |
 35| MiniHCraftDoorKey-v1             | `hcraft.examples.minicraft.doorkey`             |
 36| MiniHCraftUnlock-v1              | `hcraft.examples.minicraft.unlock`              |
 37| MiniHCraftUnlockPickup-v1        | `hcraft.examples.minicraft.unlockpickup`        |
 38| MiniHCraftBlockedUnlockPickup-v1 | `hcraft.examples.minicraft.unlockpickupblocked` |
 39
 40##Parametrised toy structures
 41| Gym name                         | CLI name          | Reference                                       |
 42|:---------------------------------|:------------------|:------------------------------------------------|
 43| TowerHcraft-v1                   | `tower`           | `hcraft.examples.tower`                         |
 44| RecursiveHcraft-v1               | `recursive`       | `hcraft.examples.recursive`                     |
 45| LightRecursiveHcraft-v1          | `light-recursive` | `hcraft.examples.light_recursive`               |
 46
 47##Stochastic parametrised toy structures
 48| Gym name                         | CLI name          | Reference                                       |
 49|:---------------------------------|:------------------|:------------------------------------------------|
 50| RandomHcraft-v1                  | `random`          | `hcraft.examples.random_simple`                 |
 51
 52##Other examples
 53| Gym name                         | CLI name          | Reference                                       |
 54|:---------------------------------|:------------------|:------------------------------------------------|
 55| Treasure-v1                      | `treasure`        | `hcraft.examples.treasure`                      |
 56
 57
 58"""
 59
 60import hcraft.examples.minecraft as minecraft
 61import hcraft.examples.minicraft as minicraft
 62import hcraft.examples.random_simple as random_simple
 63import hcraft.examples.recursive as recursive
 64import hcraft.examples.light_recursive as light_recursive
 65import hcraft.examples.tower as tower
 66import hcraft.examples.treasure as treasure
 67
 68
 69from hcraft.examples.minecraft import MineHcraftEnv, MINEHCRAFT_GYM_ENVS
 70from hcraft.examples.minicraft import MINICRAFT_ENVS, MINICRAFT_GYM_ENVS
 71from hcraft.examples.recursive import RecursiveHcraftEnv
 72from hcraft.examples.light_recursive import LightRecursiveHcraftEnv
 73from hcraft.examples.tower import TowerHcraftEnv
 74from hcraft.examples.treasure import TreasureEnv
 75from hcraft.examples.random_simple import RandomHcraftEnv
 76
 77EXAMPLE_ENVS = [
 78    MineHcraftEnv,
 79    *MINICRAFT_ENVS,
 80    TowerHcraftEnv,
 81    RecursiveHcraftEnv,
 82    LightRecursiveHcraftEnv,
 83    TreasureEnv,
 84    # RandomHcraftEnv,
 85]
 86
 87HCRAFT_GYM_ENVS = [
 88    *MINEHCRAFT_GYM_ENVS,
 89    *MINICRAFT_GYM_ENVS,
 90    "TowerHcraft-v1",
 91    "RecursiveHcraft-v1",
 92    "LightRecursiveHcraft-v1",
 93    "Treasure-v1",
 94]
 95
 96
 97__all__ = [
 98    "minecraft",
 99    "minicraft",
100    "recursive",
101    "light_recursive",
102    "tower",
103    "treasure",
104    "random_simple",
105    "MineHcraftEnv",
106    "RandomHcraftEnv",
107    "LightRecursiveHcraftEnv",
108    "RecursiveHcraftEnv",
109    "TowerHcraftEnv",
110]

API Documentation

class MineHcraftEnv(typing.Generic[~ObsType, ~ActType]):
35class MineHcraftEnv(HcraftEnv):
36    """MineHcraft Environment: A minecraft-like HierarchyCraft Environment.
37
38    Default purpose is None (sandbox).
39
40    """
41
42    def __init__(self, **kwargs):
43        mc_transformations = build_minehcraft_transformations()
44        start_zone = kwargs.pop("start_zone", FOREST)
45        purpose = kwargs.pop("purpose", None)
46        if purpose == "all":
47            purpose = get_platinum_purpose()
48        mc_world = world_from_transformations(
49            mc_transformations,
50            start_zone=start_zone,
51            start_zones_items={
52                NETHER: [Stack(OPEN_NETHER_PORTAL)],
53                STRONGHOLD: [Stack(CLOSE_ENDER_PORTAL)],
54            },
55        )
56        mc_world.resources_path = Path(__file__).parent / "resources"
57        super().__init__(world=mc_world, name="MineHcraft", purpose=purpose, **kwargs)
58        self.metadata["video.frames_per_second"] = kwargs.pop("fps", 10)

MineHcraft Environment: A minecraft-like HierarchyCraft Environment.

Default purpose is None (sandbox).

MineHcraftEnv(**kwargs)
42    def __init__(self, **kwargs):
43        mc_transformations = build_minehcraft_transformations()
44        start_zone = kwargs.pop("start_zone", FOREST)
45        purpose = kwargs.pop("purpose", None)
46        if purpose == "all":
47            purpose = get_platinum_purpose()
48        mc_world = world_from_transformations(
49            mc_transformations,
50            start_zone=start_zone,
51            start_zones_items={
52                NETHER: [Stack(OPEN_NETHER_PORTAL)],
53                STRONGHOLD: [Stack(CLOSE_ENDER_PORTAL)],
54            },
55        )
56        mc_world.resources_path = Path(__file__).parent / "resources"
57        super().__init__(world=mc_world, name="MineHcraft", purpose=purpose, **kwargs)
58        self.metadata["video.frames_per_second"] = kwargs.pop("fps", 10)
Arguments:
  • world: World defining the environment.
  • purpose: Purpose of the player, defining rewards and termination. Defaults to None, hence a sandbox environment.
  • invalid_reward: Reward given to the agent for invalid actions. Defaults to -1.0.
  • render_window: Window using to render the environment with pygame.
  • name: Name of the environement. Defaults to 'HierarchyCraft'.
  • max_step: (Optional[int], optional): Maximum number of steps before episode truncation. If None, never truncates the episode. Defaults to None.
class RandomHcraftEnv(typing.Generic[~ObsType, ~ActType]):
 21class RandomHcraftEnv(HcraftEnv):
 22    """Random HierarchyCraft Environment"""
 23
 24    def __init__(
 25        self,
 26        n_items_per_n_inputs: Optional[Dict[int, int]] = None,
 27        seed: int = None,
 28        **kwargs,
 29    ):
 30        """Random HierarchyCraft Environment.
 31
 32        Args:
 33            n_items_per_n_inputs: Mapping from the number of inputs to the number of items
 34                with this number of inputs.
 35            max_step: The maximum number of steps until done.
 36        """
 37        if n_items_per_n_inputs is None:
 38            n_items_per_n_inputs = {0: 5, 1: 5, 2: 10, 3: 5}
 39
 40        self.seed = seed
 41        self.np_random = np.random.RandomState(seed)
 42        self.n_items = sum(n_items_per_n_inputs.values())
 43        env_characteristics = "".join(
 44            [
 45                f"{n_inputs}I{n_items}"
 46                for n_inputs, n_items in n_items_per_n_inputs.items()
 47            ]
 48        )
 49        name = f"RandomCrafing-{env_characteristics}-S{seed}"
 50        self.items: List[Item] = []
 51        transformations = self._transformations(n_items_per_n_inputs)
 52        world = world_from_transformations(transformations)
 53        if "purpose" not in kwargs:
 54            purpose = Purpose()
 55            for item in self.items:
 56                purpose.add_task(GetItemTask(item))
 57            kwargs["purpose"] = purpose
 58        super().__init__(world, name=name, **kwargs)
 59
 60    def _transformations(
 61        self,
 62        n_items_per_n_inputs: Dict[int, int],
 63    ) -> List[Transformation]:
 64        """Build transformations for a RandomHcraft environement.
 65
 66        Args:
 67            n_items_per_n_inputs: Mapping from the number of inputs to the number of items
 68                with this number of inputs.
 69        Returns:
 70            A list of random (but accessible) transformations.
 71
 72        """
 73
 74        for n_inputs, n_items in n_items_per_n_inputs.items():
 75            self.items += [Item(f"{n_inputs}_{i}") for i in range(n_items)]
 76
 77        transformations = []
 78
 79        # Items with 0 inputs are accessible from the start
 80        accessible_items = []
 81        for item in self.items:
 82            if item.name.startswith("0"):
 83                search_item = Transformation(inventory_changes=[Yield(PLAYER, item)])
 84                transformations.append(search_item)
 85                accessible_items.append(item)
 86
 87        # Other items are built with inputs
 88        unaccessible_items = [
 89            item for item in self.items if item not in accessible_items
 90        ]
 91        self.np_random.shuffle(unaccessible_items)
 92
 93        while len(accessible_items) < len(self.items):
 94            new_accessible_item = unaccessible_items.pop()
 95            inventory_changes = [Yield(PLAYER, new_accessible_item)]
 96
 97            n_inputs = int(new_accessible_item.name.split("_")[0])
 98            n_inputs = min(n_inputs, len(accessible_items))
 99
100            # Chooses randomly accessible items
101            input_items = list(
102                self.np_random.choice(accessible_items, size=n_inputs, replace=False)
103            )
104            inventory_changes += [Use(PLAYER, item, consume=1) for item in input_items]
105
106            # Build recipe
107            new_recipe = Transformation(inventory_changes=inventory_changes)
108            transformations.append(new_recipe)
109            accessible_items.append(new_accessible_item)
110
111        return transformations

Random HierarchyCraft Environment

RandomHcraftEnv( n_items_per_n_inputs: Optional[Dict[int, int]] = None, seed: int = None, **kwargs)
24    def __init__(
25        self,
26        n_items_per_n_inputs: Optional[Dict[int, int]] = None,
27        seed: int = None,
28        **kwargs,
29    ):
30        """Random HierarchyCraft Environment.
31
32        Args:
33            n_items_per_n_inputs: Mapping from the number of inputs to the number of items
34                with this number of inputs.
35            max_step: The maximum number of steps until done.
36        """
37        if n_items_per_n_inputs is None:
38            n_items_per_n_inputs = {0: 5, 1: 5, 2: 10, 3: 5}
39
40        self.seed = seed
41        self.np_random = np.random.RandomState(seed)
42        self.n_items = sum(n_items_per_n_inputs.values())
43        env_characteristics = "".join(
44            [
45                f"{n_inputs}I{n_items}"
46                for n_inputs, n_items in n_items_per_n_inputs.items()
47            ]
48        )
49        name = f"RandomCrafing-{env_characteristics}-S{seed}"
50        self.items: List[Item] = []
51        transformations = self._transformations(n_items_per_n_inputs)
52        world = world_from_transformations(transformations)
53        if "purpose" not in kwargs:
54            purpose = Purpose()
55            for item in self.items:
56                purpose.add_task(GetItemTask(item))
57            kwargs["purpose"] = purpose
58        super().__init__(world, name=name, **kwargs)

Random HierarchyCraft Environment.

Arguments:
  • n_items_per_n_inputs: Mapping from the number of inputs to the number of items with this number of inputs.
  • max_step: The maximum number of steps until done.
seed
np_random: numpy.random._generator.Generator
225    @property
226    def np_random(self) -> np.random.Generator:
227        """Returns the environment's internal :attr:`_np_random` that if not set will initialise with a random seed.
228
229        Returns:
230            Instances of `np.random.Generator`
231        """
232        if self._np_random is None:
233            self._np_random, self._np_random_seed = seeding.np_random()
234        return self._np_random

Returns the environment's internal _np_random that if not set will initialise with a random seed.

Returns:

Instances of np.random.Generator

n_items
items: List[hcraft.Item]
class LightRecursiveHcraftEnv(typing.Generic[~ObsType, ~ActType]):
44class LightRecursiveHcraftEnv(HcraftEnv):
45    """LightRecursive environment."""
46
47    def __init__(self, n_items: int = 6, n_required_previous: int = 2, **kwargs):
48        self.n_items = n_items
49        self.n_required_previous = n_required_previous
50        if n_required_previous == 1:
51            env_name = "LinearRecursiveHcraft"
52        else:
53            env_name = f"LightRecursiveHcraft-K{n_required_previous}-I{n_items}"
54        items = [Item(str(i)) for i in range(n_items)]
55        transformations = self._transformations(items)
56        world = world_from_transformations(transformations)
57        if "purpose" not in kwargs:
58            kwargs["purpose"] = GetItemTask(items[-1])
59        super().__init__(world, name=env_name, **kwargs)
60
61    def _transformations(self, items: List[Item]) -> List[Transformation]:
62        """Build recipes to make every item accessible.
63
64        Args:
65            items: List of items.
66
67        Returns:
68            List of craft recipes.
69
70        """
71        transformation = []
72
73        for index, item in enumerate(items):
74            low_id = max(0, index - self.n_required_previous)
75            inventory_changes = [Yield(PLAYER, item)]
76            if index > 0:
77                inventory_changes += [
78                    Use(PLAYER, items[item_id], consume=1)
79                    for item_id in range(low_id, index)
80                ]
81
82            new_recipe = Transformation(inventory_changes=inventory_changes)
83            transformation.append(new_recipe)
84
85        return transformation

LightRecursive environment.

LightRecursiveHcraftEnv(n_items: int = 6, n_required_previous: int = 2, **kwargs)
47    def __init__(self, n_items: int = 6, n_required_previous: int = 2, **kwargs):
48        self.n_items = n_items
49        self.n_required_previous = n_required_previous
50        if n_required_previous == 1:
51            env_name = "LinearRecursiveHcraft"
52        else:
53            env_name = f"LightRecursiveHcraft-K{n_required_previous}-I{n_items}"
54        items = [Item(str(i)) for i in range(n_items)]
55        transformations = self._transformations(items)
56        world = world_from_transformations(transformations)
57        if "purpose" not in kwargs:
58            kwargs["purpose"] = GetItemTask(items[-1])
59        super().__init__(world, name=env_name, **kwargs)
Arguments:
  • world: World defining the environment.
  • purpose: Purpose of the player, defining rewards and termination. Defaults to None, hence a sandbox environment.
  • invalid_reward: Reward given to the agent for invalid actions. Defaults to -1.0.
  • render_window: Window using to render the environment with pygame.
  • name: Name of the environement. Defaults to 'HierarchyCraft'.
  • max_step: (Optional[int], optional): Maximum number of steps before episode truncation. If None, never truncates the episode. Defaults to None.
n_items
n_required_previous
class RecursiveHcraftEnv(typing.Generic[~ObsType, ~ActType]):
44class RecursiveHcraftEnv(HcraftEnv):
45    """RecursiveHcraft Environment"""
46
47    def __init__(self, n_items: int = 6, **kwargs):
48        items = [Item(str(i)) for i in range(n_items)]
49        self.n_items = n_items
50        transformations = self.build_transformations(items)
51        world = world_from_transformations(transformations)
52        if "purpose" not in kwargs:
53            kwargs["purpose"] = GetItemTask(items[-1])
54        super().__init__(
55            world,
56            name=f"RecursiveHcraft-I{n_items}",
57            **kwargs,
58        )
59
60    def build_transformations(self, items: List[Item]) -> List[Transformation]:
61        """Build transformations to make every item accessible.
62
63        Args:
64            items: List of items.
65
66        Returns:
67            List of transformations.
68
69        """
70        transformation = []
71
72        for index, item in enumerate(items):
73            inventory_changes = [Yield(PLAYER, item)]
74            if index > 0:
75                inventory_changes += [
76                    Use(PLAYER, items[item_id], consume=1) for item_id in range(index)
77                ]
78            new_recipe = Transformation(inventory_changes=inventory_changes)
79            transformation.append(new_recipe)
80
81        return transformation

RecursiveHcraft Environment

RecursiveHcraftEnv(n_items: int = 6, **kwargs)
47    def __init__(self, n_items: int = 6, **kwargs):
48        items = [Item(str(i)) for i in range(n_items)]
49        self.n_items = n_items
50        transformations = self.build_transformations(items)
51        world = world_from_transformations(transformations)
52        if "purpose" not in kwargs:
53            kwargs["purpose"] = GetItemTask(items[-1])
54        super().__init__(
55            world,
56            name=f"RecursiveHcraft-I{n_items}",
57            **kwargs,
58        )
Arguments:
  • world: World defining the environment.
  • purpose: Purpose of the player, defining rewards and termination. Defaults to None, hence a sandbox environment.
  • invalid_reward: Reward given to the agent for invalid actions. Defaults to -1.0.
  • render_window: Window using to render the environment with pygame.
  • name: Name of the environement. Defaults to 'HierarchyCraft'.
  • max_step: (Optional[int], optional): Maximum number of steps before episode truncation. If None, never truncates the episode. Defaults to None.
n_items
def build_transformations( self, items: List[hcraft.Item]) -> List[hcraft.Transformation]:
60    def build_transformations(self, items: List[Item]) -> List[Transformation]:
61        """Build transformations to make every item accessible.
62
63        Args:
64            items: List of items.
65
66        Returns:
67            List of transformations.
68
69        """
70        transformation = []
71
72        for index, item in enumerate(items):
73            inventory_changes = [Yield(PLAYER, item)]
74            if index > 0:
75                inventory_changes += [
76                    Use(PLAYER, items[item_id], consume=1) for item_id in range(index)
77                ]
78            new_recipe = Transformation(inventory_changes=inventory_changes)
79            transformation.append(new_recipe)
80
81        return transformation

Build transformations to make every item accessible.

Arguments:
  • items: List of items.
Returns:

List of transformations.

class TowerHcraftEnv(typing.Generic[~ObsType, ~ActType]):
 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.

TowerHcraftEnv(height: int = 2, width: int = 3, **kwargs)
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.
height
width
items
def build_transformations( self, items: List[hcraft.Item]) -> List[hcraft.Transformation]:
 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.