Finished implementing everything except prepare

This commit is contained in:
Anthony Wang 2021-05-06 20:22:30 -05:00
parent 3ae7abec05
commit 7269261439
Signed by: a
GPG key ID: 6FD3502572299774

View file

@ -1,4 +1,4 @@
import {canPlay, Card, cmpCard, Suit} from 'bsx-core'; import {Card, Suit} from 'bsx-core';
import Client from './Client'; import Client from './Client';
import logSocket from './logSocket'; import logSocket from './logSocket';
@ -9,6 +9,7 @@ class Player {
game: Game; game: Game;
client: Client; client: Client;
cards: Card[] = []; cards: Card[] = [];
stack: Card[] = [];
disconnected = false; disconnected = false;
disconnectListener?: () => void; disconnectListener?: () => void;
rank = 0; rank = 0;
@ -17,7 +18,6 @@ class Player {
this.client = client; this.client = client;
} }
sendGameState() { sendGameState() {
this.cards.sort(cmpCard);
const i = this.game.players.indexOf(this); const i = this.game.players.indexOf(this);
const otherPlayers = []; const otherPlayers = [];
for (let j = 1; j < this.game.players.length; ++j) for (let j = 1; j < this.game.players.length; ++j)
@ -30,6 +30,7 @@ class Player {
numCards: p.cards.length, numCards: p.cards.length,
rank: p.rank, rank: p.rank,
})), })),
phase: this.game.phase,
lastPlayed: this.game.lastPlayed, lastPlayed: this.game.lastPlayed,
lastPlayedPlayer: this.game.lastPlayedPlayer < 0 ? null : this.game.players[this.game.lastPlayedPlayer].client.username, lastPlayedPlayer: this.game.lastPlayedPlayer < 0 ? null : this.game.players[this.game.lastPlayedPlayer].client.username,
playerTurn: this.game.players[this.game.playerTurn].client.username playerTurn: this.game.players[this.game.playerTurn].client.username
@ -76,7 +77,7 @@ export default class Game {
}); });
if (playersLeft.length < 2) { if (playersLeft.length < 2) {
if (playersLeft.length === 1) if (playersLeft.length === 1)
playersLeft[0].rank = ++this.playersFinished; playersLeft[0].rank = ++this.playersFinished; // rank is reversed, fix later
break; break;
} }
await this.round(); await this.round();
@ -93,33 +94,56 @@ export default class Game {
} }
async round() { async round() {
this.phase = 0; this.phase = 0;
await this.prepare(); await this.prepare(); // Phase 0
this.phase = 1; this.phase = 1;
while (true) { this.lastPlayed = 0;
while (true) { // Phase 1
const p = this.players[this.playerTurn]; const p = this.players[this.playerTurn];
if (p.rank || p.disconnected) { if (p.rank || p.disconnected) {
this.playerTurn = (this.playerTurn + 1) % this.players.length; this.playerTurn = (this.playerTurn + 1) % this.players.length;
continue; continue;
} }
let result = await this.turn(); await this.turn();
if (result === false) break; // Called BS! if (this.phase === 2) break; // Called BS!
this.lastPlayedPlayer = this.playerTurn; this.lastPlayedPlayer = this.playerTurn;
this.playerTurn = (this.playerTurn + 1) % this.players.length; this.playerTurn = (this.playerTurn + 1) % this.players.length;
} }
this.phase = 2; while (this.lastPlayed > 0) { // Phase 2
while (this.lastPlayed > 0) { await this.flip();
let result = await this.flip(); if (this.phase === 3) { // Oops, flipped over a red card!
if (result === false) { // Oops, flipped over a red card await this.giveup(); // The player who called BS won and now the challenged player must give up a card!
return;
} }
} }
this.lastPlayed = 0; await this.giveup(); // The player who called BS won and now they must give up a card!
} }
async prepare() { async prepare() { // Players prepare their hand for this round
this.broadcastGameState(); this.broadcastGameState();
const playerPromises = [];
for (let i = 0; i < this.room.clients.length; ++i) {
const p = this.players[i];
if (p.rank || p.disconnected) continue;
playerPromises.push(new Promise<void>(resolve => {
p.client.once('prepare', order => {
delete p.disconnectListener;
(() => {
p.client.socket.disconnect();
logSocket(p.client.socket, 'Bad cards argument on turn');
})();
resolve();
});
p.disconnectListener = () => {
delete p.disconnectListener;
p.client.removeAllListeners('prepare');
resolve();
};
}));
}
await Promise.all(playerPromises);
} }
async turn() { async turn() { // Do a turn
const p = this.players[this.playerTurn]; const p = this.players[this.playerTurn];
this.broadcastGameState(); this.broadcastGameState();
await new Promise<void>(resolve => { await new Promise<void>(resolve => {
@ -127,11 +151,12 @@ export default class Game {
delete p.disconnectListener; delete p.disconnectListener;
(() => { (() => {
if (num === -1) { if (num === -1) {
return false; // Called BS! this.phase = 2; // Called BS, move on to the next phase!
return;
} }
if (num > this.lastPlayed) { if (num > this.lastPlayed) {
this.lastPlayed = num; this.lastPlayed = num;
return true; return;
} }
p.client.socket.disconnect(); p.client.socket.disconnect();
logSocket(p.client.socket, 'Bad cards argument on turn'); logSocket(p.client.socket, 'Bad cards argument on turn');
@ -145,17 +170,19 @@ export default class Game {
}; };
}); });
} }
async flip() { async flip() { // Someone called BS and now the challenged player must flip over a card
const p = this.players[this.lastPlayedPlayer]; const p = this.players[this.lastPlayedPlayer];
this.broadcastGameState(); this.broadcastGameState();
await new Promise<void>(resolve => { await new Promise<void>(resolve => {
p.client.once('turn', selectedPlayer => { p.client.once('turn', selectedPlayer => {
delete p.disconnectListener; delete p.disconnectListener;
(() => { (() => {
if (this.players[selectedPlayer].cards === -1) { if (this.players[selectedPlayer].stack.length > 0) {
return false; if (this.players[selectedPlayer].stack[0].suit === Suit.Diamonds ||
this.players[selectedPlayer].stack[0].suit === Suit.Hearts) this.phase = 3; // Red card
this.players[selectedPlayer].stack.splice(0);
return;
} }
p.client.socket.disconnect(); p.client.socket.disconnect();
logSocket(p.client.socket, 'Bad cards argument on turn'); logSocket(p.client.socket, 'Bad cards argument on turn');
})(); })();
@ -163,7 +190,27 @@ export default class Game {
}); });
p.disconnectListener = () => { p.disconnectListener = () => {
delete p.disconnectListener; delete p.disconnectListener;
p.client.removeAllListeners('turn'); p.client.removeAllListeners('flip');
resolve();
};
});
}
async giveup() { // Give up a card
const p = this.players[this.lastPlayed ? this.lastPlayedPlayer : this.playerTurn];
this.broadcastGameState();
await new Promise<void>(resolve => {
p.client.once('giveup', card => {
delete p.disconnectListener;
(() => {
p.cards.splice(card); // Remove card, may want to check if it is valid
p.client.socket.disconnect();
logSocket(p.client.socket, 'Bad cards argument on turn');
})();
resolve();
});
p.disconnectListener = () => {
delete p.disconnectListener;
p.client.removeAllListeners('giveup');
resolve(); resolve();
}; };
}); });