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 30a6c299415a6450a8751477a507397fb39c9b18 (patch)
parent 638f7769babb1016e2a0ddfcf88aaaffb753321b
Author: Alex Karle <alex@karle.co>
Date:   Sun, 29 Mar 2020 01:02:13 -0400

Dealer: Add sit/stand routines, with basic html test

This adds two new routines for the pre-game state management: take_seat
and stand_up. These two will be crucial for players to form teams,
moving from spectator status to a full player.

Some basic testing found it to be robust enough to push.

The other notable big change to state management is that the Empty seats
will all be 'undef' to simplify the standing up logic.

Diffstat:
Mlib/Euchre/Dealer.pm | 51+++++++++++++++++++++++++++++++++++++++++++++++----
Mpublic/index.html | 15++++++++++++++-
2 files changed, 61 insertions(+), 5 deletions(-)

diff --git a/lib/Euchre/Dealer.pm b/lib/Euchre/Dealer.pm @@ -94,6 +94,8 @@ sub handle_msg { my %dispatch = ( # Game management endpoints join_game => \&join_game, + take_seat => \&take_seat, + stand_up => \&stand_up, ); if (exists $dispatch{$msg->{action}}) { @@ -114,7 +116,7 @@ sub join_game { if (!exists $GAMES{$id}) { $GAMES{$id} = { id => $id, - players => [], + players => [undef, undef, undef, undef], spectators => [], turn => -1, dealer => -1, @@ -127,7 +129,7 @@ sub join_game { } # Handle full game case - my $num_players = scalar @{$GAMES{$id}->{players}}; + my $num_players = scalar grep { defined } @{$GAMES{$id}->{players}}; if ($num_players >= 4) { send_error($cid, 'Already 4 players'); } @@ -135,12 +137,52 @@ sub join_game { # Add player to Game and cross-link in %PLAYERS for handle_msg # All players start as spectators and have to take a seat explicitly $PLAYERS{$cid}->{name} = $msg->{player_name}; + $PLAYERS{$cid}->{game_id} = $id; push @{$GAMES{$id}->{spectators}}, $cid; # XXX: for fast prototyping we just broadcast gamestate broadcast_gamestate($GAMES{$id}); } +# seat +sub take_seat { + my ($cid, $msg) = @_; + + my $game = $GAMES{$PLAYERS{$cid}->{game_id}}; + my $seat = $msg->{seat}; + + if (defined $game->{players}->[$seat]) { + send_error($cid, 'Seat is taken'); + } else { + # Move from standing to sitting + $game->{players}->[$seat] = $cid; + $PLAYERS{$cid}->{seat} = $seat; + for (my $i = 0; $i < @{$game->{spectators}}; $i++) { + if ($game->{spectators}->[$i] eq $cid) { + splice(@{$game->{spectators}}, $i, 1); + } + } + } + broadcast_gamestate($game); +} + +sub stand_up { + my ($cid) = @_; + + my $game = $GAMES{$PLAYERS{$cid}->{game_id}}; + my $seat = $PLAYERS{$cid}->{seat}; + + if (!defined $seat) { + send_error($cid, 'Already standing!'); + } else { + # Move from sitting to standing + push @{$game->{spectators}}, $cid; + $game->{players}->[$seat] = undef; + broadcast_gamestate($game); + } + +} + # XXX: The most simplest (bulkiest) message we can send is to just # broadcast the gamestate to all clients. This will be our temporary @@ -150,10 +192,11 @@ sub broadcast_gamestate { # Get all players in the game my @all_ws = map { $PLAYERS{$_}->{ws} } - (@{$game->{players}}, @{$game->{spectators}}); + grep { defined } + (@{$game->{players}}, @{$game->{spectators}}); # Translate to human readable names for clients - my @pnames = map { $PLAYERS{$_}->{name} } @{$game->{players}}; + my @pnames = map { defined ? $PLAYERS{$_}->{name} : 'Empty' } @{$game->{players}}; my @snames = map { $PLAYERS{$_}->{name} } @{$game->{spectators}}; my $msg = { %$game, diff --git a/public/index.html b/public/index.html @@ -10,6 +10,7 @@ var ws = new WebSocket('ws://localhost:3000/play'); ws.onmessage = function (event) { msg = JSON.parse(JSON.parse(event.data)); // double parsed? + console.log(msg) document.body.innerHTML += '<br>Game: ' + msg.game.id + '<br>' document.body.innerHTML += 'Players: ' + msg.game.players + '<br>' document.body.innerHTML += 'Spectators: ' + msg.game.spectators + '<br>' @@ -21,6 +22,13 @@ console.log('U: ' + uname + ' G: ' + gname); ws.send(JSON.stringify({action:'join_game', player_name: uname, game_id: gname})) } + function sit() { + seat = document.getElementById('seat_no').value; + ws.send(JSON.stringify({action:'take_seat', seat: seat})) + } + function stand() { + ws.send(JSON.stringify({action:'stand_up'})) + } </script> <h1>Hello, World</h1> @@ -29,6 +37,11 @@ <label for="gamename">Game:</label> <input type="text" id="gamename"> <button onclick="joinGame()">Join Game</button> - + <br> + <button onclick="stand()">Stand</button> + <br> + <label for="seat_no">Seat:</label> + <input type="number" id="seat_no"> + <button onclick="sit()">Sit</button> </body> </html>