summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/tilde30.t39
-rw-r--r--lib/constants.fnl30
-rw-r--r--main.fnl20
-rw-r--r--src/game.fnl53
4 files changed, 99 insertions, 43 deletions
diff --git a/doc/tilde30.t b/doc/tilde30.t
index c931c07..8a6911a 100644
--- a/doc/tilde30.t
+++ b/doc/tilde30.t
@@ -272,5 +272,44 @@ and will be spending a lot of time on my back.
So I'm either going to get a lot on 9mm,
or nothing at all.
We'll see!
+.
+.
+.IP "20 - 21"
+I was having back surgery!
+.
+.
+.IP "WEEK THREE REVIEW"
+Finished the game, and then had a major surgery.
+Doing some tidying up and housekeeping now.
+Organzing tests,
+breaking stuff out into modules.
+Rewriting and refactoring a couple of functions.
+Generally getting ready to start thinking
+about Stretch Goal 1: Story Mode.
+I have a vague inkling of an idea about
+doing some kind of generative story / narration
+based on each move of the game.
+Assign symbolic meaning to the outer, middle, and inner rings of the board.
+Add a little twist based on whether the move is a capture, a slide, a placement.
+That kind of thing.
+Not sure how I want to do it exactly yet.
+I'd like to be able to show the story progress as you play.
+But updating the story every move seems like kind of a lot.
+Maybe just at every game phase.
+So three installments.
+One at the end of Placement,
+the second at the end of Movement,
+and the third at the end of the game?
+Anyway.
+
+Up next: big refactor of the validation logic.
+I don't want it to just print to console
+if I'm going to eventually support multiple frontends.
+I need to return an error code or something
+for the client to interpret.
+I'm still interested in the Result / Either monad option
+but I think I'm doing to first try the conventional lua way
+and throw an error, and then 'pcall' the function and handle the error politely.
+
.pl \n[nl]u
diff --git a/lib/constants.fnl b/lib/constants.fnl
index be9a6be..996c11c 100644
--- a/lib/constants.fnl
+++ b/lib/constants.fnl
@@ -97,9 +97,33 @@
:complete 5 ;; no more cows! jk the cows are fine. the game's just over okay
})
-{: board
+
+;; errror codes
+(local errors {
+ :not-a-space "That space does not exist!\nHint: 1a 1A A1 a1 are all the same move."
+ :occupied "That space is occupied!"
+ :not-an-opponent "Choose an opponent's piece to remove."
+ :is-mill "Ma'am, it is ILLEGAL to break up a mill."
+ :bad-move-format "Try a move like B2B4 or A7 D7"
+ :not-yours "That's not yours, don't touch it."
+ :not-neighbor "That ain't your neighbor, Johnny"
+})
+
+
+;; if you like it then you shoulda put a ...
+(local rings {
+ :outer [ 1 2 3 15 24 23 22 10 ]
+ :middle [ 4 5 6 14 21 20 19 11 ]
+ :inner [ 7 8 9 13 18 17 16 12 ]
+})
+
+
+{
+ : board
+ : errors
: mills
: neighbors
+ : rings
+ : spaces
: stages
- : spaces}
-
+ }
diff --git a/main.fnl b/main.fnl
index c205454..8144b11 100644
--- a/main.fnl
+++ b/main.fnl
@@ -34,17 +34,23 @@
;; game loop
(while (not (= game.stage const.stages.complete))
(with-board game.moves)
- ;; validation loop
(var is-valid false)
(var move "")
+ ;; validation loop
(while (not is-valid)
(set move (get-move))
- (set is-valid (game.validate-move move))
- (if (not is-valid)
- (print "Try again.")
- (do
- (print (string.format "Turn %d: You chose %s" game.turns move))
- (game:update move)))))
+ (case (pcall game.validate-move move)
+ (false msg)
+ (do
+ (let [(i j) (string.find msg ": ")
+ key (string.sub msg (+ 1 j))]
+ (print (. const.errors key)))
+ (print "Try again."))
+ ok
+ (do
+ (set is-valid true)
+ (print (string.format "Turn %d: You chose %s" game.turns move))
+ (game:update move)))))
;; game is complete
(print "Congratulations!")
(print (string.format "Player %d is the winner!" game.player)))
diff --git a/src/game.fnl b/src/game.fnl
index b48a6ac..4a24ce2 100644
--- a/src/game.fnl
+++ b/src/game.fnl
@@ -4,15 +4,15 @@
} (require :lib.index))
(local {
: all-mills?
- :mill-at? mill-at-maker
- :no-moves? no-moves-maker
- :space-is-neighbor? space-is-neighbor-maker
+ :mill-at? full-mill-at ;; stay with me...
+ :no-moves? full-no-moves
+ :space-is-neighbor? full-space-is-neighbor
} (require :lib.game.index))
(local const (require :lib.constants))
-;; front-loading with some partials
-(local mill-at? (partial mill-at-maker const.mills))
-(local space-is-neighbor? (partial space-is-neighbor-maker const.neighbors))
-(local no-moves? (partial no-moves-maker const.neighbors))
+;; front-loading the "fulls" with some partials
+(local mill-at? (partial full-mill-at const.mills))
+(local space-is-neighbor? (partial full-space-is-neighbor const.neighbors))
+(local no-moves? (partial full-no-moves const.neighbors))
;; story mode:
@@ -124,8 +124,7 @@
; 2 = Player 2
; NOTE: I think it might be a good idea to make moves
; a list of moves. so that there can be undo and history
- (set self.moves (fcollect [i 1 24] 0))
- )
+ (set self.moves (fcollect [i 1 24] 0)))
})
@@ -164,40 +163,28 @@
; is this a legal move?
+; note: string argument to assert funs are defined in /lib/constants
(fn valid-move? [move]
(or
(and
(= const.stages.placing game.stage)
- (or (space-exists? move)
- (print "That space does not exist!\nHint: 1a 1A A1 a1 are all the same move."))
- (or (space-is-unoccupied? move)
- (print "That space is occupied!")))
+ (assert (space-exists? move) :not-a-space)
+ (assert (space-is-unoccupied? move) :occupied))
(and
(= const.stages.capture game.stage)
- (or (space-is-occupied-by-opponent? move)
- (print "Choose an opponent's piece to remove."))
- (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.")
- ))
+ (assert (space-is-occupied-by-opponent? move) :not-an-opponent)
+ (assert (or (all-mills? game.moves game.player) (not (mill-at? game.moves (index-of-move move)))) :is-mill))
(and
(= const.stages.moving 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!"))
- (or (space-is-neighbor? (index-of-move (string.sub move 1 2)) (index-of-move (string.sub move -2 -1)))
- (print "That ain't your neighbor, Johnny")) )
+ (assert (moving-format? move) :bad-move-format)
+ (assert (not (space-is-occupied-by-opponent? (string.sub move 1 2))) :not-yours)
+ (assert (space-is-unoccupied? (string.sub move -2 -1)) :occupied)
+ (assert (space-is-neighbor? (index-of-move (string.sub move 1 2)) (index-of-move (string.sub move -2 -1))) :not-neighbor) )
(and
(= const.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!")))))
+ (assert (moving-format? move) :bad-move-format)
+ (assert (not (space-is-occupied-by-opponent? (string.sub move 1 2))) :not-yours)
+ (assert (space-is-unoccupied? (string.sub move -2 -1)) :occupied))))
(tset game :validate-move valid-move?)