Yatzy/Work in progress/gameLogic.js
2025-12-17 17:43:55 +01:00

153 lines
6.5 KiB
JavaScript
Executable File

export const SCORE_CATEGORIES = {
upper: [
{ id: 'ones', name: 'Ettor', maxCount: 5, multiple: 1, inputType: 'count' },
{ id: 'twos', name: 'Tvåor', maxCount: 5, multiple: 2, inputType: 'count' },
{ id: 'threes', name: 'Treor', maxCount: 5, multiple: 3, inputType: 'count' },
{ id: 'fours', name: 'Fyror', maxCount: 5, multiple: 4, inputType: 'count' },
{ id: 'fives', name: 'Femmor', maxCount: 5, multiple: 5, inputType: 'count' },
{ id: 'sixes', name: 'Sexor', maxCount: 5, multiple: 6, inputType: 'count' }
],
lower: [
{ id: 'pair', name: 'Ett par', inputType: 'options', options: [2, 4, 6, 8, 10, 12] },
{ id: 'twoPair', name: 'Två par', min: 6, max: 22, inputType: 'score' },
{ id: 'threeOfAKind', name: 'Tretal', inputType: 'options', options: [3, 6, 9, 12, 15, 18] },
{ id: 'fourOfAKind', name: 'Fyrtal', inputType: 'options', options: [4, 8, 12, 16, 20, 24] },
{ id: 'smallStraight', name: 'Liten stege', fixed: 15, inputType: 'score' },
{ id: 'largeStraight', name: 'Stor stege', fixed: 20, inputType: 'score' },
{ id: 'fullHouse', name: 'Kåk', min: 7, max: 28, inputType: 'score' },
{ id: 'chance', name: 'Chans', min: 5, max: 30, inputType: 'score' },
{ id: 'yatzee', name: 'Yatzy', fixed: 50, inputType: 'score' }
]
};
export const ALL_CATEGORIES = [...SCORE_CATEGORIES.upper, ...SCORE_CATEGORIES.lower];
// Hjälpfunktion för att räkna förekomsten av varje tärningsvärde
function countDice(dice) {
const counts = { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0 };
dice.forEach(die => {
counts[die]++;
});
return counts;
}
// Hjälpfunktion för att beräkna poäng för en specifik kategori
function calculateCategoryScore(dice, categoryId) {
const counts = countDice(dice);
switch (categoryId) {
case 'ones':
return counts[1] * 1;
case 'twos':
return counts[2] * 2;
case 'threes':
return counts[3] * 3;
case 'fours':
return counts[4] * 4;
case 'fives':
return counts[5] * 5;
case 'sixes':
return counts[6] * 6;
case 'pair':
for (let i = 6; i >= 1; i--) {
if (counts[i] >= 2) return i * 2;
}
return 0;
case 'twoPair':
const pairs = [];
for (let i = 6; i >= 1; i--) {
if (counts[i] >= 2) pairs.push(i * 2);
}
if (pairs.length >= 2) {
return pairs[0] + pairs[1];
} else if (pairs.length === 1) {
// Om det bara finns ett par, ta det högsta möjliga paret och lägg till högsta enkeltärning
const highestSingle = Math.max(...dice.filter(die => counts[die] === 1));
return pairs[0] + (highestSingle || 0);
}
return 0;
case 'threeOfAKind':
for (let i = 6; i >= 1; i--) {
if (counts[i] >= 3) return i * 3;
}
return 0;
case 'fourOfAKind':
for (let i = 6; i >= 1; i--) {
if (counts[i] >= 4) return i * 4;
}
return 0;
case 'smallStraight':
const hasSmallStraight = dice.some(die => {
const has1234 = dice.includes(1) && dice.includes(2) && dice.includes(3) && dice.includes(4);
const has2345 = dice.includes(2) && dice.includes(3) && dice.includes(4) && dice.includes(5);
const has3456 = dice.includes(3) && dice.includes(4) && dice.includes(5) && dice.includes(6);
return has1234 || has2345 || has3456;
});
return hasSmallStraight ? 15 : 0;
case 'largeStraight':
const has12345 = dice.includes(1) && dice.includes(2) && dice.includes(3) && dice.includes(4) && dice.includes(5);
const has23456 = dice.includes(2) && dice.includes(3) && dice.includes(4) && dice.includes(5) && dice.includes(6);
return (has12345 || has23456) ? 20 : 0;
case 'fullHouse':
const hasThreeOfAKind = Object.values(counts).some(count => count >= 3);
const hasPair = Object.values(counts).some(count => count >= 2);
return (hasThreeOfAKind && hasPair) ? dice.reduce((sum, die) => sum + die, 0) : 0;
case 'chance':
return dice.reduce((sum, die) => sum + die, 0);
case 'yatzee':
return Object.values(counts).some(count => count === 5) ? 50 : 0;
default:
return 0;
}
}
// Funktion för att beräkna möjliga poäng för en kategori
export function calculatePossibleScores(gameData, playerId, categoryId) {
// Hämta de senast kastade tärningarna för spelaren (detta måste implementeras i main.js)
const currentDice = gameData.currentDice || [1, 1, 1, 1, 1]; // Exempelvärden, ersätt med riktiga tärningar
const category = ALL_CATEGORIES.find(cat => cat.id === categoryId);
if (!category) return [];
const score = calculateCategoryScore(currentDice, categoryId);
if (category.inputType === 'count') {
return [score];
} else if (category.inputType === 'options') {
return category.options.includes(score) ? [score] : [0];
} else if (category.inputType === 'score') {
if (category.fixed) {
return [category.fixed];
} else if (category.min !== undefined && category.max !== undefined) {
return score >= category.min && score <= category.max ? [score] : [0];
} else {
return [score];
}
}
return [score];
}
export function calculateTotals(gameData) {
const playerTotals = {};
gameData.players.forEach(p => {
const pScores = gameData.scores[p.id] || {};
const upperSum = SCORE_CATEGORIES.upper.reduce((sum, cat) => sum + (pScores[cat.id] || 0), 0);
const upperBonus = upperSum >= 63 ? 50 : 0;
const upperTotal = upperSum + upperBonus;
const lowerTotal = SCORE_CATEGORIES.lower.reduce((sum, cat) => sum + (pScores[cat.id] || 0), 0);
const grandTotal = upperTotal + lowerTotal;
playerTotals[p.id] = { upperSum, upperBonus, upperTotal, lowerTotal, grandTotal };
});
return playerTotals;
}
export function isGameComplete(gameData) {
if (!gameData || !gameData.players || !gameData.scores) return false;
return gameData.players.every(p => {
return ALL_CATEGORIES.every(cat => {
return gameData.scores[p.id]?.[cat.id] !== null && gameData.scores[p.id]?.[cat.id] !== undefined;
});
});
}