Work on backend

This commit is contained in:
Anthony Wang 2021-05-06 17:29:41 -05:00
parent 0b98e7df89
commit 563a662e24
Signed by: a
GPG key ID: 6FD3502572299774
3 changed files with 56 additions and 45 deletions

View file

@ -12,7 +12,6 @@ class Player {
disconnected = false;
disconnectListener?: () => void;
rank = 0;
passed = false;
constructor(game: Game, client: Client) {
this.game = game;
this.client = client;
@ -26,12 +25,10 @@ class Player {
this.client.socket.emit('gameState', {
cards: this.cards,
rank: this.rank,
passed: this.passed,
players: otherPlayers.map((p: Player) => ({
username: p.client.username,
numCards: p.cards.length,
rank: p.rank,
passed: p.passed
})),
lastPlayed: this.game.lastPlayed,
lastPlayedPlayer: this.game.lastPlayedPlayer < 0 ? null : this.game.players[this.game.lastPlayedPlayer].client.username,
@ -43,7 +40,8 @@ class Player {
export default class Game {
room: Room;
players: Player[] = [];
lastPlayed: Card[] | null = null;
phase = 0;
lastPlayed = 0;
lastPlayedPlayer = -1;
playerTurn = 0;
playersFinished = 0;
@ -56,23 +54,21 @@ export default class Game {
for (let i = 1; i <= 13; ++i)
for (let j = 0; j < 4; ++j)
cards.push({rank: i, suit: j});
// Shuffle cards
for (let i = 0; i < 52; ++i) {
const j = Math.floor(Math.random() * (i+1));
[cards[i], cards[j]] = [cards[j], cards[i]];
}
const handSize = Math.floor(52 / this.room.clients.length);
const handSize = 5 - this.room.clients.length/7;
for (let i = 0; i < this.room.clients.length; ++i) {
this.players.push(new Player(this, this.room.clients[i]));
this.players[i].cards = cards.slice(i * handSize, (i + 1) * handSize);
}
const startingPlayer = this.players.find((p: Player) => p.cards.some(
(card: Card) => card.rank === 3 && card.suit === Suit.Clubs
)) || this.players[0];
if (this.room.clients.length === 3)
startingPlayer.cards.push(cards[51]);
const startingPlayer = this.players[0]; // Pick a random starting player instead??
this.playerTurn = this.players.indexOf(startingPlayer);
while (true) {
// Check if game ended
// Rewrite
const playersLeft: Player[] = [];
this.players.forEach((p: Player) => {
if (!p.rank && !p.disconnected)
@ -96,54 +92,46 @@ export default class Game {
this.players.forEach((p: Player) => p.sendGameState());
}
async round() {
this.phase = 0;
await this.prepare();
this.phase = 1;
while (true) {
// Everyone passes
if (this.playerTurn === this.lastPlayedPlayer) break;
const p = this.players[this.playerTurn];
// Guy passes
if (p.rank || p.disconnected || p.passed) {
if (p.rank || p.disconnected) {
this.playerTurn = (this.playerTurn + 1) % this.players.length;
continue;
}
await this.turn();
let result = await this.turn();
if (result === false) break; // Called BS!
this.lastPlayedPlayer = this.playerTurn;
this.playerTurn = (this.playerTurn + 1) % this.players.length;
// Check if person ends
if (p.rank)
break;
}
this.lastPlayed = null;
this.lastPlayedPlayer = -1;
this.players.forEach((p: Player) => p.passed = false);
this.phase = 2;
while (this.lastPlayed > 0) {
let result = await this.flip();
if (result === false) { // Oops, flipped over a red card
}
}
this.lastPlayed = 0;
}
async prepare() {
this.broadcastGameState();
}
async turn() {
const p = this.players[this.playerTurn];
if (p.passed) return;
this.broadcastGameState();
await new Promise<void>(resolve => {
p.client.once('turn', cards => {
p.client.once('turn', num => {
delete p.disconnectListener;
(() => {
// Pass
if (cards === null) {
p.passed = true;
return;
if (num === -1) {
return false; // Called BS!
}
// Play
if (cards && Array.isArray(cards) && cards.every((a: Card) => a && p.cards.some((b: Card) => !cmpCard(a, b))) && canPlay(this.lastPlayed, cards)) {
// Cards have to be ascending
let ok = true;
for (let i = 0; i + 1 < cards.length; ++i)
ok = ok && cmpCard(cards[i], cards[i + 1]) < 0;
if (ok) {
// Remove cards
p.cards = p.cards.filter((a: Card) => !cards.some((b: Card) => !cmpCard(a, b)));
// Check if won
if (!p.cards.length)
p.rank = ++this.playersFinished;
this.lastPlayed = cards;
this.lastPlayedPlayer = this.playerTurn;
return;
}
if (num > this.lastPlayed) {
this.lastPlayed = num;
return true;
}
p.client.socket.disconnect();
logSocket(p.client.socket, 'Bad cards argument on turn');
@ -157,6 +145,29 @@ export default class Game {
};
});
}
async flip() {
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;
}
p.client.socket.disconnect();
logSocket(p.client.socket, 'Bad cards argument on turn');
})();
resolve();
});
p.disconnectListener = () => {
delete p.disconnectListener;
p.client.removeAllListeners('turn');
resolve();
};
});
}
updateSocket(client: Client) {
this.players.find((p: Player) => p.client === client)!.sendGameState();
}

View file

@ -64,7 +64,7 @@ export default class Room {
this.game.remove(client);
}
startGame() {
if (this.clients.length < 3) {
if (this.clients.length < 2) {
this.host.socket.disconnect();
logSocket(this.host.socket, 'Not enough users for startGame');
return;

View file

@ -95,7 +95,7 @@ server.on('connection', (socket: Socket) => {
return;
}
// Make sure room has space
if (room.clients.length > 3) {
if (room.clients.length >= 20) {
socket.emit('joinRoomRes', {success: false, error: 'Room does not have enough space'});
return;
}