From 6bec2167d77c51885a936ee06d378cceef29b221 Mon Sep 17 00:00:00 2001 From: Andrey Piterkin Date: Thu, 9 Nov 2023 20:57:07 -0500 Subject: [PATCH 1/8] optional contracts --- Q/Common/game-state.rkt | 76 ++++++++++----------- Q/Common/interfaces/playable.rkt | 10 +-- Q/Common/map.rkt | 110 ++++++++++++++++--------------- Q/Common/player-state.rkt | 52 ++++++++------- Q/Common/posn.rkt | 59 +++++++++-------- Q/Common/tile.rkt | 23 +++---- Q/Lib/contracts.rkt | 45 +++++++++++++ Q/Lib/image.rkt | 12 ++-- Q/Lib/list.rkt | 27 ++++---- Q/Lib/result.rkt | 23 ++++--- Q/Player/strategy.rkt | 36 +++++----- 11 files changed, 266 insertions(+), 207 deletions(-) create mode 100644 Q/Lib/contracts.rkt diff --git a/Q/Common/game-state.rkt b/Q/Common/game-state.rkt index 56d9a44..3cc2b19 100644 --- a/Q/Common/game-state.rkt +++ b/Q/Common/game-state.rkt @@ -22,50 +22,52 @@ (require Q/Lib/list) (require Q/Lib/image) (require Q/Lib/misc) +(require Q/Lib/contracts) (require Q/Common/interfaces/serializable) (require Q/Common/interfaces/playable) +(provide/cond-contract + [hash->pub-state + (-> hash? pub-state/c)] + [hash->priv-state + (-> hash? priv-state/c)] + [render-game-state + (-> priv-state/c image?)] + [make-game-state + (->i ([tiles (listof tile?)] [players (listof (is-a?/c playable<%>))]) + #:pre/name (tiles players) + "not enough tiles!" + (< (add1 (* (length players) + (*hand-size*))) + (length tiles)) + [result priv-state/c])] + [priv-state->pub-state + (-> priv-state/c pub-state/c)] + [remove-player + (-> priv-state/c priv-state/c)] + [turn-valid? + (-> game-state/c turn-action? boolean?)] + [do-turn/action + (-> game-state/c turn-action? game-state/c)] + [do-turn/score + (-> game-state/c turn-action? natural?)] + [do-turn/rotate + (-> priv-state/c priv-state/c)] + [do-turn-without-rotate + (-> priv-state/c turn-action? (values priv-state/c boolean?))] + [new-tiles + (-> priv-state/c (listof tile?))] + [players-left? + (-> game-state/c boolean?)] + [winners+losers + (-> priv-state/c (values (listof player-state?) + (listof player-state?)))]) + (provide pub-state/c priv-state/c game-state/c - (struct-out game-state) - (contract-out - [hash->pub-state - (-> hash? pub-state/c)] - [hash->priv-state - (-> hash? priv-state/c)] - [render-game-state - (-> priv-state/c image?)] - [make-game-state - (->i ([tiles (listof tile?)] [players (listof (is-a?/c playable<%>))]) - #:pre/name (tiles players) - "not enough tiles!" - (< (add1 (* (length players) - (*hand-size*))) - (length tiles)) - [result priv-state/c])] - [priv-state->pub-state - (-> priv-state/c pub-state/c)] - [remove-player - (-> priv-state/c priv-state/c)] - [turn-valid? - (-> game-state/c turn-action? boolean?)] - [do-turn/action - (-> game-state/c turn-action? game-state/c)] - [do-turn/score - (-> game-state/c turn-action? natural?)] - [do-turn/rotate - (-> priv-state/c priv-state/c)] - [do-turn-without-rotate - (-> priv-state/c turn-action? (values priv-state/c boolean?))] - [new-tiles - (-> priv-state/c (listof tile?))] - [players-left? - (-> game-state/c boolean?)] - [winners+losers - (-> priv-state/c (values (listof player-state?) - (listof player-state?)))])) + (struct-out game-state)) diff --git a/Q/Common/interfaces/playable.rkt b/Q/Common/interfaces/playable.rkt index 6abec71..a737b19 100644 --- a/Q/Common/interfaces/playable.rkt +++ b/Q/Common/interfaces/playable.rkt @@ -19,16 +19,16 @@ (interface () #; {Playable -> String} ;; Retrieve the name of the player - [name (->m string?)] + name #; {Playable Board Tile -> Void} ;; Set up the player's knowledge of the game - [setup (->m unprotected-board/c (listof tile?) void?)] + setup #; {Playable TurnInfo -> TurnAction} ;; Execute the player's strategy with the given turn information to produce an action. - [take-turn (->m pub-state/c turn-action?)] + take-turn #; {[Listof Tile] -> Void} ;; Give tiles to the player - [new-tiles (->m (listof tile?) void?)] + new-tiles #; {Boolean -> Void} ;; Send information on whether the player won - [win (->m boolean? void?)])) + win)) diff --git a/Q/Common/map.rkt b/Q/Common/map.rkt index 0494046..65e7445 100644 --- a/Q/Common/map.rkt +++ b/Q/Common/map.rkt @@ -17,66 +17,68 @@ (require Q/Common/turn-action) (require Q/Lib/function) (require Q/Lib/list) +(require Q/Lib/contracts) (require Q/Common/interfaces/serializable) +(provide/cond-contract + [make-board (-> tile? unprotected-board/c)] + [has-adjacent-tiles? (-> unprotected-board/c posn? boolean?)] + [tile-at (-> unprotected-board/c posn? (or/c tile? #f))] + [valid-placement? + (-> unprotected-board/c + placement? + boolean?)] + [valid-placements? + (-> unprotected-board/c + (listof placement?) + boolean?)] + [add-tiles + (->i ([b unprotected-board/c] [pments (listof placement?)]) + #:pre/name (b pments) + "posns aren't empty" + (andmap (negate (curry tile-at b)) + pments) + [result unprotected-board/c])] + [add-tile + (->i ([b unprotected-board/c] [pment placement?]) + #:pre/name (b pment) + "given posn isn't empty" + ((negate tile-at) b (placement-posn pment)) + #:pre/name (b pment) + "given posn has no adjacent tiles" + (has-adjacent-tiles? b (placement-posn pment)) + [result unprotected-board/c])] + [adjacent-tiles + (-> unprotected-board/c + posn? + (listof tile?))] + [valid-tile-placements + (-> tile? + unprotected-board/c + (listof posn?))] + [collect-sequence + (-> unprotected-board/c + posn? + axis? + sequence?)] + [open-posns + (-> unprotected-board/c + (listof posn?))] + [q-sequence? + (-> (listof placement?) boolean?)] + [get-sequences + (-> unprotected-board/c (listof placement?) (listof (listof placement?)))] + [hash->board++ + (-> (listof (cons/c integer? (listof (cons/c integer? any/c)))) + unprotected-board/c)] + [render-board + (-> unprotected-board/c image?)]) + (provide sequence? bounds unprotected-board/c - protected-board/c - (contract-out - [make-board (-> tile? unprotected-board/c)] - [has-adjacent-tiles? (-> unprotected-board/c posn? boolean?)] - [tile-at (-> unprotected-board/c posn? (or/c tile? #f))] - [valid-placement? - (-> unprotected-board/c - placement? - boolean?)] - [valid-placements? - (-> unprotected-board/c - (listof placement?) - boolean?)] - [add-tiles - (->i ([b unprotected-board/c] [pments (listof placement?)]) - #:pre/name (b pments) - "posns aren't empty" - (andmap (negate (curry tile-at b)) - pments) - [result unprotected-board/c])] - [add-tile - (->i ([b unprotected-board/c] [pment placement?]) - #:pre/name (b pment) - "given posn isn't empty" - ((negate tile-at) b (placement-posn pment)) - #:pre/name (b pment) - "given posn has no adjacent tiles" - (has-adjacent-tiles? b (placement-posn pment)) - [result unprotected-board/c])] - [adjacent-tiles - (-> unprotected-board/c - posn? - (listof tile?))] - [valid-tile-placements - (-> tile? - unprotected-board/c - (listof posn?))] - [collect-sequence - (-> unprotected-board/c - posn? - axis? - sequence?)] - [open-posns - (-> unprotected-board/c - (listof posn?))] - [q-sequence? - (-> (listof placement?) boolean?)] - [get-sequences - (-> unprotected-board/c (listof placement?) (listof (listof placement?)))] - [hash->board++ - (-> (listof (cons/c integer? (listof (cons/c integer? any/c)))) - unprotected-board/c)] - [render-board - (-> unprotected-board/c image?)])) + protected-board/c) ;; {type Sequence = [Listof TilePlacement]} diff --git a/Q/Common/player-state.rkt b/Q/Common/player-state.rkt index 16fabd3..c7a86c6 100644 --- a/Q/Common/player-state.rkt +++ b/Q/Common/player-state.rkt @@ -10,38 +10,40 @@ (require Q/Common/tile) (require Q/Lib/list) (require Q/Lib/test) +(require Q/Lib/contracts) (require Q/Common/interfaces/serializable) (require Q/Common/interfaces/playable) +(provide/cond-contract + [make-player-state + (-> (listof tile?) + any/c + player-state?)] + [add-to-hand + (-> player-state? (listof tile?) + player-state?)] + [remove-from-hand + (->i ([ps player-state?] + [tls (listof tile?)]) + #:pre/name (ps tls) + "hand must contain given tiles!" + (contains-all? (player-state-hand ps) tls) + [result player-state?])] + [clear-hand + (-> player-state? player-state?)] + [add-points + (-> player-state? + natural? + player-state?)] + [render-player-state + (-> player-state? + image?)]) + (provide player-state++ set-player-state-payload hash->player-state++ - (struct-out player-state) - (contract-out - [make-player-state - (-> (listof tile?) - any/c - player-state?)] - [add-to-hand - (-> player-state? (listof tile?) - player-state?)] - [remove-from-hand - (->i ([ps player-state?] - [tls (listof tile?)]) - #:pre/name (ps tls) - "hand must contain given tiles!" - (contains-all? (player-state-hand ps) tls) - [result player-state?])] - [clear-hand - (-> player-state? player-state?)] - [add-points - (-> player-state? - natural? - player-state?)] - [render-player-state - (-> player-state? - image?)])) + (struct-out player-state)) ;; ======================================================================================== diff --git a/Q/Common/posn.rkt b/Q/Common/posn.rkt index f8ef4c0..7212701 100644 --- a/Q/Common/posn.rkt +++ b/Q/Common/posn.rkt @@ -6,6 +6,7 @@ (require Q/Lib/list) (require Q/Lib/struct) +(require Q/Lib/contracts) (require Q/Common/interfaces/serializable) (provide @@ -20,35 +21,35 @@ horizontal-axis direction-names direction-name? - axis? - (contract-out - #:unprotected-submodule no-contract - [posn-translate - (-> posn? direction-name? posn?)] - [neighbors? - (-> posn? posn? boolean?)] - [posn-neighbors/dirs - (->i ([p posn?] [dirs (listof direction-name?)]) - [result (p) (listof (flat-contract (curry neighbors? p)))])] - [posns-same-row? - (-> (listof posn?) boolean?)] - [posns-same-column? - (-> (listof posn?) boolean?)] - [same-axis? - (-> (listof posn?) boolean?)] - [axis-of - (->i ([pns (listof posn?)]) - #:pre/name (pns) - "must be more than one posn in the list" - (>= (length pns) 2) - #:pre/name (pns) - "posns must be aligned on an axis" - (same-axis? pns) - [result axis?])] - [posn posn? posn? boolean?)] - [sort-posns - (-> (listof posn?) (listof posn?))])) + axis?) + +(provide/cond-contract + [posn-translate + (-> posn? direction-name? posn?)] + [neighbors? + (-> posn? posn? boolean?)] + [posn-neighbors/dirs + (->i ([p posn?] [dirs (listof direction-name?)]) + [result (p) (listof (flat-contract (curry neighbors? p)))])] + [posns-same-row? + (-> (listof posn?) boolean?)] + [posns-same-column? + (-> (listof posn?) boolean?)] + [same-axis? + (-> (listof posn?) boolean?)] + [axis-of + (->i ([pns (listof posn?)]) + #:pre/name (pns) + "must be more than one posn in the list" + (>= (length pns) 2) + #:pre/name (pns) + "posns must be aligned on an axis" + (same-axis? pns) + [result axis?])] + [posn posn? posn? boolean?)] + [sort-posns + (-> (listof posn?) (listof posn?))]) #; {type Posn = (posn Integer Integer)} ;; A Posn is a (posn r c), which represent a row and column. diff --git a/Q/Common/tile.rkt b/Q/Common/tile.rkt index 9e9f38c..7dbe41b 100644 --- a/Q/Common/tile.rkt +++ b/Q/Common/tile.rkt @@ -7,6 +7,7 @@ (require Q/Common/config) (require Q/Lib/list) (require Q/Lib/struct) +(require Q/Lib/contracts) (require Q/Common/interfaces/serializable) (provide @@ -20,17 +21,17 @@ hash->tile++ empty-tile-image start-tiles - tile-set - (contract-out - #:unprotected-submodule no-contract - [tile-shapes (listof symbol?)] - [tile-colors (listof symbol?)] - [tile-shape? (-> any/c boolean?)] - [tile-color? (-> any/c boolean?)] - [tile< (-> tile? tile? boolean?)] - [sort-tiles (-> (listof tile?) (listof tile?))] - [render-tile (-> tile? image?)] - [render-tiles (-> (listof tile?) image?)])) + tile-set) + +(provide/cond-contract + [tile-shapes (listof symbol?)] + [tile-colors (listof symbol?)] + [tile-shape? (-> any/c boolean?)] + [tile-color? (-> any/c boolean?)] + [tile< (-> tile? tile? boolean?)] + [sort-tiles (-> (listof tile?) (listof tile?))] + [render-tile (-> tile? image?)] + [render-tiles (-> (listof tile?) image?)]) ;; ======================================================================================== ;; DATA DEFINITIONS diff --git a/Q/Lib/contracts.rkt b/Q/Lib/contracts.rkt new file mode 100644 index 0000000..9e5b981 --- /dev/null +++ b/Q/Lib/contracts.rkt @@ -0,0 +1,45 @@ +#lang racket/base +;; --------------------------------------------------------------------------------------------------- +(require (for-syntax racket/base racket/string) + racket/contract + racket/require-syntax racket/provide-syntax + racket/match + racket/list + syntax/parse/define + racket/struct-info) + +(provide provide/cond-contract + compiled-with-contracts? + (all-from-out racket/contract)) + +;; --------------------------------------------------------------------------------------------------- +;; +;; Enables contracts optionally, depending on the value of ENABLE_CONTRACTS. +;; +;; This work was based on the typed-racket implementation of optional contracts: +;; https://github.com/racket/typed-racket/blob/master/typed-racket-lib/typed-racket/utils/utils.rkt +(define-for-syntax enable-contracts? + (and (getenv "ENABLE_CONTRACTS") #true)) + +(begin-for-syntax + (define-syntax-class clause + #:attributes (i) + (pattern [(~datum struct) (~or nm:id (nm:id super:id)) (flds ...)] + #:with i #'(struct-out nm)) + (pattern [(~datum rename) out:id in:id cnt:expr] + #:with i #'(rename-out [out in])) + (pattern [i:id cnt:expr]))) + +(define-syntax provide/cond-contract + (if enable-contracts? + (lambda (stx) + (syntax-parse stx + [(_ c:clause ...) + #'(provide (contract-out c ...))])) + (lambda (stx) + (syntax-parse stx + [(_ c:clause ...) + #'(provide c.i ...)])))) + +(define-syntax (compiled-with-contracts? stx) + (datum->syntax stx enable-contracts?)) diff --git a/Q/Lib/image.rkt b/Q/Lib/image.rkt index 56d74df..69eae27 100644 --- a/Q/Lib/image.rkt +++ b/Q/Lib/image.rkt @@ -3,13 +3,13 @@ (require 2htdp/image) (require Q/Common/config) +(require Q/Lib/contracts) -(provide - (contract-out - [empty-space - (-> (and/c real? (not/c negative?)) - (and/c real? (not/c negative?)) - image?)])) +(provide/cond-contract + [empty-space + (-> (and/c real? (not/c negative?)) + (and/c real? (not/c negative?)) + image?)]) (define (empty-space width height) (rectangle width height 'solid (*background-color*))) diff --git a/Q/Lib/list.rkt b/Q/Lib/list.rkt index f7645ad..acf1223 100644 --- a/Q/Lib/list.rkt +++ b/Q/Lib/list.rkt @@ -2,22 +2,23 @@ (require Q/Lib/hash) (require Q/Lib/function) +(require Q/Lib/contracts) (provide find-remf - cons-if - (contract-out - #:unprotected-submodule no-contract - [member? (any/c (or/c list? any/c) . -> . boolean?)] - [all-same? (list? . -> . boolean?)] - [rotate-left (natural? list? . -> . list?)] - [rotate-left-1 (list? . -> . list?)] - [remove-from (list? list? . -> . list?)] - [contains-all? (list? list? . -> . boolean?)] - [same-elements? (list? list? . -> . boolean?)] - [segment (natural? list? . -> . list?)] - [index . boolean?)] - [sort-by ((listof (cons/c (any/c any/c . -> . any/c) (any/c . -> . any/c))) . -> . ((listof any/c) . -> . (listof any/c)))])) + cons-if) + +(provide/cond-contract + [member? (any/c (or/c list? any/c) . -> . boolean?)] + [all-same? (list? . -> . boolean?)] + [rotate-left (natural? list? . -> . list?)] + [rotate-left-1 (list? . -> . list?)] + [remove-from (list? list? . -> . list?)] + [contains-all? (list? list? . -> . boolean?)] + [same-elements? (list? list? . -> . boolean?)] + [segment (natural? list? . -> . list?)] + [index . boolean?)] + [sort-by ((listof (cons/c (any/c any/c . -> . any/c) (any/c . -> . any/c))) . -> . ((listof any/c) . -> . (listof any/c)))]) #; {(X) X [Listof X] -> Boolean} ;; Is the given element `v` a member of the given list `lst`? diff --git a/Q/Lib/result.rkt b/Q/Lib/result.rkt index 7118817..ef0231c 100644 --- a/Q/Lib/result.rkt +++ b/Q/Lib/result.rkt @@ -1,17 +1,20 @@ #lang racket +(require Q/Lib/contracts) + (provide (struct-out success) - (struct-out failure) - (contract-out - [unwrap-or - (-> result? - any/c - any)] - [unwrap-or-else - (-> result? - procedure? - any)])) + (struct-out failure)) + +(provide/cond-contract + [unwrap-or + (-> result? + any/c + any)] + [unwrap-or-else + (-> result? + procedure? + any)]) #; {type [Result X Y] (U [Success X] [Failure Y])} diff --git a/Q/Player/strategy.rkt b/Q/Player/strategy.rkt index 7d01258..88ebf89 100644 --- a/Q/Player/strategy.rkt +++ b/Q/Player/strategy.rkt @@ -11,25 +11,27 @@ (require Q/Common/config) (require Q/Common/turn-action) (require Q/Lib/list) +(require Q/Lib/contracts) (provide - player-strategy<%> - (contract-out - [choose-tile - (-> (listof tile?) - unprotected-board/c - (or/c (cons/c tile? (listof posn?)) - #f))] - [choose-placement - (-> tile? - (listof posn?) - procedure? - turn-action?)] - [combine-actions - (-> turn-action? - turn-action? - turn-action?)])) + player-strategy<%>) + +(provide/cond-contract + [choose-tile + (-> (listof tile?) + unprotected-board/c + (or/c (cons/c tile? (listof posn?)) + #f))] + [choose-placement + (-> tile? + (listof posn?) + procedure? + turn-action?)] + [combine-actions + (-> turn-action? + turn-action? + turn-action?)]) ;; A PlayerStrategy is an interface that represents the functionality that any player strategy will @@ -39,7 +41,7 @@ #; {PlayerStrategy PublicState -> TurnAction} ;; Given some turn information for the player, produce an action to influence the game ;; state. - [choose-action (->m pub-state/c turn-action?)])) + choose-action)) #; {[Listof Tile] Board -> [Maybe [Pairof Tile [Listof TilePlacement]]]} From aad9a048959f415d2ea9ce98bcf221783293782b Mon Sep 17 00:00:00 2001 From: Andrey Piterkin Date: Thu, 9 Nov 2023 21:32:12 -0500 Subject: [PATCH 2/8] feat: struct++ getting removed --- Q/Common/game-state.rkt | 10 +++++----- Q/Common/map.rkt | 15 +++++++------- Q/Common/player-state.rkt | 9 ++++----- Q/Common/posn.rkt | 19 +++++++++--------- Q/Common/tile.rkt | 22 ++++++++++----------- Q/Common/turn-action.rkt | 41 +++++++++++++++++++++------------------ Q/Referee/referee.rkt | 1 - Q/Test/integration.rkt | 4 +++- 8 files changed, 60 insertions(+), 61 deletions(-) diff --git a/Q/Common/game-state.rkt b/Q/Common/game-state.rkt index 3cc2b19..a403b2f 100644 --- a/Q/Common/game-state.rkt +++ b/Q/Common/game-state.rkt @@ -419,8 +419,8 @@ (define jplayer (first players)) (define scores* (rest players)) - (define state (hash->player-state++ jplayer)) - (define board (hash->board++ jmap)) + (define state (hash->player-state jplayer)) + (define board (hash->board jmap)) (game-state board tile* (cons state scores*))) ;; ---------------------------------------------------------------------------------------- @@ -431,9 +431,9 @@ (define tile* (hash-ref jpub 'tile*)) (define jplayers (hash-ref jpub 'players)) - (define board (hash->board++ jmap)) - (define tiles (map hash->tile++ tile*)) - (define players (map hash->player-state++ jplayers)) + (define board (hash->board jmap)) + (define tiles (map hash->tile tile*)) + (define players (map hash->player-state jplayers)) (game-state board tiles players)) diff --git a/Q/Common/map.rkt b/Q/Common/map.rkt index 65e7445..513f8d3 100644 --- a/Q/Common/map.rkt +++ b/Q/Common/map.rkt @@ -68,7 +68,7 @@ (-> (listof placement?) boolean?)] [get-sequences (-> unprotected-board/c (listof placement?) (listof (listof placement?)))] - [hash->board++ + [hash->board (-> (listof (cons/c integer? (listof (cons/c integer? any/c)))) unprotected-board/c)] [render-board @@ -125,8 +125,7 @@ ;; INVARIANT 2: A position on the board is occupied by a tile IFF the position is a key in the hash ;; map. ;; INVARIANT 3: There must be at least one tile on the board. -(struct++ board - ([map (hash/c posn? tile?)]) +(struct board (map) #:transparent #:methods gen:serializable [(define/generic ->jsexpr* ->jsexpr) @@ -187,13 +186,13 @@ #; {JMap -> Board} -(define (hash->board++ rows) +(define (hash->board rows) (define h (make-hash)) (for* ([row rows] [cell (rest row)]) (define r (first row)) (match-define [list c jtile] cell) (define p (posn r c)) - (define t (hash->tile++ jtile)) + (define t (hash->tile jtile)) (hash-set! h p t)) (board (make-immutable-hash (hash->list h)))) @@ -204,7 +203,7 @@ ;; tile of a game, which is the only referee-placed tile. (define (make-board root-tile) (define root-posn (posn 0 0)) - (board++ #:map (hash root-posn root-tile))) + (board (hash root-posn root-tile))) #; {Board [Listof TilePlacement] -> Board} @@ -420,12 +419,12 @@ (test-equal? "create a board with the referees tile being a red square" (make-board (tile 'red 'square)) - (board++ #:map (hash (posn 0 0) (tile 'red 'square)))) + (board (hash (posn 0 0) (tile 'red 'square)))) (test-equal? "create a board with the referees tile being a blue circle" (make-board (tile 'blue 'circle)) - (board++ #:map (hash (posn 0 0) (tile 'blue 'circle)))) + (board (hash (posn 0 0) (tile 'blue 'circle)))) (test-equal? "board tile at (0, 0) with existing tile" diff --git a/Q/Common/player-state.rkt b/Q/Common/player-state.rkt index c7a86c6..c568db3 100644 --- a/Q/Common/player-state.rkt +++ b/Q/Common/player-state.rkt @@ -42,7 +42,7 @@ (provide player-state++ set-player-state-payload - hash->player-state++ + hash->player-state (struct-out player-state)) @@ -94,11 +94,10 @@ #; {JPlayer -> PlayerState} -(define (hash->player-state++ jp) +(define (hash->player-state jp) (define score (hash-ref jp 'score)) - (define hand (map hash->tile++ (hash-ref jp 'tile*))) - (player-state++ #:score score - #:hand hand)) + (define hand (map hash->tile (hash-ref jp 'tile*))) + (player-state score hand #f #f)) #; {PlayerState [Listof Tile] -> PlayerState} diff --git a/Q/Common/posn.rkt b/Q/Common/posn.rkt index 7212701..785ec5d 100644 --- a/Q/Common/posn.rkt +++ b/Q/Common/posn.rkt @@ -10,9 +10,8 @@ (require Q/Common/interfaces/serializable) (provide - posn - posn++ posn? + hash->posn posn-row posn-column directions @@ -24,6 +23,7 @@ axis?) (provide/cond-contract + [posn (-> integer? integer? posn?)] [posn-translate (-> posn? direction-name? posn?)] [neighbors? @@ -53,20 +53,19 @@ #; {type Posn = (posn Integer Integer)} ;; A Posn is a (posn r c), which represent a row and column. -(struct++ posn - ([row integer?] - [column integer?]) - (#:convert-from - (hash - [hash? - (hash-table ('row row) ('column column)) - (row column)])) +(struct posn (row column) #:transparent #:methods gen:serializable [(define (->jsexpr p) (match-define [posn row column] p) (hash 'row row 'column column))]) +#; {JCoord -> Posn} +(define (hash->posn jcoord) + (define row (hash-ref jcoord 'row)) + (define col (hash-ref jcoord 'column)) + (posn row col)) + #; {Posn Posn -> Boolean} ;; Is the first posn smaller than the second in row-column order? diff --git a/Q/Common/tile.rkt b/Q/Common/tile.rkt index 7dbe41b..eb4ae74 100644 --- a/Q/Common/tile.rkt +++ b/Q/Common/tile.rkt @@ -8,22 +8,22 @@ (require Q/Lib/list) (require Q/Lib/struct) (require Q/Lib/contracts) + (require Q/Common/interfaces/serializable) (provide - tile tile? - tile++ tile-shape tile-color tiles-equal-color? tiles-equal-shape? - hash->tile++ + hash->tile empty-tile-image start-tiles tile-set) (provide/cond-contract + [tile (-> tile-color? tile-shape? tile?)] [tile-shapes (listof symbol?)] [tile-colors (listof symbol?)] [tile-shape? (-> any/c boolean?)] @@ -87,15 +87,7 @@ #; {type Tile = (tile TileShape TileColor)} ;; A Tile is a distinguishable object by shapes and colors, placed and held by players in the Q ;; board game. -(struct++ tile - ([color tile-color?] - [shape tile-shape?]) - (#:convert-from - (hash - [hash? - (hash-table ('color (app string->symbol color)) - ('shape (app string->symbol shape))) - (color shape)])) +(struct tile (color shape) #:transparent #:methods gen:serializable [(define (->jsexpr t) @@ -103,6 +95,12 @@ (hash 'color (symbol->string color) 'shape (symbol->string shape)))]) +#; {JTile -> Tile} +(define (hash->tile h) + (define color (hash-ref h 'color)) + (define shape (hash-ref h 'shape)) + (tile color shape)) + ;; ======================================================================================== ;; CORE FUNCTIONALITY diff --git a/Q/Common/turn-action.rkt b/Q/Common/turn-action.rkt index 99d3a35..bd2a2dc 100644 --- a/Q/Common/turn-action.rkt +++ b/Q/Common/turn-action.rkt @@ -7,34 +7,37 @@ (require Q/Common/posn) (require Q/Common/tile) (require Q/Common/interfaces/serializable) +(require Q/Lib/contracts) (provide (struct-out place) (struct-out exchange) (struct-out pass) turn-action? - hash->placement++ + hash->placement (struct-out placement)) +(provide/cond-contract + [placement (-> posn? tile? placement?)] + [place (-> (listof placement?) place?)]) + #; {type TilePlacement = (placement Posn Tile)} ;; A TilePlacement represents a request from the player to place the given tile at the given ;; position. -(struct++ placement - ([posn posn?] - [tile tile?]) - #:transparent - #:methods gen:serializable - [(define/generic ->jsexpr* ->jsexpr) - (define (->jsexpr pment) - (match-define [placement posn tile] pment) - (hash 'coordinate (->jsexpr* posn) - '1tile (->jsexpr* tile)))]) - - -(define (hash->placement++ h) - (define p (hash->struct++ posn++ (hash-ref h 'coordinate))) - (define t (hash->tile++ (hash-ref h '1tile))) +(struct placement (posn tile) + #:transparent + #:methods gen:serializable + [(define/generic ->jsexpr* ->jsexpr) + (define (->jsexpr pment) + (match-define [placement posn tile] pment) + (hash 'coordinate (->jsexpr* posn) + '1tile (->jsexpr* tile)))]) + + +(define (hash->placement h) + (define p (hash->posn (hash-ref h 'coordinate))) + (define t (hash->tile (hash-ref h '1tile))) (placement p t)) @@ -45,9 +48,9 @@ ;; - A placement of tiles onto the board at the corresponding locations in the given order ;; - An exchange of all tiles in a player's hand ;; - Skipping a player's turn (withdrawing from performing any actions) -(struct++ place ([placements (listof placement?)]) #:transparent) -(struct exchange () #:transparent) -(struct pass () #:transparent) +(struct place (placements) #:transparent) +(struct exchange () #:transparent) +(struct pass () #:transparent) #; {Any -> Boolean} diff --git a/Q/Referee/referee.rkt b/Q/Referee/referee.rkt index bee3731..a3a18c4 100644 --- a/Q/Referee/referee.rkt +++ b/Q/Referee/referee.rkt @@ -191,7 +191,6 @@ (stop-turn (cons (kick-player g-info name k) #f))) (define action (success-val turn-result)) - (println action) (define placed? (place? action)) (unless (turn-valid? priv-state action) diff --git a/Q/Test/integration.rkt b/Q/Test/integration.rkt index db99a28..8302657 100644 --- a/Q/Test/integration.rkt +++ b/Q/Test/integration.rkt @@ -34,15 +34,17 @@ (define expected-port (open-input-file output-file)) (define expected (read-json expected-port)) (close-input-port expected-port) - + (define command (racket-path)) (define script-file (path->string script)) (define-values (s result-port op err-port) (subprocess #f in-port #f command script-file)) (subprocess-wait s) + (close-input-port in-port) + (define result (let/ec return (unless (zero? (subprocess-status s)) From 20dd66f6ccc0f2eec9d73abe2720cffed9819a4a Mon Sep 17 00:00:00 2001 From: Andrey Piterkin Date: Thu, 9 Nov 2023 21:50:18 -0500 Subject: [PATCH 3/8] removed s++ --- Q/Common/player-state.rkt | 52 +++++++++++++++++++++++++-------------- Q/Common/posn.rkt | 2 +- Q/Common/turn-action.rkt | 5 +--- Q/Referee/referee.rkt | 6 ++--- 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/Q/Common/player-state.rkt b/Q/Common/player-state.rkt index 1f7f74f..026843f 100644 --- a/Q/Common/player-state.rkt +++ b/Q/Common/player-state.rkt @@ -40,7 +40,7 @@ image?)]) (provide - player-state++ + player-state set-player-state-payload hash->player-state (struct-out player-state)) @@ -56,18 +56,33 @@ ;; the points the player accrued during the game, along with the tiles in their hand during a move, ;; and a payload of type `Any`. ;; INVARIANT: The hand of a player state has a length L such that 0 ≤ L ≤ (*hand-size*). -(struct++ player-state - ([(score 0) natural?] - [hand (listof tile?)] - [(name #f) (or/c symbol? #f)] - [(payload #f) any/c]) - #:transparent - #:methods gen:serializable - [(define/generic ->jsexpr* ->jsexpr) - (define (->jsexpr ps) - (match-define [player-state score hand _name _payload] ps) - (hash 'score score - 'tile* (map ->jsexpr* hand)))]) +(struct player-state (score hand name payload) + #:transparent + #:methods gen:serializable + [(define/generic ->jsexpr* ->jsexpr) + (define (->jsexpr ps) + (match-define [player-state score hand _name _payload] ps) + (hash 'score score + 'tile* (map ->jsexpr* hand)))]) + +#; {PlayerState [Listof Tile] -> PlayerState} +;; Creates a copy of the given player state with the given hand as +;; that player state's new hand. +(define (set-player-state-hand ps new-hand) + (match-define [player-state score hand name payload] ps) + (player-state score new-hand name payload)) + +#; {PlayerState Natural -> PlayerState} +;; Creates a copy of the given player state with the new given score. +(define (set-player-state-score ps new-score) + (match-define [player-state score hand name payload] ps) + (player-state new-score hand name payload)) + +#; {PlayerState Any -> PlayerState} +;; Creates a copy of the given player state with the new given payload +(define (set-player-state-payload ps new-payload) + (match-define [player-state score hand name payload] ps) + (player-state score hand name new-payload)) ;; ======================================================================================== @@ -79,7 +94,7 @@ ;; Creates a player with the given hand, a default score of 0, ;; and the given optional payload (default of #f). (define (make-player-state hand [payload #f]) - (player-state++ #:hand hand #:payload payload)) + (player-state 0 hand #f payload)) #; {([Listof Tile] -> [Listof Tile]) PlayerState -> PlayerState} @@ -96,14 +111,15 @@ #; {JPlayer -> PlayerState} (define (hash->player-state jp) (define score (hash-ref jp 'score)) - (define hand (map hash->tile++ (hash-ref jp 'tile*))) + (define hand (map hash->tile (hash-ref jp 'tile*))) (define name (if (hash-has-key? jp 'name) (string->symbol (hash-ref jp 'name)) #f)) - (player-state++ #:score score - #:hand hand - #:name name)) + (player-state score + hand + name + #f)) #; {PlayerState [Listof Tile] -> PlayerState} diff --git a/Q/Common/posn.rkt b/Q/Common/posn.rkt index 785ec5d..4d6492b 100644 --- a/Q/Common/posn.rkt +++ b/Q/Common/posn.rkt @@ -11,6 +11,7 @@ (provide posn? + posn hash->posn posn-row posn-column @@ -23,7 +24,6 @@ axis?) (provide/cond-contract - [posn (-> integer? integer? posn?)] [posn-translate (-> posn? direction-name? posn?)] [neighbors? diff --git a/Q/Common/turn-action.rkt b/Q/Common/turn-action.rkt index bd2a2dc..8db401d 100644 --- a/Q/Common/turn-action.rkt +++ b/Q/Common/turn-action.rkt @@ -11,16 +11,13 @@ (provide (struct-out place) + place-placements (struct-out exchange) (struct-out pass) turn-action? hash->placement (struct-out placement)) -(provide/cond-contract - [placement (-> posn? tile? placement?)] - [place (-> (listof placement?) place?)]) - #; {type TilePlacement = (placement Posn Tile)} ;; A TilePlacement represents a request from the player to place the given tile at the given diff --git a/Q/Referee/referee.rkt b/Q/Referee/referee.rkt index a3a18c4..749ded5 100644 --- a/Q/Referee/referee.rkt +++ b/Q/Referee/referee.rkt @@ -37,10 +37,8 @@ ;; progression of a game. It contains the current state, as well as ;; the list of players that broke the rules, in the increasing ;; time-order of elimination. -(struct/contract game-info - ([state priv-state/c] - [sinners (listof string?)]) - #:transparent) +(struct game-info (state sinners) + #:transparent) #; {GameInfo PrivateState -> GameInfo} ;; Creates a copy of the given game info with the given new private state. From db56f08a9ae24d8306df6bac8ecee726c7ace45a Mon Sep 17 00:00:00 2001 From: Andrey Piterkin Date: Thu, 9 Nov 2023 21:59:07 -0500 Subject: [PATCH 4/8] integration test --- Q/Test/integration.rkt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Q/Test/integration.rkt b/Q/Test/integration.rkt index 8302657..d48ec51 100644 --- a/Q/Test/integration.rkt +++ b/Q/Test/integration.rkt @@ -4,7 +4,7 @@ (require threading) (require racket/place/distributed) -(define dirs '("3" "4" "5" "6" "7")) +(define dirs '("7")) (define root-directory (build-path (current-directory) 'up 'up)) @@ -35,11 +35,11 @@ (define expected (read-json expected-port)) (close-input-port expected-port) - (define command (racket-path)) + #;(define command (racket-path)) (define script-file (path->string script)) (define-values (s result-port op err-port) - (subprocess #f in-port #f command script-file)) + (subprocess #f in-port #f script script-file)) (subprocess-wait s) (close-input-port in-port) @@ -101,9 +101,10 @@ (define script (for/first ([file-path (directory-list test-dir)] - #:when (path-has-extension? file-path ".rkt")) + #:when (string-suffix? (path->string file-path) "xgames")) (simplify-path (build-path test-dir file-path)))) + (println script) (define group-test-dir (simplify-path (build-path test-dir "Tests"))) (define inputs1 (filter-input-files group-test-dir)) From 37c9a1879577ac56158c0547f204ab81b82ffd8e Mon Sep 17 00:00:00 2001 From: Andrey Piterkin Date: Fri, 10 Nov 2023 14:07:45 -0500 Subject: [PATCH 5/8] contract no bugs --- Q/Common/player-state.rkt | 2 +- Q/Common/tile.rkt | 4 ++-- Q/Lib/contracts.rkt | 2 +- Q/Referee/referee.rkt | 1 - 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Q/Common/player-state.rkt b/Q/Common/player-state.rkt index 026843f..a7ec84a 100644 --- a/Q/Common/player-state.rkt +++ b/Q/Common/player-state.rkt @@ -115,7 +115,7 @@ (define name (if (hash-has-key? jp 'name) (string->symbol (hash-ref jp 'name)) - #f)) + "foo")) (player-state score hand name diff --git a/Q/Common/tile.rkt b/Q/Common/tile.rkt index eb4ae74..521bacf 100644 --- a/Q/Common/tile.rkt +++ b/Q/Common/tile.rkt @@ -97,8 +97,8 @@ #; {JTile -> Tile} (define (hash->tile h) - (define color (hash-ref h 'color)) - (define shape (hash-ref h 'shape)) + (define color (string->symbol (hash-ref h 'color))) + (define shape (string->symbol (hash-ref h 'shape))) (tile color shape)) diff --git a/Q/Lib/contracts.rkt b/Q/Lib/contracts.rkt index 9e5b981..db51a59 100644 --- a/Q/Lib/contracts.rkt +++ b/Q/Lib/contracts.rkt @@ -19,7 +19,7 @@ ;; This work was based on the typed-racket implementation of optional contracts: ;; https://github.com/racket/typed-racket/blob/master/typed-racket-lib/typed-racket/utils/utils.rkt (define-for-syntax enable-contracts? - (and (getenv "ENABLE_CONTRACTS") #true)) + (and (getenv "ENABLE_CONTRACTS") #false)) (begin-for-syntax (define-syntax-class clause diff --git a/Q/Referee/referee.rkt b/Q/Referee/referee.rkt index 749ded5..4856921 100644 --- a/Q/Referee/referee.rkt +++ b/Q/Referee/referee.rkt @@ -70,7 +70,6 @@ #:tiles [tiles start-tiles] #:game-state [gs* (make-game-state tiles playables)]) (define gs (bind-playables gs* playables)) - (define game-info0 (setup gs)) (send (*obman*) observe (game-info-state game-info0)) (define game-info1 (run-game game-info0)) From 10e1cdd291cefa1542fa4c8d4c9c71034aede8a1 Mon Sep 17 00:00:00 2001 From: Andrey Piterkin Date: Fri, 10 Nov 2023 19:03:51 -0500 Subject: [PATCH 6/8] feat: script changes --- 3/xmap.rkt | 40 ++++++++++++---------- 4/xlegal.rkt | 34 +++++++++++-------- 5/xscore.rkt | 27 +++++++++------ 6/xstrategy.rkt | 60 ++++++++++++++++++--------------- 7/xgames.rkt | 17 ++++++---- 8/xgames-with-observer.rkt | 6 +++- Q/Test/integration.rkt | 68 +++++++++++++++----------------------- 7 files changed, 135 insertions(+), 117 deletions(-) diff --git a/3/xmap.rkt b/3/xmap.rkt index 4e08abb..41409d8 100644 --- a/3/xmap.rkt +++ b/3/xmap.rkt @@ -8,26 +8,32 @@ (require Q/Common/tile) (require Q/Common/posn) -(define jboard (read-json (current-input-port))) -(define jtile (read-json (current-input-port))) +(provide main) -(define board (hash->board++ jboard)) -(define tile (hash->tile++ jtile)) -(define valid-placements (valid-tile-placements tile board)) +(define (main) + (define jboard (read-json (current-input-port))) + (define jtile (read-json (current-input-port))) -(define (sort^ lst extract-key) - (sort lst < #:key extract-key)) + (define board (hash->board jboard)) + (define tile (hash->tile jtile)) + (define valid-placements (valid-tile-placements tile board)) -(define sorted-placements - (~> valid-placements - (sort^ posn-column) - (sort^ posn-row))) + (define (sort^ lst extract-key) + (sort lst < #:key extract-key)) -(define (posn->hash p) - (struct->hash posn p)) + (define sorted-placements + (~> valid-placements + (sort^ posn-column) + (sort^ posn-row))) -(define out-json (map posn->hash sorted-placements)) + (define (posn->hash p) + (struct->hash posn p)) -(write-json out-json (current-output-port)) -(displayln "") -(flush-output) + (define out-json (map posn->hash sorted-placements)) + + (write-json out-json (current-output-port)) + (displayln "") + (flush-output)) + +(module+ main + (main)) diff --git a/4/xlegal.rkt b/4/xlegal.rkt index 7e69e4c..47c424e 100644 --- a/4/xlegal.rkt +++ b/4/xlegal.rkt @@ -7,22 +7,30 @@ (require Q/Common/game-state) (require Q/Common/interfaces/serializable) -(define jpub (read-json (current-input-port))) -(define jplacements (read-json (current-input-port))) +(provide main) -(define pub (hash->pub-state jpub)) -(define placements (map hash->placement++ jplacements)) +(define (main) + (define jpub (read-json (current-input-port))) + (define jplacements (read-json (current-input-port))) -(unless (turn-valid? pub (place placements)) - (write-json #f) + (define pub (hash->pub-state jpub)) + (define placements (map hash->placement jplacements)) + + (unless (turn-valid? pub (place placements)) + (write-json #f) + (displayln "") + (flush-output) + (exit)) + + (define b+ (game-state-board (do-turn/action pub (place placements)))) + + (define out-json (->jsexpr b+)) + + (write-json out-json (current-output-port)) (displayln "") - (flush-output) - (exit)) + (flush-output)) -(define b+ (game-state-board (do-turn/action pub (place placements)))) +(module+ main + (main)) -(define out-json (->jsexpr b+)) -(write-json out-json (current-output-port)) -(displayln "") -(flush-output) diff --git a/5/xscore.rkt b/5/xscore.rkt index 552de8f..8ab82a6 100644 --- a/5/xscore.rkt +++ b/5/xscore.rkt @@ -8,18 +8,23 @@ (require Q/Common/player-state) (require Q/Common/config) -(define jmap (read-json)) -(define jplacements (read-json)) +(provide main) -(define b (hash->board++ jmap)) +(define (main) (define jmap (read-json)) + (define jplacements (read-json)) -(define placements (map hash->placement++ jplacements)) + (define b (hash->board jmap)) -(define pub (game-state b 0 (list (make-player-state '())))) + (define placements (map hash->placement jplacements)) -(define score - (parameterize ([*bonus* 0]) - (do-turn/score pub (place placements)))) -(write-json score) -(displayln "") -(flush-output) + (define pub (game-state b 0 (list (make-player-state '())))) + + (define score + (parameterize ([*bonus* 0]) + (do-turn/score pub (place placements)))) + (write-json score) + (displayln "") + (flush-output)) + +(module+ main + (main)) diff --git a/6/xstrategy.rkt b/6/xstrategy.rkt index a93439d..8c96950 100644 --- a/6/xstrategy.rkt +++ b/6/xstrategy.rkt @@ -9,30 +9,36 @@ (require json) - -(define j1 (read-json)) -(define j2 (read-json)) - -(define jstrat (if (string? j1) - j1 - j2)) -(define jpub (if (string? j1) - j2 - j1)) - -(define pub-state (hash->pub-state jpub)) -(define strat - (match jstrat - ["dag" (new dag%)] - ["ldasg" (new ldasg%)])) - -(define action (send strat choose-action pub-state)) -(define serialized-action - (match action - [(place pments) (->jsexpr (first pments))] - [(exchange) "replace"] - [(pass) "pass"])) - -(write-json serialized-action) -(displayln "") -(flush-output) +(provide main) + + +(define (main) + (define j1 (read-json)) + (define j2 (read-json)) + + (define jstrat (if (string? j1) + j1 + j2)) + (define jpub (if (string? j1) + j2 + j1)) + + (define pub-state (hash->pub-state jpub)) + (define strat + (match jstrat + ["dag" (new dag%)] + ["ldasg" (new ldasg%)])) + + (define action (send strat choose-action pub-state)) + (define serialized-action + (match action + [(place pments) (->jsexpr (first pments))] + [(exchange) "replace"] + [(pass) "pass"])) + + (write-json serialized-action) + (displayln "") + (flush-output)) + +(module+ main + (main)) diff --git a/7/xgames.rkt b/7/xgames.rkt index 86eb4b0..3644caf 100644 --- a/7/xgames.rkt +++ b/7/xgames.rkt @@ -6,19 +6,24 @@ (require Q/Player/player) (require Q/Referee/referee) +(provide main) -(module+ main +(define (main) (define jstate (read-json)) (define jactors (read-json)) - + (define start-state (hash->priv-state jstate)) (define players (map hash->player++ jactors)) - + (define result (play-game players #:game-state start-state)) (define winners (first result)) (define sinners (second result)) - + (define sorted-winners (sort winners string<=?)) - + (write-json (list sorted-winners sinners)) - (displayln "")) ;; TODO: flush + (displayln "") + (void)) + +(module+ main + (main)) diff --git a/8/xgames-with-observer.rkt b/8/xgames-with-observer.rkt index 0a26ba2..c989c4c 100644 --- a/8/xgames-with-observer.rkt +++ b/8/xgames-with-observer.rkt @@ -9,8 +9,9 @@ (require Q/Referee/observer) (require Q/Lib/json) +(provide main) -(module+ main +(define (main) (define show (make-parameter #f)) (command-line #:once-each @@ -34,3 +35,6 @@ (define sorted-winners (sort winners string<=?)) (json-write+flush (list sorted-winners sinners))) + +(module+ main + (main)) diff --git a/Q/Test/integration.rkt b/Q/Test/integration.rkt index d48ec51..53f4a2c 100644 --- a/Q/Test/integration.rkt +++ b/Q/Test/integration.rkt @@ -2,9 +2,9 @@ (require json) (require threading) -(require racket/place/distributed) +(require racket/sandbox) -(define dirs '("7")) +(define dirs '("3" "4" "5" "6" "7")) (define root-directory (build-path (current-directory) 'up 'up)) @@ -31,48 +31,33 @@ (define (run-script-for-tests script input-file output-file) (define in-port (open-input-file input-file)) + (define out-port (open-output-string)) (define expected-port (open-input-file output-file)) (define expected (read-json expected-port)) (close-input-port expected-port) - #;(define command (racket-path)) - (define script-file (path->string script)) - - (define-values (s result-port op err-port) - (subprocess #f in-port #f script script-file)) - (subprocess-wait s) - - (close-input-port in-port) + (parameterize ([current-input-port in-port] + [current-output-port out-port]) + (with-handlers ([exn:fail? (lambda (e) (raise e))]) + ((dynamic-require (make-resolved-module-path script) 'main)))) - (define result - (let/ec return - (unless (zero? (subprocess-status s)) - (displayln "ERRORED") - (display "test: ") - (println input-file) - (displayln "error:") - (displayln (port->string err-port)) - (return #f)) - - (define result (read-json result-port)) - (unless (equal? expected result) - (displayln "DIFFERENT OUTPUT") - (display "test: ") - (println input-file) - (displayln "expected:") - (println expected) - (displayln "received:") - (println result) - (return #f)) - - #t)) - - (close-input-port result-port) - (when op (close-output-port op)) - (close-input-port err-port) - - result) + (close-input-port in-port) + (define output-string (get-output-string out-port)) + (define actual-output (read-json (open-input-string output-string))) + + (cond + [(equal? expected actual-output) + #t] + [else + (displayln "DIFFERENT OUTPUT") + (display "test: ") + (println input-file) + (displayln "expected:") + (println expected) + (displayln "received:") + (println actual-output) + #f])) (define (run-test-dir script inputs outputs) (for/fold ([passed 0] @@ -101,10 +86,9 @@ (define script (for/first ([file-path (directory-list test-dir)] - #:when (string-suffix? (path->string file-path) "xgames")) + #:when (string-suffix? (path->string file-path) ".rkt")) (simplify-path (build-path test-dir file-path)))) - (println script) (define group-test-dir (simplify-path (build-path test-dir "Tests"))) (define inputs1 (filter-input-files group-test-dir)) @@ -113,6 +97,7 @@ (define-values (passed+ failed+ total+) (run-test-dir script inputs1 outputs1)) + (set! passed* (+ passed* passed+)) (set! failed* (+ failed* failed+)) (set! total* (+ total* total+)) @@ -127,8 +112,7 @@ (cons "staff-tests" (~>> (build-path test-dir "grade") directory-list - (filter (compose string-numeric? path->string))) - )) + (filter (compose string-numeric? path->string))))) (for ([other-dir other-test-dirs]) (define other-test-dir (simplify-path (build-path test-dir "grade" other-dir))) From bbc83b9e4d23c9c03daa1fdadee1beab486e2194 Mon Sep 17 00:00:00 2001 From: Lucas Sta Maria Date: Fri, 10 Nov 2023 19:53:53 -0500 Subject: [PATCH 7/8] fix: remove premature `exit` script call, clean up integration script Signed-off-by: Lucas Sta Maria --- 4/xlegal.rkt | 29 +++++++++++++---------------- Q/Test/integration.rkt | 7 ++++--- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/4/xlegal.rkt b/4/xlegal.rkt index 47c424e..948c1a2 100644 --- a/4/xlegal.rkt +++ b/4/xlegal.rkt @@ -7,30 +7,27 @@ (require Q/Common/game-state) (require Q/Common/interfaces/serializable) +(require Q/Lib/json) + (provide main) (define (main) - (define jpub (read-json (current-input-port))) - (define jplacements (read-json (current-input-port))) + (let/ec return + (define jpub (read-json (current-input-port))) + (define jplacements (read-json (current-input-port))) - (define pub (hash->pub-state jpub)) - (define placements (map hash->placement jplacements)) + (define pub (hash->pub-state jpub)) + (define placements (map hash->placement jplacements)) - (unless (turn-valid? pub (place placements)) - (write-json #f) - (displayln "") - (flush-output) - (exit)) + (unless (turn-valid? pub (place placements)) + (json-write+flush #f) + (return)) - (define b+ (game-state-board (do-turn/action pub (place placements)))) + (define b+ (game-state-board (do-turn/action pub (place placements)))) - (define out-json (->jsexpr b+)) + (define out-json (->jsexpr b+)) - (write-json out-json (current-output-port)) - (displayln "") - (flush-output)) + (json-write+flush out-json))) (module+ main (main)) - - diff --git a/Q/Test/integration.rkt b/Q/Test/integration.rkt index 53f4a2c..31bfbba 100644 --- a/Q/Test/integration.rkt +++ b/Q/Test/integration.rkt @@ -4,7 +4,7 @@ (require threading) (require racket/sandbox) -(define dirs '("3" "4" "5" "6" "7")) +(define dirs '("3" "4" "5" "6" "7" "8")) (define root-directory (build-path (current-directory) 'up 'up)) @@ -35,7 +35,7 @@ (define expected-port (open-input-file output-file)) (define expected (read-json expected-port)) (close-input-port expected-port) - + (parameterize ([current-input-port in-port] [current-output-port out-port]) @@ -44,8 +44,9 @@ (close-input-port in-port) (define output-string (get-output-string out-port)) + (close-output-port out-port) (define actual-output (read-json (open-input-string output-string))) - + (cond [(equal? expected actual-output) #t] From 1abb41e7e03b568c92d0e8409bca400900877a0e Mon Sep 17 00:00:00 2001 From: Andrey Piterkin Date: Fri, 10 Nov 2023 20:36:10 -0500 Subject: [PATCH 8/8] test: integration tests for 8 --- 8/Tests/0-in.json | 123 ++++++++++++++++++++++++++++++++++ 8/Tests/0-out.json | 1 + 8/Tests/1-in.json | 123 ++++++++++++++++++++++++++++++++++ 8/Tests/1-out.json | 1 + 8/Tests/2-in.json | 164 +++++++++++++++++++++++++++++++++++++++++++++ 8/Tests/2-out.json | 2 + 8/Tests/3-in.json | 152 +++++++++++++++++++++++++++++++++++++++++ 8/Tests/3-out.json | 1 + 8/Tests/4-in.json | 148 ++++++++++++++++++++++++++++++++++++++++ 8/Tests/4-out.json | 1 + 8/Tests/5-in.json | 151 +++++++++++++++++++++++++++++++++++++++++ 8/Tests/5-out.json | 1 + 8/Tests/6-in.json | 151 +++++++++++++++++++++++++++++++++++++++++ 8/Tests/6-out.json | 1 + 8/Tests/7-in.json | 100 +++++++++++++++++++++++++++ 8/Tests/7-out.json | 1 + 8/Tests/8-in.json | 104 ++++++++++++++++++++++++++++ 8/Tests/8-out.json | 1 + 8/Tests/9-in.json | 131 ++++++++++++++++++++++++++++++++++++ 8/Tests/9-out.json | 1 + 20 files changed, 1358 insertions(+) create mode 100644 8/Tests/0-in.json create mode 100644 8/Tests/0-out.json create mode 100644 8/Tests/1-in.json create mode 100644 8/Tests/1-out.json create mode 100644 8/Tests/2-in.json create mode 100644 8/Tests/2-out.json create mode 100644 8/Tests/3-in.json create mode 100644 8/Tests/3-out.json create mode 100644 8/Tests/4-in.json create mode 100644 8/Tests/4-out.json create mode 100644 8/Tests/5-in.json create mode 100644 8/Tests/5-out.json create mode 100644 8/Tests/6-in.json create mode 100644 8/Tests/6-out.json create mode 100644 8/Tests/7-in.json create mode 100644 8/Tests/7-out.json create mode 100644 8/Tests/8-in.json create mode 100644 8/Tests/8-out.json create mode 100644 8/Tests/9-in.json create mode 100644 8/Tests/9-out.json diff --git a/8/Tests/0-in.json b/8/Tests/0-in.json new file mode 100644 index 0000000..1d00744 --- /dev/null +++ b/8/Tests/0-in.json @@ -0,0 +1,123 @@ +{ + "map": [ + [ + 0, + [ + 0, + { + "color": "red", + "shape": "square" + } + ] + ] + ], + "players": [ + { + "name": "andrey", + "score": 0, + "tile*": [ + { + "color": "orange", + "shape": "star" + }, + { + "color": "blue", + "shape": "circle" + }, + { + "color": "green", + "shape": "8star" + }, + { + "color": "yellow", + "shape": "clover" + }, + { + "color": "purple", + "shape": "diamond" + }, + { + "color": "blue", + "shape": "square" + } + ] + }, + { + "name": "lucas", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "star" + }, + { + "color": "blue", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "clover" + }, + { + "color": "red", + "shape": "diamond" + }, + { + "color": "blue", + "shape": "circle" + } + ] + }, + { + "name": "matthias", + "score": 0, + "tile*": [ + { + "color": "orange", + "shape": "clover" + }, + { + "color": "blue", + "shape": "clover" + }, + { + "color": "green", + "shape": "diamond" + }, + { + "color": "yellow", + "shape": "star" + }, + { + "color": "purple", + "shape": "circle" + }, + { + "color": "blue", + "shape": "8star" + } + ] + } + ], + "tile*": [] +} +[ + [ + "andrey", + "dag" + ], + [ + "lucas", + "ldasg" + ], + [ + "matthias", + "dag", + "a cheat", + "non-adjacent-coordinate" + ] +] diff --git a/8/Tests/0-out.json b/8/Tests/0-out.json new file mode 100644 index 0000000..ce9c29b --- /dev/null +++ b/8/Tests/0-out.json @@ -0,0 +1 @@ +[["lucas"],["matthias"]] diff --git a/8/Tests/1-in.json b/8/Tests/1-in.json new file mode 100644 index 0000000..112299d --- /dev/null +++ b/8/Tests/1-in.json @@ -0,0 +1,123 @@ +{ + "map": [ + [ + 0, + [ + 0, + { + "color": "red", + "shape": "square" + } + ] + ] + ], + "players": [ + { + "name": "andrey", + "score": 0, + "tile*": [ + { + "color": "orange", + "shape": "star" + }, + { + "color": "blue", + "shape": "circle" + }, + { + "color": "green", + "shape": "8star" + }, + { + "color": "yellow", + "shape": "clover" + }, + { + "color": "purple", + "shape": "diamond" + }, + { + "color": "blue", + "shape": "square" + } + ] + }, + { + "name": "lucas", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "star" + }, + { + "color": "blue", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "clover" + }, + { + "color": "red", + "shape": "diamond" + }, + { + "color": "blue", + "shape": "circle" + } + ] + }, + { + "name": "matthias", + "score": 0, + "tile*": [ + { + "color": "orange", + "shape": "clover" + }, + { + "color": "blue", + "shape": "clover" + }, + { + "color": "green", + "shape": "diamond" + }, + { + "color": "yellow", + "shape": "star" + }, + { + "color": "purple", + "shape": "circle" + }, + { + "color": "blue", + "shape": "8star" + } + ] + } + ], + "tile*": [] +} +[ + [ + "andrey", + "dag" + ], + [ + "lucas", + "ldasg" + ], + [ + "matthias", + "dag", + "a cheat", + "tile-not-owned" + ] +] diff --git a/8/Tests/1-out.json b/8/Tests/1-out.json new file mode 100644 index 0000000..ce9c29b --- /dev/null +++ b/8/Tests/1-out.json @@ -0,0 +1 @@ +[["lucas"],["matthias"]] diff --git a/8/Tests/2-in.json b/8/Tests/2-in.json new file mode 100644 index 0000000..f54a11c --- /dev/null +++ b/8/Tests/2-in.json @@ -0,0 +1,164 @@ +{ + "map": [ + [ + 0, + [ + 0, + { + "color": "red", + "shape": "square" + } + ] + ] + ], + "players": [ + { + "name": "andrey", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "8star" + } + ] + }, + { + "name": "lucas", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "8star" + } + ] + }, + { + "name": "matthias", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "8star" + }, + { + "color": "orange", + "shape": "star" + } + ] + } + ], + "tile*": [ + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "orange", + "shape": "star" + }, + { + "color": "orange", + "shape": "star" + }, + { + "color": "orange", + "shape": "star" + }, + { + "color": "orange", + "shape": "star" + } + ] +} +[ + [ + "andrey", + "dag" + ], + [ + "lucas", + "ldasg" + ], + [ + "matthias", + "dag", + "a cheat", + "bad-ask-for-tiles" + ] +] diff --git a/8/Tests/2-out.json b/8/Tests/2-out.json new file mode 100644 index 0000000..86cfe78 --- /dev/null +++ b/8/Tests/2-out.json @@ -0,0 +1,2 @@ +[["andrey"],[ +]] diff --git a/8/Tests/3-in.json b/8/Tests/3-in.json new file mode 100644 index 0000000..a451672 --- /dev/null +++ b/8/Tests/3-in.json @@ -0,0 +1,152 @@ +{ + "map": [ + [ + 0, + [ + 0, + { + "color": "red", + "shape": "square" + } + ] + ] + ], + "players": [ + { + "name": "andrey", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "8star" + } + ] + }, + { + "name": "lucas", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "8star" + } + ] + }, + { + "name": "matthias", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "8star" + }, + { + "color": "orange", + "shape": "star" + } + ] + } + ], + "tile*": [ + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "orange", + "shape": "star" + } + ] +} +[ + [ + "andrey", + "dag" + ], + [ + "lucas", + "ldasg" + ], + [ + "matthias", + "dag", + "a cheat", + "bad-ask-for-tiles" + ] +] diff --git a/8/Tests/3-out.json b/8/Tests/3-out.json new file mode 100644 index 0000000..ce9c29b --- /dev/null +++ b/8/Tests/3-out.json @@ -0,0 +1 @@ +[["lucas"],["matthias"]] diff --git a/8/Tests/4-in.json b/8/Tests/4-in.json new file mode 100644 index 0000000..0da2606 --- /dev/null +++ b/8/Tests/4-in.json @@ -0,0 +1,148 @@ +{ + "map": [ + [ + 0, + [ + 0, + { + "color": "red", + "shape": "square" + } + ] + ] + ], + "players": [ + { + "name": "andrey", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "8star" + } + ] + }, + { + "name": "lucas", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "8star" + } + ] + }, + { + "name": "matthias", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "8star" + }, + { + "color": "orange", + "shape": "star" + } + ] + } + ], + "tile*": [ + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "red", + "shape": "8star" + } + ] +} +[ + [ + "andrey", + "dag" + ], + [ + "lucas", + "ldasg" + ], + [ + "matthias", + "dag", + "a cheat", + "bad-ask-for-tiles" + ] +] diff --git a/8/Tests/4-out.json b/8/Tests/4-out.json new file mode 100644 index 0000000..ce9c29b --- /dev/null +++ b/8/Tests/4-out.json @@ -0,0 +1 @@ +[["lucas"],["matthias"]] diff --git a/8/Tests/5-in.json b/8/Tests/5-in.json new file mode 100644 index 0000000..1c4af59 --- /dev/null +++ b/8/Tests/5-in.json @@ -0,0 +1,151 @@ +{ + "map": [ + [ + 0, + [ + 0, + { + "color": "red", + "shape": "square" + } + ] + ] + ], + "players": [ + { + "name": "andrey", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "8star" + } + ] + }, + { + "name": "lucas", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "8star" + } + ] + }, + { + "name": "matthias", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "8star" + }, + { + "color": "orange", + "shape": "star" + } + ] + } + ], + "tile*": [ + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "red", + "shape": "8star" + } + ] +} [ + [ + "andrey", + "dag" + ], + [ + "lucas", + "ldasg" + ], + [ + "matthias", + "dag", + "a cheat", + "not-a-line" + ] +] diff --git a/8/Tests/5-out.json b/8/Tests/5-out.json new file mode 100644 index 0000000..1fd3d44 --- /dev/null +++ b/8/Tests/5-out.json @@ -0,0 +1 @@ +[["andrey"],[]] diff --git a/8/Tests/6-in.json b/8/Tests/6-in.json new file mode 100644 index 0000000..b0072c0 --- /dev/null +++ b/8/Tests/6-in.json @@ -0,0 +1,151 @@ +{ + "map": [ + [ + 0, + [ + 0, + { + "color": "red", + "shape": "square" + } + ] + ] + ], + "players": [ + { + "name": "andrey", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "8star" + } + ] + }, + { + "name": "lucas", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "8star" + } + ] + }, + { + "name": "matthias", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "8star" + }, + { + "color": "red", + "shape": "8star" + } + ] + } + ], + "tile*": [ + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "blue", + "shape": "8star" + }, + { + "color": "red", + "shape": "8star" + } + ] +} [ + [ + "andrey", + "dag" + ], + [ + "lucas", + "ldasg" + ], + [ + "matthias", + "dag", + "a cheat", + "not-a-line" + ] +] diff --git a/8/Tests/6-out.json b/8/Tests/6-out.json new file mode 100644 index 0000000..ce9c29b --- /dev/null +++ b/8/Tests/6-out.json @@ -0,0 +1 @@ +[["lucas"],["matthias"]] diff --git a/8/Tests/7-in.json b/8/Tests/7-in.json new file mode 100644 index 0000000..e63a6d0 --- /dev/null +++ b/8/Tests/7-in.json @@ -0,0 +1,100 @@ +{ + "map": [ + [ + 0, + [ + -1, + { + "color": "red", + "shape": "square" + } + ], + [ + + 0, + { + "color": "red", + "shape": "square" + } + ] + ,[ + + 1, + { + "color": "red", + "shape": "square" + } + ] + ] + ,[ + -1, + [ + -1, + { + "color": "red", + "shape": "square" + } + ] + ,[ + + 1, + { + "color": "red", + "shape": "square" + } + ] + ] + ], + "players": [ + { + "name": "andrey", + "score": 0, + "tile*": [ + { + "color": "blue", + "shape": "square" + } + ] + }, + { + "name": "lucas", + "score": 0, + "tile*": [ + { + "color": "blue", + "shape": "square" + } + ] + }, + { + "name": "matthias", + "score": 0, + "tile*": [ + { + "color": "blue", + "shape": "square" + } + ] + } + ], + "tile*": [ + + ] +} [ + [ + "andrey", + "ldasg", + "a cheat", + "no-fit" + ], + [ + "lucas", + "ldasg" + ], + [ + "matthias", + "dag", + "a cheat", + "not-a-line" + ] +] diff --git a/8/Tests/7-out.json b/8/Tests/7-out.json new file mode 100644 index 0000000..1fd3d44 --- /dev/null +++ b/8/Tests/7-out.json @@ -0,0 +1 @@ +[["andrey"],[]] diff --git a/8/Tests/8-in.json b/8/Tests/8-in.json new file mode 100644 index 0000000..6320832 --- /dev/null +++ b/8/Tests/8-in.json @@ -0,0 +1,104 @@ +{ + "map": [ + [ + 0, + [ + -1, + { + "color": "red", + "shape": "square" + } + ], + [ + + 0, + { + "color": "red", + "shape": "square" + } + ] + ,[ + + 1, + { + "color": "red", + "shape": "square" + } + ] + ] + ,[ + -1, + [ + -1, + { + "color": "red", + "shape": "square" + } + ] + ,[ + + 1, + { + "color": "red", + "shape": "square" + } + ] + ] + ], + "players": [ + { + "name": "andrey", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "star" + } + ] + }, + { + "name": "lucas", + "score": 0, + "tile*": [ + { + "color": "blue", + "shape": "square" + } + ] + }, + { + "name": "matthias", + "score": 0, + "tile*": [ + { + "color": "blue", + "shape": "square" + } + ] + } + ], + "tile*": [ + + ] +} [ + [ + "andrey", + "ldasg", + "a cheat", + "no-fit" + ], + [ + "lucas", + "ldasg" + ], + [ + "matthias", + "dag", + "a cheat", + "not-a-line" + ] +] diff --git a/8/Tests/8-out.json b/8/Tests/8-out.json new file mode 100644 index 0000000..c2d1786 --- /dev/null +++ b/8/Tests/8-out.json @@ -0,0 +1 @@ +[["lucas"],["andrey"]] diff --git a/8/Tests/9-in.json b/8/Tests/9-in.json new file mode 100644 index 0000000..cb1098b --- /dev/null +++ b/8/Tests/9-in.json @@ -0,0 +1,131 @@ +{ + "map": [ + [ + 0, + [ + -1, + { + "color": "red", + "shape": "square" + } + ], + [ + + 0, + { + "color": "red", + "shape": "square" + } + ] + ,[ + + 1, + { + "color": "red", + "shape": "square" + } + ] + ] + ,[ + -1, + [ + -1, + { + "color": "red", + "shape": "square" + } + ], + [ + 0, + { + "color": "blue", + "shape": "circle" + } + ] + ,[ + + 1, + { + "color": "red", + "shape": "square" + } + ] + ] + ], + "players": [ + { + "name": "andrey", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "blue", + "shape": "star" + } + ] + }, + { + "name": "lucas", + "score": 0, + "tile*": [ + { + "color": "orange", + "shape": "8star" + } + ] + }, + { + "name": "matthias", + "score": 0, + "tile*": [ + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + }, + { + "color": "red", + "shape": "square" + } + ] + } + ], + "tile*": [ + + ] +} [ + [ + "andrey", + "ldasg", + "a cheat", + "no-fit" + ], + [ + "lucas", + "ldasg" + ], + [ + "matthias", + "dag", + "a cheat", + "no-fit" + ] +] diff --git a/8/Tests/9-out.json b/8/Tests/9-out.json new file mode 100644 index 0000000..161662b --- /dev/null +++ b/8/Tests/9-out.json @@ -0,0 +1 @@ +[["lucas"],["andrey","matthias"]]