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 logSocket from './logSocket';
@ -9,6 +9,7 @@ class Player {
game: Game;
client: Client;
cards: Card[] = [];
stack: Card[] = [];
disconnected = false;
disconnectListener?: () => void;
rank = 0;
@ -17,7 +18,6 @@ class Player {
this.client = client;
}
sendGameState() {
this.cards.sort(cmpCard);
const i = this.game.players.indexOf(this);
const otherPlayers = [];
for (let j = 1; j < this.game.players.length; ++j)
@ -30,6 +30,7 @@ class Player {
numCards: p.cards.length,
rank: p.rank,
})),
phase: this.game.phase,
lastPlayed: this.game.lastPlayed,
lastPlayedPlayer: this.game.lastPlayedPlayer < 0 ? null : this.game.players[this.game.lastPlayedPlayer].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 === 1)
playersLeft[0].rank = ++this.playersFinished;
playersLeft[0].rank = ++this.playersFinished; // rank is reversed, fix later
break;
}
await this.round();
@ -93,33 +94,56 @@ export default class Game {
}
async round() {
this.phase = 0;
await this.prepare();
await this.prepare(); // Phase 0
this.phase = 1;
while (true) {
this.lastPlayed = 0;
while (true) { // Phase 1
const p = this.players[this.playerTurn];
if (p.rank || p.disconnected) {
this.playerTurn = (this.playerTurn + 1) % this.players.length;
continue;
}
let result = await this.turn();
if (result === false) break; // Called BS!
await this.turn();
if (this.phase === 2) break; // Called BS!
this.lastPlayedPlayer = this.playerTurn;
this.playerTurn = (this.playerTurn + 1) % this.players.length;
}
this.phase = 2;
while (this.lastPlayed > 0) {
let result = await this.flip();
if (result === false) { // Oops, flipped over a red card
while (this.lastPlayed > 0) { // Phase 2
await this.flip();
if (this.phase === 3) { // 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();
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];
this.broadcastGameState();
await new Promise<void>(resolve => {
@ -127,11 +151,12 @@ export default class Game {
delete p.disconnectListener;
(() => {
if (num === -1) {
return false; // Called BS!
this.phase = 2; // Called BS, move on to the next phase!
return;
}
if (num > this.lastPlayed) {
this.lastPlayed = num;
return true;
return;
}
p.client.socket.disconnect();
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];
this.broadcastGameState();
await new Promise<void>(resolve => {
p.client.once('turn', selectedPlayer => {
delete p.disconnectListener;
(() => {
if (this.players[selectedPlayer].cards === -1) {
return false;
if (this.players[selectedPlayer].stack.length > 0) {
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();
logSocket(p.client.socket, 'Bad cards argument on turn');
})();
@ -163,7 +190,27 @@ export default class Game {
});
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();
};
});