Uno (Card Game)/Julia: Difference between revisions

Content added Content deleted
m (add scoring)
m (move logging area to side)
Line 4: Line 4:
<lang julia>using Random, Colors, Gtk, Cairo
<lang julia>using Random, Colors, Gtk, Cairo


#=========== Channel section ===================#
#=========== Channel and flag (IPC) section ===================#


""" channel, communicates player's mouse choice of card or color to game logic """
""" channel, communicates player's mouse choice of card or color to game logic """
Line 11: Line 11:
""" flush the channel from mouse choice to game logic """
""" flush the channel from mouse choice to game logic """
flushchannel() = while !isempty(channel) take!(channel); end
flushchannel() = while !isempty(channel) take!(channel); end

""" challenge flag: true if challenge taken by player """
const challenge = [false]


#============ Game play section ==================#
#============ Game play section ==================#
Line 59: Line 62:
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 flags: taken by player, display button """
const challenge = [false, 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 162: Line 161:
hand = game.players[game.pnow].hand
hand = game.players[game.pnow].hand
if any(i -> color(hand[i]) != "Wild", playableindices(game))
if any(i -> color(hand[i]) != "Wild", playableindices(game))
logline("Challenge sustained! Challenged player draws 4.")
logline("Challenge sustained! Challenged Draw Four player draws 4.")
drawcardsfromdeck!(game, 4)
drawcardsfromdeck!(game, 2); drawcardsfromdeck!(game, 2)
game.pnow, game.colornow = challenger, savecolor
game.pnow, game.colornow = challenger, savecolor
return
return
Line 172: Line 171:
game.pnow, game.colornow = challenger, savecolor
game.pnow, game.colornow = challenger, savecolor
end
end
challenge[begin] = false
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").")
Line 334: Line 334:
const cairocolor = Dict("Red" => colorant"red", "Yellow" => colorant"gold",
const cairocolor = Dict("Red" => colorant"red", "Yellow" => colorant"gold",
"Green" => colorant"green", "Blue" => colorant"blue", "Wild" => colorant"black")
"Green" => colorant"green", "Blue" => colorant"blue", "Wild" => colorant"black")

function colorbutton(txt::String, clr::String)
button = GtkButton(txt)
sc = Gtk.GAccessor.style_context(button)
pr = Gtk.CssProviderLeaf(data="button {color:$(clr); font-weight: bolder}")
push!(sc, Gtk.StyleProvider(pr), 600)
return button
end


""" Draw a UnoCard as a rectangle with rounded corners. """
""" Draw a UnoCard as a rectangle with rounded corners. """
Line 403: Line 411:
Uno card game Gtk app. Draws game on a canvas, logs play on box below canvas.
Uno card game Gtk app. Draws game on a canvas, logs play on box below canvas.
"""
"""
function UnoCardGameApp(w = 864, hcan = 700, hlog = 100)
function UnoCardGameApp(w = 1120, wcan = 810, h = 700)
win = GtkWindow("Uno Card Game", w, hcan + hlog) |> (GtkFrame() |> (vbox = GtkBox(:v)))
win = GtkWindow("Uno Card Game", w, h) |> (GtkFrame() |> (hbox = GtkBox(:h)))
swin = GtkScrolledWindow()
vbox = GtkBox(:v)
can = GtkCanvas(w, hcan)
can = GtkCanvas(wcan, h)
set_gtk_property!(can, :expand, true)
push!(hbox, can)
push!(swin, can)
push!(vbox, swin)
push!(vbox, logwindow) # from log section
push!(vbox, logwindow) # from log section
set_gtk_property!(logwindow, :expand, true)
b, g = colorbutton("Blue", "blue"), colorbutton("Green", "green")
r, y = colorbutton("Red", "red"), colorbutton("Yellow", "gold")
chal = GtkButton("Challenge")
signal_connect(w -> push!(channel, "Blue"), b, "clicked")
signal_connect(w -> push!(channel, "Green"), g, "clicked")
signal_connect(w -> push!(channel, "Red"), r, "clicked")
signal_connect(w -> push!(channel, "Yellow"), y, "clicked")
signal_connect(w -> (challenge[begin] = true), chal, "clicked")
push!(vbox, b, g, r, y, chal)
push!(hbox, vbox)
fontpointsize = w / 50
fontpointsize = w / 50
cardpositions = Dict{Int, Vector{Int}}()
cardpositions = Dict{Int, Vector{Int}}()

colorpositions = Dict("Red" => [280, 435, 320, 475], "Yellow" => [340, 435, 380, 475],
# announce the rules and penalties per task description
"Green" => [400, 435, 440, 475], "Blue" => [460, 435, 500, 475])
info_dialog(unodocshtml, win)
challengeposition = [300, 475, 470, 465]

# create a game instance to start play
game = UnoCardGameState()
game = UnoCardGameState()


Line 430: Line 449:
color = colorant"navy"
color = colorant"navy"
set_source(ctx, color)
set_source(ctx, color)
move_to(ctx, 360, 400)
move_to(ctx, 360, 420)
show_text(ctx, game.players[1].name)
show_text(ctx, game.players[1].name)
stroke(ctx)
stroke(ctx)
Line 444: Line 463:
cairocard(ctx, last(game.discardpile), 350, 240, 40, 80)
cairocard(ctx, last(game.discardpile), 350, 240, 40, 80)
cairodrawfacedowncard(ctx, 410, 240, 40, 80)
cairodrawfacedowncard(ctx, 410, 240, 40, 80)
if challenge[end]
set_source(ctx, colorant"black")
move_to(ctx, challengeposition[1], challengeposition[2])
show_text(ctx, "Challenge Draw Four")
stroke(ctx)
else
for (i, p) in enumerate(colorpositions)
set_source(ctx, cairocolor[first(p)])
x0, y0, x1, y1 = last(p)
rectangle(ctx, x0, y0, 40, 40)
fill(ctx)
end
end
hand = first(game.players).hand
hand = first(game.players).hand
isempty(hand) && return
isempty(hand) && return
Line 473: Line 479:
""" Gtk mouse callback: translates valid mouse clicks to a channel item """
""" Gtk mouse callback: translates valid 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
x0, y0, x1, y1 = last(p)
if x0 < evt.x < x1 && y0 < evt.y < y1
push!(channel, first(p))
return
end
end
for p in cardpositions
for p in cardpositions
x0, y0, x1, y1 = last(p)
x0, y0, x1, y1 = last(p)
Line 495: Line 488:
end
end


