overworld.util.lisp 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. ;;;; Copyright © 2023, Jaidyn Ann <jadedctrl@posteo.at>
  2. ;;;;
  3. ;;;; This program is free software: you can redistribute it and/or
  4. ;;;; modify it under the terms of the GNU General Public License as
  5. ;;;; published by the Free Software Foundation, either version 3 of
  6. ;;;; the License, or (at your option) any later version.
  7. ;;;;
  8. ;;;; This program is distributed in the hope that it will be useful,
  9. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;;;; GNU General Public License for more details.
  12. ;;;;
  13. ;;;; You should have received a copy of the GNU General Public License
  14. ;;;; along with this program. If not, see <https://www.gnu.org/licenses/>.
  15. ;;;; FLORA-SEARCH-AURORA.OVERWORLD.UTIL
  16. ;;;; Utility functions used by multiple overworld packages (overworld.tiled & overworld).
  17. (in-package :flora-search-aurora.overworld.util)
  18. (defun coords->symbol (x y)
  19. (intern (format nil "~A,~A" x y) "KEYWORD"))
  20. (defun symbol->coords (coords-symbol)
  21. (str:split #\, (symbol-name coords-symbol)))
  22. (defun string->symbol (string)
  23. "Given a STRING with an optionally defined package (e.g., “package:symbol”),
  24. return it as an appopriate symbol."
  25. (let* ((split (str:split ":" (string-upcase string)))
  26. (package (when (eq (length split) 2)
  27. (car split)))
  28. (symbol (or (cadr split) (car split))))
  29. (if package
  30. (intern symbol package)
  31. (intern symbol))))
  32. (defun world-coords->screen-coords (world-coords &key (chunk-width 72) (chunk-height 20))
  33. "Given a set of “world” coordinates, determine where this spot would be on the screen.
  34. The world is split into screen-sized “chunks” to this end.
  35. — Chester P. Runk"
  36. (let* ((chunk-x (floor (/ (getf world-coords :x)
  37. chunk-width)))
  38. (chunk-y (floor (/ (getf world-coords :y)
  39. chunk-height)))
  40. (x (- (getf world-coords :x) (* chunk-x chunk-width)))
  41. (y (- (getf world-coords :y) (* chunk-y chunk-height))))
  42. (list :x x
  43. :y y
  44. :chunk (coords->symbol chunk-x chunk-y))))
  45. (defun world-coords-chunk (coords)
  46. (getf (world-coords->screen-coords coords) :chunk))
  47. (defun map->plist (map-hash)
  48. "Convert a map(-HASH) into a friendly, property-list format!
  49. Used by SAVE-MAP-TO-FILE."
  50. (alexandria:hash-table-plist map-hash))
  51. (defun plist->map (plist)
  52. "Convert a map from a MAP->PLIST’ed PLIST into a normal
  53. map hash-table, as used by the game."
  54. (let ((hash (make-hash-table)))
  55. ;; Add the core map-data…
  56. (setf (gethash :tiles hash) (getf plist :tiles))
  57. (setf (gethash :top-tiles hash) (getf plist :top-tiles))
  58. (setf (gethash :bump-map hash) (getf plist :bump-map))
  59. (setf (gethash :entities hash) (getf plist :entities))
  60. (setf (gethash :triggers hash) (getf plist :triggers))
  61. ;; And now the user’s data…
  62. (setf (gethash :seconds hash) (getf plist :seconds))
  63. (setf (gethash :day hash) (getf plist :day))
  64. (setf (gethash :acts hash) (getf plist :acts))
  65. (setf (gethash :knows hash) (getf plist :knows))
  66. (setf (gethash :items hash) (getf plist :items))
  67. hash))
  68. (defun save-map-to-file (path map &optional (package ":FLORA-SEARCH-AURORA") (variable "*map-plist*"))
  69. "Given a map, generate source-code that corresponds to it."
  70. (with-open-file (file-stream path :direction :output :if-exists :supersede)
  71. (format file-stream "(in-package ~A)~%(defvar ~A ~% (QUOTE ~S))"
  72. package variable (map->plist map))))