Uno (Card Game)/Julia: Difference between revisions

Content added Content deleted
m (→‎Gtk based graphical version.: change display of large hands)
m (add challenge methods)
Line 36: Line 36:
pnow::Int
pnow::Int
colornow::String
colornow::String
lastcolor::String
clockwise::Bool
clockwise::Bool
commandsvalid::Bool
commandsvalid::Bool
Line 56: Line 57:
const originaldeck = [vec([UnoCard(c, v) for v in ttypes, c in colors]);
const originaldeck = [vec([UnoCard(c, v) for v in ttypes, c in colors]);
fill(UnoCard("Wild", "Wild"), 4); fill(UnoCard("Wild", "Draw Four"), 4)]
fill(UnoCard("Wild", "Wild"), 4); fill(UnoCard("Wild", "Draw Four"), 4)]

""" challenge flag """
const challenge = [false]


""" Set the next player to play to game.pnow (clockwise or counterclockwise) """
""" Set the next player to play to game.pnow (clockwise or counterclockwise) """
Line 91: Line 95:
game = UnoCardGameState(drawpile, discardpile, [UnoCardGamePlayer(playernames[i],
game = UnoCardGameState(drawpile, discardpile, [UnoCardGamePlayer(playernames[i],
startswith(playernames[i], "Bot") ? true : false, hands[i])
startswith(playernames[i], "Bot") ? true : false, hands[i])
for i in 1:length(playernames)], 1, "Wild", true, true)
for i in 1:length(playernames)], 1, "Wild", "Wild", true, true)
dealer = rand(1:length(playernames))
dealer = rand(1:length(playernames))
logline("Player $(playernames[dealer]) is dealer.")
logline("Player $(playernames[dealer]) is dealer.")
Line 134: Line 138:
""" Current player to draw n cards from the draw pile. """
""" Current player to draw n cards from the draw pile. """
function drawcardsfromdeck!(game, n=1)
function drawcardsfromdeck!(game, n=1)
if n == 4 # draw four
# bot will challenge half the time, player must challenge in 5 seconds.
if game.players[game.pnow].isabot && rand() < 0.5 ||
(!game.players[game.pnow].isabot && challenge[begin] == true)
challenge[begin] = false
logline("$(game.players[game.pnow].name) challenged Draw Four!")
challenger, savecolor = game.pnow, game.colornow
nextplayer!(game); nextplayer!(game); nextplayer!(game); # prior player
game.colornow = game.lastcolor
indices = playableindices(game)
hand = game.players[game.pnow].hand
if any(i -> color(hand[i]) != "Wild", playableindices(game))
logline("Challenge sustained! Challenged playerr draws 4.")
drawcardsfromdeck!(game, 4)
game.pnow, game.colornow = challenger, savecolor
return
else
logline("Challenge fails. Challenging player now draws 6.")
n = 6
end
game.pnow, game.colornow = challenger, savecolor
end
end
logline("Player $(game.players[game.pnow].name) draws $n card$(n == 1 ? "" : "s").")
logline("Player $(game.players[game.pnow].name) draws $n card$(n == 1 ? "" : "s").")
for _ in 1:n
for _ in 1:n
Line 144: Line 171:


Current player to discard card at index idx in hand (last card in hand as default).
Current player to discard card at index idx in hand (last card in hand as default).
Handle wild cartd discard by having current player choose the new game.colornow.
Handle wild card discard by having current player choose the new game.colornow.
"""
"""
function discard!(game, idx = -1)
function discard!(game, idx = -1)
Line 154: Line 181:
lastdiscard = last(game.discardpile)
lastdiscard = last(game.discardpile)
logline("Player $(game.players[game.pnow].name) discarded $lastdiscard")
logline("Player $(game.players[game.pnow].name) discarded $lastdiscard")
game.lastcolor = game.colornow
if color(lastdiscard) == "Wild" # wild card discard, so choose a color to be colornow
if color(lastdiscard) == "Wild" # wild card discard, so choose a color to be colornow
choosecolor!(game)
choosecolor!(game)
Line 176: Line 204:
game.commandsvalid = false
game.commandsvalid = false
if mtype == "Draw Four"
if mtype == "Draw Four"
logline("$name must draw four.")
drawcardsfromdeck!(game, 4)
drawcardsfromdeck!(game, 4)
elseif mtype == "Draw Two"
elseif mtype == "Draw Two"
logline("$name must draw two.")
drawcardsfromdeck!(game, 2)
drawcardsfromdeck!(game, 2)
elseif mtype == "Skip" # skip, no uno check
elseif mtype == "Skip" # skip, no uno check
Line 241: Line 267:
logline("Current color is now $(game.colornow).")
logline("Current color is now $(game.colornow).")
end
end

#================ required documentation section ======================#

