Work on backend
This commit is contained in:
parent
0b98e7df89
commit
563a662e24
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue