Browse Source

Got board loading working

master
Macoy Madson 3 years ago
parent
commit
0d34e29448
  1. 172
      src/Main.cake

172
src/Main.cake

@ -16,6 +16,10 @@
;;
;; Constants
;;
(var debug-log-enabled bool true)
;; (var debug-log-enabled bool false)
(define-constant DATA_DIR "data/")
(defmacro in-data-dir (path-in-data string)
@ -76,7 +80,11 @@
;; 36 squares / 2 (min piece size) = 13; if two walls, need 14
(var g-game-board-pieces ([] 14 board-piece) (array 0))
(defmacro on-each-existing-board-piece (piece-pointer-name symbol piece-index-name symbol &rest body any)
(defun-local game-board-reset-pieces ()
(memset g-game-board-pieces 0 (sizeof g-game-board-pieces)))
(defmacro on-each-board-piece (piece-pointer-name symbol piece-index-name symbol
&rest body any)
(tokenize-push
output
(var next-piece-index int 0)
@ -86,10 +94,35 @@
(addr (at next-piece-index g-game-board-pieces)))
(set (token-splice piece-index-name) next-piece-index)
(incr next-piece-index) ;; In case expansions include (continue), we've already incremented
(when (path (token-splice piece-pointer-name) > num-cells)
(token-splice-rest body tokens))))
(token-splice-rest body tokens)))
(return true))
(defmacro on-each-existing-board-piece (piece-pointer-name symbol piece-index-name symbol
&rest body any)
(tokenize-push
output
(on-each-board-piece
(token-splice piece-pointer-name) (token-splice piece-index-name)
(when (path (token-splice piece-pointer-name) > num-cells)
(token-splice-rest body tokens))))
(return true))
(defun-local game-board-print ()
(var row int 0)
(while (< row g-game-board-grid-size)
(var column int 0)
(while (< column g-game-board-grid-size)
(var index BoardPieceIndex (at row column g-game-board-occupied-state))
(if (and (>= index 0) (field (at index g-game-board-pieces) num-cells))
(scope
(var piece-in-cell (* board-piece) (addr (at index g-game-board-pieces)))
(var label char (path piece-in-cell > label))
(printf "%c " (? label label '#')))
(printf ". "))
(incr column))
(printf "\n")
(incr row)))
(defun-local print-board-piece (piece (* (const board-piece)) index int)
(printf "Piece %c ([%d] %p )
\n\tgrid-position %d %d
@ -112,7 +145,8 @@
(sizeof g-game-board-occupied-state))
(on-each-existing-board-piece
piece piece-index
(print-board-piece piece piece-index)
(when debug-log-enabled
(print-board-piece piece piece-index))
(var num-cells int (path piece > num-cells))
@ -154,22 +188,100 @@
(set (deref occupy-space-pointer) piece-index)
(incr cell-offset)))
;; Print board
(var row int 0)
(while (< row g-game-board-grid-size)
(var column int 0)
(while (< column g-game-board-grid-size)
(var index BoardPieceIndex (at row column g-game-board-occupied-state))
(if (and (>= index 0) (field (at index g-game-board-pieces) num-cells))
(scope
(var piece-in-cell (* board-piece) (addr (at index g-game-board-pieces)))
(var label char (path piece-in-cell > label))
(printf "%c " (? label label '#')))
(printf ". "))
(incr column))
(printf "\n")
(incr row))
(when debug-log-enabled
(game-board-print))
(return true))
(defun-local game-board-piece-from-char (board-char char piece-cell-position grid-vec2)
(when (= board-char 'x') ;; Handle walls specially
(on-each-board-piece
piece piece-index
(unless (= 0 (field (deref piece) label))
(continue))
(set (field (deref piece) label) board-char)
(set (field (deref piece) grid-position) piece-cell-position)
(set (field (deref piece) is-wall) true)
(incr (field (deref piece) num-cells))
(break))
(return))
(on-each-board-piece
piece piece-index
(cond
((= board-char (field (deref piece) label)) ;; Existing piece
(cond ;; Determine direction
((> (vec-x piece-cell-position) (vec-x (field (deref piece) grid-position)))
(set (field (deref piece) is-vertical) false))
((> (vec-y piece-cell-position) (vec-y (field (deref piece) grid-position)))
(set (field (deref piece) is-vertical) true)))
(incr (field (deref piece) num-cells))
(break))
((= 0 (field (deref piece) label)) ;; New piece
(set (field (deref piece) label) board-char)
(set (field (deref piece) grid-position) piece-cell-position)
(set (field (deref piece) is-primary-piece) (= board-char 'A'))
(incr (field (deref piece) num-cells))
(break)))))
;; (The following text is copied from [[https://www.michaelfogleman.com/rush/][Michael Fogleman's Rush Hour database]]
;; ([[https://web.archive.org/web/20201101044241/https://www.michaelfogleman.com/rush/][archive.org]]),
;; for easier reference)
;; The database is a simple text file with just a few columns. There is one row for every valid
;; (solvable, minimal) cluster. The columns are: number of moves, board description, and cluster
;; size (number of reachable states).
;; The board description is a 36-character string representing the state of the unsolved board. It
;; is a 6x6 2D array in row-major order. The characters in the description follow these simple rules:
;; - o empty cell
;; - x wall (fixed obstacle)
;; - A primary piece (red car)
;; - B - Z all other pieces
;; I used lowercase ~o~ instead of periods ~.~ for the empty cells in the database so that the entire board description can be selected with a double-click.
;; Example format:
;; 60 IBBxooIooLDDJAALooJoKEEMFFKooMGGHHHM 2332
(defun-local game-board-load (fogleman-board-string (* (const char)) &return bool)
(game-board-reset-pieces)
(var num-moves int 0)
(var num-states int 0)
(var pieces-read bool false)
(var buffer ([] 37 char) (array 0))
(var write-char (* char) buffer)
(var current-char (* (const char)) fogleman-board-string)
(while (deref current-char)
(cond
;; Space field delimiter
((= (deref current-char) (space-hack))
(cond
((not num-moves)
(set num-moves (atoi buffer)))
(true ;; Reading pieces
(var board-char (* (const char)) buffer)
(while (deref board-char)
(cond
((= (deref board-char) 'o')
(debug-log "empty\n")) ;; Empty space
(true ;; Wall or piece
(var char-index int (- board-char buffer))
(var piece-cell-position grid-vec2 (array (% char-index g-game-board-grid-size)
(/ char-index g-game-board-grid-size)))
(debug-log "[%d] '%c' = (%d %d)\n" char-index (deref board-char) (vec-xy piece-cell-position))
(game-board-piece-from-char (deref board-char) piece-cell-position)))
(incr board-char))))
;; Reset buffer
(memset buffer 0 (sizeof buffer))
(set write-char buffer))
(true
(set (deref write-char) (deref current-char))
(incr write-char)))
(incr current-char))
(set num-states (atoi buffer))
(game-board-sync-occupied-state)
(printf "Board loaded. %d moves, %d states.\n" num-moves num-states)
(printf "%s\n" fogleman-board-string)
(return true))
;;
@ -278,6 +390,8 @@ Rush Hour database from Michael Fogleman.\n\n")
(unless (game-board-sync-occupied-state)
(return 1))
(game-board-load "60 IBBxooIooLDDJAALooJoKEEMFFKooMGGHHHM 2332")
;;
;; Game loop
;;
@ -308,6 +422,17 @@ Rush Hour database from Michael Fogleman.\n\n")
(sdl-shutdown window)
(return 0))
;;
;; Macros and generators
;;
(defmacro debug-log (&rest arguments any)
(tokenize-push
output
(when debug-log-enabled
(printf (token-splice-rest arguments tokens))))
(return true))
(defgenerator define-constant (define-name symbol value any)
(var define-statement (const ([] CStatementOperation))
(array
@ -331,6 +456,15 @@ Rush Hour database from Michael Fogleman.\n\n")
statement (array-size statement)
output)))
;; cakelisp's tokenizer doesn't properly parse ' '
(defgenerator space-hack ()
(var statement (const ([] CStatementOperation))
(array
(array Keyword "' '" -1)))
(return (CStatementOutput environment context tokens startTokenIndex
statement (array-size statement)
output)))
;;
;; Building
;;

Loading…
Cancel
Save