A Rush Hour game made with Cakelisp
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

145 lines
5.6 KiB

(comptime-define-symbol 'Unix)
(set-cakelisp-option cakelisp-src-dir "Dependencies/cakelisp/src")
(add-cakelisp-search-directory "test/src" "Dependencies/cakelisp/runtime")
(import &comptime-only "Macros.cake")
(add-c-search-directory-module "../../src") ;; Building from Dependencies/gamelib
(c-import "<stdio.h>" "<stdlib.h>" "<fcntl.h>" "<unistd.h>"
"bunzip.h")
(add-c-build-dependency "bunzip-4.1.c") ;; LGPLv2
(var g-known-num-puzzles (const int) 2577412)
;; This controls how many should be exported!
(var g-num-puzzles-to-read (const int) 50000)
(var-global g-bunzip-debug bool false)
(def-function-signature-global bunzip-decompress-callback (buffer (* char) num-bytes-this-read int
user-data (* void) &return bool))
(defun bunzip-decompress (bz2-file (* (const char))
receive-data-callback bunzip-decompress-callback
user-data (* void)
&return bool)
(var file-descriptor int (open bz2-file O_RDONLY))
(when (= -1 file-descriptor)
(printf "Failed to load file %s\n" bz2-file)
(return false))
;; Prints all of it, which is a lot!
;; (unless (= 0 (uncompressStream file-descriptor 1))
;; (return false))
(var header-data (* bunzip_data) null)
(var error-code int 0)
(set error-code (start_bunzip (addr header-data) file-descriptor
null 0)) ;; Unused: Input buffer
(when error-code
(printf "Bunzip error %d\n" error-code)
(free header-data)
(close file-descriptor)
(return false))
;; Add room for null terminator. Not necessary for binary data
(var output ([] 4097 char) (array 0))
(var num-bytes-read int 0)
(while true
(var return-code int (read_bunzip header-data output (- (array-size output) 1)))
(when (< return-code RETVAL_LAST_BLOCK) ;; On success, return code = num bytes written
(printf "Bunzip error %d\n" return-code)
(free header-data)
(close file-descriptor)
(return false))
(var num-bytes-this-read int 0)
(when (> return-code 0)
(set num-bytes-this-read return-code)
;; Set null terminator
(set (at num-bytes-this-read output) 0)
(set num-bytes-read (+ num-bytes-read num-bytes-this-read)))
(when receive-data-callback
(unless (receive-data-callback output num-bytes-this-read user-data)
(free header-data)
(close file-descriptor)
(return false)))
;; (printf "Output: %d bytes\n%s[end]\n" return-code output)
(when (= return-code RETVAL_LAST_BLOCK)
(when g-bunzip-debug (printf "Last Output: %s[end]\n" output))
(break)))
(when g-bunzip-debug (printf "Output: %d bytes\n" num-bytes-read))
(free header-data)
(close file-descriptor)
(return true))
(comptime-cond
('Kitty-Main)
(true ;; Generate puzzles.txt
;; Note that this doesn't change the distribution of puzzles
(var g-puzzle-skip-count (const int) (/ g-known-num-puzzles g-num-puzzles-to-read))
(defstruct-local puzzle-line-buffer
buffer (* char)
buffer-size int
buffer-write (* char)
num-puzzles-read int
file-out (* FILE))
(defun-local process-puzzle-data (buffer (* char) num-bytes-this-read int
user-data (* void) &return bool)
(var work-in-progress-line (* puzzle-line-buffer) (type-cast user-data (* puzzle-line-buffer)))
(var current-char (* char) buffer)
(while (< (- current-char buffer) num-bytes-this-read)
(cond
((= '\n' (deref current-char)) ;; Found puzzle delimiter
(set (deref (path work-in-progress-line > buffer-write)) 0)
;; Output puzzle
(when (= 0 (mod (path work-in-progress-line > num-puzzles-read) g-puzzle-skip-count))
(printf "%s\n" (path work-in-progress-line > buffer))
(when (path work-in-progress-line > file-out)
(fprintf (path work-in-progress-line > file-out) "%s\n"
(path work-in-progress-line > buffer))))
(set (path work-in-progress-line > buffer-write)
(path work-in-progress-line > buffer))
(incr (path work-in-progress-line > num-puzzles-read)))
(true ;; Reading a puzzle in
(set (deref (path work-in-progress-line > buffer-write)) (deref current-char))
(incr (path work-in-progress-line > buffer-write))
(when (>= (- (path work-in-progress-line > buffer-write)
(path work-in-progress-line > buffer))
(- (path work-in-progress-line > buffer-size) 1))
(printf "Error: didn't encounter newline before end of buffer\n")
(return false))))
(incr current-char))
(return true))
(defun main (&return int)
(var bz2-file (* (const char)) "assets/rush.txt.bz2")
(var file-out (* FILE) (fopen "data/puzzles.txt" "w"))
(unless file-out
(printf "Could not open output file\n")
(return 1))
(fprintf file-out "%d\n" g-num-puzzles-to-read)
;; For when the read buffer straddles a single puzzle
;; 46 chars max per puzzle, plus newline, plus room for null terminator for easy printing
(var work-in-progress-buffer ([] 48 char) (array 0))
(var work-in-progress-line puzzle-line-buffer
(array work-in-progress-buffer (array-size work-in-progress-buffer)
work-in-progress-buffer 0 file-out))
(unless (bunzip-decompress bz2-file process-puzzle-data (addr work-in-progress-line))
(fclose file-out)
(return 1))
(fclose file-out)
(return 0))
(set-cakelisp-option executable-output "../../decompression-test")))