const unodocshtml = """
Official Rules For Uno Card Game

The aim of the game is to be the first player to score 500 points, achieved (usually over several rounds of play) by being the first to play all of one's own cards and scoring points for the cards still held by the other players.


The deck consists of 108 cards: four each of "Wild" and "Wild Draw Four", and 25 each of four colors (red, yellow, green, blue). Each color consists of one zero, two each of 1 through 9, and two each of "Skip", "Draw Two", and "Reverse". These last three types are known as "action cards".


To start a hand, seven cards are dealt to each player, and the top card of the remaining deck is flipped over and set aside to begin the discard pile. The player to the dealer's left plays first unless the first card on the discard pile is an action or Wild card (see below). On a player's turn, they must do one of the following:
* play one card matching the discard in color, number, or symbol
* play a Wild card, or a playable Wild Draw Four card (see restriction below)
* draw the top card from the deck, then play it if possible

Cards are played by laying them face-up on top of the discard pile. Play proceeds clockwise around the table.

Action or Wild cards have the following effects:

===============================================================================================================================================================
Card Effect when played from hand Effect as first discard
---------------------------------------------------------------------------------------------------------------------------------------------------------------
Skip Next player in sequence misses a turn Player to dealer's left misses a turn
Reverse Order of play switches directions (clockwise to counterclockwise, or vice versa) Dealer plays first; play proceeds counterclockwise
Draw Two Next player in sequence draws two cards and misses a turn Player to dealer's left draws two cards and misses a turn
Wild Player declares the next color to be matched ; current color may be chosen Player to dealer's left declares the first color to be matched and plays a card in it
Wild Draw Four Player declares the next color to be matched; next player in sequence draws four Return card to the deck, shuffle, flip top card to start discard pile

A player who draws from the deck must either play or keep that card and may play no other card from their hand on that turn.

A player may play a Wild card at any time, even if that player has other playable cards.

A player may play a Wild Draw Four card only if that player has no cards matching the current color. The player may have cards of a different color matching the current number or symbol or a Wild card and still play the Wild Draw Four card.[5] A player who plays a Wild Draw Four may be challenged by the next player in sequence (see Penalties) to prove that their hand meets this condition.

If the entire deck is used during play, the top discard is set aside and the rest of the pile is shuffled to create a new deck. Play then proceeds normally.

It is illegal to trade cards of any sort with another player.

A player who plays their next-to-last-card must call "uno" as a warning to the other players.[6]

The first player to get rid of their last card ("going out") wins the hand and scores points for the cards held by the other players. Number cards count their face value, all action cards count 20, and Wild and Wild Draw Four cards count 50. If a Draw Two or Wild Draw Four card is played to go out, the next player in the sequence must draw the appropriate number of cards before the score is tallied.

The first player to score 500 points wins the game.

Penalties
=========
If a player does not call "uno" after laying down their next-to-last card and is caught before the next player in sequence takes a turn (i.e., plays a card from their hand, draws from the deck, or touches the discard pile), they must draw two cards as a penalty. If the player is not caught in time (subject to interpretation) or remembers to call "uno" before being caught, they suffer no penalty.

If a player plays a Wild Draw Four card, the following player can challenge its use. The player who used the Wild Draw Four must privately show their hand to the challenging player, in order to demonstrate that they had no matching colored cards. If the challenge is correct, then the challenged player draws four cards instead. If the challenge is wrong, then the challenger must draw six cards; the four cards they were already required to draw plus two more cards.

"""




Line 340: Line 419:
colorpositions = Dict("Red" => [280, 435, 320, 475], "Yellow" => [340, 435, 380, 475],
colorpositions = Dict("Red" => [280, 435, 320, 475], "Yellow" => [340, 435, 380, 475],
"Green" => [400, 435, 440, 475], "Blue" => [460, 435, 500, 475])
"Green" => [400, 435, 440, 475], "Blue" => [460, 435, 500, 475])
challengeposition = [300, 492, 470, 482]
game = UnoCardGameState()
game = UnoCardGameState()


Line 374: Line 454:
fill(ctx)
fill(ctx)
end
end
set_source(ctx, colorant"black")
move_to(ctx, challengeposition[1], challengeposition[2])
show_text(ctx, "Challenge Draw Four")
stroke(ctx)
hand = first(game.players).hand
hand = first(game.players).hand
isempty(hand) && return
isempty(hand) && return
Line 390: Line 474:
""" Gtk mouse callback: translates vaild mouse clicks to a channel item """
""" Gtk mouse callback: translates vaild mouse clicks to a channel item """
signal_connect(can, "button-press-event") do b, evt
signal_connect(can, "button-press-event") do b, evt
if challengeposition[1] < evt.x < challengeposition[3] &&
challengeposition[4] < evt.y < challengeposition[2]
challenge[begin] = true
return
end
challenge[begin] = false
for p in colorpositions
for p in colorpositions
x0, y0, x1, y1 = last(p)
x0, y0, x1, y1 = last(p)
Line 406: Line 496:
end
end


info_dialog(unodocshtml, win)
draw(can)
draw(can)
Gtk.showall(win)
Gtk.showall(win)
while !any(i -> isempty(game.players[i].hand), 1:4)
while !any(i -> isempty(game.players[i].hand), 1:4)
turn!(game)
turn!(game)
if type(game.discardpile[end]) == "Draw Four" && game.pnow == 1
sleep(3)
draw(can)
show(can)
info_dialog("Choose Challenge to challenge a Draw Four")
sleep(5)
end
sleep(2)
draw(can)
draw(can)
show(can)
show(can)