From d045db0d8fa00b3088f80916ac2f66b411814b81 Mon Sep 17 00:00:00 2001 From: Robby Findler Date: Fri, 5 Apr 2013 11:00:18 -0500 Subject: [PATCH] Tally Maze --- collects/games/scribblings/std-games.scrbl | 1 + collects/games/scribblings/tally-maze.scrbl | 35 + .../tally-maze/bmps/pumpkin/pumpkin-48x48.png | Bin 0 -> 3961 bytes .../tally-maze/bmps/pumpkin/pumpkin-64x64.png | Bin 0 -> 6631 bytes .../tally-maze/bmps/very-emotional/64 (1).png | Bin 0 -> 9503 bytes .../bmps/very-emotional/64 (19).png | Bin 0 -> 9172 bytes .../bmps/very-emotional/64 (20).png | Bin 0 -> 9191 bytes .../bmps/very-emotional/64 (21).png | Bin 0 -> 8514 bytes .../bmps/very-emotional/64 (35).png | Bin 0 -> 8705 bytes .../bmps/very-emotional/64 (36).png | Bin 0 -> 8434 bytes .../bmps/very-emotional/64 (37).png | Bin 0 -> 8419 bytes collects/games/tally-maze/game.rkt | 285 +++++++ collects/games/tally-maze/godel.rkt | 738 ++++++++++++++++++ collects/games/tally-maze/info.rkt | 4 + collects/games/tally-maze/maze.rkt | 495 ++++++++++++ collects/games/tally-maze/tally-maze.png | Bin 0 -> 5089 bytes 16 files changed, 1558 insertions(+) create mode 100644 collects/games/scribblings/tally-maze.scrbl create mode 100644 collects/games/tally-maze/bmps/pumpkin/pumpkin-48x48.png create mode 100644 collects/games/tally-maze/bmps/pumpkin/pumpkin-64x64.png create mode 100644 collects/games/tally-maze/bmps/very-emotional/64 (1).png create mode 100644 collects/games/tally-maze/bmps/very-emotional/64 (19).png create mode 100644 collects/games/tally-maze/bmps/very-emotional/64 (20).png create mode 100644 collects/games/tally-maze/bmps/very-emotional/64 (21).png create mode 100644 collects/games/tally-maze/bmps/very-emotional/64 (35).png create mode 100644 collects/games/tally-maze/bmps/very-emotional/64 (36).png create mode 100644 collects/games/tally-maze/bmps/very-emotional/64 (37).png create mode 100644 collects/games/tally-maze/game.rkt create mode 100644 collects/games/tally-maze/godel.rkt create mode 100644 collects/games/tally-maze/info.rkt create mode 100644 collects/games/tally-maze/maze.rkt create mode 100644 collects/games/tally-maze/tally-maze.png diff --git a/collects/games/scribblings/std-games.scrbl b/collects/games/scribblings/std-games.scrbl index 02c7cbd3b1..59f052c3be 100644 --- a/collects/games/scribblings/std-games.scrbl +++ b/collects/games/scribblings/std-games.scrbl @@ -23,4 +23,5 @@ @include-section["parcheesi.scrbl"] @include-section["checkers.scrbl"] @include-section["chat-noir.scrbl"] +@include-section["tally-maze.scrbl"] @include-section["gcalc.scrbl"] diff --git a/collects/games/scribblings/tally-maze.scrbl b/collects/games/scribblings/tally-maze.scrbl new file mode 100644 index 0000000000..8ba0700831 --- /dev/null +++ b/collects/games/scribblings/tally-maze.scrbl @@ -0,0 +1,35 @@ +#lang scribble/doc +@(require "common.rkt" racket/class racket/draw (only-in slideshow/pict dc)) + +@gametitle["Tally Maze" "tally-maze" "Maze Enumeration Game"] + +The object of @game{Tally Maze} is to help the blue ball +reach the exit of the maze without being caught by the pumpkins. + +Control the blue ball with the keyboard: +@itemlist[@item{the arrow keys move one step in each direction;} + @item{space and @litchar{.} let the pumpkins move without moving the blue ball;} + @item{@litchar{z} undoes the most recent move; and} + @item{@litchar{n} changes the maze.}] + +As you can quickly discover, simply moving around in the maze +is a recipe for failure. The pumpkins know the best route +in the maze to reach your blue ball and they take it. + +The @litchar{n} key, however, adjusts the maze. More precisely, +it moves forward to the next maze in an enumeration of all +40058175322602445443958933855600640 of the mazes that the game +supports. Each maze is only a little bit different from +the one before, so you have to plan ahead in order to understand +how the current maze differs from the next one. (Use the +undo key to help you plan.) + +Beware, however, that planning ahead one maze is not enough; +although one pumpkin just chases you in the current maze, +the other pumpkin tries to track where you might go if +you advance to the next maze and to wait for you there. +Not all games are winnable, although I believe most are. + +Thanks to Lazy Crazy (@url{http://lazycrazy.deviantart.com}) for +the blue ball icons and to YOOtheme (@url{http://www.yootheme.com/icons}) +for the pumpkin icon. \ No newline at end of file diff --git a/collects/games/tally-maze/bmps/pumpkin/pumpkin-48x48.png b/collects/games/tally-maze/bmps/pumpkin/pumpkin-48x48.png new file mode 100644 index 0000000000000000000000000000000000000000..97e5f153f88d7f21724211d87c2fd95863ddb6fb GIT binary patch literal 3961 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 T1$y$X00000NkvXXu0mjfm~Nks literal 0 HcmV?d00001 diff --git a/collects/games/tally-maze/bmps/pumpkin/pumpkin-64x64.png b/collects/games/tally-maze/bmps/pumpkin/pumpkin-64x64.png new file mode 100644 index 0000000000000000000000000000000000000000..1dd1ff09991ee01bbb1e69d5c01889be6794d665 GIT binary patch literal 6631 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 aLjX84%jdF0Hje-K^`fb&tMUP26Z~I-G)zzc literal 0 HcmV?d00001 diff --git a/collects/games/tally-maze/bmps/very-emotional/64 (1).png b/collects/games/tally-maze/bmps/very-emotional/64 (1).png new file mode 100644 index 0000000000000000000000000000000000000000..b697711a3ac756c4c86403c7d962a25468c09d73 GIT binary patch literal 9503 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 literal 0 HcmV?d00001 diff --git a/collects/games/tally-maze/bmps/very-emotional/64 (19).png b/collects/games/tally-maze/bmps/very-emotional/64 (19).png new file mode 100644 index 0000000000000000000000000000000000000000..6892fe9dfb3d6a2992e5d2acfa4d96ba5b4ee66c GIT binary patch literal 9172 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 literal 0 HcmV?d00001 diff --git a/collects/games/tally-maze/bmps/very-emotional/64 (35).png b/collects/games/tally-maze/bmps/very-emotional/64 (35).png new file mode 100644 index 0000000000000000000000000000000000000000..507fdb572e504417b6efb8861b58ba125e97377c GIT binary patch literal 8705 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 FV1k_AFYo{W literal 0 HcmV?d00001 diff --git a/collects/games/tally-maze/game.rkt b/collects/games/tally-maze/game.rkt new file mode 100644 index 0000000000..0682bc810e --- /dev/null +++ b/collects/games/tally-maze/game.rkt @@ -0,0 +1,285 @@ +#lang racket/base + +(require "maze.rkt" + (except-in "godel.rkt" unit/s) + "../show-scribbling.rkt" + racket/gui/base + racket/class + racket/set + racket/list + racket/path + racket/runtime-path + racket/unit) + +(provide game@) + +(define-runtime-path bmps "bmps") +(define big-pumpkin (read-bitmap (build-path bmps "pumpkin" "pumpkin-64x64.png"))) +(define two-pumpkins (make-bitmap (send big-pumpkin get-width) (send big-pumpkin get-height))) +(let ([small-pumpkin (read-bitmap (build-path bmps "pumpkin" "pumpkin-48x48.png"))] + [bdc (make-object bitmap-dc% two-pumpkins)]) + (send bdc draw-bitmap small-pumpkin 0 0) + (send bdc draw-bitmap small-pumpkin + (- (send big-pumpkin get-width) + (send small-pumpkin get-width)) + (- (send big-pumpkin get-height) + (send small-pumpkin get-height))) + (send bdc set-bitmap #f)) + +(define small-icon-size 4) +(define (mk-small color) + (define bmp (make-bitmap small-icon-size small-icon-size)) + (define bdc (make-object bitmap-dc% bmp)) + (send bdc set-brush color 'solid) + (send bdc set-pen "black" 1 'transparent) + (send bdc draw-ellipse 0 0 small-icon-size small-icon-size) + (send bdc set-bitmap #f) + bmp) + +(define small-pumpkin (mk-small "orange")) +(define small-player (mk-small "blue")) + +(define game@ + (unit (import) + (export) +(define maze-w 10) +(define maze-h 10) + +(struct state + (maze-index maze edges + player + computer1 + computer2 + player-icon) + #:transparent) +(define maze-count (spec-k (maze/s maze-w maze-h))) + +(define (state-next-edges the-state) + (build-walls + (decode (maze/s maze-w maze-h) + (modulo (+ (state-maze-index the-state) 1) + maze-count)) + maze-w + maze-h)) + +(define (fill-in-maze the-state new-val) + (define current-maze (decode-maze maze-w maze-h new-val)) + (struct-copy state the-state + [maze-index new-val] + [maze current-maze] + [edges (build-walls current-maze maze-w maze-h)])) + +(define initial-number (pick-a-maze maze-w maze-h)) +(define the-states + (list (fill-in-maze (state #f #f #f + (cons 0 0) + (cons (- maze-w 1) (- maze-h 1)) + (cons (- maze-w 1) (- maze-h 1)) + 21) + initial-number))) +(define (current-state) (car the-states)) +(define (set-the-states! new-states) + (set! the-states new-states) + (send game-canvas refresh)) + +(define (next-state! state) + (set-the-states! (cons state the-states))) + +(define (get-player-icon the-state) + (cond + [(and (= (car (state-player the-state)) (- maze-w 1)) + (= (cdr (state-player the-state)) (- maze-h 1))) + ;; winner + (pick '(1))] + [(edge-connecting? (state-edges the-state) + (state-player the-state) + (cons (- maze-w 1) (- maze-h 1))) + ;; about to win + (pick '(19))] + [(or (edge-connecting? (state-edges the-state) + (state-computer1 the-state) + (state-player the-state)) + (edge-connecting? (state-edges the-state) + (state-computer2 the-state) + (state-player the-state))) + ;; about to lose + (pick '(20 35))] + [else + ;; nothing much going on + (pick '(21 36 37))])) + +(define (edge-connecting? edges a b) (set-member? (hash-ref edges a) b)) + +(define (pick args) + (define pr (state-player (current-state))) + (list-ref args (modulo (+ (car pr) (cdr pr)) + (length args)))) + +(define players (make-hash)) +(for ([file (in-directory (build-path bmps "very-emotional"))]) + (when (regexp-match #rx"png$" (path->string file)) + (define name (path->string (last (explode-path file)))) + (define m-num (regexp-match #rx"[(]([0-9]+)[)]" name)) + (define num (if m-num + (string->number (list-ref m-num 1)) + 0)) + (hash-set! players num (read-bitmap file)))) + +(define (move dx dy) + (unless (game-over?) + (define new-x (+ dx (car (state-player (current-state))))) + (define new-y (+ dy (cdr (state-player (current-state))))) + (define new-pr (cons new-x new-y)) + (when (and (<= 0 new-x (- maze-w 1)) + (<= 0 new-y (- maze-w 1)) + (edge-connecting? (state-edges (current-state)) + (state-player (current-state)) + new-pr)) + (next-state! + (struct-copy state (move-computer (current-state)) + [player new-pr]))))) + +(define (stay-put) + (next-state! (move-computer (current-state)))) + +(define (next-maze) + (define next-maze-state + (fill-in-maze (current-state) + (modulo (+ (state-maze-index (current-state)) 1) maze-count))) + (next-state! + (if (game-over?) + next-maze-state + (move-computer next-maze-state)))) + +(define (undo-maze) + (unless (null? (cdr the-states)) + (set-the-states! (cdr the-states)))) + +(define (move-computer the-state) + (cond + [(or (equal? (state-player (current-state)) + (state-computer1 (current-state))) + (equal? (state-player (current-state)) + (state-computer2 (current-state)))) + the-state] + [else + (define end (state-player the-state)) + (define this-edges (state-edges the-state)) + (define next-edges (state-next-edges the-state)) + + (define-values (this-maze-c1 this-maze-c1-dist) + (preferred-direction this-edges (state-computer1 the-state) end)) + (define-values (this-maze-c2 this-maze-c2-dist) + (preferred-direction this-edges (state-computer2 the-state) end)) + + (define-values (next-maze-c1 next-maze-c1-dist) + (preferred-direction next-edges (state-computer1 the-state) end)) + (define-values (next-maze-c2 next-maze-c2-dist) + (preferred-direction next-edges (state-computer2 the-state) end)) + (cond + [(<= this-maze-c1-dist this-maze-c2-dist) + (struct-copy state the-state + [computer1 this-maze-c1] + [computer2 (if (edge-connecting? this-edges + (state-computer2 the-state) + next-maze-c2) + next-maze-c2 + (state-computer2 the-state))])] + [else + (struct-copy state the-state + [computer1 (if (edge-connecting? this-edges + (state-computer1 the-state) + next-maze-c1) + next-maze-c1 + (state-computer1 the-state))] + [computer2 this-maze-c2])])])) + +(define (preferred-direction edges start end) + (define visited (make-hash)) + (define dir + (let loop ([node start] + [dist 0]) + (cond + [(hash-ref visited node #f) #f] + [else + (hash-set! visited node dist) + (cond + [(equal? node end) + node] + [else + (for/or ([neighbor (in-set (hash-ref edges node))]) + (and (loop neighbor (+ dist 1)) + neighbor))])]))) + (values dir (hash-ref visited end))) + + +(define (add1/f n) (and n (+ n 1))) + +(define game-canvas% + (class canvas% + (inherit get-dc get-client-size) + (define/override (on-paint) + (define dc (get-dc)) + (send dc set-smoothing 'smoothed) + (define-values (w h) (get-client-size)) + (draw-a-state dc 0 0 w h (current-state) #f)) + (define/override (on-char evt) + (case (send evt get-key-code) + [(left) (move -1 0)] + [(up) (move 0 -1)] + [(right) (move 1 0)] + [(down) (move 0 1)] + [(#\space #\.) (stay-put)] + [(#\n) (next-maze)] + [(#\z) (undo-maze)])) + (super-new))) + +(define (draw-a-state dc dx dy w h the-state small?) + (draw-maze dc dx dy + w h (state-edges the-state) + maze-w maze-h + #:images + (cons (list (if small? + (list small-player) + (list (hash-ref players (get-player-icon the-state)))) + (car (state-player the-state)) + (cdr (state-player the-state))) + (if (equal? (state-computer1 the-state) + (state-computer2 the-state)) + (list (list (if small? (list small-pumpkin) (list two-pumpkins)) + (car (state-computer1 the-state)) + (cdr (state-computer1 the-state)))) + (list (list (if small? (list small-pumpkin) (list big-pumpkin)) + (car (state-computer1 the-state)) + (cdr (state-computer1 the-state))) + (list (if small? (list small-pumpkin) (list big-pumpkin)) + (car (state-computer2 the-state)) + (cdr (state-computer2 the-state)))))))) + +(define (game-over?) + (or (equal? (state-player (current-state)) + (state-computer1 (current-state))) + (equal? (state-player (current-state)) + (state-computer2 (current-state))) + (and (= (car (state-player (current-state))) (- maze-w 1)) + (= (cdr (state-player (current-state))) (- maze-h 1))))) + + +(define f (new frame% [label "Tally Maze"] [width 600] [height 600])) +(define game-canvas (new game-canvas% + [parent f] + [min-width (* maze-w 60)] + [min-height (* maze-h 60)])) +(define hp (new horizontal-panel% [parent f] [alignment '(right center)] [stretchable-height #f])) +(define msg (new message% [parent hp] [label (format "Game #~a" initial-number)])) +(void (new vertical-panel% [parent hp])) +(define show-help (show-scribbling + '(lib "games/scribblings/games.scrbl") + "tally-maze")) +(define help-button (new button% + [label "Help"] + [parent hp] + [callback (lambda (_1 _2) (show-help))])) +(send f show #t))) + +(module+ main (invoke-unit game@)) \ No newline at end of file diff --git a/collects/games/tally-maze/godel.rkt b/collects/games/tally-maze/godel.rkt new file mode 100644 index 0000000000..51f7524052 --- /dev/null +++ b/collects/games/tally-maze/godel.rkt @@ -0,0 +1,738 @@ +#lang racket/base + +#| + +Originally from Jay McCarthy's gb library. + +|# + +(require racket/match + racket/contract + racket/function + racket/list) + + +(provide k*k-bind/s + cons/s list/s + nat-range/s wrap/s enum/s unit/s + decode encode spec-k) + +(module+ test + (require rackunit) + (define N 10)) + +;; The core: Pairing functions +(define (core-nat-cons x y) + (arithmetic-shift (bitwise-ior 1 (arithmetic-shift y 1)) + x)) + +(define (core-nat-hd n) + (unless (> n 0) + (error 'core-nat-hd "Cannot take the head of 0")) + (if (= 1 (bitwise-and n 1)) + 0 + (add1 (core-nat-hd (arithmetic-shift n -1))))) + +(define (core-nat-tl n) + (arithmetic-shift n (* -1 (add1 (core-nat-hd n))))) + +(define (nat-cons x y) + (sub1 (core-nat-cons x y))) +(define (nat-hd z) + (core-nat-hd (add1 z))) +(define (nat-tl z) + (core-nat-tl (add1 z))) + +(define (pair hd-k tl-k hd tl) + (match* (hd-k tl-k) + [(+inf.0 +inf.0) + (nat-cons hd tl)] + [(+inf.0 tl-k) + (+ (* hd tl-k) tl)] + [(hd-k +inf.0) + (+ hd (* tl hd-k))] + [(hd-k tl-k) + (+ hd (* tl hd-k))])) +(define (pair-hd hd-k tl-k n) + (match* (hd-k tl-k) + [(+inf.0 +inf.0) + (nat-hd n)] + [(+inf.0 tl-k) + (quotient n tl-k)] + [(hd-k +inf.0) + (remainder n hd-k)] + [(hd-k tl-k) + (remainder n hd-k)])) +(define (pair-tl hd-k tl-k n) + (match* (hd-k tl-k) + [(+inf.0 +inf.0) + (nat-tl n)] + [(+inf.0 tl-k) + (remainder n tl-k)] + [(hd-k +inf.0) + (quotient n hd-k)] + [(hd-k tl-k) + (quotient n hd-k)])) + +(module+ test + (for ([i (in-range N)]) + (define fst (random (* N N))) + (define snd (random (* N N))) + (define n (nat-cons fst snd)) + (test-equal? (format "~a,~a" fst snd) (nat-hd n) fst) + (test-equal? (format "~a,~a" fst snd) (nat-tl n) snd))) + +;; Encoding +(struct spec (k in out) #:transparent) + +(define (encode spec v) + (define n ((spec-out spec) v)) + (define k (spec-k spec)) + (unless (< n k) + (error + 'encode + "spec(~e) returned encoding[~e] outside range[~e] for value[~e]" + spec n k v)) + n) +(define (decode spec n) + (define k (spec-k spec)) + (unless (< n k) + (error + 'decode + "spec(~e) received encoding[~e] outside range[~e]" + spec n k)) + ((spec-in spec) n)) +(module+ test + (define-syntax-rule (test-en/de s-e v-e) + (let () + (define n 's-e) + (define s s-e) + (define v v-e) + (test-equal? (format "s=~a v=~a" n v) + (decode s (encode s v)) + v))) + (define-syntax-rule (test-spec s-e) + (let () + (define n 's-e) + (define s s-e) + (for ([i (in-range (min N (spec-k s)))]) + (define v (decode s i)) + (test-equal? (format "n=~a i=~a v=~a" n i v) + (encode s v) i)))) + (define-syntax-rule (test-spec-ex s-e v-e n-e) + (let () + (define v v-e) + (define n n-e) + (define s s-e) + (test-equal? (format "encode ~a ~a = ~a" 's-e v n) (encode s v) n) + (test-equal? (format "decode ~a ~a = ~a" 's-e n v) (decode s n) v))) + (define-syntax-rule (test-spec-exs s-e [v n] ...) + (let () + (test-spec-ex s-e v n) + ...))) + +;; Specs +(define null/s + (spec 0 error error)) +(define (unit/s v) + (spec 1 (λ (n) v) (λ (v) 0))) +(module+ test + (define empty/s (unit/s empty)) + (test-spec empty/s) + (for ([i (in-range N)]) + (test-en/de empty/s empty))) + +(define nat/s + (spec +inf.0 identity identity)) +(module+ test + (test-spec nat/s) + (for ([i (in-range N)]) + (test-en/de nat/s (random (* N N))))) + +(define (nat-range/s k) + (spec k identity identity)) +(module+ test + (test-spec (nat-range/s N)) + (for ([i (in-range N)]) + (test-en/de (nat-range/s N) i))) + +(define (cons/s hd/s tl/s) + (match-define (spec hd-k _ _) hd/s) + (match-define (spec tl-k _ _) tl/s) + (spec (* hd-k tl-k) + (λ (n) + (cons (decode hd/s (pair-hd hd-k tl-k n)) + (decode tl/s (pair-tl hd-k tl-k n)))) + (λ (v) + (pair hd-k tl-k + (encode hd/s (car v)) + (encode tl/s (cdr v)))))) +(module+ test + (define 2nats/s (cons/s nat/s nat/s)) + (test-spec 2nats/s) + (for ([i (in-range N)]) + (test-en/de 2nats/s + (cons (random (* N N)) + (random (* N N)))))) + +(define (cantor-cons/s hd/s tl/s) + (match-define (spec hd-k _ _) hd/s) + (match-define (spec tl-k _ _) tl/s) + (unless (= +inf.0 hd-k) + (raise-argument-error 'cantor-cons/s + "an infinite /s" + 0 + (list hd/s tl/s))) + (unless (= +inf.0 tl-k) + (raise-argument-error 'cantor-cons/s + "an infinite /s" + 1 + (list hd/s tl/s))) + (spec (* hd-k tl-k) + (λ (z) + (define q (- (integer-sqrt (+ (* 8 z) 1)) 1)) + (define w (if (even? q) + (/ q 2) + (/ (- q 1) 2))) + (define t (/ (+ (* w w) w) 2)) + (define y (- z t)) + (define x (- w y)) + (cons (decode hd/s x) (decode tl/s y))) + (λ (v) + (define k1 (encode hd/s (car v))) + (define k2 (encode tl/s (cdr v))) + (+ (* 1/2 (+ k1 k2) (+ k1 k2 1)) k2)))) + +(module+ test + (define cantor-2nats/s (cantor-cons/s nat/s nat/s)) + (test-spec cantor-2nats/s) + (for ([i (in-range N)]) + (test-en/de cantor-2nats/s + (cons (random (* N N)) + (random (* N N))))) + (let () + ;; big-n has the digits you get by doing to the cantor + ;; pairing function using normal sqrt (via floats) + ;; and then finding the first number that goes wrong + ;; via repeated squaring (due to the imprecision of floats) + ;; and then concatenating that number's digits with itself + (define big-n + 340282366920938463463374607431768211456340282366920938463463374607431768211456) + (test-en/de cantor-2nats/s (cons big-n big-n)))) + +(define (or/s left? left/s right? right/s) + (match-define (spec left-k _ _) left/s) + (match-define (spec right-k _ _) right/s) + (match* (left-k right-k) + [(+inf.0 +inf.0) + (spec +inf.0 + (λ (n) + (match (pair-hd 2 +inf.0 n) + [0 + (decode left/s (pair-tl 2 +inf.0 n))] + [1 + (decode right/s (pair-tl 2 +inf.0 n))])) + (λ (v) + (match v + [(? left?) + (pair 2 +inf.0 0 (encode left/s v))] + [(? right?) + (pair 2 +inf.0 1 (encode right/s v))])))] + [(+inf.0 right-k) + (or/s right? right/s left? left/s)] + [(left-k right-k) + (spec (+ left-k right-k) + (λ (n) + (if (< n left-k) + (decode left/s n) + (decode right/s (- n left-k)))) + (λ (v) + (match v + [(? left?) + (encode left/s v)] + [(? right?) + (+ (encode right/s v) left-k)])))])) + +(module+ test + (define int/s + (or/s exact-nonnegative-integer? nat/s + negative? (wrap/s (wrap/s nat/s + (λ (n) (* -1 n)) + (λ (n) (* -1 n))) + (λ (n) (- n 1)) + (λ (n) (+ n 1))))) + (test-spec int/s) + (for ([i (in-range N)]) + (test-en/de int/s + (if (zero? (random 2)) + (add1 (random (* N N))) + (* -1 (add1 (random (* N N))))))) + + (define weird-nat/s + (or/s (λ (i) (<= 0 i 3)) (enum/s '(0 1 2 3)) + (λ (i) (< 3 i)) (wrap/s nat/s + (λ (n) (+ n 4)) + (λ (n) (- n 4))))) + (test-spec weird-nat/s) + (for ([i (in-range N)]) + (test-en/de weird-nat/s + (random (* N N)))) + + (define weird-nat/s-2 + (or/s (λ (i) (< 3 i)) (wrap/s nat/s + (λ (n) (+ n 4)) + (λ (n) (- n 4))) + (λ (i) (<= 0 i 3)) (enum/s '(0 1 2 3)))) + (test-spec weird-nat/s-2) + (for ([i (in-range N)]) + (test-en/de weird-nat/s-2 + (random (* N N)))) + + (define weird-nat/s-3 + (or/s (λ (i) (<= 0 i 3)) (enum/s '(0 1 2 3)) + (λ (i) (<= 4 i 6)) (enum/s '(4 5 6)))) + (test-spec weird-nat/s-3) + (for ([i (in-range N)]) + (test-en/de weird-nat/s-3 + (random 7)))) + +(define (enum/s elems) + (define elem->i + (for/hash ([e (in-list elems)] + [i (in-naturals)]) + (values e i))) + (spec (length elems) + (λ (n) (list-ref elems n)) + (λ (v) (hash-ref elem->i v)))) +(define bool/s + (enum/s (list #f #t))) + +(module+ test + (define (test-enum/s os) + (define bool/s (enum/s os)) + + (test-spec bool/s) + (for ([x (in-list os)]) + (test-en/de bool/s x)) + + (define b*b/s (cons/s bool/s bool/s)) + (test-spec b*b/s) + (for* ([x (in-list os)] + [y (in-list os)]) + (test-en/de b*b/s (cons x y))) + + (define n*b/s (cons/s nat/s bool/s)) + (test-spec n*b/s) + (for* ([x (in-range N)] + [y (in-list os)]) + (test-en/de n*b/s (cons (random (* N N)) y))) + + (define b*n/s (cons/s bool/s nat/s)) + (test-spec b*n/s) + (for* ([y (in-range N)] + [x (in-list os)]) + (test-en/de b*n/s (cons x (random (* N N)))))) + + (test-enum/s '(#f #t)) + (test-enum/s '(0 1 2))) + +(define (flist/s k elem/s) + (match k + [0 + (unit/s empty)] + [n + (cons/s elem/s (flist/s (sub1 k) elem/s))])) +(module+ test + (test-spec-exs (flist/s 0 (enum/s '(0 1 2))) + [empty 0]) + (test-spec-exs (flist/s 1 (enum/s '(0 1 2))) + [(cons 0 empty) 0] + [(cons 1 empty) 1] + [(cons 2 empty) 2]) + (test-spec-exs (flist/s 2 (enum/s '(0 1 2))) + [(cons 0 (cons 0 empty)) 0] + [(cons 1 (cons 0 empty)) 1] + [(cons 2 (cons 0 empty)) 2] + + [(cons 0 (cons 1 empty)) 3] + [(cons 1 (cons 1 empty)) 4] + [(cons 2 (cons 1 empty)) 5] + + [(cons 0 (cons 2 empty)) 6] + [(cons 1 (cons 2 empty)) 7] + [(cons 2 (cons 2 empty)) 8]) + + (define 3nats/s (flist/s 3 nat/s)) + (test-spec 3nats/s) + (for ([i (in-range N)]) + (test-en/de 3nats/s + (cons (random (* N N)) + (cons (random (* N N)) + (cons (random (* N N)) + empty)))))) + +(define (wrap/s inner/s wrap-in wrap-out) + (match-define (spec inner-k _ _) inner/s) + (spec inner-k + (λ (n) (wrap-in (decode inner/s n))) + (λ (v) (encode inner/s (wrap-out v))))) + +(define (hetero-vector/s vector-of-spec) + (define list-spec + (foldr (λ (elem/s s) (cons/s elem/s s)) + (unit/s empty) + (vector->list vector-of-spec))) + (wrap/s list-spec list->vector vector->list)) +(module+ test + (define weird-vector/s + (hetero-vector/s + (vector (nat-range/s 2) + (nat-range/s 3) + (nat-range/s 4)))) + (test-spec weird-vector/s) + (for ([i (in-range N)]) + (test-en/de weird-vector/s + (vector (random 2) + (random 3) + (random 4))))) + +(define (bind/s fst/s fst->rst/s + #:count + [given-count #f] + #:fst->rst/s-k + [given-fst->rst/s-k + #f] + #:rst-always-inf? + [rst-always-inf? #f]) + (define fst->rst/s-k + (or given-fst->rst/s-k + (λ (i) + (define fst (decode fst/s i)) + (define rst/s (fst->rst/s fst)) + (spec-k rst/s)))) + (define fst-k (spec-k fst/s)) + (cond + [rst-always-inf? + (spec (* fst-k +inf.0) + (λ (n) + (define fst-n + (pair-hd fst-k +inf.0 n)) + (define fst + (decode fst/s fst-n)) + (define rst/s (fst->rst/s fst)) + (define rst-n + (pair-tl fst-k +inf.0 n)) + (define rst + (decode rst/s rst-n)) + (cons fst rst)) + (λ (v) + (match-define (cons fst rst) v) + (define rst/s (fst->rst/s fst)) + (pair fst-k +inf.0 + (encode fst/s fst) + (encode rst/s rst))))] + [else + (define (check-rst-k! rst-k) + (when (= +inf.0 rst-k) + (error 'bind/s + "rst/s not always inf, but ever inf not supported"))) + (define count + (cond + [given-count + given-count] + [(= +inf.0 fst-k) + ;; XXX This is not actually correct if (sum (forall (f) (spec-k + ;; (fst->rst/s f)))) is finite, such as when the rst is always + ;; empty except a finite number of times, etc. + +inf.0] + [else + (for/fold ([total 0]) + ([i (in-range fst-k)]) + (define rst-k + (fst->rst/s-k i)) + (check-rst-k! rst-k) + (+ total rst-k))])) + + (define (bind-in i n) + (define fst (decode fst/s i)) + (define rst/s (fst->rst/s fst)) + (define rst-k (spec-k rst/s)) + (check-rst-k! rst-k) + (cond + [(>= n rst-k) + (bind-in (add1 i) (- n rst-k))] + [else + (cons fst (decode rst/s n))])) + (define (bind-out-sum i) + (cond + [(< i 0) + 0] + [else + (define fst (decode fst/s i)) + (define rst/s (fst->rst/s fst)) + (define rst-k (spec-k rst/s)) + (check-rst-k! rst-k) + (+ rst-k (bind-out-sum (sub1 i)))])) + + (spec count + (λ (n) (bind-in 0 n)) + (λ (v) + (define fst (car v)) + (define fst-n (encode fst/s fst)) + (define rst/s (fst->rst/s fst)) + (check-rst-k! (spec-k rst/s)) + (+ (bind-out-sum (sub1 fst-n)) + (encode rst/s (cdr v)))))])) + +(define (k*k-bind/s fst/s fst->rst/s + #:count [count #f] + #:rst-k [given-rst-k #f]) + (bind/s fst/s fst->rst/s + #:count count + #:fst->rst/s-k + (and given-rst-k + (λ (i) given-rst-k)))) + +(module+ test + (let () + (define outer-s + (nat-range/s 3)) + (define ex-s + (k*k-bind/s outer-s + (λ (i) + (define inner-s + (nat-range/s (+ i 1))) + inner-s))) + (check-equal? + (for/list ([i (in-range (spec-k ex-s))]) + (decode ex-s i)) + '((0 . 0) + (1 . 0) + (1 . 1) + (2 . 0) + (2 . 1) + (2 . 2)))) + + (define 3+less-than-three/s + (k*k-bind/s (enum/s '(0 1 2 3)) (λ (i) (nat-range/s (add1 i))))) + (test-spec + 3+less-than-three/s) + (test-spec-exs + 3+less-than-three/s + [(cons 0 0) 0] + [(cons 1 0) 1] + [(cons 1 1) 2] + [(cons 2 0) 3] + [(cons 2 1) 4] + [(cons 2 2) 5] + [(cons 3 0) 6] + [(cons 3 1) 7] + [(cons 3 2) 8] + [(cons 3 3) 9])) + +(define (k*k-bind2/s fst/s fst->rst/s + #:count [count #f] + #:rst-k [given-rst-k #f]) + ;; XXX check + (match-define (spec fst-k _ _) fst/s) + + (define size-table (make-hash)) + (define total-size 0) + (define subs + (for/list ([i (in-range fst-k)]) + (define fst (decode fst/s i)) + (define sub (fst->rst/s fst)) + (define size (spec-k sub)) + (hash-set! size-table fst total-size) + (set! total-size (+ total-size size)) + sub)) + (spec total-size + (λ (n) + (let loop ([subs subs] + [n n] + [i 0]) + (define sub (car subs)) + (define sub-k (spec-k sub)) + (cond + [(< n sub-k) + (define fst (decode fst/s i)) + (define rst/s (fst->rst/s fst)) + (match-define (spec rst-k _ _) rst/s) + (cons fst (decode rst/s n))] + [else + (loop (cdr subs) (- n (spec-k sub)) (+ i 1))]))) + (λ (v) + (match-define (cons fst rst) v) + (define rst/s (fst->rst/s fst)) + (match-define (spec rst-k _ _) rst/s) + (+ (hash-ref size-table fst) (encode rst/s rst))))) + +(module+ test + (define 3+less-than-three2/s + (k*k-bind2/s (enum/s '(0 1 2 3)) (λ (i) (nat-range/s (add1 i))))) + (test-spec + 3+less-than-three2/s) + (test-spec-exs + 3+less-than-three2/s + [(cons 0 0) 0] + [(cons 1 0) 1] + [(cons 1 1) 2] + [(cons 2 0) 3] + [(cons 2 1) 4] + [(cons 2 2) 5] + [(cons 3 0) 6] + [(cons 3 1) 7] + [(cons 3 2) 8] + [(cons 3 3) 9])) + +(define (k*inf-bind/s fst/s fst->rst/s) + (bind/s fst/s fst->rst/s + #:rst-always-inf? #t)) +(module+ test + (define 3+more-than-three/s + (k*inf-bind/s (enum/s '(0 1 2 3)) + (λ (i) + (wrap/s nat/s + (λ (out) (+ out i)) + (λ (in) (- in i)))))) + (test-spec + 3+more-than-three/s) + (test-spec-exs + 3+more-than-three/s + [(cons 0 0) 0] + [(cons 1 1) 1] + [(cons 2 2) 2] + [(cons 2 3) 6] + [(cons 3 3) 3])) + +;; XXX Add an optional function arg that tells you how many elements +;; there are for each n +(define (inf*k-bind/s fst/s fst->rst/s) + (bind/s fst/s fst->rst/s)) + +(module+ test + (define nat+less-than-n/s + (inf*k-bind/s nat/s (λ (i) (nat-range/s (add1 i))))) + (test-spec-exs + nat+less-than-n/s + [(cons 0 0) 0] + [(cons 1 0) 1] + [(cons 1 1) 2] + [(cons 2 0) 3] + [(cons 2 1) 4] + [(cons 2 2) 5] + [(cons 3 0) 6] + [(cons 3 1) 7] + [(cons 3 2) 8] + [(cons 3 3) 9])) + +(define (inf*inf-bind/s fst/s fst->rst/s) + (bind/s fst/s fst->rst/s + #:rst-always-inf? #t)) +(module+ test + (define nat+greater-than-n/s + (inf*inf-bind/s + nat/s (λ (i) + (wrap/s nat/s + (λ (out) (+ out i)) + (λ (in) (- in i)))))) + (test-spec nat+greater-than-n/s)) + +;; XXX +;; (define (union/s pred->spec) +;; (define pred/s (enum/s (hash-keys pred->spec))) +;; (wrap/s +;; (bind/s pred/s (λ (pred) ((hash-ref pred->spec pred)))) +;; (λ (de) (cdr de)) +;; (λ (en) (cons (for/or ([pred (in-hash-keys pred->spec)]) +;; (and (pred en) +;; pred)) +;; en)))) + +;; (define (union-list/s elem/s) +;; (define this/s +;; (union/s (hash empty? (λ () (unit/s empty)) +;; cons? (λ () (cons/s elem/s this/s))))) +;; this/s) + +(define (flist-prep/s inner/s) + (wrap/s + inner/s + (λ (v) (cdr v)) + (λ (l) (cons (length l) l)))) + +(define nat-greater-than-1/s + (wrap/s nat/s + (λ (out) (+ out 1)) + (λ (in) (- in 1)))) + +(define (nelist/s elem/s) + (define f-elem-list/s + (λ (len) (flist/s len elem/s))) + (cond + [(= +inf.0 (spec-k elem/s)) + (flist-prep/s + (inf*inf-bind/s + nat-greater-than-1/s + f-elem-list/s))] + [else + (flist-prep/s + (inf*k-bind/s + nat-greater-than-1/s f-elem-list/s))])) + +(define (bind-list/s elem/s) + (define f-elem-list/s + (λ (len) (flist/s len elem/s))) + (cond + [(= +inf.0 (spec-k elem/s)) + (or/s empty? + (unit/s empty) + cons? + (flist-prep/s + (inf*inf-bind/s + nat-greater-than-1/s + f-elem-list/s)))] + [else + (flist-prep/s + (inf*k-bind/s + nat/s f-elem-list/s))])) + +(define list/s bind-list/s) + +(module+ test + (define 012-list/s (list/s (enum/s '(0 1 2)))) + (test-spec 012-list/s) + (for ([i (in-range N)]) + (test-en/de 012-list/s + (build-list (random (* N N)) + (λ (_) (random 3))))) + + (define nat-list/s (list/s nat/s)) + (test-spec nat-list/s) + (for ([i (in-range N)]) + (test-en/de nat-list/s + (build-list (random (* N N)) + (λ (_) (random (* N N))))))) + + +;; XXX +(define (spec/c result/c) + spec?) + +;; XXX +(provide (all-defined-out)) + +(module+ main + (let ([np/s (cons/s (nat-range/s 4) (nat-range/s 4))]) + (define (number->bits n) + (reverse + (let loop ([n n]) + (cond + [(zero? n) '()] + [(odd? n) (cons 1 (loop (/ (- n 1) 2)))] + [(even? n) (cons 0 (loop (/ n 2)))])))) + (define (f p) + (+ (length (number->bits (car p))) + (length (number->bits (cdr p))))) + (for/list ([i (in-range 16)]) + (f (decode np/s i))))) diff --git a/collects/games/tally-maze/info.rkt b/collects/games/tally-maze/info.rkt new file mode 100644 index 0000000000..b1e8efff70 --- /dev/null +++ b/collects/games/tally-maze/info.rkt @@ -0,0 +1,4 @@ +#lang setup/infotab + +(define game-set "Puzzle Games") +(define game "game.rkt") diff --git a/collects/games/tally-maze/maze.rkt b/collects/games/tally-maze/maze.rkt new file mode 100644 index 0000000000..efe57690f3 --- /dev/null +++ b/collects/games/tally-maze/maze.rkt @@ -0,0 +1,495 @@ +#lang racket/base + +(require "godel.rkt" + racket/gui/base + racket/class + racket/set + racket/list) +(module+ test (require rackunit)) + +(provide pick-a-maze + draw-maze + build-walls + decode-maze + maze/s) + +(define (decode-maze maze-w maze-h n) + (define mazes (maze/s maze-w maze-h)) + (unless (and (exact-nonnegative-integer? n) + (< n (spec-k mazes))) + (raise-argument-error 'decode-maze + (format "number less than ~a" (spec-k mazes)) + n)) + (decode mazes n)) + +(define (memoize f) + (define ht (make-hash)) + (λ args + (hash-ref + ht args + (λ () + (hash-set! ht args (apply f args)) + (hash-ref ht args))))) + +(define maze/s + (memoize + (λ (width height) + (cond + [(or (= 1 height) (= 1 width)) (unit/s #f)] + [else + (k*k-bind/s + (wrap/s (fixed-length-list/s + (enum/s '(l t r b)) + (wrap/s (nat-range/s (- height 1)) add1 sub1) + (wrap/s (nat-range/s (- width 1)) add1 sub1)) + reverse reverse) + (λ (ul-w/h-and-break) + (define ul-w (list-ref ul-w/h-and-break 0)) + (define ul-h (list-ref ul-w/h-and-break 1)) + (define missing (list-ref ul-w/h-and-break 2)) + (define lr-w (- width ul-w)) + (define lr-h (- height ul-h)) + (fixed-length-list/s + + (case missing + [(l) + (fixed-length-list/s (unit/s #f) + (nat-range/s ul-h) + (nat-range/s lr-w) + (nat-range/s lr-h))] + [(t) + (fixed-length-list/s (nat-range/s ul-w) + (unit/s #f) + (nat-range/s lr-w) + (nat-range/s lr-h))] + [(r) + (fixed-length-list/s (nat-range/s ul-w) + (nat-range/s ul-h) + (unit/s #f) + (nat-range/s lr-h))] + [(b) + (fixed-length-list/s (nat-range/s ul-w) + (nat-range/s ul-h) + (nat-range/s lr-w) + (unit/s #f))]) + + (maze/s ul-w ul-h) + (maze/s lr-w ul-h) + (maze/s ul-w lr-h) + (maze/s lr-w lr-h))))])))) + +(define (fixed-length-list/s . args) + (let loop ([args args]) + (cond + [(null? args) (unit/s '())] + [else (cons/s (car args) (loop (cdr args)))]))) + +(define (pick-a-maze maze-w maze-h) + (define maze-count (spec-k (maze/s maze-w maze-h))) + (define digits (max 1 (- (string-length (number->string maze-count)) 1))) + (string->number + (apply + string-append + (for/list ([i (in-range digits)]) + (format "~a" + (if (= i 0) + (+ (random 9) 1) + (random 10))))))) + +(define (draw-maze dc dx dy w h edges maze-w maze-h + #:next-edges [next-edges #f] + #:solution [solution #f] + #:images [images '()]) + (define cell-size (min (/ w (+ maze-w 1/2)) (/ h (+ maze-h 1/2)))) + (define wall-pen-size (max 2 (ceiling (/ cell-size 6)))) + (define tot-maze-w (* cell-size maze-w)) + (define tot-maze-h (* cell-size maze-h)) + (define x-margin (/ (- w tot-maze-w) 2)) + (define y-margin (/ (- h tot-maze-h) 2)) + (define (mx->dcx mx) (+ (* mx cell-size) x-margin)) + (define (my->dcy my) (+ (* my cell-size) y-margin)) + + #; + (begin + (define start-distances (find-distances (cons 0 0) edges)) + (define end-distances (find-distances (cons (- maze-w 1) (- maze-h 1)) edges)) + (for* ([x (in-range maze-w)] + [y (in-range maze-h)]) + (define k (cons x y)) + (define ds (hash-ref start-distances k)) + (define de (hash-ref end-distances k)) + (define color (cond + [(= ds de) "white"] + [(< ds de) "Khaki"] + [(> ds de) "Lavender"])) + (define dx (mx->dcx x)) + (define dy (my->dcy y)) + (send dc set-pen color 1 'transparent) + (send dc set-brush color 'solid) + (send dc draw-rectangle dx dy cell-size cell-size))) + + (send dc set-pen "lightblue" 1 'solid) + (for ([x (in-range 1 maze-w)]) + (define e (mx->dcx x)) + (send dc draw-line (+ dx e) (+ dy y-margin) (+ dx e) (+ dy y-margin tot-maze-h))) + (for ([y (in-range 1 maze-h)]) + (define e (my->dcy y)) + (send dc draw-line (+ dx x-margin) (+ dy e) (+ dx x-margin tot-maze-w) (+ dy e))) + + (send dc set-pen "black" wall-pen-size 'solid) + (send dc draw-line + (+ dx x-margin) (+ dy y-margin cell-size) + (+ dx x-margin) (+ dy y-margin tot-maze-h)) + (send dc draw-line + (+ dx x-margin cell-size) (+ dy y-margin) + (+ dx x-margin tot-maze-w) (+ dy y-margin)) + (send dc draw-line + (+ dx x-margin) (+ dy y-margin tot-maze-h) + (+ dx x-margin tot-maze-w (- cell-size)) (+ dy y-margin tot-maze-h)) + (send dc draw-line + (+ dx x-margin tot-maze-w) (+ dy y-margin) + (+ dx x-margin tot-maze-w) (+ dy y-margin tot-maze-h (- cell-size))) + + (define (connect x1 y1 x2 y2) + (unless (and (= x1 x2) + (= y1 y2)) + (send dc draw-line + (+ dx (mx->dcx x1)) + (+ dy (my->dcy y1)) + (+ dx (mx->dcx x2)) + (+ dy (my->dcy y2))))) + + (for ([(from neighbors) (in-hash edges)]) + (define from-x (car from)) + (define from-y (cdr from)) + (define (try to-x to-y) + (when (<= 0 to-x (- maze-w 1)) + (when (<= 0 to-y (- maze-h 1)) + (define k (cons to-x to-y)) + (unless (set-member? neighbors k) + (send dc set-pen "black" + wall-pen-size + 'solid) + (cond + [(= from-x to-x) + (connect from-x + to-y + (+ from-x 1) + to-y)] + [(= from-y to-y) + (connect to-x + to-y + to-x + (+ to-y 1))]))))) + (try (+ from-x 1) from-y) + (try from-x (+ from-y 1))) + + (when solution + (send dc set-pen "red" wall-pen-size 'solid) + (for ([solution1 (in-list solution)] + [solution2 (in-list (cdr solution))]) + (connect (+ (car solution1) 1/2) + (+ (cdr solution1) 1/2) + (+ (car solution2) 1/2) + (+ (cdr solution2) 1/2)))) + + (for ([image (in-list images)]) + (define-values (icons x y) (apply values image)) + (define icon (or (for/or ([icon (in-list icons)]) + (and (<= (send icon get-width) cell-size) + (<= (send icon get-height) cell-size) + icon)) + (last icons))) + (send dc draw-bitmap + icon + (+ dx (mx->dcx x) (/ (- cell-size (send icon get-width)) 2)) + (+ dy (my->dcy y) (/ (- cell-size (send icon get-height)) 2))))) + +(define (find-solution edges maze-w maze-h) + (define start (cons 0 0)) + (define end (cons (- maze-w 1) (- maze-h 1))) + (define visited (make-hash)) + (let loop ([node start]) + (cond + [(equal? node end) (list end)] + [(hash-ref visited node #f) #f] + [else + (hash-set! visited node #t) + (define neighbor-ans + (for/or ([neighbor (in-set (hash-ref edges node))]) + (loop neighbor))) + (and neighbor-ans + (cons node neighbor-ans))]))) + +(define (find-distances end edges) + (define distances (make-hash)) + (let loop ([node end] + [distance 0]) + (cond + [(hash-ref distances node #f) (void)] + [else + (hash-set! distances node distance) + (for ([neighbor (in-set (hash-ref edges node))]) + (loop neighbor + (+ distance 1)))])) + distances) + +(define (build-walls maze-spec maze-w maze-h) + (define edges (make-hash)) + + (define (add-edge! x1 y1 x2 y2) + (add->edge! x1 y1 x2 y2) + (add->edge! x2 y2 x1 y1)) + (define (add->edge! x1 y1 x2 y2) + (define k (cons x1 y1)) + (hash-set! edges k (set-add (hash-ref edges k (set)) (cons x2 y2)))) + + + (define (remove-edge! x1 y1 x2 y2) + (remove->edge! x1 y1 x2 y2) + (remove->edge! x2 y2 x1 y1)) + (define (remove->edge! x1 y1 x2 y2) + (define k (cons x1 y1)) + (define new-edges (set-remove (hash-ref edges k) (cons x2 y2))) + (hash-set! edges k new-edges)) + + (for* ([x (in-range 0 maze-w)] + [y (in-range 0 maze-h)]) + (unless (zero? x) + (add-edge! x y (- x 1) y)) + (unless (zero? y) + (add-edge! x y x (- y 1)))) + + ;; draws a line between (x1,y1) and (x2,y2) + ;; which removes some edges + (define (connect x1 y1 x2 y2) + (let loop ([x1 (min x1 x2)] + [y1 (min y1 y2)] + [x2 (max x1 x2)] + [y2 (max y1 y2)]) + (cond + [(and (= x1 x2) (= y1 y2)) + (void)] + [(= x1 x2) + (remove-edge! (- x1 1) y1 x1 y1) + (loop x1 (+ y1 1) x1 y2)] + [(= y1 y2) + (remove-edge! x1 (- y1 1) x1 y1) + (loop (+ x1 1) y1 x2 y2)] + [else + (error 'connect "ack ~s => ~s\n" (cons x1 y1) (cons x2 y2))]))) + + (define (draw-horizontal-line line-break width x-start y-start) + (cond + [line-break + (connect x-start y-start (+ x-start line-break) y-start) + (connect (+ x-start line-break 1) y-start (+ x-start width) y-start)] + [else + (connect x-start y-start (+ x-start width) y-start)])) + + (define (draw-vertical-line line-break height x-start y-start) + (cond + [line-break + (connect x-start y-start x-start (+ y-start line-break)) + (connect x-start (+ y-start line-break 1) x-start (+ y-start height))] + [else + (connect x-start y-start x-start (+ y-start height))])) + + (let loop ([maze maze-spec] + [x 0] + [y 0] + [maze-w maze-w] + [maze-h maze-h]) + (when maze + (define sub-maze-info (list-ref maze 0)) + (define ul-w (list-ref sub-maze-info 0)) + (define ul-h (list-ref sub-maze-info 1)) + (define lr-w (- maze-w ul-w)) + (define lr-h (- maze-h ul-h)) + + (define line-break-info (list-ref maze 1)) + (define-values (lb-left lb-top lb-right lb-bottom) (apply values line-break-info)) + (draw-horizontal-line lb-left ul-w x (+ y ul-h)) + (draw-vertical-line lb-top ul-h (+ x ul-w) y) + (draw-horizontal-line lb-right lr-w (+ x ul-w) (+ y ul-h)) + (draw-vertical-line lb-bottom lr-h (+ x ul-w) (+ y ul-h)) + (define ul-submaze (list-ref maze 2)) + (define ur-submaze (list-ref maze 3)) + (define ll-submaze (list-ref maze 4)) + (define lr-submaze (list-ref maze 5)) + + (loop ul-submaze x y ul-w ul-h) + (loop ur-submaze (+ x ul-w) y lr-w ul-h) + (loop ll-submaze x (+ y ul-h) ul-w lr-h) + (loop lr-submaze (+ x ul-w) (+ y ul-h) lr-w lr-h))) + edges) + +(module+ test + + (check-equal? + (build-walls '((1 1 t) (0 #f 0 0) #f #f #f #f) 2 2) + (make-hash + (list (cons '(0 . 0) (set '(0 . 1))) + (cons '(0 . 1) (set '(0 . 0) '(1 . 1))) + (cons '(1 . 0) (set '(1 . 1))) + (cons '(1 . 1) (set '(0 . 1) '(1 . 0)))))) + + (check-equal? + (build-walls + '((1 2 b) (0 1 1 #f) #f ((1 1 l) (#f 0 0 0) #f #f #f #f) #f #f) + 3 + 3) + (make-hash + (list (cons '(0 . 0) (set '(0 . 1))) + (cons '(0 . 1) (set '(0 . 0) '(1 . 1) '(0 . 2))) + (cons '(0 . 2) (set '(0 . 1))) + (cons '(1 . 0) (set '(2 . 0))) + (cons '(1 . 1) (set '(0 . 1) '(2 . 1))) + (cons '(1 . 2) (set '(2 . 2))) + (cons '(2 . 0) (set '(1 . 0) '(2 . 1))) + (cons '(2 . 1) (set '(2 . 0) '(2 . 2) '(1 . 1))) + (cons '(2 . 2) (set '(2 . 1) '(1 . 2)))))) + + (check-equal? + (build-walls '((2 2 l) (#f 0 0 0) ((1 1 l) (#f 0 0 0) #f #f #f #f) #f #f #f) + 3 3) + (make-hash + (list (cons '(0 . 0) (set '(1 . 0))) + (cons '(0 . 1) (set '(1 . 1))) + (cons '(0 . 2) (set '(1 . 2))) + (cons '(1 . 0) (set '(0 . 0) '(1 . 1) '(2 . 0))) + (cons '(1 . 1) (set '(0 . 1) '(1 . 0))) + (cons '(1 . 2) (set '(0 . 2) '(2 . 2))) + (cons '(2 . 0) (set '(1 . 0) '(2 . 1))) + (cons '(2 . 1) (set '(2 . 0) '(2 . 2))) + (cons '(2 . 2) (set '(2 . 1) '(1 . 2))))))) + +(define (show-mazes) + + ;(define maze-w 34) (define maze-h 44) + (define maze-w 20) (define maze-h 20) + ;(define maze-w 2) (define maze-h 3) + ;(define maze-w 16) (define maze-h 16) + ;(define maze-w 8) (define maze-h 8) + + (define mazes (time (maze/s maze-w maze-h))) + (define maze-count (spec-k mazes)) + (printf "~a mazes\n" maze-count) + + (define slider-max-value (min maze-count 10000)) + (define max-starting-point (- maze-count slider-max-value)) + (define starting-point (pick-a-maze maze-w maze-h)) + (define f (new frame% [label ""] [width 400] [height 400])) + + (define current-solution #f) + (define current-edges #f) + (define next-edges #f) + (define which 0) + + (define c (new canvas% [parent f] + [paint-callback + (λ (c dc) + (send dc set-smoothing 'smoothed) + (define-values (w h) (send c get-client-size)) + (draw-maze dc w h current-edges maze-w maze-h + #:next-edges next-edges + #:solution current-solution))])) + (define bp (new horizontal-panel% [parent f] [stretchable-height #f])) + (define (move-to n) + (set! which (modulo n maze-count)) + (set! current-edges (build-walls (decode mazes which) maze-w maze-h)) + (set! current-solution (find-solution current-edges maze-w maze-h)) + (set! next-edges (build-walls (decode mazes (modulo (+ which 1) maze-count)) + maze-w maze-h)) + (send slider set-value (- which starting-point)) + (send c refresh)) + + (define slider + (new slider% + [label #f] + [min-value 0] + [max-value slider-max-value] + [parent bp] + [callback + (λ args + (move-to (+ starting-point (send slider get-value))))])) + (define tf (new text-field% + [label "Starting point"] + [parent f] + [stretchable-width #t] + [init-value ""] + [callback + (λ args + (define n (string->number (send tf get-value))) + (define n-ok? (and n (<= n max-starting-point))) + (send tf set-field-background + (send the-color-database find-color + (if n-ok? "white" "pink"))) + (when n-ok? + (set! starting-point n) + (move-to starting-point)))])) + + (send tf set-value (format "~a" starting-point)) + (define (mk-b lab adj) + (new button% + [parent bp] + [label lab] + [callback + (λ args + (move-to (adj which)))])) + (mk-b "Next" add1) + (mk-b "Previous" sub1) + (new button% + [parent bp] + [label "Random"] + [callback + (λ args + (set! starting-point (pick-a-maze maze-w maze-h)) + (send tf set-value (format "~a" starting-point)) + (move-to starting-point))]) + + (define run? #f) + (define timer + (new timer% + [notify-callback + (λ () (move-to (+ which 1)))])) + + (define run/stop-button + (new button% + [label "Run"] + [parent f] + [stretchable-width #t] + [callback + (λ args + (send run/stop-button set-label + (if run? "Run" "Stop")) + (set! run? (not run?)) + (if run? + (send timer start 100) + (send timer stop)))])) + (move-to starting-point) + (send f show #t)) + +;(module+ main (show-mazes)) +(module+ main + (define chan (make-channel)) + (collect-garbage) (collect-garbage) (collect-garbage) + (collect-garbage) (collect-garbage) (collect-garbage) + (void + (thread + (λ () + (let loop ([m (current-memory-use)]) + (sync + (handle-evt + (alarm-evt (+ (current-inexact-milliseconds) 100)) + (λ (_) (loop (max m (current-memory-use))))) + + (handle-evt + chan + (λ (c) + (channel-put c m)))))))) + (void (time (maze/s 20 20))) + (let ([c (make-channel)]) + (channel-put chan c) + (printf "peak mem use ~ak\n" (round (/ (channel-get c) 1024))))) + diff --git a/collects/games/tally-maze/tally-maze.png b/collects/games/tally-maze/tally-maze.png new file mode 100644 index 0000000000000000000000000000000000000000..f0d8d75bee07075a5f2014c42ce244f4ccb71054 GIT binary patch literal 5089 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