open.py 5.1 KB

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