# do the turns of play in the game, keeping score totals from the rounds
for n in 1:1000
for n in 1:1000
draw(can)
draw(can)
Line 502: Line 496:
if startswith(game.players[game.pnow].name, "Play") &&
if startswith(game.players[game.pnow].name, "Play") &&
type(game.discardpile[end]) == "Draw Four" && game.commandsvalid
type(game.discardpile[end]) == "Draw Four" && game.commandsvalid
challenge[end] = true
draw(can)
draw(can)
Gtk.showall(win)
Gtk.showall(win)
info_dialog("Choose Challenge to challenge a Draw Four")
info_dialog("Click Challenge within 5 seconds to challenge Draw Four")
sleep(5)
sleep(3)
challenge[end] = false
end
end
sleep(2)
sleep(2)
Line 516: Line 508:
if type(game.discardpile[end]) == "Draw Two"
if type(game.discardpile[end]) == "Draw Two"
nextplayer!(game) # next player might have to draw before scoring done
nextplayer!(game) # next player might have to draw before scoring done
drawcards(game, 2)
drawcardsfromdeck!(game, 2)
elseif type(game.discardpile[end]) == "Draw Four"
elseif type(game.discardpile[end]) == "Draw Four"
nextplayer!(game)
nextplayer!(game)
drawcardsfromdeck(game, 2)
drawcardsfromdeck!(game, 2)
drawcardsfromdeck(game, 2) # D2 twice because not to be contested as a D4
drawcardsfromdeck!(game, 2) # D2 twice because not to be contested as a D4
end
end
roundpoints = sum(x -> handscore(x.hand), game.players)
roundpoints = sum(x -> handscore(x.hand), game.players)
Line 528: Line 520:
info_dialog("The winner of round $n is $(game.players[winner].name).\n" *
info_dialog("The winner of round $n is $(game.players[winner].name).\n" *
"Winner gains $roundpoints points.", win)
"Winner gains $roundpoints points.", win)
logline("Scores: $([x.score for x in game.players])")
if any(x -> x.score >= 500, game.players)
if any(x -> x.score >= 500, game.players)
s = "Game over. Scores:\n\n"
s = "Game over. Scores:\n\n"