Skip to content

Instantly share code, notes, and snippets.

@Lorenzobattistela
Created July 2, 2024 22:07
Show Gist options
  • Save Lorenzobattistela/1484a94f29cd5225fc4e0fec3b25f37f to your computer and use it in GitHub Desktop.
Save Lorenzobattistela/1484a94f29cd5225fc4e0fec3b25f37f to your computer and use it in GitHub Desktop.
UNO! This is a 2 player uno simulation written in bend!
# --------------------------
# optimization possibility: use List/got instead of successive removes + igets
type Option:
None
Some { value }
def List/got(idx,list):
switch idx:
case 0:
match list:
case List/Nil:
return (Option/None, [])
case List/Cons:
return (Option/Some(list.head), list.tail)
case _:
match list:
case List/Nil:
return (Option/None, [])
case List/Cons:
(elem, tail) = List/got((idx - 1), list.tail)
return (elem, List/Cons(list.head, tail))
# ----------------------------------------------
# simple uno simulation written in bend!
TIE = 4
P2_WIN = 3
P1_WIN = 2
TRUE = 1
FALSE = 0
# a card is a tuple (Color, number)
type Color:
red
green
blue
yellow
type Turn:
p1
p2
def get_color_id(color):
match color:
case Color/red:
return 1
case Color/green:
return 2
case Color/blue:
return 3
case Color/yellow:
return 4
def get_color(color_id):
switch color_id:
# defaulting to red, it should not happen though since we use % 4 in rnd
case 0:
return Color/red
case 1:
return Color/red
case 2:
return Color/green
case 3:
return Color/blue
case 4:
return Color/yellow
case _:
return Color/red
# uno supports cards from 1-9
def generate_deck(n, seed):
bend n, state=1:
when n != 0:
state = state ^ (state << 13)
state = state ^ (state >> 17)
state = state ^ (state << 5)
state = state ^ (state << seed)
color_id = state % 4 + 1
color = get_color(color_id)
return List/Cons(((state % 9) + 1, color), fork(n - 1, state))
else:
return List/Nil
def deck_length(deck):
fold deck with idx = 0:
case List/Nil:
return idx
case List/Cons:
return deck.tail(idx + 1)
# returns the index of the card picked
def pick_card(deck, table_card):
fold deck with idx = 0:
case List/Nil:
# for now we can use 10 (not sure abt neg numbers yet), but this assumes we cant pick up new cards from a suffled deck
# this is for simplicity now
return 10
case List/Cons:
# check if card is of the same color or same number
(number, color) = table_card
table_card_cpy = (number, color)
color_id = get_color_id(color)
(h_num, h_color) = deck.head
head_id = get_color_id(h_color)
# check for matching colors
if color_id == head_id:
return idx
else:
if number == h_num:
return idx
else:
return deck.tail(idx + 1)
def iget(deck, idx):
match deck:
case List/Nil:
return List/Nil
case List/Cons:
if idx == 0:
return deck.head
else:
return iget(deck.tail, idx - 1)
def remove(deck, card_idx):
match deck:
case List/Nil:
return List/Nil
case List/Cons:
if card_idx == 0:
return deck.tail
else:
return List/Cons(deck.head, remove(deck.tail, card_idx - 1))
def empty_deck(deck):
match deck:
case List/Nil:
return TRUE
case List/Cons:
return FALSE
def play(p1_deck, p2_deck, table_card, turn, turns_with_no_play):
if turns_with_no_play == 2:
return (TIE, (p1_deck, p2_deck))
else:
empty_p1 = empty_deck(p1_deck)
empty_p2 = empty_deck(p2_deck)
if empty_p1 == TRUE:
if empty_p2 == TRUE:
return "BOTH ARE EMPTY. SOMETHING WENT WRONG!"
else:
return (P1_WIN, 0)
else:
if empty_p2 == TRUE:
return (P2_WIN, 0)
else:
match turn:
case Turn/p1:
picked = pick_card(p1_deck, table_card)
if picked == 10:
return play(p1_deck, p2_deck, table_card, Turn/p2, turns_with_no_play + 1)
else:
# i need the card here to rec call with the new table_card
new_table_card = iget(p1_deck, picked)
p1_deck_new = remove(p1_deck, picked)
return play(p1_deck_new, p2_deck, new_table_card, Turn/p2, 0)
case Turn/p2:
picked = pick_card(p2_deck, table_card)
if picked == 10:
return play(p1_deck, p2_deck, table_card, Turn/p1, turns_with_no_play + 1)
else:
new_table_card = iget(p2_deck, picked)
p2_deck_new = remove(p2_deck, picked)
return play(p1_deck, p2_deck_new, new_table_card, Turn/p1, 0)
def untie(p1_d, p2_d):
p1_d_length = deck_length(p1_d)
p2_d_length = deck_length(p2_d)
if (p1_d_length == p2_d_length):
return "It is indeed a tie!"
else:
diff = p1_d_length - p2_d_length
# if diff is less than 9, it means p2 won. we cant check for negs cause in this case it will return the shifted number
if diff > 9:
return "Player 2 won because he has less cards!"
else:
return "Player 1 won because he has less cards!"
def get_game_result_str(game_result_t):
(game_result, decks) = game_result_t
switch game_result:
case 0:
return "Whoops. Something went wrong."
case 1:
return "Whoops. Something went wrong."
case 2:
return "Player 1 Wins!"
case 3:
return "Player 2 Wins!"
case 4:
(p1_deck, p2_deck) = decks
return untie(p1_deck, p2_deck)
case _:
return "Something went wrong"
def main():
init_card = (1, Color/red)
# writing a simple test!
# p1_deck = [(2, Color/red), (4, Color/yellow), (8, Color/green)]
# p2_deck = [(2, Color/yellow), (4, Color/green), (1, Color/red)]
# result should be p1 wins! because p1 will have no cards wile p2 will have (1, Color/red)
# maybe it should be possible to simulate various rounds with different start players
# here ez win for p2!
p1_deck = [(1, Color/red), (4, Color/yellow), (8, Color/green)]
p2_deck = [(1, Color/red), (1, Color/red), (1, Color/red)]
# a random simulation of one round could happen simply by redefinining player decks:
# its possible also to randomize the init card
# 213 is just a seed so we dont get same cards for the 2 players
# p1_deck = generate_deck(9, 213)
# p2_deck = generate_deck(9, 100)
# to extend this implementation, some ideas are:
# refactor to have a list of players instead of 2 of them and alternate rounds between them
# the ability to pick a card from a shuffled deck when you have no options
# add "power cards" such as +2, block, etc.
# for now these are out of scope for a 30/40 min project
# another thing to do is to use the List/Got in the top of the file to enhance performance
game_res = play(p1_deck, p2_deck, init_card, Turn/p1, 0)
str_res = get_game_result_str(game_res)
return str_res
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment