Version 1.0 #102
Vendored
+3
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"postman.settings.dotenv-detection-notification-visibility": false
|
||||||
|
}
|
||||||
@@ -4,252 +4,5 @@ import { toast } from 'vue-sonner'
|
|||||||
import { useApiStore } from './api'
|
import { useApiStore } from './api'
|
||||||
|
|
||||||
export const useGameStore = defineStore('game', () => {
|
export const useGameStore = defineStore('game', () => {
|
||||||
const apiStore = useApiStore()
|
|
||||||
|
|
||||||
// Game state
|
|
||||||
const game = ref({
|
|
||||||
players: {
|
|
||||||
human: { hand: [], score: 0, wonCards: [] },
|
|
||||||
bot: { hand: [], score: 0, wonCards: [] },
|
|
||||||
},
|
|
||||||
deck: [],
|
|
||||||
trump: null,
|
|
||||||
currentTrick: [],
|
|
||||||
lastWinner: null,
|
|
||||||
gameOver: false,
|
|
||||||
winner: null,
|
|
||||||
})
|
|
||||||
|
|
||||||
const gameStarted = ref(false)
|
|
||||||
const isHumanTurn = ref(true)
|
|
||||||
const selectedCard = ref(null)
|
|
||||||
const beganAt = ref(null)
|
|
||||||
const endedAt = ref(null)
|
|
||||||
const moves = ref([])
|
|
||||||
|
|
||||||
// Computed
|
|
||||||
const humanScore = computed(() => {
|
|
||||||
return game.value.players.human.wonCards.reduce((sum, card) => sum + card.value, 0)
|
|
||||||
})
|
|
||||||
|
|
||||||
const botScore = computed(() => {
|
|
||||||
return game.value.players.bot.wonCards.reduce((sum, card) => sum + card.value, 0)
|
|
||||||
})
|
|
||||||
|
|
||||||
// Initialize deck
|
|
||||||
const initializeDeck = () => {
|
|
||||||
const suits = ['H', 'D', 'C', 'S']
|
|
||||||
const ranks = ['2', '3', '4', '5', '6', '7', 'J', 'Q', 'K', 'A']
|
|
||||||
const values = { '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, 'J': 2, 'Q': 3, 'K': 4, 'A': 11 }
|
|
||||||
|
|
||||||
const deck = []
|
|
||||||
for (const suit of suits) {
|
|
||||||
for (const rank of ranks) {
|
|
||||||
deck.push({ rank, suit, value: values[rank] })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return deck.sort(() => Math.random() - 0.5)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start new game
|
|
||||||
const startGame = () => {
|
|
||||||
game.value.deck = initializeDeck()
|
|
||||||
game.value.trump = game.value.deck[game.value.deck.length - 1]
|
|
||||||
game.value.players.human.hand = game.value.deck.splice(0, 3)
|
|
||||||
game.value.players.bot.hand = game.value.deck.splice(0, 3)
|
|
||||||
game.value.currentTrick = []
|
|
||||||
game.value.gameOver = false
|
|
||||||
game.value.winner = null
|
|
||||||
game.value.players.human.score = 0
|
|
||||||
game.value.players.bot.score = 0
|
|
||||||
game.value.players.human.wonCards = []
|
|
||||||
game.value.players.bot.wonCards = []
|
|
||||||
gameStarted.value = true
|
|
||||||
isHumanTurn.value = true
|
|
||||||
beganAt.value = new Date()
|
|
||||||
endedAt.value = null
|
|
||||||
moves.value = []
|
|
||||||
}
|
|
||||||
|
|
||||||
// Play card
|
|
||||||
const playCard = async (cardIndex) => {
|
|
||||||
if (!isHumanTurn.value || game.value.gameOver) return
|
|
||||||
|
|
||||||
const card = game.value.players.human.hand[cardIndex]
|
|
||||||
game.value.currentTrick.push({ player: 'human', card })
|
|
||||||
game.value.players.human.hand.splice(cardIndex, 1)
|
|
||||||
selectedCard.value = null
|
|
||||||
|
|
||||||
// Track move
|
|
||||||
moves.value.push({
|
|
||||||
player: 'human',
|
|
||||||
card,
|
|
||||||
timestamp: new Date(),
|
|
||||||
})
|
|
||||||
|
|
||||||
isHumanTurn.value = false
|
|
||||||
|
|
||||||
// Bot plays
|
|
||||||
setTimeout(() => {
|
|
||||||
botPlay()
|
|
||||||
}, 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bot play logic
|
|
||||||
const botPlay = () => {
|
|
||||||
const botHand = game.value.players.bot.hand
|
|
||||||
let cardToPlay
|
|
||||||
|
|
||||||
if (game.value.currentTrick.length === 0) {
|
|
||||||
cardToPlay = botHand[0]
|
|
||||||
} else {
|
|
||||||
const leadCard = game.value.currentTrick[0].card
|
|
||||||
const canWin = botHand.some((c) => canBeat(c, leadCard))
|
|
||||||
|
|
||||||
if (canWin) {
|
|
||||||
cardToPlay = botHand.filter((c) => canBeat(c, leadCard)).sort((a, b) => a.value - b.value)[0]
|
|
||||||
} else {
|
|
||||||
cardToPlay = botHand.sort((a, b) => a.value - b.value)[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
game.value.currentTrick.push({ player: 'bot', card: cardToPlay })
|
|
||||||
game.value.players.bot.hand.splice(game.value.players.bot.hand.indexOf(cardToPlay), 1)
|
|
||||||
|
|
||||||
// Track move
|
|
||||||
moves.value.push({
|
|
||||||
player: 'bot',
|
|
||||||
card: cardToPlay,
|
|
||||||
timestamp: new Date(),
|
|
||||||
})
|
|
||||||
|
|
||||||
// Resolve trick
|
|
||||||
setTimeout(() => {
|
|
||||||
resolveTrick()
|
|
||||||
}, 500)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if card can beat
|
|
||||||
const canBeat = (card, leadCard) => {
|
|
||||||
if (card.suit === leadCard.suit) {
|
|
||||||
return rankValue(card.rank) > rankValue(leadCard.rank)
|
|
||||||
}
|
|
||||||
return card.suit === game.value.trump.suit
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get rank value for comparison
|
|
||||||
const rankValue = (rank) => {
|
|
||||||
const values = { '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, 'J': 11, 'Q': 12, 'K': 13, 'A': 14 }
|
|
||||||
return values[rank] || 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resolve trick
|
|
||||||
const resolveTrick = () => {
|
|
||||||
const trick = game.value.currentTrick
|
|
||||||
const card1 = trick[0].card
|
|
||||||
const card2 = trick[1].card
|
|
||||||
|
|
||||||
let winner
|
|
||||||
if (card2.suit === card1.suit) {
|
|
||||||
winner = rankValue(card2.rank) > rankValue(card1.rank) ? 'bot' : 'human'
|
|
||||||
} else if (card2.suit === game.value.trump.suit) {
|
|
||||||
winner = 'bot'
|
|
||||||
} else {
|
|
||||||
winner = 'human'
|
|
||||||
}
|
|
||||||
|
|
||||||
game.value.lastWinner = winner
|
|
||||||
game.value.players[winner].wonCards.push(card1, card2)
|
|
||||||
|
|
||||||
// Refill hands
|
|
||||||
refillHands(winner)
|
|
||||||
|
|
||||||
game.value.currentTrick = []
|
|
||||||
|
|
||||||
// Check if game is over
|
|
||||||
if (game.value.players.human.hand.length === 0 && game.value.deck.length === 0) {
|
|
||||||
endGame()
|
|
||||||
} else {
|
|
||||||
isHumanTurn.value = winner === 'human'
|
|
||||||
if (winner === 'bot') {
|
|
||||||
setTimeout(() => botPlay(), 1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refill hands
|
|
||||||
const refillHands = (winner) => {
|
|
||||||
const order = winner === 'human' ? ['human', 'bot'] : ['bot', 'human']
|
|
||||||
|
|
||||||
for (const player of order) {
|
|
||||||
while (game.value.players[player].hand.length < 3 && game.value.deck.length > 0) {
|
|
||||||
game.value.players[player].hand.push(game.value.deck.pop())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// End game
|
|
||||||
const endGame = () => {
|
|
||||||
game.value.gameOver = true
|
|
||||||
game.value.winner = humanScore.value > botScore.value ? 'human' : 'bot'
|
|
||||||
endedAt.value = new Date()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save game to API
|
|
||||||
const saveGame = async () => {
|
|
||||||
const gameData = {
|
|
||||||
type: 'S', // Standalone game
|
|
||||||
status: 'E', // Ended
|
|
||||||
player1_moves: moves.value,
|
|
||||||
began_at: beganAt.value,
|
|
||||||
ended_at: endedAt.value,
|
|
||||||
total_time: Math.ceil((endedAt.value - beganAt.value) / 1000),
|
|
||||||
}
|
|
||||||
|
|
||||||
return toast.promise(apiStore.postGame(gameData), {
|
|
||||||
loading: 'Sending data to API...',
|
|
||||||
success: () => {
|
|
||||||
return '[API] Game saved successfully'
|
|
||||||
},
|
|
||||||
error: (data) => `[API] Error saving game - ${data?.response?.data?.message}`,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset game
|
|
||||||
const reset = () => {
|
|
||||||
gameStarted.value = false
|
|
||||||
selectedCard.value = null
|
|
||||||
beganAt.value = null
|
|
||||||
endedAt.value = null
|
|
||||||
moves.value = []
|
|
||||||
game.value = {
|
|
||||||
players: {
|
|
||||||
human: { hand: [], score: 0, wonCards: [] },
|
|
||||||
bot: { hand: [], score: 0, wonCards: [] },
|
|
||||||
},
|
|
||||||
deck: [],
|
|
||||||
trump: null,
|
|
||||||
currentTrick: [],
|
|
||||||
lastWinner: null,
|
|
||||||
gameOver: false,
|
|
||||||
winner: null,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
game,
|
|
||||||
gameStarted,
|
|
||||||
isHumanTurn,
|
|
||||||
selectedCard,
|
|
||||||
beganAt,
|
|
||||||
endedAt,
|
|
||||||
moves,
|
|
||||||
humanScore,
|
|
||||||
botScore,
|
|
||||||
startGame,
|
|
||||||
playCard,
|
|
||||||
saveGame,
|
|
||||||
reset,
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user