euchre-live

Euchre web-app for the socially distant family
git clone git://git.alexkarle.com/euchre-live.git
Log | Files | Refs | README | LICENSE

commit 24f8594070f3b458d6f3bc5500d552245483e77c (patch)
parent 4998a030cad3e1c188b183d5c47a7414b8241b30
Author: Alex Karle <alex@karle.co>
Date:   Sat,  4 Apr 2020 11:55:22 -0400

debug: Add options to vote/pass/play cards!

This exposed a lot of little logic bugs in my play_card and start_turn
methods, which was great! Patching them up with this commit because they
bugs are all over the place, from not returning, to not importing `sum`,
to just Perl syntax whoopsies.

It's coming together!

Diffstat:
Mlib/Euchre/Dealer.pm | 47++++++++++++++++++++++++++++++++++-------------
Mpublic/debug.html | 40+++++++++++++++++++++++++++++++++++-----
2 files changed, 69 insertions(+), 18 deletions(-)

diff --git a/lib/Euchre/Dealer.pm b/lib/Euchre/Dealer.pm @@ -4,7 +4,7 @@ use warnings; package Euchre::Dealer; -use List::Util; +use List::Util qw(sum); use Euchre::Card; use Euchre::Game; @@ -181,6 +181,7 @@ sub take_seat { if (defined $game->{players}->[$seat]) { send_error($p, 'Seat is taken'); + return; } else { # Move from standing (or sitting) to sitting stand_up($p) if defined $p->{seat}; @@ -219,10 +220,11 @@ sub start_game { if (num_players($game->{id}) < 4) { send_error($p, "Can't start with empty seats!"); - } else { - # TODO: kick spectators out? - # TODO: deal! + return; } + + # TODO: kick spectators out? + # TODO: deal! start_new_round($game); } @@ -237,10 +239,11 @@ sub start_new_round { # Shift dealer and deal $game->{dealer} = ($game->{dealer} + 1 % 4); $game->{table} = []; + $game->{tricks} = [0,0,0,0]; deal_players_hands($game); # Signal vote of player next to dealer... - $game->{turn} = ($game->{dealer} + 1 % 4); + reset_turn($game); $game->{phase} = 'vote'; $game->{pass_count} = 0; broadcast_gamestate($game); # includes trump_nominee @@ -272,7 +275,7 @@ sub vote_trump { my $game = $p->{game}; if ($msg->{vote} eq 'pass') { - $game->{turn} = ($game->{turn} + 1 % 4); + next_turn($game); $game->{pass_count}++; if ($game->{pass_count} >= 8) { # Throw em in @@ -287,10 +290,10 @@ sub vote_trump { $game->{trump} = suit_to_id($msg->{vote}); $game->{caller} = $p->{seat}; $game->{phase} = 'play'; - $game->{turn} = ($game->{dealer} + 1 % 4); + reset_turn($game); broadcast_gamestate($game); } else { - send_error("Bad vote"); + send_error($p, "Bad vote"); } } @@ -304,23 +307,27 @@ sub play_card { # Update the table and current player push @{$game->{table}}, $msg->{card}; - $game->{turn} = ($game->{turn} + 1 % 4); # XXX: loner turn + next_turn($game); - if (@{$game->{table} >= 4}) { + if (@{$game->{table}} >= 4) { # End trick -- update tricks, clear table, and set current player my @table = map { cname_to_id($_) } @{$game->{table}}; my $winner_id = trick_winner($game->{trump}, @table); + # this is the id in TABLE, not players + # at this point turn is back to the start... + $winner_id = ($winner_id + $game->{turn}) % 4; + $game->{tricks}->[$winner_id]++; - $game->{table} = []; $game->{turn} = $winner_id; + $game->{table} = []; if (sum(@{$game->{tricks}}) >= 5) { # End round -- update scores, clear tricks, push dealer my ($team_id, $score) = score_round($game->{caller}, @{$game->{tricks}}); - $game->{scores}->[$team_id] += $score; + $game->{score}->[$team_id] += $score; - if ($game->{scores}->[$team_id] >= 10) { + if ($game->{score}->[$team_id] >= 10) { # End game... no need to redeal signal_game_end($game); } else { @@ -381,4 +388,18 @@ sub send_error { $ws->send({ json => $json}); } +sub next_turn { + my ($game) = @_; + + $game->{turn} = ($game->{turn} + 1) % 4; + # XXX pass again if loner! +} + +sub reset_turn { + my ($game) = @_; + + $game->{turn} = ($game->{dealer} + 1) % 4; + # XXX pass again if loner! +} + 1; diff --git a/public/debug.html b/public/debug.html @@ -21,18 +21,35 @@ gameState = '<br>Game: ' + msg.game.id + '<br>' + 'Players: ' + msg.game.players + '<br>' + 'Spectators: ' + msg.game.spectators + '<br>' + - 'Game Phase: ' + msg.game.phase + '<br>' + 'Game Phase: ' + msg.game.phase + '<br>' + + 'Player Turn: ' + msg.game.turn + '<br>' + + 'Dealer: ' + msg.game.dealer + '<br>' + + 'Trump: ' + msg.game.trump + '<br>' + + 'Tricks: ' + msg.game.tricks + '<br>' + + 'Score: ' + msg.game.score + '<br>' - if (typeof msg.game.trump_nominee !== 'undefined') { - gameState += 'Trump Nominee: ' + '<img class="card" src="cards/' + msg.game.trump_nominee + '.svg"><br>' + if (typeof msg.game.trump_nominee !== 'undefined') { + gameState += 'Trump Nominee: ' + '<img class="card" src="cards/' + msg.game.trump_nominee + '.svg"><br>' + vote_trump_suit = msg.game.trump_nominee.substring(1,2); + } + + if (msg.game.table.length) { + document.getElementById('table').innerHTML = '' + for (var i = 0; i < msg.game.table.length; i++) { + var c = msg.game.table[i] + document.getElementById('table').innerHTML += '<img class="card" src="cards/' + c + '.svg">' } + } else { + document.getElementById('table').innerHTML = 'No cards on table' + } document.getElementById('game').innerHTML = gameState } else if (msg.msg_type === 'error') { document.getElementById('error').innerHTML += msg.msg + '<br>' } else if (msg.msg_type === 'deal') { document.getElementById('hand').innerHTML = 'HAND: <br>' for (var i = 0; i < msg.hand.length; i++) { - document.getElementById('hand').innerHTML += '<img class="card" src="cards/' + msg.hand[i] + '.svg">' + var c = msg.hand[i] + document.getElementById('hand').innerHTML += '<img onclick="play(' + "'" + c + "'" + ')" class="card" src="cards/' + c + '.svg">' } } }; @@ -53,6 +70,15 @@ function start_game() { ws.send(JSON.stringify({action:'start_game'})) } + function vote() { + ws.send(JSON.stringify({action:'vote_trump', vote: vote_trump_suit})) + } + function pass() { + ws.send(JSON.stringify({action:'vote_trump', vote: 'pass'})) + } + function play(card) { + ws.send(JSON.stringify({action:'play_card', card: card})) + } </script> <h1>Hello, World</h1> @@ -73,8 +99,12 @@ <br><br> <div id="game">Not in a game</div> <br><br> + <div id="table">No cards on table</div> + <br> <br> <div id="hand">No cards in hand</div> - <div id="nominee"></div> + <br> + <button onclick="vote()">Vote Trump</button> + <button onclick="pass()">Pass</button> <br><br> <div id="error" style="color:red"> </div> </body>