Changing from coops to define-record.

master
Thomas Hintz 5 years ago
parent fbc8706893
commit 48b178327b

@ -18,7 +18,7 @@
;;; <https://www.gnu.org/licenses/>. ;;; <https://www.gnu.org/licenses/>.
(import chicken scheme srfi-1 data-structures) (import chicken scheme srfi-1 data-structures)
(use http-session srfi-69 coops coops-utils uri-common (use http-session srfi-69 uri-common
srfi-18 medea numbers spiffy spiffy-cookies srfi-18 medea numbers spiffy spiffy-cookies
intarweb pll sxml-transforms websockets miscmacros intarweb pll sxml-transforms websockets miscmacros
mailbox) mailbox)
@ -96,88 +96,149 @@
(lambda () (set! (,(first (second x)) obj) res)) (lambda () (set! (,(first (second x)) obj) res))
(lambda () (mutex-unlock! mutex)))))))) (lambda () (mutex-unlock! mutex))))))))
(define-class <player> () (define-record player
((cash initform: 5000 accessor: player-cash) (setter cash)
(display-cash initform: 5000 accessor: player-display-cash) (setter display-cash)
(debt initform: 5000 accessor: player-debt) (setter debt)
(space initform: 0 accessor: player-space) (setter space)
(previous-space initform: 0 accessor: player-previous-space) (setter previous-space)
(state initform: 'turn-ended accessor: player-state) (setter state)
(finished initform: #f accessor: player-finished) (setter finished)
(assets initform: (setter assets)
'((hay . 10) (grain . 10) (fruit . 0) (cows . 0) (setter ridges)
(harvester . 0) (tractor . 0) (setter harvest-mult)
(birthday . 0)) (setter otbs)
accessor: player-assets) (setter farmers-fates)
(ridges initform: (setter revealed-cards)
'((ridge1 . 0) (ridge2 . 0) (ridge3 . 0) (ridge4 . 0)) (setter year-rules)
accessor: player-ridges) (setter next-year-rules)
(harvest-mult initform: 1 accessor: player-harvest-mult) (setter color)
(otbs initform: '() accessor: player-otbs) (setter name)
(farmers-fates initform: '() accessor: player-farmers-fates) (setter user-id)
(revealed-cards initform: '() accessor: player-revealed-cards) (setter trade)
(year-rules initform: '() accessor: player-year-rules) (setter last-updated)
(next-year-rules initform: '() accessor: player-next-year-rules) (setter last-cash)
(color initform: #f accessor: player-color) (setter mailbox)
(name initform: "PLAYER X" accessor: player-name) (setter mutex)
(user-id initform: -1 accessor: player-user-id) (setter harvesting)
(trade initform: '() accessor: player-trade) (setter hay-doubled)
(last-updated initform: 0 accessor: player-last-updated) (setter corn-doubled)
(last-cash initform: 5000 accessor: player-last-cash) (setter ready-to-start)
(mailbox initform: (make-mailbox) accessor: player-mailbox) (setter stats)
(mutex initform: (make-mutex 'player) accessor: player-mutex) (setter ai?)
(harvesting initform: #f accessor: player-harvesting) (setter processing-turn))
(hay-doubled initform: #f accessor: player-hay-doubled)
(corn-doubled initform: #f accessor: player-corn-doubled) (define (build-arg-list args)
(ready-to-start initform: #f accessor: player-ready-to-start) (letrec ((build-alist (lambda (args out)
(stats initform: (if (null? args)
'((pro . 0) out
(back . 0) (build-alist (cddr args) (cons (cons (car args) (cadr args)) out))))))
(tax-person . 0) (build-alist args '())))
(emergency . 0)
(num-harvests . 0) (define (make-player* #!rest args)
(harvest-rolls . 0)) (let ((args (build-arg-list args)))
accessor: player-stats))) (make-player
(alist-ref 'cash args eqv? 5000)
(define-class <ai> (<player>) (alist-ref 'display-cash args eqv? 5000)
((processing-turn initform: #f accessor: ai-processing-turn))) (alist-ref 'debt args eqv? 5000)
(alist-ref 'space args eqv? 0)
(define-class <game> () (alist-ref 'previous-space args eqv? 0)
((id initform: 0 accessor: game-id) (alist-ref 'state args eqv? 'turn-ended)
(players initform: '() accessor: game-players) (alist-ref 'finished args eqv? #f)
(messages initform: '() accessor: game-messages) (alist-ref 'assets args eqv? '((hay . 10) (grain . 10) (fruit . 0) (cows . 0)
(otbs initform: '() accessor: game-otbs) (harvester . 0) (tractor . 0)
(used-otbs initform: '() accessor: game-used-otbs) (birthday . 0)))
(farmers-fates initform: '() accessor: game-farmers-fates) (alist-ref 'ridges args eqv? '((ridge1 . 0) (ridge2 . 0) (ridge3 . 0) (ridge4 . 0)))
(operating-expenses initform: '() accessor: game-operating-expenses) (alist-ref 'harvest-mult args eqv? 1)
(operating-expense-index initform: 0 accessor: game-operating-expense-index) (alist-ref 'otbs args eqv? '())
(colors initform: '() accessor: game-colors) (alist-ref 'farmers-fates args eqv? '())
(last-updated initform: 0 accessor: game-last-updated) (alist-ref 'revealed-cards args eqv? '())
(called-audit initform: #f accessor: game-called-audit) (alist-ref 'year-rules args eqv? '())
(state initform: 'pre-game accessor: game-state) (alist-ref 'next-year-rules args eqv? '())
(name initform: "game" accessor: game-name) (alist-ref 'color args eqv? #f)
(turn initform: 1 accessor: game-turn) (alist-ref 'name args eqv? "PLAYER X")
(current-player initform: #f accessor: game-current-player) (alist-ref 'user-id args eqv? -1)
(actions initform: '() accessor: game-actions) (alist-ref 'trade args eqv? '())
(settings initform: (alist-ref 'last-updated args eqv? 0)
'((down-payment . 0.2) (alist-ref 'last-cash args eqv? 5000)
(loan-interest . 0.2) (alist-ref 'mailbox args eqv? (make-mailbox))
(max-debt . 50000) (alist-ref 'mutex args eqv? (make-mutex 'player))
(audit-threshold . 250000) (alist-ref 'harvesting args eqv? #f)
(starting-cash . 5000) (alist-ref 'hay-doubled args eqv? #f)
(starting-debt . 5000) (alist-ref 'corn-doubled args eqv? #f)
(trade . #t) (alist-ref 'ready-to-start args eqv? #f)
(starting-otbs . 2)) (alist-ref 'stats args eqv? '((pro . 0)
accessor: game-settings) (back . 0)
(mutex initform: (make-mutex 'game) accessor: game-mutex))) (tax-person . 0)
(emergency . 0)
(num-harvests . 0)
(harvest-rolls . 0)))
(alist-ref 'ai? args eqv? #f)
(alist-ref 'processing-turn args eqv? #f))))
(define-record game
(setter id)
(setter players)
(setter messages)
(setter otbs)
(setter used-otbs)
(setter farmers-fates)
(setter operating-expenses)
(setter operating-expense-index)
(setter colors)
(setter last-updated)
(setter called-audit)
(setter state)
(setter name)
(setter turn)
(setter current-player)
(setter actions)
(setter settings)
(setter mutex))
(define (make-game* #!rest args)
(let ((args (build-arg-list args)))
(make-game
(alist-ref 'id args eqv? 0)
(alist-ref 'players args eqv? '())
(alist-ref 'messages args eqv? '())
(alist-ref 'otbs args eqv? '())
(alist-ref 'used-otbs args eqv? '())
(alist-ref 'farmers-fates args eqv? '())
(alist-ref 'operating-expenses args eqv? '())
(alist-ref 'operating-expense-index args eqv? 0)
(alist-ref 'colors args eqv? '())
(alist-ref 'last-updated args eqv? 0)
(alist-ref 'called-audit args eqv? #f)
(alist-ref 'state args eqv? 'pre-game)
(alist-ref 'name args eqv? "game")
(alist-ref 'turn args eqv? 1)
(alist-ref 'current-player args eqv? #f)
(alist-ref 'actions args eqv? '())
(alist-ref 'settings args eqv? '((down-payment . 0.2)
(loan-interest . 0.2)
(max-debt . 50000)
(audit-threshold . 250000)
(starting-cash . 5000)
(starting-debt . 5000)
(trade . #t)
(starting-otbs . 2)))
(alist-ref 'mutex args eqv? (make-mutex 'game)))))
(define (game-setting setting game) (define (game-setting setting game)
(alist-ref setting (game-settings game))) (alist-ref setting (game-settings game)))
(define-class <app> () (define-record app
((games initform: '() accessor: app-games) (setter games)
(last-game-id initform: 0 accessor: app-last-game-id) (setter last-game-id)
(mutex initform: (make-mutex 'app) accessor: app-mutex))) (setter mutex))
(define (make-app* #!rest args)
(let ((args (build-arg-list args)))
(make-app
(alist-ref 'games args eqv? '())
(alist-ref 'last-game-id args eqv? 0)
(alist-ref 'mutex args eqv? (make-mutex 'app)))))
(define (player->sexp player) (define (player->sexp player)
`((cash . ,(inexact->exact (round (player-cash player)))) `((cash . ,(inexact->exact (round (player-cash player))))
@ -203,7 +264,7 @@
(hay-doubled . ,(player-hay-doubled player)) (hay-doubled . ,(player-hay-doubled player))
(corn-doubled . ,(player-corn-doubled player)) (corn-doubled . ,(player-corn-doubled player))
(stats . ,(player-stats player)) (stats . ,(player-stats player))
(ai . ,(ai-player? player)))) (ai . ,(player-ai? player))))
(define (game->sexp g) (define (game->sexp g)
`((id . ,(game-id g)) `((id . ,(game-id g))
@ -227,7 +288,7 @@
(define (sexp->game x) (define (sexp->game x)
(let ((players (map sexp->player (let ((players (map sexp->player
(alist-ref 'players x)))) (alist-ref 'players x))))
(apply make <game> (apply make-game*
'players players 'players players
'farmers-fates (let ((ffs (alist-ref 'farmers-fates x))) 'farmers-fates (let ((ffs (alist-ref 'farmers-fates x)))
(list-copy (list-copy
@ -257,19 +318,19 @@
(last-game-id . ,(app-last-game-id a)))) (last-game-id . ,(app-last-game-id a))))
(define (sexp->app x) (define (sexp->app x)
(make <app> (make-app*
'games (map sexp->game (alist-ref 'games x)) 'games (map sexp->game (alist-ref 'games x))
'last-game-id (alist-ref 'last-game-id x))) 'last-game-id (alist-ref 'last-game-id x)))
(define (validate-game g) (define (validate-game g)
(assert (instance-of? g <game>)) (assert (game? g))
(assert (number? (game-id g))) (assert (number? (game-id g)))
(assert (list? (game-players g))) (assert (list? (game-players g)))
(for-each (lambda (p) (for-each (lambda (p)
(when (not (= (player-cash p) (player-display-cash p))) (when (not (= (player-cash p) (player-display-cash p)))
(print "display cash out-of-sync") (print "display cash out-of-sync")
(safe-set! (player-display-cash p) (player-cash p))) (safe-set! (player-display-cash p) (player-cash p)))
(assert (instance-of? p <player>)) (assert (player? p))
(assert (number? (player-cash p))) (assert (number? (player-cash p)))
(assert (number? (player-display-cash p))) (assert (number? (player-display-cash p)))
(assert (= (player-cash p) (player-display-cash p))) (assert (= (player-cash p) (player-display-cash p)))
@ -301,12 +362,12 @@
(assert (list? (game-operating-expenses g))) (assert (list? (game-operating-expenses g)))
(assert (number? (game-operating-expense-index g))) (assert (number? (game-operating-expense-index g)))
(assert (list? (game-colors g))) (assert (list? (game-colors g)))
(assert (or (instance-of? (game-called-audit g) <player>) (assert (or (player? (game-called-audit g))
(boolean? (game-called-audit g)))) (boolean? (game-called-audit g))))
(assert (symbol? (game-state g))) ;; TODO test all symbols (assert (symbol? (game-state g))) ;; TODO test all symbols
(assert (string? (game-name g))) (assert (string? (game-name g)))
(assert (number? (game-turn g))) (assert (number? (game-turn g)))
(assert (or (instance-of? (game-current-player g) <player>) (assert (or (player? (game-current-player g))
(boolean? (game-current-player g)))) (boolean? (game-current-player g))))
(assert (list? (game-settings g)))) (assert (list? (game-settings g))))
@ -321,12 +382,13 @@
(set! *app* (sexp->app (read)))))) (set! *app* (sexp->app (read))))))
(define (sexp->player x) (define (sexp->player x)
(let ((p (apply make (if (alist-ref 'ai x) <ai> <player>) (let ((p (apply make-player*
'farmers-fates (let ((ffs (alist-ref 'farmers-fates x))) 'farmers-fates (let ((ffs (alist-ref 'farmers-fates x)))
(list-copy (list-copy
(filter (lambda (card) (filter (lambda (card)
(member (alist-ref 'id card) ffs)) (member (alist-ref 'id card) ffs))
*farmers-fates-cards*))) *farmers-fates-cards*)))
'ai? (alist-ref 'ai x)
(fold (lambda (k r) (cons k (cons (alist-ref k x) r))) (fold (lambda (k r) (cons k (cons (alist-ref k x) r)))
'() '()
'(cash debt space previous-space state assets ridges '(cash debt space previous-space state assets ridges
@ -342,7 +404,7 @@
(sort (map (lambda (x) (cons (random 100) x)) l) (sort (map (lambda (x) (cons (random 100) x)) l)
(lambda (x y) (< (car x) (car y)))))) (lambda (x y) (< (car x) (car y))))))
(define *app* (make <app>)) (define *app* (make-app*))
(define (next-game-id app) (define (next-game-id app)
(safe-set! (app-last-game-id app) (+ (app-last-game-id app) 1)) (safe-set! (app-last-game-id app) (+ (app-last-game-id app) 1))
@ -410,7 +472,7 @@
color)) color))
(define (add-player-to-game game color name user-id) (define (add-player-to-game game color name user-id)
(let ((player (make <player> (let ((player (make-player*
'cash (game-setting 'starting-cash game) 'cash (game-setting 'starting-cash game)
'display-cash (game-setting 'starting-cash game) 'display-cash (game-setting 'starting-cash game)
'debt (game-setting 'starting-debt game) 'debt (game-setting 'starting-debt game)
@ -425,7 +487,8 @@
player)) player))
(define (add-ai-to-game game color name) (define (add-ai-to-game game color name)
(let ((player (make <ai> (let ((player (make-player*
'ai? #t
'cash (game-setting 'starting-cash game) 'cash (game-setting 'starting-cash game)
'display-cash (game-setting 'starting-cash game) 'display-cash (game-setting 'starting-cash game)
'debt (game-setting 'starting-debt game) 'debt (game-setting 'starting-debt game)
@ -529,7 +592,7 @@
(safe-set! (game-current-player game) first-player) (safe-set! (game-current-player game) first-player)
(message-players! game #f '() type: "update")) (message-players! game #f '() type: "update"))
(define-method (player->list (p <player>)) (define (player->list p)
`((player . ((assets . ,(player-assets p)) `((player . ((assets . ,(player-assets p))
(ridges . ,(player-ridges p)) (ridges . ,(player-ridges p))
(cash . ,(player-cash p)) (cash . ,(player-cash p))
@ -547,30 +610,7 @@
(lastCash . ,(player-last-cash p)) (lastCash . ,(player-last-cash p))
(hayDoubled . ,(player-hay-doubled p)) (hayDoubled . ,(player-hay-doubled p))
(cornDoubled . ,(player-corn-doubled p)) (cornDoubled . ,(player-corn-doubled p))
(ai . #f))))) (ai . ,(player-ai? p))))))
(define-method (player->list (p <ai>))
`((player . ((assets . ,(player-assets p))
(ridges . ,(player-ridges p))
(cash . ,(player-cash p))
(displayCash . ,(player-display-cash p))
(debt . ,(player-debt p))
(space . ,(player-space p))
(state . ,(symbol->string (player-state p)))
(cards . ,(list->vector (append (player-farmers-fates p)
(player-otbs p))))
(revealedCards . ,(list->vector (player-revealed-cards p)))
(color . ,(symbol->string (player-color p)))
(name . ,(player-name p))
(user-id . ,(player-user-id p))
(trade . ,(player-trade p))
(lastCash . ,(player-last-cash p))
(hayDoubled . ,(player-hay-doubled p))
(cornDoubled . ,(player-corn-doubled p))
(ai . #t)))))
(define-method (ai-player? (p <ai>)) #t)
(define-method (ai-player? (p <player>)) #f)
(define (game->list g player) (define (game->list g player)
`((game . ((messages . ,(list->vector (reverse (game-messages g)))) `((game . ((messages . ,(list->vector (reverse (game-messages g))))
@ -1050,7 +1090,7 @@
(let ((db-game (sexp->game (db-fetch-game id)))) (let ((db-game (sexp->game (db-fetch-game id))))
(push! db-game (app-games *app*)) (push! db-game (app-games *app*))
(for-each (lambda (p) (for-each (lambda (p)
(when (ai-player? p) (when (player-ai? p)
(thread-start! (make-ai-push-receiver db-game p)))) (thread-start! (make-ai-push-receiver db-game p))))
(game-players db-game)) (game-players db-game))
db-game)))) db-game))))
@ -1268,12 +1308,12 @@
(else ;; TODO make error (else ;; TODO make error
(create-ws-response player "action" `((action . ,name))))))))) (create-ws-response player "action" `((action . ,name)))))))))
((and (string=? type "next-action") ((and (string=? type "next-action")
(ai-player? (game-current-player game))) (player-ai? (game-current-player game)))
(print "ai next action trigger") (print "ai next action trigger")
(message-players! game player '() type: "ai-next-action") (message-players! game player '() type: "ai-next-action")
(create-ws-response player "update" `())) (create-ws-response player "update" `()))
((and (string=? type "buy-uncle-bert") ((and (string=? type "buy-uncle-bert")
(ai-player? (game-current-player game))) (player-ai? (game-current-player game)))
(print "ai uncle bert trigger") (print "ai uncle bert trigger")
(message-players! game player '() type: "ai-uncle-bert") (message-players! game player '() type: "ai-uncle-bert")
(create-ws-response player "update" `())) (create-ws-response player "update" `()))
@ -1424,8 +1464,9 @@
((string=? type "new-game") ((string=? type "new-game")
(let* ((color (string->symbol (alist-ref 'checkedColor msg))) (let* ((color (string->symbol (alist-ref 'checkedColor msg)))
(user (fetch-user-by-id (session-ref (sid) 'user-id))) (user (fetch-user-by-id (session-ref (sid) 'user-id)))
(game (make <game> 'colors (filter (cut neq? <> color) (game (make-game*
'(green red blue yellow black)) 'colors (filter (cut neq? <> color)
'(green red blue yellow black))
'name (alist-ref 'gameName msg) 'name (alist-ref 'gameName msg)
'id (next-game-id *app*) 'id (next-game-id *app*)
'otbs (setup-otbs) 'otbs (setup-otbs)
@ -1449,9 +1490,7 @@
(player (add-player-to-game game (player (add-player-to-game game
color color
(alist-ref 'username user) (alist-ref 'username user)
(alist-ref 'id user))) (alist-ref 'id user))))
;; (ai-player (add-ai-to-game game 'red "AI Player 1"))
)
(push! game (app-games *app*)) (push! game (app-games *app*))
(let ((gid (db-add-game "pre-game" (game->sexp game)))) (let ((gid (db-add-game "pre-game" (game->sexp game))))
(safe-set! (game-id game) gid) (safe-set! (game-id game) gid)
@ -1461,8 +1500,6 @@
(*game* game) (*game* game)
(*player* player) (*player* player)
(set-startup-otbs game player (alist-ref 'starting-otbs (game-settings game))) (set-startup-otbs game player (alist-ref 'starting-otbs (game-settings game)))
;; (set-startup-otbs game ai-player 2)
;; (thread-start! (make-ai-push-receiver game ai-player))
(create-start-response "new-game-started"))) (create-start-response "new-game-started")))
((string=? type "join-game") ((string=? type "join-game")
(let* ((user (fetch-user-by-id (session-ref (sid) 'user-id))) (let* ((user (fetch-user-by-id (session-ref (sid) 'user-id)))
@ -1488,7 +1525,7 @@
((string=? type "add-ai-player") ((string=? type "add-ai-player")
(let* ((user (fetch-user-by-id (session-ref (sid) 'user-id))) (let* ((user (fetch-user-by-id (session-ref (sid) 'user-id)))
(name (conc "AI Player " (name (conc "AI Player "
(+ 1 (length (filter ai-player? (game-players game)))))) (+ 1 (length (filter player-ai? (game-players game))))))
(game (*game*)) (game (*game*))
(color (car (game-colors game))) (color (car (game-colors game)))
(player (add-ai-to-game game (player (add-ai-to-game game
@ -1657,8 +1694,8 @@
(case (string->symbol (alist-ref 'type msg)) (case (string->symbol (alist-ref 'type msg))
((update) ((update)
(if (and (eq? (player-state player) 'pre-turn) (if (and (eq? (player-state player) 'pre-turn)
(not (ai-processing-turn player))) (not (player-processing-turn player)))
(begin (set! (ai-processing-turn player) #t) (begin (set! (player-processing-turn player) #t)
;; time to buy ;; time to buy
(when (and (>= (player-space player) 9) (<= (player-space player) 14)) (when (and (>= (player-space player) 9) (<= (player-space player) 14))
(let loop ((cont (ai-buy player game))) (let loop ((cont (ai-buy player game)))
@ -1669,7 +1706,7 @@
(print "ai auto-skip")) (print "ai auto-skip"))
((ai-next-action) ((ai-next-action)
(print "ai-next-action") (print "ai-next-action")
(when (ai-processing-turn player) (when (player-processing-turn player)
(let ((res (process-message player game "next-action" '((type . "next-action"))))) (let ((res (process-message player game "next-action" '((type . "next-action")))))
res res
;; (display "res: ") ;; (display "res: ")
@ -1678,7 +1715,7 @@
))) )))
((ai-uncle-bert) ((ai-uncle-bert)
(print "ai-uncle-bert") (print "ai-uncle-bert")
(when (ai-processing-turn player) (when (player-processing-turn player)
(safe-set! (player-debt player) (+ (player-debt player) 10000)) (safe-set! (player-debt player) (+ (player-debt player) 10000))
(safe-set! (player-assets player) (safe-set! (player-assets player)
(alist-update 'hay (+ (alist-ref 'hay (player-assets player)) 10) (alist-update 'hay (+ (alist-ref 'hay (player-assets player)) 10)
@ -1686,7 +1723,7 @@
((end-ai-turn) ((end-ai-turn)
(if (eq? (player-state player) 'pre-turn) (if (eq? (player-state player) 'pre-turn)
(process-ai-push-message player game '((type . "update"))) ;; restarting at AI player's turn (process-ai-push-message player game '((type . "update"))) ;; restarting at AI player's turn
(if (ai-processing-turn player) (if (player-processing-turn player)
(begin (begin
(when (< (player-cash player) 0) (when (< (player-cash player) 0)
(print "taking out loan") (print "taking out loan")
@ -1701,7 +1738,7 @@
-1))))) -1)))))
(print "ending turn") (print "ending turn")
;; (thread-sleep! 0.5) ;; (thread-sleep! 0.5)
(set! (ai-processing-turn player) #f) (set! (player-processing-turn player) #f)
(process-message player game "turn-ended" '())) (process-message player game "turn-ended" '()))
;; this could happen if we restart the game in the middle of a turn ;; this could happen if we restart the game in the middle of a turn
;; so lets just force the next turn ;; so lets just force the next turn

Loading…
Cancel
Save