guile-sokoban/player.scm

51 lines
1.4 KiB
Scheme
Executable file

#! /usr/bin/env guile -e main -s
!#
(add-to-load-path ".")
(use-modules (engine)
(rnrs io ports)
(ice-9 regex))
(load "min-steps.scm")
(define help "\
usage: player.scm puzzle-file [puzzle-number]
If puzzle-number is zero or omitted, treat the entire file as one puzzle.
")
(define (make-puzzle-number-regexp n)
(make-regexp (format #f "\\s*;+\\s*~a[^0-9]*$" n) regexp/newline))
(define (load-puzzle path number)
(define n (string->number number))
(or n (error "bad number" number))
(define src (call-with-input-file path get-string-all))
(string->board
(cond
[(zero? n) src]
[else
(define start (match:end (regexp-exec (make-puzzle-number-regexp n) src)))
(define end (match:start (regexp-exec (make-puzzle-number-regexp (1+ n)) src start)))
(substring src start end)])))
;; i thought it was (main . args) instead of (main args), oops
(define (main args)
(apply
(case-lambda*
[(_ puzzle-file #:optional (puzzle-number 0))
(when (member puzzle-file '("--help" "-h"))
(display help)
(exit))
(game-loop
(load-puzzle puzzle-file puzzle-number)
(lambda (b c)
(case c
[(u) (board-step b 0 -1)]
[(d) (board-step b 0 1)]
[(l) (board-step b -1 0)]
[(r) (board-step b 1 0)]))
#:done? board-won?)]
[_ (display _) (display help) (exit 1)])
args))