From 1250f9f057c2e21a0edab87f0a6003a25decd1b7 Mon Sep 17 00:00:00 2001 From: dozens Date: Sat, 8 Jun 2024 20:58:40 -0600 Subject: feat: add flying phase --- main.fnl | 114 +++++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 75 insertions(+), 39 deletions(-) (limited to 'main.fnl') diff --git a/main.fnl b/main.fnl index bf6933e..fae5445 100644 --- a/main.fnl +++ b/main.fnl @@ -5,6 +5,7 @@ : kvflip : pprint : slice + : all-mills? :mill-at? mill-at-maker :space-is-neighbor? space-is-neighbor-maker } (require :lib.index)) @@ -28,21 +29,29 @@ }) +;; story mode: ;; there are two players -;; their names are LUIGI and MARIO +;; their names are WIGI and MALO (local player { - :one 1 ;; luigi has light cows - :two 2 ;; mario has DARK cows >:) + :one 1 ;; wigi has light cows + :two 2 ;; malo has DARK cows >:) }) ; return the numerical index (1-24) of a [A-Za-z0-9] formatted move (fn index-of-move [m] - (let [upper (string.upper m) - rev (string.reverse upper) - idx (head (icollect [i v (ipairs const.spaces)] - (if (or (= v upper) (= v rev)) i)))] - idx)) + (assert (= "string" (type m)) "index-of-move needs a string argument") + (let [upper (string.upper m) + rev (string.reverse upper) + idx (head (icollect [i v (ipairs const.spaces)] + (if (or (= v upper) (= v rev)) i)))] + idx)) + + +(fn player-count [moves player] + (accumulate [count 0 + _ x (ipairs moves)] + (if (= x player) (+ count 1) count))) ;; game state object @@ -51,34 +60,57 @@ :stage stages.placing :update (fn [self move] (case self.stage - 4 ;; capture + 4 ;; CAPTURE (do - ;; TODO: capturing during moving is not working? (tset self.moves (index-of-move move) 0) (tset self :player (self:next-player)) - (tset self :stage (if (> self.pieces-placed 17) stages.moving stages.placing)) - (tset self.moves (index-of-move move) self.player) - ) - 1 ;; placing + (let [flytime (and (> self.pieces-placed 17) (= 3 (player-count self.moves self.player))) + movetime (and (> self.pieces-placed 17) (> (player-count self.moves self.player) 3))] + (tset self :stage (if flytime stages.flying + movetime stages.moving + stages.placing)))) + 1 ;; PLACING (do (set self.pieces-placed (+ 1 self.pieces-placed)) (tset self :stage (if (> self.pieces-placed 17) stages.moving stages.placing)) (tset self.moves (index-of-move move) self.player) - (if (mill-at? self.moves (index-of-move move)) - (tset self :stage stages.capture) - (tset self :player (self:next-player)) - ) - ) - 2 ;; moving + (let [flytime (and (> self.pieces-placed 17) (= 3 (player-count self.moves self.player))) + movetime (and (> self.pieces-placed 17) (> (player-count self.moves self.player) 3)) + capturetime (mill-at? self.moves (index-of-move move))] + (tset self :stage (if + capturetime stages.capture + flytime stages.flying + movetime stages.moving + stages.placing)) + (if (not capturetime) (tset self :player (self:next-player))))) + 2 ;; MOVING (let [from (index-of-move (string.sub move 1 2)) to (index-of-move (string.sub move -2 -1))] + (tset self.moves from 0) + (tset self.moves to self.player) + (let [flytime (and (> self.pieces-placed 17) (= 3 (player-count self.moves (self:next-player)))) + movetime (and (> self.pieces-placed 17) (> (player-count self.moves (self:next-player)) 3)) + capturetime (mill-at? self.moves (index-of-move (string.sub move -2 -1)))] + (tset self :stage (if + capturetime stages.capture + flytime stages.flying + movetime stages.moving + stages.placing)) + (if (not capturetime) (tset self :player (self:next-player))))) + 3 ;; FLYING + (let [from (index-of-move (string.sub move 1 2)) + to (index-of-move (string.sub move -2 -1))] (tset self.moves from 0) (tset self.moves to self.player) - (if (mill-at? self.moves to) - (tset self :stage stages.capture) - (tset self :player (self:next-player)) - ) - ) + (let [flytime (and (> self.pieces-placed 17) (= 3 (player-count self.moves (self:next-player)))) + movetime (and (> self.pieces-placed 17) (> (player-count self.moves (self:next-player)) 3)) + capturetime (mill-at? self.moves (index-of-move (string.sub move -2 -1)))] + (tset self :stage (if + capturetime stages.capture + flytime stages.flying + movetime stages.moving + stages.placing)) + (if (not capturetime) (tset self :player (self:next-player))))) ) ) :next-player (fn [self] (if (= player.one self.player) player.two player.one)) @@ -98,6 +130,7 @@ (game:init) +; TODO: move to lib utility (fn string-upper [s] (.. (string.upper (string.sub s 1 1)) (string.sub s 2))) @@ -136,27 +169,23 @@ (let [unoccupied? 0] ; i.e. is move equal to 0 (= unoccupied? (. game.moves (index-of-move m))))) - +; is the space m occupied by the player's opponent? (fn space-is-occupied-by-opponent? [m] + "is the space m occupied by the player's opponent?" (let [opponent (if (= game.player 1) 2 1) result (= opponent (. game.moves (index-of-move m))) ] result)) - +; checks that the first 2 charcters and the last 2 characters +; of a string are legal spaces +; moving-format is the same as flying-format (fn moving-format? [m] (let [from (string.sub m 1 2) to (string.sub m -2 -1)] - (and (space-exists? from) (space-exists? to)))) + (and (>= (length m) 4) (space-exists? from) (space-exists? to)))) + ; is this a legal move? -; maybe some functional error handling here? -; https://mostly-adequate.gitbook.io/mostly-adequate-guide/ch08#pure-error-handling -; https://mostly-adequate.gitbook.io/mostly-adequate-guide/appendix_b#either -; or maybe all i need is a case-try statement.. -; https://fennel-lang.org/reference#case-try-for-matching-multiple-steps -; update: i didn't really like that -; i think maybe i do want the monad after all.. -; i'll come back to it later (fn valid-move? [move] (or (and @@ -169,8 +198,10 @@ (= stages.capture game.stage) (or (space-is-occupied-by-opponent? move) (print "Choose an opponent's piece to remove.")) - (or (not (mill-at? game.moves (index-of-move move))) - (print "Ma'am, it is ILLEGAL to break up a mill.")) + (or (or (all-mills? game.moves game.player) + (not (mill-at? game.moves (index-of-move move)))) + (print "Ma'am, it is ILLEGAL to break up a mill.") + ) ) (and (= stages.moving game.stage) @@ -184,8 +215,13 @@ (print "That ain't your neighbor, Johnny")) ) (and - ;; TODO: add flying phase (= stages.flying game.stage) + (or (moving-format? move) + (print "Try a move like A1A2 or A7 D7")) + (or (not (space-is-occupied-by-opponent? (string.sub move 1 2))) + (print "That's not yours, don't touch it.")) + (or (space-is-unoccupied? (string.sub move -2 -1)) + (print "That space is occupied!")) ) ) ) -- cgit 1.4.1-2-gfad0