300 lines
7.4 KiB
JavaScript
300 lines
7.4 KiB
JavaScript
import { defineStore } from 'pinia'
|
|
import { ref } from 'vue'
|
|
|
|
export const useBiscaStore = defineStore('bisca', () => {
|
|
const isDealing = ref(false)
|
|
const isGameRunning = ref(false)
|
|
const isGameOver = ref(false)
|
|
const gameType = ref(3)
|
|
const isLoggingOut = ref(false)
|
|
|
|
const deck = ref([])
|
|
const playerHand = ref([])
|
|
const opponentHand = ref([])
|
|
const trumpCard = ref(null)
|
|
const playerScore = ref(0)
|
|
const opponentScore = ref(0)
|
|
|
|
const currentTurn = ref('player')
|
|
|
|
const playerTricks = ref(0)
|
|
const opponentTricks = ref(0)
|
|
|
|
const winner = ref(null)
|
|
|
|
const table = ref({
|
|
playerCard: null,
|
|
opponentCard: null,
|
|
firstToPlay: null,
|
|
})
|
|
|
|
const startGame = async (type = 3) => {
|
|
if (isDealing.value) return
|
|
|
|
isDealing.value = true
|
|
isGameRunning.value = true
|
|
gameType.value = type
|
|
isGameOver.value = false
|
|
isLoggingOut.value = false
|
|
|
|
playerScore.value = 0
|
|
opponentScore.value = 0
|
|
playerTricks.value = 0
|
|
opponentTricks.value = 0
|
|
|
|
deck.value = []
|
|
playerHand.value = []
|
|
opponentHand.value = []
|
|
trumpCard.value = null
|
|
|
|
currentTurn.value = 'player'
|
|
|
|
table.value = {
|
|
playerCard: null,
|
|
opponentCard: null,
|
|
firstToPlay: null,
|
|
}
|
|
|
|
deck.value = createDeck()
|
|
|
|
trumpCard.value = deck.value[0]
|
|
|
|
await wait(500)
|
|
|
|
await dealInitialCards()
|
|
|
|
if (currentTurn.value === 'opponent') {
|
|
setTimeout(botPlayCard, 1000)
|
|
}
|
|
|
|
isDealing.value = false
|
|
}
|
|
|
|
const playerPlayCard = (card) => {
|
|
if (!isGameRunning.value || currentTurn.value !== 'player') return
|
|
if (table.value.playerCard) return
|
|
|
|
playerHand.value = playerHand.value.filter((c) => c.id !== card.id)
|
|
table.value.playerCard = card
|
|
|
|
if (!table.value.firstToPlay) table.value.firstToPlay = 'player'
|
|
|
|
checkEndOfTrick()
|
|
}
|
|
|
|
const botPlayCard = () => {
|
|
if (!isGameRunning.value) return
|
|
if (opponentHand.value.length === 0) return
|
|
|
|
let cardToPlay = null
|
|
|
|
if (table.value.playerCard) {
|
|
const pCard = table.value.playerCard
|
|
const trump = trumpCard.value.suit
|
|
|
|
const winningCards = opponentHand.value.filter((botCard) =>
|
|
doesCardWin(botCard, pCard, trump),
|
|
)
|
|
|
|
if (winningCards.length > 0) {
|
|
winningCards.sort((a, b) => a.strength - b.strength)
|
|
cardToPlay = winningCards[0]
|
|
} else {
|
|
const sortedHand = [...opponentHand.value].sort((a, b) => {
|
|
if (a.points === b.points) return a.strength - b.strength
|
|
return a.points - b.points
|
|
})
|
|
cardToPlay = sortedHand[0]
|
|
}
|
|
} else {
|
|
const sortedHand = [...opponentHand.value].sort((a, b) => {
|
|
if (a.suit === trumpCard.value.suit && b.suit !== trumpCard.value.suit) return 1
|
|
if (a.suit !== trumpCard.value.suit && b.suit === trumpCard.value.suit) return -1
|
|
|
|
return a.strength - b.strength
|
|
})
|
|
cardToPlay = sortedHand[0]
|
|
table.value.firstToPlay = 'opponent'
|
|
}
|
|
|
|
opponentHand.value = opponentHand.value.filter((c) => c.id !== cardToPlay.id)
|
|
table.value.opponentCard = cardToPlay
|
|
|
|
checkEndOfTrick()
|
|
}
|
|
|
|
const checkEndOfTrick = () => {
|
|
if (table.value.playerCard && table.value.opponentCard) {
|
|
currentTurn.value = 'resolving'
|
|
setTimeout(resolveTrick, 1500)
|
|
} else {
|
|
if (table.value.playerCard) {
|
|
currentTurn.value = 'opponent'
|
|
setTimeout(botPlayCard, 1000)
|
|
} else {
|
|
currentTurn.value = 'player'
|
|
}
|
|
}
|
|
}
|
|
|
|
const resolveTrick = () => {
|
|
const pCard = table.value.playerCard
|
|
const oCard = table.value.opponentCard
|
|
const trumpSuit = trumpCard.value.suit
|
|
let trickWinner = ''
|
|
|
|
if (pCard.suit === trumpSuit && oCard.suit !== trumpSuit) trickWinner = 'player'
|
|
else if (oCard.suit === trumpSuit && pCard.suit !== trumpSuit) trickWinner = 'opponent'
|
|
else if (pCard.suit === oCard.suit) {
|
|
trickWinner = getStrength(pCard.rank) > getStrength(oCard.rank) ? 'player' : 'opponent'
|
|
} else {
|
|
trickWinner = table.value.firstToPlay
|
|
}
|
|
|
|
const points = pCard.points + oCard.points
|
|
|
|
if (trickWinner === 'player') {
|
|
playerScore.value += points
|
|
playerTricks.value++
|
|
} else {
|
|
opponentScore.value += points
|
|
opponentTricks.value++
|
|
}
|
|
|
|
table.value = { playerCard: null, opponentCard: null, firstToPlay: null }
|
|
|
|
if (
|
|
deck.value.length === 0 &&
|
|
playerHand.value.length === 0 &&
|
|
opponentHand.value.length === 0
|
|
) {
|
|
endGame()
|
|
return
|
|
}
|
|
|
|
if (deck.value.length > 0) {
|
|
if (trickWinner === 'player') {
|
|
playerHand.value.push(deck.value.pop())
|
|
opponentHand.value.push(deck.value.pop())
|
|
} else {
|
|
opponentHand.value.push(deck.value.pop())
|
|
playerHand.value.push(deck.value.pop())
|
|
}
|
|
}
|
|
|
|
currentTurn.value = trickWinner
|
|
if (trickWinner === 'opponent') {
|
|
setTimeout(botPlayCard, 1000)
|
|
}
|
|
}
|
|
|
|
const doesCardWin = (attacker, defender, trumpSuit) => {
|
|
if (attacker.suit === trumpSuit && defender.suit !== trumpSuit) return true
|
|
|
|
if (defender.suit === trumpSuit && attacker.suit !== trumpSuit) return false
|
|
|
|
if (attacker.suit === defender.suit) {
|
|
return attacker.strength > defender.strength
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
const endGame = () => {
|
|
isGameRunning.value = false
|
|
isGameOver.value = true
|
|
|
|
if (playerScore.value > opponentScore.value) winner.value = 'player'
|
|
else if (opponentScore.value > playerScore.value) winner.value = 'opponent'
|
|
else winner.value = 'draw'
|
|
}
|
|
|
|
const dealInitialCards = async () => {
|
|
const cardsToDeal = gameType.value === 9 ? 9 : 3
|
|
|
|
const dealSpeed = gameType.value === 9 ? 200 : 500
|
|
|
|
for (let i = 0; i < cardsToDeal; i++) {
|
|
if (deck.value.length > 0) {
|
|
const card = deck.value.pop()
|
|
playerHand.value.push(card)
|
|
await wait(dealSpeed)
|
|
}
|
|
|
|
if (deck.value.length > 0) {
|
|
const card = deck.value.pop()
|
|
opponentHand.value.push(card)
|
|
await wait(dealSpeed)
|
|
}
|
|
}
|
|
}
|
|
|
|
const createDeck = () => {
|
|
const suits = ['c', 'e', 'o', 'p']
|
|
const ranks = [1, 2, 3, 4, 5, 6, 7, 11, 12, 13]
|
|
let newDeck = []
|
|
|
|
for (const suit of suits) {
|
|
for (const rank of ranks) {
|
|
newDeck.push({
|
|
id: `${suit}-${rank}`,
|
|
suit,
|
|
rank,
|
|
points: getPoints(rank),
|
|
strength: getStrength(rank),
|
|
})
|
|
}
|
|
}
|
|
return newDeck.sort(() => Math.random() - 0.5)
|
|
}
|
|
|
|
const getPoints = (rank) => {
|
|
if (rank === 1) return 11
|
|
if (rank === 7) return 10
|
|
if (rank === 13) return 4
|
|
if (rank === 11) return 3
|
|
if (rank === 12) return 2
|
|
return 0
|
|
}
|
|
|
|
const getStrength = (rank) => {
|
|
const strengthMap = { 1: 10, 7: 9, 13: 8, 11: 7, 12: 6, 6: 5, 5: 4, 4: 3, 3: 2, 2: 1 }
|
|
return strengthMap[rank] || 0
|
|
}
|
|
|
|
const quitGame = () => {
|
|
if (!isGameRunning.value) return
|
|
opponentScore.value = 120
|
|
playerScore.value = 0
|
|
winner.value = 'opponent'
|
|
|
|
isGameRunning.value = false
|
|
isGameOver.value = true
|
|
}
|
|
|
|
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
|
|
|
|
return {
|
|
isDealing,
|
|
isGameRunning,
|
|
gameType,
|
|
deck,
|
|
playerHand,
|
|
opponentHand,
|
|
isLoggingOut,
|
|
trumpCard,
|
|
playerScore,
|
|
opponentScore,
|
|
currentTurn,
|
|
table,
|
|
playerTricks,
|
|
opponentTricks,
|
|
isGameOver,
|
|
winner,
|
|
startGame,
|
|
quitGame,
|
|
resolveTrick,
|
|
playerPlayCard,
|
|
}
|
|
})
|