187 lines
4.8 KiB
JavaScript
187 lines
4.8 KiB
JavaScript
const games = new Map();
|
|
let currentGameID = 0;
|
|
|
|
// Bisca deck configuration
|
|
const suits = ["hearts", "diamonds", "clubs", "spades"];
|
|
const cards = [
|
|
{ face: "A", value: 11, points: 11 },
|
|
{ face: "7", value: 10, points: 10 },
|
|
{ face: "K", value: 4, points: 4 },
|
|
{ face: "J", value: 3, points: 3 },
|
|
{ face: "Q", value: 2, points: 2 },
|
|
{ face: "6", value: 0, points: 0 },
|
|
{ face: "5", value: 0, points: 0 },
|
|
{ face: "4", value: 0, points: 0 },
|
|
{ face: "3", value: 0, points: 0 },
|
|
{ face: "2", value: 0, points: 0 },
|
|
];
|
|
|
|
const createDeck = () => {
|
|
const deck = [];
|
|
suits.forEach((suit) => {
|
|
cards.forEach((card) => {
|
|
deck.push({ ...card, suit });
|
|
});
|
|
});
|
|
return deck;
|
|
};
|
|
|
|
const shuffleDeck = (deck) => {
|
|
const shuffled = [...deck];
|
|
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
const j = Math.floor(Math.random() * (i + 1));
|
|
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
|
}
|
|
return shuffled;
|
|
};
|
|
|
|
const dealCards = (deck, cardsPerPlayer = 3) => {
|
|
const player1Hand = deck.slice(0, cardsPerPlayer);
|
|
const player2Hand = deck.slice(cardsPerPlayer, cardsPerPlayer * 2);
|
|
const trumpCard = deck.pop();
|
|
return {
|
|
player1Hand,
|
|
player2Hand,
|
|
trumpCard,
|
|
remainingDeck: deck,
|
|
};
|
|
};
|
|
|
|
export const createGame = (type, host) => {
|
|
const gameID = currentGameID++;
|
|
const game = {
|
|
match_id: gameID,
|
|
type: type,
|
|
player1_user_id: host.id,
|
|
player2_user_id: null,
|
|
is_draw: false,
|
|
winner_user_id: null,
|
|
loser_user_id: null,
|
|
status: "pending",
|
|
began_at: null,
|
|
ended_at: null,
|
|
player1_points: 0,
|
|
player2_points: 0,
|
|
// Game-specific state
|
|
player1_hand: [],
|
|
player2_hand: [],
|
|
trump_card: null,
|
|
trump_suit: null,
|
|
current_trick: [],
|
|
current_player: null,
|
|
round_number: 0,
|
|
};
|
|
games.set(gameID, game);
|
|
return game;
|
|
};
|
|
|
|
export const joinGame = (gameID, player2) => {
|
|
const game = games.get(gameID);
|
|
game.player2_user_id = player2.id;
|
|
game.status = "playing";
|
|
game.began_at = new Date();
|
|
|
|
const cardCount = parseInt(game.type, 10);
|
|
if (![3, 9].includes(cardCount)) {
|
|
throw new Error("Unsupported game type");
|
|
}
|
|
|
|
// Initialize game state
|
|
const deck = shuffleDeck(createDeck());
|
|
const { player1Hand, player2Hand, trumpCard, remainingDeck } = dealCards(
|
|
deck,
|
|
cardCount
|
|
);
|
|
|
|
game.player1_hand = player1Hand;
|
|
game.player2_hand = player2Hand;
|
|
game.trump_card = trumpCard;
|
|
game.trump_suit = trumpCard.suit;
|
|
game.remaining_deck = remainingDeck;
|
|
game.current_player = game.player1_user_id; // Player 1 starts
|
|
|
|
return game;
|
|
};
|
|
|
|
export const playCard = (gameID, playerID, cardIndex) => {
|
|
const game = games.get(gameID);
|
|
if (game.current_player !== playerID) {
|
|
throw new Error("Not this player's turn");
|
|
}
|
|
|
|
const isPlayer1 = playerID === game.player1_user_id;
|
|
const playerHand = isPlayer1 ? game.player1_hand : game.player2_hand;
|
|
const playedCard = playerHand.splice(cardIndex, 1)[0];
|
|
|
|
game.current_trick.push({ playerID, card: playedCard });
|
|
|
|
if (game.current_trick.length === 2) {
|
|
resolveTrick(game);
|
|
} else {
|
|
game.current_player = isPlayer1
|
|
? game.player2_user_id
|
|
: game.player1_user_id;
|
|
}
|
|
return game;
|
|
};
|
|
|
|
const resolveTrick = (game) => {
|
|
const [first, second] = game.current_trick;
|
|
let winner;
|
|
|
|
if (first.card.suit === second.card.suit) {
|
|
winner = first.card.value > second.card.value ? first : second;
|
|
} else if (second.card.suit === game.trump_suit) {
|
|
winner = second;
|
|
} else {
|
|
winner = first; // First card wins if no trump and different suits
|
|
}
|
|
|
|
const points = first.card.points + second.card.points;
|
|
winner.playerID === game.player1_user_id
|
|
? (game.player1_points += points)
|
|
: (game.player2_points += points);
|
|
|
|
if (deck.length > 0) {
|
|
const winnerHand =
|
|
winner.playerID === game.player1_user_id
|
|
? game.player1_hand
|
|
: game.player2_hand;
|
|
loserHand =
|
|
winner.playerID === game.player1_user_id
|
|
? game.player2_hand
|
|
: game.player1_hand;
|
|
|
|
winnerHand.push(game.deck.shift());
|
|
if (game.deck.length > 0) {
|
|
loserHand.push(game.deck.shift());
|
|
}
|
|
}
|
|
|
|
game.current_trick = [];
|
|
game.current_player = winner.playerID;
|
|
game.round_number += 1;
|
|
|
|
if (game.player1_hand.length === 0 && game.player2_hand.length === 0) {
|
|
endGame(game);
|
|
}
|
|
};
|
|
|
|
const endGame = (game) => {
|
|
game.status = "ended";
|
|
game.ended_at = new Date();
|
|
|
|
if (game.player1_points > game.player2_points) {
|
|
game.winner_user_id = game.player1_user_id;
|
|
game.loser_user_id = game.player2_user_id;
|
|
} else if (game.player2_points > game.player1_points) {
|
|
game.winner_user_id = game.player2_user_id;
|
|
game.loser_user_id = game.player1_user_id;
|
|
} else {
|
|
game.is_draw = true;
|
|
}
|
|
};
|
|
|
|
export const getGame = (gameID) => games.get(gameID);
|
|
export const getAllGames = () => Array.from(games.values());
|