#lang racket/base

; Cell of Yggdrasil generator
(provide
  yggdrasil-cell-type
  yggdrasil-cell-feature
  ; Accessors to premade cells
  get-yggdrasil-cell
  yggdrasil-cell-undefined
  ; Conversion from/to characters, for hard-coded blocks of dungeon
  character->yggdrasil-cell
  yggdrasil-cell->character
  ; Some features of the cells
  yggdrasil-cell-defined?
  yggdrasil-cell-blocker?
  yggdrasil-cell-path?
  yggdrasil-cell-wall?
  yggdrasil-cell-event?
  )

; Structure
(struct yggdrasil-cell
  (type ; Type of cell
   feature ; Feature of cell
   character ; Character representing the cell
   ))

; Type of cell is among:
; #f (not defined)
; path
; wall

; Feature of cell is among:
; #f (no feature)
; door
; shortcut-EW
; shortcut-WE
; shortcut-NS
; shortcut-SN
; staircase-down
; staircase-up
; event
; check
; resource-mine
; resource-take
; resource-chop
; resource-harvest
; chest

; Collection of cells
(define *yggdrasil-cells*
  (make-immutable-hash
    `((undefined . ,(yggdrasil-cell #f #f #\$))
      (wall . ,(yggdrasil-cell 'wall #f #\#))
      (path . ,(yggdrasil-cell 'path #f #\.))
      (staircase-down . ,(yggdrasil-cell 'path 'staircase-down #\L))
      (staircase-up . ,(yggdrasil-cell 'path 'staircase-up #\7))
      (shortcut-EW . ,(yggdrasil-cell 'wall 'shortcut-EW #\<))
      (shortcut-WE . ,(yggdrasil-cell 'wall 'shortcut-WE #\>))
      (shortcut-NS . ,(yggdrasil-cell 'wall 'shortcut-NS #\v))
      (shortcut-SN . ,(yggdrasil-cell 'wall 'shortcut-SN #\^))
      (door . ,(yggdrasil-cell 'wall 'door #\+))
      (event . ,(yggdrasil-cell 'path 'event #\!))
      (check . ,(yggdrasil-cell 'path 'check #\?))
      (chest . ,(yggdrasil-cell 'path 'chest #\O))
      (resource-mine . ,(yggdrasil-cell 'path 'resource-mine #\m))
      (resource-take . ,(yggdrasil-cell 'path 'resource-take #\t))
      (resource-chop . ,(yggdrasil-cell 'path 'resource-chop #\c))
      (resource-harvest . ,(yggdrasil-cell 'path 'resource-harvest #\h))
      )))
; Characters to cells
(define *char->cell*
  (make-immutable-hash
    (map
      (lambda (c)
        (cons
          (yggdrasil-cell-character c)
          c))
      (hash-values *yggdrasil-cells*))))

; Accessor to premade cells
(define (get-yggdrasil-cell id)
  (hash-ref *yggdrasil-cells* id (yggdrasil-cell-undefined)))

(define (yggdrasil-cell-undefined)
  (hash-ref *yggdrasil-cells* 'undefined))

; Additional predicates
; Indicate if a cell is defined
(define (yggdrasil-cell-defined? cl)
  (not (not (yggdrasil-cell-type cl))))

; Indicate if a cell is blocking the path
(define (yggdrasil-cell-blocker? cl)
  (eq? 'wall (yggdrasil-cell-type cl)))

; Is a path?
(define (yggdrasil-cell-path? cl)
  (and (eq? (yggdrasil-cell-type cl) 'path)
       (not (yggdrasil-cell-feature cl))))

; Is a wall?
(define (yggdrasil-cell-wall? cl)
  (and (eq? (yggdrasil-cell-type cl) 'wall)
       (not (yggdrasil-cell-feature cl))))

; Is an event?
(define (yggdrasil-cell-event? cl)
  (eq? (yggdrasil-cell-feature cl) 'event))

; Conversion from/to characters
(define (character->yggdrasil-cell chr)
  (hash-ref *char->cell* chr (yggdrasil-cell-undefined)))
(define (yggdrasil-cell->character cl)
  (yggdrasil-cell-character cl))
