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

View file

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

View file

@ -95,7 +95,7 @@ server.on('connection', (socket: Socket) => {
return; return;
} }
// Make sure room has space // 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'}); socket.emit('joinRoomRes', {success: false, error: 'Room does not have enough space'});
return; return;
} }