Created
May 29, 2013 05:44
-
-
Save strager/5668203 to your computer and use it in GitHub Desktop.
Tic-tac-toe CLI game in Kitten
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def concat ([[a]] -> [a]): (a)[] ([a] [a] -> [a]){ + } foldDown | |
def ; ([a] a -> [a]): push | |
def show_board_cell (Char -> Char){ } | |
def cell_number_to_index (Int -> Int): | |
8 __swap - | |
def show_board_cell_at ([Char] Int -> Char): | |
cell_number_to_index get | |
show_board_cell | |
def show_board_row ([Char] Int -> [Char]): | |
->row_index | |
->b | |
row_index 3 * ->i | |
([Char])[] | |
' '; b 0 i + show_board_cell_at; | |
'|'; b 1 i + show_board_cell_at; | |
'|'; b 2 i + show_board_cell_at; | |
def show_board ([Char] -> [Char]): | |
->b | |
([Char])[] | |
" A B C\n"; | |
"1 "; b 0 show_board_row; "\n"; | |
" --+-+--\n"; | |
"2 "; b 1 show_board_row; "\n"; | |
" --+-+--\n"; | |
"3 "; b 2 show_board_row; "\n"; | |
concat | |
def print_board ([Char] ->): | |
show_board print | |
def new_board (-> [Char]): | |
[ ' ', ' ', ' ' | |
, ' ', ' ', ' ' | |
, ' ', ' ', ' ' | |
] | |
def any ([a] (a -> Bool) -> Bool): | |
map or | |
def all ([a] (a -> Bool) -> Bool): | |
map and | |
def elem ([a] a -> Bool): | |
->x | |
(Char -> Bool){ x = } any | |
def read_x (Char -> Int): | |
->c | |
if "aA" c elem: 0 | |
else if "bB" c elem: 1 | |
else if "cC" c elem: 2 | |
else: -1 | |
def read_y (Char -> Int): | |
->c | |
if "1!" c elem: 0 | |
else if "2@" c elem: 1 | |
else if "3#" c elem: 2 | |
else: -1 | |
def read_xy_ (Char Char -> Int Int Bool): | |
read_y ->y | |
read_x ->x | |
if x 0 >= y 0 >= &&: | |
x y true | |
else: | |
0 0 false | |
def read_xy (Char Char -> Int Int Bool): | |
->y | |
->x | |
x y read_xy_ | |
if: | |
true | |
else: | |
drop drop | |
y x read_xy_ | |
def read_move_line ([Char] -> Int Int Bool): | |
->chars | |
if chars length 2 =: | |
chars 1 get | |
chars 0 get | |
read_xy | |
else: | |
0 0 false | |
def xy_to_cell_number (Int Int -> Int): | |
->x ->y | |
y 3 * | |
x + | |
def edit_board ([Char] Int Char -> [Char]): | |
->c | |
->i | |
c | |
i cell_number_to_index | |
set | |
def infloop (->): infloop | |
def exit (->): | |
"Tell Jon to let me go!\n" print infloop | |
def ask_turn ([Char] Char -> [Char]): | |
->player | |
->board | |
board print_board | |
"It is " player push "'s turn. Choose your move: "+ | |
stdout __print | |
getLine ->input | |
input read_move_line | |
->parsed ->x ->y | |
if parsed: | |
board | |
x y xy_to_cell_number | |
player edit_board | |
else if input "q" =: | |
exit board | |
else: | |
"I didn't understand that. Type e.g. \"a3\" to " | |
"move in the bottom-left cell. Type \"q\" to exit.\n"+ | |
stdout __print | |
board player ask_turn | |
def next_player (Char -> Char): | |
if 'x' =: 'o' | |
else: 'x' | |
def gets ([a] [Int] -> [a]): | |
->indices | |
->xs | |
indices (Int -> a){ xs swap get } map | |
def check_sets (-> [[Int]]): | |
([[Int]])[] | |
// Rows | |
[0, 1, 2]; [3, 4, 5]; [6, 7, 8]; | |
// Columns | |
[0, 3, 6]; [1, 4, 7]; [2, 5, 8]; | |
// Diagonals | |
[0, 4, 8]; [2, 4, 6]; | |
// ' ', 'x', or 'o' | |
def get_check_set_winner ([Char] [Int] -> Char): | |
gets ->players | |
if players (Char -> Bool){ 'x' = } all: | |
'x' | |
else if players (Char -> Bool){ 'o' = } all: | |
'o' | |
else: | |
' ' | |
// ' ', 'x', 'o', or '*' | |
def get_winner ([Char] -> Char): | |
->board | |
board (Char -> Bool){ ' ' = } filter empty | |
->filled | |
if filled: | |
'*' | |
else: | |
check_sets | |
([Int] -> Char){ board swap get_check_set_winner } map | |
(Char -> Bool){ ' ' != } filter | |
->winners | |
if winners empty: | |
' ' | |
else if winners (Char -> Bool){ 'x' = } all: | |
'x' | |
else if winners (Char -> Bool){ 'o' = } all: | |
'o' | |
else: | |
'*' | |
def game_loop ([Char] Char -> [Char] Char): | |
->player | |
dup get_winner ->winner | |
if "xo*" winner elem: | |
winner | |
else: | |
player ask_turn | |
player next_player game_loop | |
def game (->): | |
new_board 'x' game_loop | |
->winner | |
->final_board | |
newline | |
if winner '*' =: | |
"It's a tie!\n" print | |
else: | |
winner " wins!\n" prepend stdout __print | |
final_board print_board | |
def pass (->){ } | |
def loop ((-> Bool) ->): | |
->f | |
if f __apply: | |
f loop | |
else: | |
pass | |
def prompt_play_another (-> Bool): | |
"Play another game? [yN] " print | |
getLine ->input | |
if input (Char -> Bool){ "yY" swap elem } any: | |
newline | |
true | |
else if input (Char -> Bool){ "nN" swap elem } any: | |
newline | |
false | |
else if input empty: | |
newline | |
false | |
else: | |
prompt_play_another | |
def main (->): | |
(-> Bool){ game prompt_play_another } loop | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment