other.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. """
  2. Copied and adapted from https://github.com/mila-iqia/babyai.
  3. Levels described in the Baby AI ICLR 2019 submission, with different instructions than those in other files.
  4. """
  5. from __future__ import annotations
  6. from minigrid.envs.babyai.core.roomgrid_level import RoomGridLevel
  7. from minigrid.envs.babyai.core.verifier import (
  8. BeforeInstr,
  9. GoToInstr,
  10. ObjDesc,
  11. OpenInstr,
  12. PickupInstr,
  13. PutNextInstr,
  14. )
  15. class ActionObjDoor(RoomGridLevel):
  16. """
  17. [pick up an object] or
  18. [go to an object or door] or
  19. [open a door]
  20. (in the current room)
  21. """
  22. def __init__(self, **kwargs):
  23. super().__init__(room_size=7, **kwargs)
  24. def gen_mission(self):
  25. objs = self.add_distractors(1, 1, num_distractors=5)
  26. for _ in range(4):
  27. door, _ = self.add_door(1, 1, locked=False)
  28. objs.append(door)
  29. self.place_agent(1, 1)
  30. obj = self._rand_elem(objs)
  31. desc = ObjDesc(obj.type, obj.color)
  32. if obj.type == "door":
  33. if self._rand_bool():
  34. self.instrs = GoToInstr(desc)
  35. else:
  36. self.instrs = OpenInstr(desc)
  37. else:
  38. if self._rand_bool():
  39. self.instrs = GoToInstr(desc)
  40. else:
  41. self.instrs = PickupInstr(desc)
  42. class FindObjS5(RoomGridLevel):
  43. """
  44. Pick up an object (in a random room)
  45. Rooms have a size of 5
  46. This level requires potentially exhaustive exploration
  47. """
  48. def __init__(self, room_size=5, max_steps: int | None = None, **kwargs):
  49. if max_steps is None:
  50. max_steps = 20 * room_size**2
  51. super().__init__(room_size=room_size, max_steps=max_steps, **kwargs)
  52. def gen_mission(self):
  53. # Add a random object to a random room
  54. i = self._rand_int(0, self.num_rows)
  55. j = self._rand_int(0, self.num_cols)
  56. obj, _ = self.add_object(i, j)
  57. self.place_agent(1, 1)
  58. self.connect_all()
  59. self.instrs = PickupInstr(ObjDesc(obj.type))
  60. class KeyCorridor(RoomGridLevel):
  61. """
  62. A ball is behind a locked door, the key is placed in a
  63. random room.
  64. """
  65. def __init__(
  66. self,
  67. num_rows=3,
  68. obj_type="ball",
  69. room_size=6,
  70. max_steps: int | None = None,
  71. **kwargs,
  72. ):
  73. self.obj_type = obj_type
  74. if max_steps is None:
  75. max_steps = 30 * room_size**2
  76. super().__init__(
  77. room_size=room_size, num_rows=num_rows, max_steps=max_steps, **kwargs
  78. )
  79. def gen_mission(self):
  80. # Connect the middle column rooms into a hallway
  81. for j in range(1, self.num_rows):
  82. self.remove_wall(1, j, 3)
  83. # Add a locked door on the bottom right
  84. # Add an object behind the locked door
  85. room_idx = self._rand_int(0, self.num_rows)
  86. door, _ = self.add_door(2, room_idx, 2, locked=True)
  87. obj, _ = self.add_object(2, room_idx, kind=self.obj_type)
  88. # Add a key in a random room on the left side
  89. self.add_object(0, self._rand_int(0, self.num_rows), "key", door.color)
  90. # Place the agent in the middle
  91. self.place_agent(1, self.num_rows // 2)
  92. # Make sure all rooms are accessible
  93. self.connect_all()
  94. self.instrs = PickupInstr(ObjDesc(obj.type))
  95. class OneRoomS8(RoomGridLevel):
  96. """
  97. Pick up the ball
  98. Rooms have a size of 8
  99. """
  100. def __init__(self, room_size=8, **kwargs):
  101. super().__init__(room_size=room_size, num_rows=1, num_cols=1, **kwargs)
  102. def gen_mission(self):
  103. obj, _ = self.add_object(0, 0, kind="ball")
  104. self.place_agent()
  105. self.instrs = PickupInstr(ObjDesc(obj.type))
  106. class MoveTwoAcross(RoomGridLevel):
  107. """
  108. Task of the form: move the A next to the B and the C next to the D.
  109. This task is structured to have a very large number of possible
  110. instructions.
  111. """
  112. def __init__(
  113. self, room_size, objs_per_room, max_steps: int | None = None, **kwargs
  114. ):
  115. assert objs_per_room <= 9
  116. self.objs_per_room = objs_per_room
  117. if max_steps is None:
  118. max_steps = 16 * room_size**2
  119. super().__init__(
  120. num_rows=1, num_cols=2, room_size=room_size, max_steps=max_steps, **kwargs
  121. )
  122. def gen_mission(self):
  123. self.place_agent(0, 0)
  124. # Add objects to both the left and right rooms
  125. # so that we know that we have two non-adjacent set of objects
  126. objs_l = self.add_distractors(0, 0, self.objs_per_room)
  127. objs_r = self.add_distractors(1, 0, self.objs_per_room)
  128. # Remove the wall between the two rooms
  129. self.remove_wall(0, 0, 0)
  130. # Select objects from both subsets
  131. objs_l = self._rand_subset(objs_l, 2)
  132. objs_r = self._rand_subset(objs_r, 2)
  133. a = objs_l[0]
  134. b = objs_r[0]
  135. c = objs_r[1]
  136. d = objs_l[1]
  137. self.instrs = BeforeInstr(
  138. PutNextInstr(ObjDesc(a.type, a.color), ObjDesc(b.type, b.color)),
  139. PutNextInstr(ObjDesc(c.type, c.color), ObjDesc(d.type, d.color)),
  140. )