From 24e4fd407ba20d2eb14cbf1a0ce996e484d4d1d8 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sat, 21 Feb 2009 13:30:22 +0000 Subject: [PATCH] chat-noir literate small repairs svn: r13765 --- .../games/{ => chat-noir}/3x3-empty-board.png | Bin .../games/{ => chat-noir}/7x7-empty-board.png | Bin .../{ => chat-noir}/cat-distance-example.png | Bin .../games/chat-noir/chat-noir-literate.ss | 18 +++++--- collects/games/scribblings/common.ss | 40 +++++++++++------- collects/scheme/private/struct-info.ss | 8 +++- collects/scribble/lp-include.ss | 12 ++++-- collects/scribble/lp/lang/lang.ss | 14 ++++-- collects/scribblings/reference/struct.scrbl | 28 +++++++----- 9 files changed, 79 insertions(+), 41 deletions(-) rename collects/games/{ => chat-noir}/3x3-empty-board.png (100%) rename collects/games/{ => chat-noir}/7x7-empty-board.png (100%) rename collects/games/{ => chat-noir}/cat-distance-example.png (100%) diff --git a/collects/games/3x3-empty-board.png b/collects/games/chat-noir/3x3-empty-board.png similarity index 100% rename from collects/games/3x3-empty-board.png rename to collects/games/chat-noir/3x3-empty-board.png diff --git a/collects/games/7x7-empty-board.png b/collects/games/chat-noir/7x7-empty-board.png similarity index 100% rename from collects/games/7x7-empty-board.png rename to collects/games/chat-noir/7x7-empty-board.png diff --git a/collects/games/cat-distance-example.png b/collects/games/chat-noir/cat-distance-example.png similarity index 100% rename from collects/games/cat-distance-example.png rename to collects/games/chat-noir/cat-distance-example.png diff --git a/collects/games/chat-noir/chat-noir-literate.ss b/collects/games/chat-noir/chat-noir-literate.ss index 930d24dd3b..988029b213 100644 --- a/collects/games/chat-noir/chat-noir-literate.ss +++ b/collects/games/chat-noir/chat-noir-literate.ss @@ -1,7 +1,8 @@ #lang scribble/lp @(require (for-label scheme/math) ;; for 'pi' below - scheme/math) + scheme/math + games/scribblings/common) @;{ The command to build this: @@ -10,8 +11,7 @@ mzc chat-noir-doc.ss && rm -rf chat-noir-doc && scribble ++xref-in setup/xref lo } -@;{would like to have [#:style 'toc] in the next line ... } -@title{Chat Noir} +@gametitle*["Chat Noir" "chat-noir" "Puzzle Game" #:style '(toc)] @author[(link "http://www.eecs.northwestern.edu/~robby" "Robby Findler") (link "http://www.barzilay.org/" "Eli Barzilay") @@ -23,13 +23,15 @@ that space, and the cat responds by taking a step. If the cat is completely boxed in and thus unable reach the border, you win. If the cat does reach the border, you lose. +@play-margin-note["Chat Noir"] + To get some insight into the cat's behavior, hold down the ``h'' key. It will show you the cells that are on the cat's shortest path to the edge, assuming that the cell underneath the mouse has been blocked, so you can experiment to see how the shortest paths change by moving your mouse around. -The game was inspired by this one the one at +The game was inspired by the one at @link["http://www.gamedesign.jp/flash/chatnoir/chatnoir.html"]{Game Design} and has essentially the same rules. It also inspired the final project for the introductory programming course at the University of @@ -39,6 +41,8 @@ The remainder of this document explains the implementation of the Chat Noir game in a @link["http://www.literateprogramming.com/"]{Literate Programming} style. +@local-table-of-contents[] + @section{Overview} Chat Noir is implemented using @link["http://www.htdp.org/"]{HtDP}'s universe @@ -167,7 +171,7 @@ The @scheme[empty-board] function builds a list of @scheme[cell]s that correspond to an empty board. For example, here's what an empty 7x7 board looks like, as a list of cells. -@image["7x7-empty-board.png"] +@image["chat-noir/7x7-empty-board.png"] It contains 7 rows and, with the exception of the first and last rows, each row contains 7 cells. Notice how the even and odd rows are offset @@ -183,7 +187,7 @@ The 3x3 board also has the same property that it consists of three rows, each with three cells, but where the first and last row are missing their left-most cells. -@image["3x3-empty-board.png"] +@image["chat-noir/3x3-empty-board.png"] And here is how that board looks as a list of cells. @@ -697,7 +701,7 @@ For example, in a world of size @scheme[7] with the cat at @scheme[(make-posn 2 2)], the circles with white centers are on the shortest path to the boundary: -@image["cat-distance-example.png"] +@image["chat-noir/cat-distance-example.png"] So we can formulate two test cases using this world, one in the white circles and one not: diff --git a/collects/games/scribblings/common.ss b/collects/games/scribblings/common.ss index 8dfedc8bcb..8cac002f69 100644 --- a/collects/games/scribblings/common.ss +++ b/collects/games/scribblings/common.ss @@ -6,26 +6,36 @@ setup/main-collects) (provide (all-from-out scribble/manual) selflink - gametitle + gametitle gametitle* play-margin-note game) (define (selflink str) (link str (tt str))) (define game onscreen) -(define (gametitle name subcol subtitle) +(define (gametitle name subcol subtitle + #:style [style #f]) (make-splice (list - (title #:tag subcol - (make-element - "noborder" - (list - (image (path->main-collects-relative - (build-path (collection-path "games" subcol) - (format "~a.png" subcol)))))) - " " (onscreen name) " --- " subtitle) - (margin-note "To play " - (onscreen name) - ", run the " - (exec "PLT Games") " program." - " (Under Unix, it's called " (exec "plt-games") ").")))) + (gametitle* name subcol subtitle #:style style) + (play-margin-note name)))) + +(define (gametitle* name subcol subtitle + #:style [style #f]) + (title #:tag subcol + #:style style + (make-element + "noborder" + (list + (image (path->main-collects-relative + (build-path (collection-path "games" subcol) + (format "~a.png" subcol)))))) + " " (onscreen name) " --- " subtitle)) + +(define (play-margin-note name) + (margin-note "To play " + (onscreen name) + ", run the " + (exec "PLT Games") " program." + " (Under Unix, it's called " (exec "plt-games") ").")) + diff --git a/collects/scheme/private/struct-info.ss b/collects/scheme/private/struct-info.ss index 16e38f8f47..8ccef0325c 100644 --- a/collects/scheme/private/struct-info.ss +++ b/collects/scheme/private/struct-info.ss @@ -39,12 +39,16 @@ (error 'extract-struct-info "struct-info procedure result not properly formed: ~e" v)))) - si))) + (if (set!-transformer? si) + (extract-struct-info (set!-transformer-procedure si)) + si)))) (define-values (struct-info?) (lambda (si) (or (struct-info-rec? si) - (struct-declaration-info? si)))) + (struct-declaration-info? si) + (and (set!-transformer? si) + (struct-info-rec? (set!-transformer-procedure si)))))) (define-values (struct-declaration-info?) (lambda (x) diff --git a/collects/scribble/lp-include.ss b/collects/scribble/lp-include.ss index 0dc35fb3b6..2c68e8c195 100644 --- a/collects/scribble/lp-include.ss +++ b/collects/scribble/lp-include.ss @@ -32,12 +32,18 @@ (if (n . > . 1) #'(void) (with-syntax ([tag str] - [str str]) + [str str] + [((for-label-mod ...) ...) + (map (lambda (expr) + (syntax-case expr (require) + [(require mod ...) + #'(mod ...)] + [else null])) + (syntax->list #'(expr ...)))]) #`(begin - ;; ---- This is the new part -------- (define-syntax name (make-element-id-transformer (lambda (stx) #'(chunkref name)))) - ;; ---------------------------------- + (require (for-label for-label-mod ... ...)) (make-splice (list (make-toc-element #f diff --git a/collects/scribble/lp/lang/lang.ss b/collects/scribble/lp/lang/lang.ss index f25595809f..7911f772d9 100644 --- a/collects/scribble/lp/lang/lang.ss +++ b/collects/scribble/lp/lang/lang.ss @@ -68,7 +68,7 @@ chunk-mentions)]) #`(begin body ... (let ([b-id (void)]) b-use) ...))) -(define-syntax (module-begin stx) +(define-syntax (literate-begin stx) (syntax-case stx () [(module-begin expr ...) (with-syntax @@ -98,6 +98,12 @@ #%provide))) (cons expanded (loop (cdr exprs)))] [else (loop (cdr exprs))]))]))]) - #'(#%module-begin - body-code ... - (tangle)))])) + #'(begin + body-code ... + (tangle)))])) + +(define-syntax (module-begin stx) + (syntax-case stx () + [(_ id exprs . body) + #'(#%module-begin + (literate-begin id exprs . body))])) diff --git a/collects/scribblings/reference/struct.scrbl b/collects/scribblings/reference/struct.scrbl index 65da253f7c..1c45f97154 100644 --- a/collects/scribblings/reference/struct.scrbl +++ b/collects/scribblings/reference/struct.scrbl @@ -543,9 +543,7 @@ transformer to generate information about imported structure types, so that @scheme[match] and subtyping @scheme[define-struct] forms work within the unit. -The expansion-time information for a structure type is represented -either as a structure that encapsulates a procedure that takes no -arguments and returns a list of six element, or it can be represented +The expansion-time information for a structure type can be represented directly as a list of six elements (of the same sort that the encapsulated procedure must return): @@ -585,10 +583,18 @@ encapsulated procedure must return): } -Use @scheme[struct-info?] to recognize both forms of information, and -use @scheme[extract-struct-info] to obtain a list from either -representation. Use @scheme[make-struct-info] to encapsulate a -procedure that represents structure type information. +Instead of this direct representation, the representation can +be a structure created by @scheme[make-struct-info] (or an instance of +a subtype of @scheme[struct:struct-info]), which encapsulates a +procedure that takes no arguments and returns a list of six +elements. Finally, the representation can be an instance of a +structure type derived from @scheme[struct:struct-info] that also +implements @scheme[prop:procedure], and where the instance is further +is wrapped by @scheme[make-set!-transformer]. + +Use @scheme[struct-info?] to recognize all allowed forms of the +information, and use @scheme[extract-struct-info] to obtain a list +from any representation. The implementor of a syntactic form can expect users of the form to know what kind of information is available about a structure type. For @@ -606,15 +612,17 @@ type. @defproc[(struct-info? [v any/c]) boolean?]{ Returns @scheme[#t] if @scheme[v] is either a six-element list with -the correct shape for representing structure-type information, or a -procedure encapsulated by @scheme[make-struct-info].} +the correct shape for representing structure-type information, a +procedure encapsulated by @scheme[make-struct-info], or a structure +type derived from @scheme[struct:struct-info] and wrapped with +@scheme[make-set!-transformer].} @defproc[(checked-struct-info? [v any/c]) boolean?]{ Returns @scheme[#t] if @scheme[v] is a procedure encapsulated by @scheme[make-struct-info] and produced by @scheme[define-struct], but only when no parent type is specified or the parent type is also -specified through a transformer binding to such a value).} +specified through a transformer binding to such a value.} @defproc[(make-struct-info [thunk (-> (and/c struct-info? list?))]) struct-info?]{