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 |
||
⚫ | |||
⚫ | |||
#============ 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)] |
||
⚫ | |||
⚫ | |||
""" 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, |
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 |
||
⚫ | |||
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 = |
function UnoCardGameApp(w = 1120, wcan = 810, h = 700) |
||
win = GtkWindow("Uno Card Game", w, |
win = GtkWindow("Uno Card Game", w, h) |> (GtkFrame() |> (hbox = GtkBox(:h))) |
||
vbox = GtkBox(:v) |
|||
can = GtkCanvas( |
can = GtkCanvas(wcan, h) |
||
push!(hbox, can) |
|||
⚫ | |||
⚫ | |||
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") |
|||
⚫ | |||
⚫ | |||
⚫ | |||
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, |
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] |
|||
⚫ | |||
return |
|||
end |
|||
⚫ | |||
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(" |
info_dialog("Click Challenge within 5 seconds to challenge Draw Four") |
||
sleep( |
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 |
||
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" |