open.py 5.4 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 the `Open` instruction.
  4. """
  5. from __future__ import annotations
  6. from minigrid.core.constants import COLOR_NAMES
  7. from minigrid.envs.babyai.core.roomgrid_level import RoomGridLevel
  8. from minigrid.envs.babyai.core.verifier import (
  9. LOC_NAMES,
  10. AfterInstr,
  11. BeforeInstr,
  12. ObjDesc,
  13. OpenInstr,
  14. )
  15. class Open(RoomGridLevel):
  16. """
  17. Open a door, which may be in another room
  18. """
  19. def gen_mission(self):
  20. self.place_agent()
  21. self.connect_all()
  22. self.add_distractors(num_distractors=18, all_unique=False)
  23. self.check_objs_reachable()
  24. # Collect a list of all the doors in the environment
  25. doors = []
  26. for i in range(self.num_cols):
  27. for j in range(self.num_rows):
  28. room = self.get_room(i, j)
  29. for door in room.doors:
  30. if door:
  31. doors.append(door)
  32. door = self._rand_elem(doors)
  33. self.instrs = OpenInstr(ObjDesc(door.type, door.color))
  34. class OpenRedDoor(RoomGridLevel):
  35. """
  36. Go to the red door
  37. (always unlocked, in the current room)
  38. Note: this level is intentionally meant for debugging and is
  39. intentionally kept very simple.
  40. """
  41. def __init__(self, **kwargs):
  42. super().__init__(num_rows=1, num_cols=2, room_size=5, **kwargs)
  43. def gen_mission(self):
  44. obj, _ = self.add_door(0, 0, 0, "red", locked=False)
  45. self.place_agent(0, 0)
  46. self.instrs = OpenInstr(ObjDesc("door", "red"))
  47. class OpenDoor(RoomGridLevel):
  48. """
  49. Go to the door
  50. The door to open is given by its color or by its location.
  51. (always unlocked, in the current room)
  52. """
  53. def __init__(self, debug=False, select_by=None, **kwargs):
  54. self.select_by = select_by
  55. self.debug = debug
  56. super().__init__(**kwargs)
  57. def gen_mission(self):
  58. door_colors = self._rand_subset(COLOR_NAMES, 4)
  59. objs = []
  60. for i, color in enumerate(door_colors):
  61. obj, _ = self.add_door(1, 1, door_idx=i, color=color, locked=False)
  62. objs.append(obj)
  63. select_by = self.select_by
  64. if select_by is None:
  65. select_by = self._rand_elem(["color", "loc"])
  66. if select_by == "color":
  67. object = ObjDesc(objs[0].type, color=objs[0].color)
  68. elif select_by == "loc":
  69. object = ObjDesc(objs[0].type, loc=self._rand_elem(LOC_NAMES))
  70. else:
  71. raise NotImplementedError("Not implemented.")
  72. self.place_agent(1, 1)
  73. self.instrs = OpenInstr(object, strict=self.debug)
  74. class OpenTwoDoors(RoomGridLevel):
  75. """
  76. Open door X, then open door Y
  77. The two doors are facing opposite directions, so that the agent
  78. Can't see whether the door behind him is open.
  79. This task requires memory (recurrent policy) to be solved effectively.
  80. """
  81. def __init__(
  82. self,
  83. first_color=None,
  84. second_color=None,
  85. strict=False,
  86. max_steps: int | None = None,
  87. **kwargs,
  88. ):
  89. self.first_color = first_color
  90. self.second_color = second_color
  91. self.strict = strict
  92. room_size = 6
  93. if max_steps is None:
  94. max_steps = 20 * room_size**2
  95. super().__init__(room_size=room_size, max_steps=max_steps, **kwargs)
  96. def gen_mission(self):
  97. colors = self._rand_subset(COLOR_NAMES, 2)
  98. first_color = self.first_color
  99. if first_color is None:
  100. first_color = colors[0]
  101. second_color = self.second_color
  102. if second_color is None:
  103. second_color = colors[1]
  104. door1, _ = self.add_door(1, 1, 2, color=first_color, locked=False)
  105. door2, _ = self.add_door(1, 1, 0, color=second_color, locked=False)
  106. self.place_agent(1, 1)
  107. self.instrs = BeforeInstr(
  108. OpenInstr(ObjDesc(door1.type, door1.color), strict=self.strict),
  109. OpenInstr(ObjDesc(door2.type, door2.color)),
  110. )
  111. class OpenDoorsOrder(RoomGridLevel):
  112. """
  113. Open one or two doors in the order specified.
  114. """
  115. def __init__(self, num_doors, debug=False, max_steps: int | None = None, **kwargs):
  116. assert num_doors >= 2
  117. self.num_doors = num_doors
  118. self.debug = debug
  119. room_size = 6
  120. if max_steps is None:
  121. max_steps = 20 * room_size**2
  122. super().__init__(room_size=room_size, max_steps=max_steps, **kwargs)
  123. def gen_mission(self):
  124. colors = self._rand_subset(COLOR_NAMES, self.num_doors)
  125. doors = []
  126. for i in range(self.num_doors):
  127. door, _ = self.add_door(1, 1, color=colors[i], locked=False)
  128. doors.append(door)
  129. self.place_agent(1, 1)
  130. door1, door2 = self._rand_subset(doors, 2)
  131. desc1 = ObjDesc(door1.type, door1.color)
  132. desc2 = ObjDesc(door2.type, door2.color)
  133. mode = self._rand_int(0, 3)
  134. if mode == 0:
  135. self.instrs = OpenInstr(desc1, strict=self.debug)
  136. elif mode == 1:
  137. self.instrs = BeforeInstr(
  138. OpenInstr(desc1, strict=self.debug), OpenInstr(desc2, strict=self.debug)
  139. )
  140. elif mode == 2:
  141. self.instrs = AfterInstr(
  142. OpenInstr(desc1, strict=self.debug), OpenInstr(desc2, strict=self.debug)
  143. )
  144. else:
  145. assert False