commit
d08a76b7ff
@ -0,0 +1,19 @@ |
||||
# Ceelo |
||||
|
||||
This is a fun dice game |
||||
|
||||
<https://en.wikipedia.org/wiki/Cee-lo> |
||||
|
||||
## Getting started |
||||
|
||||
1. write fennel |
||||
|
||||
2. run the justfile |
||||
|
||||
## TODO |
||||
|
||||
1. Don't allow player to go into negative (Game over at zero dollars) |
||||
|
||||
2. Abstract common parts of `bank-roll` and `player-roll` |
||||
|
||||
3. I/O: Persist cash amt to player.fnl |
@ -0,0 +1,7 @@ |
||||
# see what recipes are available |
||||
default: |
||||
just -l |
||||
|
||||
# watch for changes |
||||
watch: |
||||
fd -e fnl | entr -c fennel main.fnl |
@ -0,0 +1,39 @@ |
||||
;; a map of return value meanings for `parse` |
||||
(local dict { |
||||
0 :no-value |
||||
1 :lose |
||||
2 :point-value |
||||
3 :point-value |
||||
4 :point-value |
||||
5 :point-value |
||||
6 :win |
||||
}) |
||||
|
||||
;; returns a code (see `dict`) and an annotation |
||||
(fn parse [t] |
||||
"parse :: [ x y z ] -> [ n str ]" |
||||
(match (doto t (table.sort)) |
||||
[ x x x ] [ 6 "trips! instawin" ] |
||||
[ 4 5 6 ] [ 6 "hi str8 instawin" ] |
||||
[ x x 6 ] [ 6 "6pt instawin" ] |
||||
[ 1 2 3 ] [ 1 "lo str8 instalose" ] |
||||
[ 1 x x ] [ 1 "1pt instalose" ] |
||||
[ x x y ] [ y (.. y "point") ] |
||||
[ y x x ] [ y (.. y "point") ] |
||||
_ [ 0 "nothing" ] |
||||
) |
||||
) |
||||
|
||||
;; Usage: |
||||
;(local {: rolls} (require :dice-roller)) |
||||
;(let [t (rolls) |
||||
; [ n str ] (parse t) |
||||
; pp (fn [x] (table.concat x " ")) |
||||
; ] |
||||
; (print (pp t) n (. dict n) str) |
||||
; ) |
||||
|
||||
{ |
||||
: parse |
||||
: dict |
||||
} |
@ -0,0 +1,18 @@ |
||||
;; dice-roller.fnl |
||||
(math.randomseed (os.time)) |
||||
|
||||
(fn roll [] |
||||
"Return a random number between 1 and 6" |
||||
(math.random 1 6) |
||||
) |
||||
|
||||
(fn rolls [] |
||||
"Return a table of 3 random numbers" |
||||
(local t []) |
||||
(for [i 1 3] |
||||
(table.insert t (roll)) |
||||
) |
||||
t |
||||
) |
||||
|
||||
{: rolls } |
@ -0,0 +1,32 @@ |
||||
(fn wrap [str limit indent indent1] |
||||
(let [indent (or indent "") |
||||
indent1 (or indent1 indent) |
||||
limit (or limit 72) |
||||
] |
||||
(var here (- 1 (# indent1))) |
||||
(fn check [sp st word fi] |
||||
(when (> (- fi here) limit) |
||||
(set here (- st (# indent))) |
||||
(.. "\n" indent word))) |
||||
(.. indent1 (: str :gsub "(%s+)()(%S+)()" check)) |
||||
) |
||||
) |
||||
|
||||
|
||||
(fn reflow [str limit indent indent1] |
||||
(doto (str:gsub "%s*\n%s+" "\n") |
||||
(: :gsub "%s%s+" " ") |
||||
(: :gsub "[^\n]+" (fn [line] (wrap line limit indent indent1))) |
||||
) |
||||
) |
||||
|
||||
|
||||
(local words "Okay ceelo is a fun dice game. It is a point-set gambling game, kind of like craps, but is more simple, and you play it with three six-sided dice.\n\n== ROLLS ==\n\nFirst, here's what the rolls mean.\n\n1. Win conditions:\n\n- n n n (triples) = instant win.\n example: 3 3 3\n\n- 4 5 6 = instant win\n\n- n n 6 (any doubles + 6) = instant win. e.g.\n example: 2 2 6\n\n2. Loss conditions:\n\n- n n 1 (any doubles + 1) = instant loss\n example: 6 6 1\n\n- 1 2 3 = instant loss\n\n3. Points:\n\n- n n x (doubles + not 6, not 1) = establish a POINT\n example: 3 3 4\n\n\nReroll:\n\n- anything else = reroll\n\n== PLAY ==\n\nNow, here's how to play.\n\n1. Make a bet against the Bank.\n\n2. The Bank will roll and will either win, lose, or establish a point.\n\n3. If a point is established, you get to roll until you win outright or beat the point, or lose, or draw.\n\nThat's it! Go play!\n\nPress Enter to continue.\n") |
||||
|
||||
(print (wrap words)) |
||||
|
||||
|
||||
{ |
||||
:wrap wrap |
||||
:reflow reflow |
||||
} |
@ -0,0 +1,17 @@ |
||||
;; main.fnl |
||||
(local player (require :player)) |
||||
(var mode (require :mode.menu)) |
||||
(var quit false) |
||||
|
||||
(fn set-mode [m] |
||||
(set mode (require m)) |
||||
) |
||||
|
||||
(while (not quit) |
||||
(os.execute :clear) |
||||
(mode.display player) |
||||
(local cmd (io.read)) |
||||
(if (= cmd "q") (set quit true)) |
||||
(mode.key-pressed player cmd set-mode) |
||||
) |
||||
|
@ -0,0 +1,19 @@ |
||||
{ |
||||
:name "bet" |
||||
|
||||
:display (fn [p] |
||||
(print (string.format "You have $%d." p.cash)) |
||||
(print (string.format "Your current bet is $%d." p.bet)) |
||||
(print "Enter a new bet.\n") |
||||
(io.write "> ") |
||||
) |
||||
|
||||
:key-pressed (fn key-pressed [p amt set-mode] |
||||
(let [valid? (<= (tonumber amt) p.cash)] |
||||
(when valid? |
||||
(set p.bet amt) |
||||
(set-mode :mode.menu) |
||||
) |
||||
) |
||||
) |
||||
} |
@ -0,0 +1,22 @@ |
||||
{ |
||||
:name "menu" |
||||
|
||||
:display (fn [player] |
||||
(print "== Ceelo Game ==\n") |
||||
(print (string.format "You have $%d." player.cash)) |
||||
(print (string.format "Your current bet is $%d.\n" player.bet)) |
||||
(print "(b)et") |
||||
(print "(p)lay") |
||||
(print "(r)ules") |
||||
(print "(q)uit\n") |
||||
(io.write "> ") |
||||
) |
||||
|
||||
:key-pressed (fn key-pressed [p k set-mode] |
||||
(match k |
||||
"p" (set-mode :mode.play) |
||||
"b" (set-mode :mode.bet) |
||||
"r" (set-mode :mode.rules) |
||||
) |
||||
) |
||||
} |
@ -0,0 +1,71 @@ |
||||
(local {: rolls} (require :lib.roller)) |
||||
(local {: parse } (require :lib.parser)) |
||||
|
||||
(fn game-over [p m s] |
||||
(set p.cash (+ p.cash (* p.bet m))) |
||||
(set p.turn false) |
||||
(print (string.format s p.bet)) |
||||
(print "\nEnter 'm' to return to menu or just press Enter to play again") |
||||
) |
||||
|
||||
(fn lose [p] |
||||
(game-over p -1 "You lose $%d")) |
||||
|
||||
(fn win [p] |
||||
(game-over p 1 "You win $%d!")) |
||||
|
||||
(fn set-point [player pt] |
||||
(set player.point pt) |
||||
(print (string.format "Point set to %d." pt)) |
||||
) |
||||
|
||||
(fn bank-roll [p] |
||||
(let [t (rolls) |
||||
[ n str ] (parse t) |
||||
pp (fn [x] (table.concat x " ")) |
||||
] |
||||
(print (pp t) str) |
||||
(match n |
||||
6 (lose p) |
||||
1 (win p) |
||||
0 (bank-roll p) |
||||
x (set-point p x) |
||||
) |
||||
) |
||||
) |
||||
|
||||
(fn player-roll [p] |
||||
(let [t (rolls) |
||||
[ n str ] (parse t) |
||||
pp (fn [x] (table.concat x " ")) |
||||
] |
||||
(print (pp t) str) |
||||
(match n |
||||
6 (win p) |
||||
1 (lose p) |
||||
(where x (> x p.point)) (win p) |
||||
_ (player-roll p) |
||||
) |
||||
) |
||||
) |
||||
|
||||
{ |
||||
:name "play" |
||||
|
||||
:display (fn [p] |
||||
(set p.turn true) |
||||
(print "Bank rolls first..") |
||||
(print (bank-roll p)) |
||||
(when p.turn |
||||
(print "Player's turn") |
||||
(player-roll p) |
||||
) |
||||
) |
||||
|
||||
:key-pressed (fn key-pressed [p k set-mode] |
||||
(match k |
||||
"m" (set-mode :mode.menu) |
||||
"p" (set-mode :mode.play) |
||||
) |
||||
) |
||||
} |
@ -0,0 +1,17 @@ |
||||
(fn dump-contents [filename] |
||||
(let [f (assert (io.open filename)) |
||||
contents (f:read "*all")] |
||||
(f:close) |
||||
contents)) |
||||
|
||||
{ |
||||
:name "rules" |
||||
|
||||
:display (fn [p] |
||||
(print (dump-contents "mode/rules.txt")) |
||||
) |
||||
|
||||
:key-pressed (fn key-pressed [p k set-mode] |
||||
(set-mode :mode.menu) |
||||
) |
||||
} |
@ -0,0 +1,54 @@ |
||||
Okay ceelo is a fun dice game. It is a point-set gambling game, kind of like |
||||
craps, but is more simple, and you play it with three six-sided dice. |
||||
|
||||
== ROLLS == |
||||
|
||||
First, here's what the rolls mean. |
||||
|
||||
1. Win conditions: |
||||
|
||||
- n n n (triples) = instant win. |
||||
|
||||
example: 3 3 3 |
||||
|
||||
- 4 5 6 = instant win |
||||
|
||||
- n n 6 (any doubles + 6) = instant win. e.g. |
||||
|
||||
example: 2 2 6 |
||||
|
||||
2. Loss conditions: |
||||
|
||||
- n n 1 (any doubles + 1) = instant loss |
||||
|
||||
example: 6 6 1 |
||||
|
||||
- 1 2 3 = instant loss |
||||
|
||||
3. Points: |
||||
|
||||
- n n x (doubles + not 6, not 1) = establish a POINT |
||||
|
||||
example: 3 3 4 |
||||
|
||||
|
||||
Reroll: |
||||
|
||||
- anything else = reroll |
||||
|
||||
== PLAY == |
||||
|
||||
Now, here's how to play. |
||||
|
||||
1. Make a bet against the Bank. |
||||
|
||||
2. The Bank will roll and will either win, lose, or establish a point. |
||||
|
||||
3. If a point is established, you get to roll until you win outright or beat |
||||
the point, or lose, or draw. |
||||
|
||||
That's it! Go play! |
||||
|
||||
Press Enter to continue. |
||||
|
||||
|
@ -0,0 +1,6 @@ |
||||
{ |
||||
:cash 100 |
||||
:point 6 |
||||
:bet 20 |
||||
:turn true |
||||
} |
Loading…
Reference in new issue