LightRecursive, a less recursive version of the RecursiveHcraft Environment.

Item n requires one of each the k previous items (n-k to n-1).

Example:
>>> env = LightRecursiveHcraftEnv(n_items=4, n_required_previous=2)
For example, if there is 5 items, the last item is 4.
But 4 requires the 2 previous items: {3, 2}.
And 3 requires the 2 previous items: {2, 1}.
And 2 requires the 2 previous items: {1, 0}.
And 1 requires the only previous items: {0}.
Finally Item 0 can be obtained directly.

Requirements graph (n_items=6, n_required_previous=2):

 1"""LightRecursive, a less recursive version of the RecursiveHcraft Environment.
 2
 3Item n requires one of each the k previous items (n-k to n-1).
 4
 5Example:
 6    >>> env = LightRecursiveHcraftEnv(n_items=4, n_required_previous=2)
 7    For example, if there is 5 items, the last item is 4.
 8    But 4 requires the 2 previous items: {3, 2}.
 9    And 3 requires the 2 previous items: {2, 1}.
10    And 2 requires the 2 previous items: {1, 0}.
11    And 1 requires the only previous items: {0}.
12    Finally Item 0 can be obtained directly.
13
14Requirements graph (n_items=6, n_required_previous=2):
15<div class="graph">
16.. include:: ../../../docs/images/requirements_graphs/LightRecursiveHcraft-K2-I6.html
17</div>
18"""
19
20from hcraft.elements import Item
21from hcraft.env import HcraftEnv
22from hcraft.task import GetItemTask
23from hcraft.transformation import PLAYER, Transformation, Use, Yield
24from hcraft.world import world_from_transformations
25
26
27from typing import List
28
29
30# gym is an optional dependency
31try:
32    import gymnasium as gym
33
34    gym.register(
35        id="LightRecursiveHcraft-v1",
36        entry_point="hcraft.examples.light_recursive:LightRecursiveHcraftEnv",
37    )
38
39except ImportError:
40    pass
41
42
43class LightRecursiveHcraftEnv(HcraftEnv):
44    """LightRecursive environment."""
45
46    def __init__(self, n_items: int = 6, n_required_previous: int = 2, **kwargs):
47        self.n_items = n_items
48        self.n_required_previous = n_required_previous
49        if n_required_previous == 1:
50            env_name = "LinearRecursiveHcraft"
51        else:
52            env_name = f"LightRecursiveHcraft-K{n_required_previous}-I{n_items}"
53        items = [Item(str(i)) for i in range(n_items)]
54        transformations = self._transformations(items)
55        world = world_from_transformations(transformations)
56        if "purpose" not in kwargs:
57            kwargs["purpose"] = GetItemTask(items[-1])
58        super().__init__(world, name=env_name, **kwargs)
59
60    def _transformations(self, items: List[Item]) -> List[Transformation]:
61        """Build recipes to make every item accessible.
62
63        Args:
64            items: List of items.
65
66        Returns:
67            List of craft recipes.
68
69        """
70        transformation = []
71
72        for index, item in enumerate(items):
73            low_id = max(0, index - self.n_required_previous)
74            inventory_changes = [Yield(PLAYER, item)]
75            if index > 0:
76                inventory_changes += [
77                    Use(PLAYER, items[item_id], consume=1)
78                    for item_id in range(low_id, index)
79                ]
80
81            new_recipe = Transformation(inventory_changes=inventory_changes)
82            transformation.append(new_recipe)
83
84        return transformation

API Documentation

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