config.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. from __future__ import annotations
  2. from dataclasses import asdict, dataclass
  3. from pathlib import Path
  4. from typing_extensions import Literal
  5. PATTERN_PATH = Path(__file__).parent / "patterns"
  6. @dataclass
  7. class WFCConfig:
  8. """Dataclass for holding WFC configuration parameters.
  9. This controls the behavior of the WFC algorithm. The parameters are passed directly to the WFC solver.
  10. Attributes:
  11. pattern_path: Path to the pattern image that will be automatically loaded.
  12. tile_size: Size of the tiles in pixels to create from the pattern image.
  13. pattern_width: Size of the patterns in tiles to take from the pattern image. (greater than 3 is quite slow)
  14. rotations: Number of rotations for each tile.
  15. output_periodic: Whether the output should be periodic (wraps over edges).
  16. input_periodic: Whether the input should be periodic (wraps over edges).
  17. loc_heuristic: Heuristic for choosing the next tile location to collapse.
  18. choice_heuristic: Heuristic for choosing the next tile to use between possible tiles.
  19. backtracking: Whether to backtrack when contradictions are discovered.
  20. """
  21. pattern_path: Path
  22. tile_size: int = 1
  23. pattern_width: int = 2
  24. rotations: int = 8
  25. output_periodic: bool = False
  26. input_periodic: bool = False
  27. loc_heuristic: Literal[
  28. "lexical", "spiral", "entropy", "anti-entropy", "simple", "random"
  29. ] = "entropy"
  30. choice_heuristic: Literal["lexical", "rarest", "weighted", "random"] = "weighted"
  31. backtracking: bool = False
  32. @property
  33. def wfc_kwargs(self):
  34. try:
  35. from imageio.v2 import imread
  36. except ImportError as e:
  37. from gymnasium.error import DependencyNotInstalled
  38. raise DependencyNotInstalled(
  39. 'imageio is missing, please run `pip install "minigrid[wfc]"`'
  40. ) from e
  41. kwargs = asdict(self)
  42. kwargs["image"] = imread(kwargs.pop("pattern_path"))[:, :, :3]
  43. return kwargs
  44. # Basic presets for WFC configurations (that should generate in <1 min)
  45. WFC_PRESETS = {
  46. "MazeSimple": WFCConfig(
  47. pattern_path=PATTERN_PATH / "SimpleMaze.png",
  48. tile_size=1,
  49. pattern_width=2,
  50. output_periodic=False,
  51. input_periodic=False,
  52. ),
  53. "DungeonMazeScaled": WFCConfig(
  54. pattern_path=PATTERN_PATH / "ScaledMaze.png",
  55. tile_size=1,
  56. pattern_width=2,
  57. output_periodic=True,
  58. input_periodic=True,
  59. ),
  60. "RoomsFabric": WFCConfig(
  61. pattern_path=PATTERN_PATH / "Fabric.png",
  62. tile_size=1,
  63. pattern_width=3,
  64. output_periodic=False,
  65. input_periodic=False,
  66. ),
  67. "ObstaclesBlackdots": WFCConfig(
  68. pattern_path=PATTERN_PATH / "Blackdots.png",
  69. tile_size=1,
  70. pattern_width=2,
  71. output_periodic=False,
  72. input_periodic=False,
  73. ),
  74. "ObstaclesAngular": WFCConfig(
  75. pattern_path=PATTERN_PATH / "Angular.png",
  76. tile_size=1,
  77. pattern_width=3,
  78. output_periodic=True,
  79. input_periodic=True,
  80. ),
  81. "ObstaclesHogs3": WFCConfig(
  82. pattern_path=PATTERN_PATH / "Hogs.png",
  83. tile_size=1,
  84. pattern_width=3,
  85. output_periodic=True,
  86. input_periodic=True,
  87. ),
  88. }
  89. # Presets that take a large number of attempts to generate a consistent environment
  90. WFC_PRESETS_INCONSISTENT = {
  91. "MazeKnot": WFCConfig(
  92. pattern_path=PATTERN_PATH / "Knot.png",
  93. tile_size=1,
  94. pattern_width=3,
  95. output_periodic=True,
  96. input_periodic=True,
  97. ), # This is not too inconsistent (often 10 attempts is enough)
  98. "MazeWall": WFCConfig(
  99. pattern_path=PATTERN_PATH / "SimpleWall.png",
  100. tile_size=1,
  101. pattern_width=2,
  102. output_periodic=True,
  103. input_periodic=True,
  104. ),
  105. "RoomsOffice": WFCConfig(
  106. pattern_path=PATTERN_PATH / "Office.png",
  107. tile_size=1,
  108. pattern_width=3,
  109. output_periodic=True,
  110. input_periodic=True,
  111. ),
  112. "ObstaclesHogs2": WFCConfig(
  113. pattern_path=PATTERN_PATH / "Hogs.png",
  114. tile_size=1,
  115. pattern_width=2,
  116. output_periodic=True,
  117. input_periodic=True,
  118. ),
  119. "Skew2": WFCConfig(
  120. pattern_path=PATTERN_PATH / "Skew2.png",
  121. tile_size=1,
  122. pattern_width=3,
  123. output_periodic=True,
  124. input_periodic=True,
  125. ),
  126. }
  127. # Slow presets for WFC configurations (Most take about 2-4 min but some take 10+ min)
  128. WFC_PRESETS_SLOW = {
  129. "Maze": WFCConfig(
  130. pattern_path=PATTERN_PATH / "Maze.png",
  131. tile_size=1,
  132. pattern_width=3,
  133. output_periodic=True,
  134. input_periodic=True,
  135. ), # This is unusually slow: ~20min per 25x25 room
  136. "MazeSpirals": WFCConfig(
  137. pattern_path=PATTERN_PATH / "Spirals.png",
  138. tile_size=1,
  139. pattern_width=3,
  140. output_periodic=True,
  141. input_periodic=True,
  142. ),
  143. "MazePaths": WFCConfig(
  144. pattern_path=PATTERN_PATH / "Paths.png",
  145. tile_size=1,
  146. pattern_width=3,
  147. output_periodic=True,
  148. input_periodic=True,
  149. ),
  150. "Mazelike": WFCConfig(
  151. pattern_path=PATTERN_PATH / "Mazelike.png",
  152. tile_size=1,
  153. pattern_width=3,
  154. output_periodic=True,
  155. input_periodic=True,
  156. ),
  157. "Dungeon": WFCConfig(
  158. pattern_path=PATTERN_PATH / "DungeonExtr.png",
  159. tile_size=1,
  160. pattern_width=3,
  161. output_periodic=True,
  162. input_periodic=True,
  163. ), # ~10 mins
  164. "DungeonRooms": WFCConfig(
  165. pattern_path=PATTERN_PATH / "Rooms.png",
  166. tile_size=1,
  167. pattern_width=3,
  168. output_periodic=True,
  169. input_periodic=True,
  170. ),
  171. "DungeonLessRooms": WFCConfig(
  172. pattern_path=PATTERN_PATH / "LessRooms.png",
  173. tile_size=1,
  174. pattern_width=3,
  175. output_periodic=True,
  176. input_periodic=True,
  177. ),
  178. "DungeonSpirals": WFCConfig(
  179. pattern_path=PATTERN_PATH / "SpiralsNeg.png",
  180. tile_size=1,
  181. pattern_width=3,
  182. output_periodic=True,
  183. input_periodic=True,
  184. ),
  185. "RoomsMagicOffice": WFCConfig(
  186. pattern_path=PATTERN_PATH / "MagicOffice.png",
  187. tile_size=1,
  188. pattern_width=3,
  189. output_periodic=True,
  190. input_periodic=True,
  191. ),
  192. "SkewCave": WFCConfig(
  193. pattern_path=PATTERN_PATH / "Cave.png",
  194. tile_size=1,
  195. pattern_width=3,
  196. output_periodic=False,
  197. input_periodic=False,
  198. ),
  199. "SkewLake": WFCConfig(
  200. pattern_path=PATTERN_PATH / "Lake.png",
  201. tile_size=1,
  202. pattern_width=3,
  203. output_periodic=True,
  204. input_periodic=True,
  205. ), # ~10 mins
  206. }