/roguelikes/dungeon-scratch.rkt

http://github.com/VincentToups/racket-lib · Racket · 228 lines · 196 code · 31 blank · 1 comment · 16 complexity · 998f1e3b1095da1a96e4581f441eff91 MD5 · raw file

  1. #lang racket
  2. (require (except-in utilities/lists any all)
  3. (rename-in utilities/lists [any lists.any] [all lists.all])
  4. functional/monads
  5. (except-in functional/point-free compose)
  6. (rename-in functional/point-free [compose comp])
  7. utilities/one-of
  8. utilities/simple-infix
  9. utilities/planar-geometry
  10. utilities/draw-planar-geometry
  11. utilities/fancy-destructuring
  12. roguelikes/turtles-monad
  13. racket/base
  14. racket/dict
  15. racket/match)
  16. (define (main)
  17. (print "Hello World"))
  18. (define turtles-retire turtles-zero)
  19. (define (add-room-centered x y w h)
  20. (let ((w (force w))
  21. (h (force h)))
  22. (mlet* m-turtles
  23. ((rooms (getg-or 'rooms '()))
  24. (non-monadically:
  25. ((room (rectangle
  26. (point (round (- x (/ w 2)))
  27. (round (- y (/ h 2))))
  28. (point (round (+ x (/ w 2)))
  29. (round (+ y (/ h 2))))))))
  30. (rooms (setg 'rooms
  31. (cons
  32. room
  33. rooms))))
  34. (m-return room))))
  35. (define (add-hall-between . args)
  36. (match args
  37. ((list p1 p2)
  38. (mlet* m-turtles
  39. ((halls (getg-or 'halls '()))
  40. (non-monadically:
  41. ((hall (line-segment p1 p2))))
  42. (halls (setg 'halls
  43. (cons
  44. hall
  45. halls))))
  46. (m-return hall)))
  47. ((list x1 y1 x2 y2)
  48. (add-hall-between (point x1 y1)
  49. (point x2 y2)))))
  50. (define (move-add-hall amt)
  51. (mlet* m-turtles
  52. ((pos (getl-or 'pos (point 0 0)))
  53. (pos2 (move amt)))
  54. (add-hall-between pos pos2)))
  55. (define (room-for-room? room rooms)
  56. (let loop ((rooms rooms))
  57. (cond ((empty? rooms) #t)
  58. ((rectangles-overlap? room (car rooms)) #f)
  59. (else
  60. (loop (cdr rooms))))))
  61. (define (undelimited-string-of-features list)
  62. (let loop ((list list)
  63. (acc ""))
  64. (cond ((empty? list) acc)
  65. (else
  66. (loop (cdr list)
  67. (string-append acc (format "~a" (feature->string (car list)))
  68. (if (empty? (cdr list)) "" " ")))))))
  69. (define (room-in-range? r rectangle)
  70. (let loop ((corners (rectangle->corners r)))
  71. (cond ((empty? corners) #t)
  72. ((not (point-in-rectangle? (car corners) rectangle)) #f)
  73. (else (loop (cdr corners))))))
  74. (define (try-to-add-room-centered x y w h)
  75. (let ((room (rectangle
  76. (point (round (- x (/ w 2)))
  77. (round (- y (/ h 2))))
  78. (point (round (+ x (/ w 2)))
  79. (round (+ y (/ h 2)))))))
  80. (mlet* m-turtles
  81. ((rooms (getg-or 'rooms '())))
  82. ;(display (format "~n(room-for-room?~n ~a~n (list ~a))~n" (feature->string room) (undelimited-string-of-features rooms)))
  83. (if (and (room-for-room? room rooms)
  84. (room-in-range? room (rectangle (point 0 0) (point 300 300))))
  85. (begin
  86. (setg 'rooms
  87. (cons room rooms)))
  88. (begin
  89. (m-return #f))))))
  90. (define (add-room-here w h)
  91. (mlet* m-turtles
  92. ((pos (getl-or 'pos (point 150 150)))
  93. (room (add-room-centered (point-x pos) (point-y pos) w h)))
  94. (m-return room)))
  95. (define (point-in-a-room? pt rooms)
  96. (cond ((empty? rooms) #f
  97. (let ((room (car rooms))
  98. (rooms (cdr rooms)))
  99. (if (point-in-rectangle? pt room) #t
  100. (point-in-a-room? pt rooms))))))
  101. (define (try-to-add-room/hall . args)
  102. (dlet1 ((:> or '((dead-end-p . 0.1)
  103. (new-connection-p . 0.4)
  104. (room-width . 6)
  105. (room-height . 6)
  106. (hall-length . 10)))
  107. hall-length 'hall-length
  108. room-width 'room-width
  109. room-height 'room-height
  110. dead-end-p 'dead-end-p
  111. new-connection-p 'new-connection-p) args
  112. (mlet* m-turtles
  113. ((old-pos (getl 'pos))
  114. (new-pos (move hall-length))
  115. (rooms (getg-or 'rooms '()))
  116. (success? (try-to-add-room-centered (point-x new-pos)
  117. (point-y new-pos)
  118. room-width room-height)))
  119. (cond
  120. ((or success?
  121. (and (point-in-a-room? new-pos rooms)
  122. ($ (random) < new-connection-p))
  123. (and (point-in-rectangle? new-pos (rectangle (point 0 0) (point 300 300)))
  124. ($ (random) < dead-end-p)))
  125. (mlet* m-turtles
  126. ((h (add-hall-between old-pos new-pos))
  127. (p (setl 'pos new-pos)))
  128. (m-return h)))
  129. (else (mlet* m-turtles
  130. ((pos (setl 'pos old-pos)))
  131. (m-return #f)))))))
  132. (define (stochastic-turn)
  133. (one-of
  134. (1 (turn (/ pi 2)))
  135. (1 (turn (- (/ pi 2))))))
  136. (define (maybe-bifurcate)
  137. (one-of
  138. (1 helicity-split)
  139. (1 pass)))
  140. (define (maybe-retire with-probability)
  141. (if ($ (random) < with-probability)
  142. turtles-retire
  143. pass))
  144. (define render-dungeon-simple
  145. (mlet* m-turtles
  146. ((rooms (getg-or 'rooms '()))
  147. (halls (getg-or 'halls '())))
  148. (setg 'draw-these (append rooms halls))))
  149. (define (maybe-turn with-probability amount)
  150. (if ($ (random) < with-probability)
  151. (turn amount)
  152. pass))
  153. (define clamp-facing
  154. (mlet* m-turtles
  155. ((dir (getl-or 'facing (/ pi 2))))
  156. (setl 'facing
  157. (point-vector->radians (round-point (radians->point-vector dir))))))
  158. (define (step)
  159. (mlet* m-turtles
  160. (
  161. (u (maybe-turn 0.5 (/ pi 2)))
  162. (r (try-to-add-room/hall '(hall-length . 16) '(new-connection-p . 0.3)))
  163. (f clamp-facing)
  164. (r (maybe-retire 0.00)))
  165. (m-return 'step)))
  166. (define (random-room-dim)
  167. (+ 8 (* 2 (random 5))))
  168. (define (random-hall-length)
  169. (+ 12 (* 2 (random 5))))
  170. (define (step*)
  171. (mlet* m-turtles
  172. (
  173. (u (maybe-turn 0.5 (/ pi 2)))
  174. (r (try-to-add-room/hall
  175. '(new-connection-p . 0.3)
  176. (cons 'room-width (random-room-dim))
  177. (cons 'room-height (random-room-dim))
  178. (cons 'hall-length (random-hall-length))
  179. ))
  180. (f clamp-facing)
  181. (r (maybe-retire 0.00)))
  182. (m-return 'step)))
  183. (turtles-go
  184. (mlet* m-turtles ((stub (setl 'pos (point 150 150)))
  185. (room (add-room-here 6 6))
  186. (_ helicity-split)
  187. (_ (n-times-call step* 64))
  188. (r render-dungeon-simple))
  189. (m-return #t)))
  190. (turtles-go->svg
  191. (mlet* m-turtles ((stub (setl 'pos (point 150 150)))
  192. (room (add-room-here 6 6))
  193. (_ helicity-split)
  194. (_ (n-times-call step* 64))
  195. (r render-dungeon-simple))
  196. (m-return #t)))
  197. (provide main)