diff --git a/src/lib/balatro.test.ts b/src/lib/balatro.test.ts index 82f74f1..8df5254 100644 --- a/src/lib/balatro.test.ts +++ b/src/lib/balatro.test.ts @@ -29,13 +29,15 @@ import case023 from './test-files/023.js' import case024 from './test-files/024.js' import case025 from './test-files/025.js' import case026 from './test-files/026.js' - -type Expected = Omit, 'scoringCards'> & { scoringCards: Partial[] } +import case027 from './test-files/027.js' +import case028 from './test-files/028.js' export type TestCase = { message: string initialState: InitialState - expected: Expected + expected: Omit, 'scoringCards'> & { + scoringCards: Partial[] + } } describe('calculateScore', () => { @@ -66,7 +68,13 @@ describe('calculateScore', () => { case024('Pair, inactive Verdant Leaf'), case025('Pair, active Verdant Leaf'), case026('Pair, The Pillar'), + case027('Lucky Pair'), + case028('Lucky Flush, Bloodstone'), ])('$message', ({ initialState, expected }) => { - expect(calculateScore(getState(initialState))).toMatchObject(expected) + const score = calculateScore(getState(initialState)) + + expect(score.hand).toEqual(expected.hand) + expect(score.scoringCards).toMatchObject(expected.scoringCards) + expect(score.scores).toMatchObject(expected.scores) }) }) diff --git a/src/lib/balatro.ts b/src/lib/balatro.ts index 220c33c..3dabcf7 100644 --- a/src/lib/balatro.ts +++ b/src/lib/balatro.ts @@ -1,5 +1,5 @@ -import { RANK_TO_CHIP_MAP, PLAYED_CARD_RETRIGGER_JOKER_NAMES, HELD_CARD_RETRIGGER_JOKER_NAMES } from '#lib/data.js' -import type { Card, Joker, JokerCardEffect, JokerEffect, Result, Score, State } from '#lib/types.js' +import { RANK_TO_CHIP_MAP, PLAYED_CARD_RETRIGGER_JOKER_NAMES, HELD_CARD_RETRIGGER_JOKER_NAMES, LUCKS } from '#lib/data.js' +import type { Card, Joker, JokerCardEffect, JokerEffect, Luck, Result, ResultScore, Score, State } from '#lib/types.js' import { formatScore } from '#utilities/formatScore.js' import { log, logGroup, logGroupEnd } from '#utilities/log.js' import { isFaceCard } from '#utilities/isFaceCard.js' @@ -8,41 +8,49 @@ import { notNullish } from '#utilities/notNullish.js' import { resolveJoker } from '#utilities/resolveJokers.js' export function calculateScore (state: State): Result { - const { chips, multiplier } = getScore(state) + const scores: ResultScore[] = [] - log('\nReceived:', { chips, multiplier }) - log('Expected:', { chips: 340, multiplier: 1685e13 }) + for (const luck of LUCKS) { + const { chips, multiplier } = getScore(state, luck) - let actualScore - if (state.deck === 'Plasma Deck') { - log('Balanced:', { chips: 2.470e16, multiplier: 2.470e16 }) - actualScore = Math.pow((chips + multiplier) / 2, 2) - } else { - actualScore = chips * multiplier - } + log('\nReceived:', { chips, multiplier }) + log('Expected:', { chips: 340, multiplier: 1685e13 }) + + let actualScore + if (state.deck === 'Plasma Deck') { + log('Balanced:', { chips: 2.470e16, multiplier: 2.470e16 }) + actualScore = Math.pow((chips + multiplier) / 2, 2) + } else { + actualScore = chips * multiplier + } - // Balatro seems to round values starting at a certain threshold and it seems to round down. 🤔 - const score = actualScore > 10000 ? Math.floor(actualScore) : actualScore + // Balatro seems to round values starting at a certain threshold and it seems to round down. 🤔 + const score = actualScore > 10000 ? Math.floor(actualScore) : actualScore + scores.push({ + score, + formattedScore: formatScore(score), + luck, + }) + } return { hand: state.playedHand, scoringCards: state.scoringCards, - score, - formattedScore: formatScore(score), + scores, } } -function getScore (state: State): Score { - const { chips: baseChips, multiplier: baseMultiplier } = state.handBaseScores[state.playedHand] +function getScore (state: State, luck: Luck): Score { + const baseScore = state.handBaseScores[state.playedHand] - // Step 0. Determine base chips and multiplier. + // Determine base chips and multiplier. log('\n0. Determining base score …') // The Flint halves the base chips and multiplier. - // The base score seems to be rounded here. const baseFactor = (state.blind.name === 'The Flint' && state.blind.isActive ? 0.5 : 1) + // The base score seems to be rounded here. const score: Score = { - chips: Math.round(baseChips * baseFactor), - multiplier: Math.round(baseMultiplier * baseFactor), + chips: Math.round(baseScore.chips * baseFactor), + multiplier: Math.round(baseScore.multiplier * baseFactor), } log('\n0. BASE SCORE =>', score) @@ -83,6 +91,12 @@ function getScore (state: State): Score { log(score, '(+Mult from mult enhancement)') break } + case 'lucky': { + const hasOops = state.jokerSet.has('Oops! All 6s') + score.multiplier += luck === 'all' ? 20 : luck === 'none' ? 0 : (hasOops ? 8 : 4) + log(score, '(+Mult from lucky enhancement)') + break + } case 'glass': { score.multiplier *= 2 log(score, '(xMult from glass enhancement)') @@ -111,7 +125,7 @@ function getScore (state: State): Score { // 4. Joker effects for played cards for (const joker of state.jokers) { - scoreJokerCardEffect(joker.playedCardEffect, { state, score, joker, card }) + scoreJokerCardEffect(joker.playedCardEffect, { state, score, joker, card, luck }) } } @@ -144,7 +158,7 @@ function getScore (state: State): Score { // 2. Joker effects for held cards for (const joker of state.jokers) { - scoreJokerCardEffect(joker.heldCardEffect, { state, score, joker, card }) + scoreJokerCardEffect(joker.heldCardEffect, { state, score, joker, card, luck }) log(score, `(${joker})`) } } @@ -177,7 +191,7 @@ function getScore (state: State): Score { } // 2. JOKER EFFECTS - scoreJokerEffect(joker.effect, { state, score, joker }) + scoreJokerEffect(joker.effect, { state, score, joker, luck }) logGroupEnd(`← ${joker}`, score) } @@ -258,7 +272,7 @@ function getHeldCardTriggers ({ state, card }: { state: State, card: Card }): st return triggers } -function scoreJokerEffect (effect: JokerEffect | undefined, { state, score, joker }: { state: State, score: Score, joker: Joker }) { +function scoreJokerEffect (effect: JokerEffect | undefined, { state, score, joker, luck }: { state: State, score: Score, joker: Joker, luck: Luck }) { const triggers = ['Regular'] // Increase triggers from Blueprint/Brainstorm @@ -276,27 +290,27 @@ function scoreJokerEffect (effect: JokerEffect | undefined, { state, score, joke for (const [index, trigger] of triggers.entries()) { log(`Trigger: ${index + 1} (${trigger})`) if (effect) { - effect.call(joker, { state, score }) + effect.call(joker, { state, score, luck }) log(score, `(${joker.name})`) } for (const target of targets) { if (target.indirectEffect) { - target.indirectEffect({ state, score, joker }) + target.indirectEffect({ state, score, joker, luck }) log(score, trigger) } } for (const jokersWithIndirectEffect of jokersWithIndirectEffects) { if (jokersWithIndirectEffect.indirectEffect) { - jokersWithIndirectEffect.indirectEffect({ state, score, joker }) + jokersWithIndirectEffect.indirectEffect({ state, score, joker, luck }) log(score, `(${jokersWithIndirectEffect.name})`) } } } } -function scoreJokerCardEffect (effect: JokerCardEffect | undefined, { state, score, joker, card }: { state: State, score: Score, joker: Joker, card: Card }) { +function scoreJokerCardEffect (effect: JokerCardEffect | undefined, { state, score, joker, card, luck }: { state: State, score: Score, joker: Joker, card: Card, luck: Luck }) { if (!effect) { return } @@ -326,7 +340,7 @@ function scoreJokerCardEffect (effect: JokerCardEffect | undefined, { state, sco for (let trigger = 0; trigger < triggers.length; trigger++) { log(`Trigger: ${trigger + 1} (${triggers[trigger]})`) - effect.call(joker, { state, score, joker, card }) + effect.call(joker, { state, score, joker, card, luck }) log(score, `(${joker.name})`) } logGroupEnd('←', score) diff --git a/src/lib/data.ts b/src/lib/data.ts index eb2ae39..8b31fe4 100644 --- a/src/lib/data.ts +++ b/src/lib/data.ts @@ -2,7 +2,7 @@ import { flush, nOfAKind, straight } from '#lib/getHand.js' import { isFaceCard } from '#utilities/isFaceCard.js' import { isRank } from '#utilities/isRank.js' import { isSuit } from '#utilities/isSuit.js' -import type { BlindName, DeckName, Edition, Enhancement, HandName, JokerDefinition, JokerEdition, JokerName, Rank, Score, Seal, Suit } from '#lib/types.js' +import type { BlindName, DeckName, Edition, Enhancement, HandName, JokerDefinition, JokerEdition, JokerName, Luck, Rank, Score, Seal, Suit } from '#lib/types.js' export const BLINDS: BlindName[] = ['Small Blind', 'Big Blind', 'The Hook', 'The Ox', 'The House', 'The Wall', 'The Wheel', 'The Arm', 'The Club', 'The Fish', 'The Psychic', 'The Goad', 'The Water', 'The Window', 'The Manacle', 'The Eye', 'The Mouth', 'The Plant', 'The Serpent', 'The Pillar', 'The Needle', 'The Head', 'The Tooth', 'The Flint', 'The Mark', 'Amber Acorn', 'Verdant Leaf', 'Violet Vessel', 'Crimson Heart', 'Cerulean Bell'] @@ -18,6 +18,8 @@ export const JOKER_EDITIONS: JokerEdition[] = ['base', 'foil', 'holographic', 'p export const RANKS: Rank[] = ['Ace', 'King', 'Queen', 'Jack', '10', '9', '8', '7', '6', '5', '4', '3', '2'] export const SUITS: Suit[] = ['Clubs', 'Spades', 'Hearts', 'Diamonds'] +export const LUCKS: Luck[] = ['none', 'average', 'all'] + export const PLANET_SCORE_SETS: Record = { 'Flush Five': { chips: 40, multiplier: 3 }, 'Flush House': { chips: 40, multiplier: 3 }, @@ -258,8 +260,8 @@ export const JOKER_DEFINITIONS: Record = { }, 'Misprint': { rarity: 'common', - effect ({ score }) { - score.multiplier += 0 + effect ({ score, luck }) { + score.multiplier += luck === 'all' ? 23 : luck === 'none' ? 0 : 11.5 }, }, 'Dusk': { @@ -711,12 +713,11 @@ export const JOKER_DEFINITIONS: Record = { }, 'Bloodstone': { rarity: 'uncommon', - probability: { - numerator: 1, - denominator: 3, - }, - playedCardEffect ({ score, card }) { - score.multiplier *= (isSuit(card, 'Hearts') ? 1 : 1) + playedCardEffect ({ score, card, state, luck }) { + if (isSuit(card, 'Hearts')) { + const hasOops = state.jokerSet.has('Oops! All 6s') + score.multiplier *= luck === 'all' ? 2 : luck === 'none' ? 1 : 1 + (hasOops ? 2 : 1)/3 + } }, }, 'Arrowhead': { diff --git a/src/lib/test-files/001.ts b/src/lib/test-files/001.ts index 938a9d1..179b685 100644 --- a/src/lib/test-files/001.ts +++ b/src/lib/test-files/001.ts @@ -23,8 +23,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Clubs' }, { rank: '7', suit: 'Diamonds' }, ], - score: 108, - formattedScore: '108', + scores: [ + { score: 108, formattedScore: '108', luck: 'none' }, + { score: 108, formattedScore: '108', luck: 'average' }, + { score: 108, formattedScore: '108', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/002.ts b/src/lib/test-files/002.ts index 53bc20c..cd2dd55 100644 --- a/src/lib/test-files/002.ts +++ b/src/lib/test-files/002.ts @@ -19,8 +19,11 @@ export default (message: string): TestCase => { { rank: '4', suit: 'Spades' }, { rank: '4', suit: 'Hearts', edition: 'holographic' }, ], - score: 600, - formattedScore: '600', + scores: [ + { score: 600, formattedScore: '600', luck: 'none' }, + { score: 600, formattedScore: '600', luck: 'average' }, + { score: 600, formattedScore: '600', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/003.ts b/src/lib/test-files/003.ts index 0adb779..7dc4006 100644 --- a/src/lib/test-files/003.ts +++ b/src/lib/test-files/003.ts @@ -25,8 +25,11 @@ export default (message: string): TestCase => { scoringCards: [ { rank: '7', suit: 'Hearts', enhancement: 'bonus' }, ], - score: 147, - formattedScore: '147', + scores: [ + { score: 147, formattedScore: '147', luck: 'none' }, + { score: 147, formattedScore: '147', luck: 'average' }, + { score: 147, formattedScore: '147', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/004.ts b/src/lib/test-files/004.ts index 6b6d5f4..501c809 100644 --- a/src/lib/test-files/004.ts +++ b/src/lib/test-files/004.ts @@ -27,8 +27,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Diamonds' }, { rank: '6', suit: 'Diamonds' }, ], - score: 539, - formattedScore: '539', + scores: [ + { score: 539, formattedScore: '539', luck: 'none' }, + { score: 539, formattedScore: '539', luck: 'average' }, + { score: 539, formattedScore: '539', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/005.ts b/src/lib/test-files/005.ts index e5cf84d..fa5642c 100644 --- a/src/lib/test-files/005.ts +++ b/src/lib/test-files/005.ts @@ -26,8 +26,11 @@ export default (message: string): TestCase => { scoringCards: [ { rank: 'Queen', suit: 'Diamonds', isDebuffed: true }, ], - score: 16.25, - formattedScore: '16', + scores: [ + { score: 16.25, formattedScore: '16', luck: 'none' }, + { score: 16.25, formattedScore: '16', luck: 'average' }, + { score: 16.25, formattedScore: '16', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/006.ts b/src/lib/test-files/006.ts index 81473fb..eaab51f 100644 --- a/src/lib/test-files/006.ts +++ b/src/lib/test-files/006.ts @@ -22,8 +22,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Spades' }, { rank: '7', suit: 'Hearts', isDebuffed: true }, ], - score: 134, - formattedScore: '134', + scores: [ + { score: 134, formattedScore: '134', luck: 'none' }, + { score: 134, formattedScore: '134', luck: 'average' }, + { score: 134, formattedScore: '134', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/007.ts b/src/lib/test-files/007.ts index 8fd1ebe..bb44d64 100644 --- a/src/lib/test-files/007.ts +++ b/src/lib/test-files/007.ts @@ -29,8 +29,11 @@ export default (message: string): TestCase => { { rank: '4', suit: 'Hearts' }, { rank: '4', suit: 'Clubs' }, ], - score: 3192, - formattedScore: '3,192', + scores: [ + { score: 3192, formattedScore: '3,192', luck: 'none' }, + { score: 3192, formattedScore: '3,192', luck: 'average' }, + { score: 3192, formattedScore: '3,192', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/008.ts b/src/lib/test-files/008.ts index 0b8995a..aee4faf 100644 --- a/src/lib/test-files/008.ts +++ b/src/lib/test-files/008.ts @@ -32,8 +32,11 @@ export default (message: string): TestCase => { { rank: '9', suit: 'Spades' }, { rank: '8', suit: 'Spades' }, ], - score: 2772, - formattedScore: '2,772', + scores: [ + { score: 2772, formattedScore: '2,772', luck: 'none' }, + { score: 2772, formattedScore: '2,772', luck: 'average' }, + { score: 2772, formattedScore: '2,772', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/009.ts b/src/lib/test-files/009.ts index c25ac72..0d4f9a7 100644 --- a/src/lib/test-files/009.ts +++ b/src/lib/test-files/009.ts @@ -32,8 +32,11 @@ export default (message: string): TestCase => { { rank: '4', suit: 'Hearts' }, { rank: '2', suit: 'Hearts' }, ], - score: 3082, - formattedScore: '3,082', + scores: [ + { score: 3082, formattedScore: '3,082', luck: 'none' }, + { score: 3082, formattedScore: '3,082', luck: 'average' }, + { score: 3082, formattedScore: '3,082', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/010.ts b/src/lib/test-files/010.ts index cd34dfc..6e1ce13 100644 --- a/src/lib/test-files/010.ts +++ b/src/lib/test-files/010.ts @@ -30,8 +30,11 @@ export default (message: string): TestCase => { { rank: '6', suit: 'Spades' }, { rank: '6', suit: 'Spades' }, ], - score: 2856, - formattedScore: '2,856', + scores: [ + { score: 2856, formattedScore: '2,856', luck: 'none' }, + { score: 2856, formattedScore: '2,856', luck: 'average' }, + { score: 2856, formattedScore: '2,856', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/011.ts b/src/lib/test-files/011.ts index 7132282..7f69310 100644 --- a/src/lib/test-files/011.ts +++ b/src/lib/test-files/011.ts @@ -28,8 +28,11 @@ export default (message: string): TestCase => { { rank: '5', suit: 'Clubs' }, { rank: '5', suit: 'Spades', enhancement: 'glass', seal: 'red' }, ], - score: 20140, - formattedScore: '20,140', + scores: [ + { score: 20140, formattedScore: '20,140', luck: 'none' }, + { score: 20140, formattedScore: '20,140', luck: 'average' }, + { score: 20140, formattedScore: '20,140', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/012.ts b/src/lib/test-files/012.ts index 4578824..eee1b96 100644 --- a/src/lib/test-files/012.ts +++ b/src/lib/test-files/012.ts @@ -29,8 +29,11 @@ export default (message: string): TestCase => { { rank: '5', suit: 'Diamonds' }, { rank: '5', suit: 'Spades', seal: 'red' }, ], - score: 13300, - formattedScore: '13,300', + scores: [ + { score: 13300, formattedScore: '13,300', luck: 'none' }, + { score: 13300, formattedScore: '13,300', luck: 'average' }, + { score: 13300, formattedScore: '13,300', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/013.ts b/src/lib/test-files/013.ts index e5b3b14..22912e4 100644 --- a/src/lib/test-files/013.ts +++ b/src/lib/test-files/013.ts @@ -35,8 +35,11 @@ export default (message: string): TestCase => { { rank: '5', suit: 'Hearts', enhancement: 'mult' }, { rank: '5', suit: 'Clubs', seal: 'gold' }, ], - score: 60382, - formattedScore: '60,382', + scores: [ + { score: 60382, formattedScore: '60,382', luck: 'none' }, + { score: 60382, formattedScore: '60,382', luck: 'average' }, + { score: 60382, formattedScore: '60,382', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/014.ts b/src/lib/test-files/014.ts index c9f4bd1..039d1f3 100644 --- a/src/lib/test-files/014.ts +++ b/src/lib/test-files/014.ts @@ -35,8 +35,11 @@ export default (message: string): TestCase => { { rank: '5', suit: 'Spades', enhancement: 'mult', seal: 'red' }, { rank: '5', suit: 'Spades', enhancement: 'mult', seal: 'red' }, ], - score: 109270, - formattedScore: '109,270', + scores: [ + { score: 109270, formattedScore: '109,270', luck: 'none' }, + { score: 109270, formattedScore: '109,270', luck: 'average' }, + { score: 109270, formattedScore: '109,270', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/015.ts b/src/lib/test-files/015.ts index 1639616..a8dded2 100644 --- a/src/lib/test-files/015.ts +++ b/src/lib/test-files/015.ts @@ -38,8 +38,11 @@ export default (message: string): TestCase => { { rank: 'Queen', suit: 'Diamonds' }, { rank: 'Queen', suit: 'Diamonds', enhancement: 'glass' }, ], - score: 354294, - formattedScore: '354,294', + scores: [ + { score: 354294, formattedScore: '354,294', luck: 'none' }, + { score: 354294, formattedScore: '354,294', luck: 'average' }, + { score: 354294, formattedScore: '354,294', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/016.ts b/src/lib/test-files/016.ts index b2f42f6..f394935 100644 --- a/src/lib/test-files/016.ts +++ b/src/lib/test-files/016.ts @@ -38,8 +38,11 @@ export default (message: string): TestCase => { { rank: 'Queen', suit: 'Diamonds', enhancement: 'glass' }, { rank: 'Queen', suit: 'Diamonds', enhancement: 'glass', seal: 'red' }, ], - score: 284173, - formattedScore: '284,173', + scores: [ + { score: 284173, formattedScore: '284,173', luck: 'none' }, + { score: 284173, formattedScore: '284,173', luck: 'average' }, + { score: 284173, formattedScore: '284,173', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/017.ts b/src/lib/test-files/017.ts index 38a5734..b76a5d1 100644 --- a/src/lib/test-files/017.ts +++ b/src/lib/test-files/017.ts @@ -42,8 +42,11 @@ export default (message: string): TestCase => { { rank: 'Ace', suit: 'Diamonds', enhancement: 'glass', seal: 'red' }, { rank: 'Ace', suit: 'Diamonds', enhancement: 'glass', seal: 'red' }, ], - score: 11_287_462_454_231_040, - formattedScore: '1.129e16', + scores: [ + { score: 11_287_462_454_231_040, formattedScore: '1.129e16', luck: 'none' }, + { score: 11_287_462_454_231_040, formattedScore: '1.129e16', luck: 'average' }, + { score: 11_287_462_454_231_040, formattedScore: '1.129e16', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/018.ts b/src/lib/test-files/018.ts index 8768337..8ba053c 100644 --- a/src/lib/test-files/018.ts +++ b/src/lib/test-files/018.ts @@ -23,8 +23,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Spades' }, { rank: '7', suit: 'Hearts', isDebuffed: true }, ], - score: 234, - formattedScore: '234', + scores: [ + { score: 234, formattedScore: '234', luck: 'none' }, + { score: 234, formattedScore: '234', luck: 'average' }, + { score: 234, formattedScore: '234', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/019.ts b/src/lib/test-files/019.ts index 9623459..88ef591 100644 --- a/src/lib/test-files/019.ts +++ b/src/lib/test-files/019.ts @@ -24,8 +24,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Spades' }, { rank: '7', suit: 'Hearts', isDebuffed: true }, ], - score: 334, - formattedScore: '334', + scores: [ + { score: 334, formattedScore: '334', luck: 'none' }, + { score: 334, formattedScore: '334', luck: 'average' }, + { score: 334, formattedScore: '334', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/020.ts b/src/lib/test-files/020.ts index 10368c7..d4bac2c 100644 --- a/src/lib/test-files/020.ts +++ b/src/lib/test-files/020.ts @@ -25,8 +25,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Spades' }, { rank: '7', suit: 'Hearts', isDebuffed: true }, ], - score: 434, - formattedScore: '434', + scores: [ + { score: 434, formattedScore: '434', luck: 'none' }, + { score: 434, formattedScore: '434', luck: 'average' }, + { score: 434, formattedScore: '434', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/021.ts b/src/lib/test-files/021.ts index f6b857b..af9f9b3 100644 --- a/src/lib/test-files/021.ts +++ b/src/lib/test-files/021.ts @@ -21,8 +21,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Hearts', isDebuffed: true }, { rank: '7', suit: 'Diamonds' }, ], - score: 567, - formattedScore: '567', + scores: [ + { score: 567, formattedScore: '567', luck: 'none' }, + { score: 567, formattedScore: '567', luck: 'average' }, + { score: 567, formattedScore: '567', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/022.ts b/src/lib/test-files/022.ts index d1c84a5..4230029 100644 --- a/src/lib/test-files/022.ts +++ b/src/lib/test-files/022.ts @@ -24,8 +24,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Hearts', isDebuffed: true }, { rank: '7', suit: 'Diamonds' }, ], - score: 1701, - formattedScore: '1,701', + scores: [ + { score: 1701, formattedScore: '1,701', luck: 'none' }, + { score: 1701, formattedScore: '1,701', luck: 'average' }, + { score: 1701, formattedScore: '1,701', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/023.ts b/src/lib/test-files/023.ts index e8a7b67..9896bd4 100644 --- a/src/lib/test-files/023.ts +++ b/src/lib/test-files/023.ts @@ -25,8 +25,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Hearts', isDebuffed: true }, { rank: '7', suit: 'Diamonds' }, ], - score: 1554, - formattedScore: '1,554', + scores: [ + { score: 1554, formattedScore: '1,554', luck: 'none' }, + { score: 1554, formattedScore: '1,554', luck: 'average' }, + { score: 1554, formattedScore: '1,554', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/024.ts b/src/lib/test-files/024.ts index 380e924..2716e22 100644 --- a/src/lib/test-files/024.ts +++ b/src/lib/test-files/024.ts @@ -23,8 +23,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Spades' }, { rank: '7', suit: 'Hearts' }, ], - score: 248, - formattedScore: '248', + scores: [ + { score: 248, formattedScore: '248', luck: 'none' }, + { score: 248, formattedScore: '248', luck: 'average' }, + { score: 248, formattedScore: '248', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/025.ts b/src/lib/test-files/025.ts index 84ab3b9..ff07dd0 100644 --- a/src/lib/test-files/025.ts +++ b/src/lib/test-files/025.ts @@ -23,8 +23,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Spades', isDebuffed: true }, { rank: '7', suit: 'Hearts', isDebuffed: true }, ], - score: 220, - formattedScore: '220', + scores: [ + { score: 220, formattedScore: '220', luck: 'none' }, + { score: 220, formattedScore: '220', luck: 'average' }, + { score: 220, formattedScore: '220', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/026.ts b/src/lib/test-files/026.ts index 35104d1..be03750 100644 --- a/src/lib/test-files/026.ts +++ b/src/lib/test-files/026.ts @@ -23,8 +23,11 @@ export default (message: string): TestCase => { { rank: '7', suit: 'Spades' }, { rank: '7', suit: 'Hearts', isDebuffed: true }, ], - score: 234, - formattedScore: '234', + scores: [ + { score: 234, formattedScore: '234', luck: 'none' }, + { score: 234, formattedScore: '234', luck: 'average' }, + { score: 234, formattedScore: '234', luck: 'all' }, + ], }, } } diff --git a/src/lib/test-files/027.ts b/src/lib/test-files/027.ts new file mode 100644 index 0000000..c16f9c7 --- /dev/null +++ b/src/lib/test-files/027.ts @@ -0,0 +1,33 @@ +import type { TestCase } from '#lib/balatro.test.js' + +export default (message: string): TestCase => { + return { + message, + initialState: { + blind: { name: 'The Pillar' }, + playedCards: [ + { rank: '8', suit: 'Spades' }, + { rank: '7', suit: 'Spades', enhancement: 'lucky' }, + { rank: '7', suit: 'Hearts', enhancement: 'lucky' }, + { rank: '5', suit: 'Spades' }, + { rank: '2', suit: 'Spades' }, + ], + jokers: [ + { name: 'Blueprint' }, + { name: 'Sly Joker' }, + ], + }, + expected: { + hand: 'Pair', + scoringCards: [ + { rank: '7', suit: 'Spades', enhancement: 'lucky' }, + { rank: '7', suit: 'Hearts', enhancement: 'lucky' }, + ], + scores: [ + { score: 248, formattedScore: '248', luck: 'none' }, + { score: 1240, formattedScore: '1,240', luck: 'average' }, + { score: 5208, formattedScore: '5,208', luck: 'all' }, + ], + }, + } +} diff --git a/src/lib/test-files/028.ts b/src/lib/test-files/028.ts new file mode 100644 index 0000000..424689a --- /dev/null +++ b/src/lib/test-files/028.ts @@ -0,0 +1,39 @@ +import type { TestCase } from '#lib/balatro.test.js' + +export default (message: string): TestCase => { + return { + message, + initialState: { + hands: 1, + playedCards: [ + { rank: 'King', suit: 'Hearts', enhancement: 'lucky' }, + { rank: 'King', suit: 'Hearts', enhancement: 'lucky' }, + { rank: 'Jack', suit: 'Hearts', enhancement: 'lucky' }, + { rank: 'Ace', suit: 'Hearts', enhancement: 'lucky' }, + { rank: '6', suit: 'Hearts', enhancement: 'lucky' }, + ], + jokers: [ + { name: 'Sock and Buskin' }, + { name: 'Dusk' }, + { name: 'Lusty Joker' }, + { name: 'Blueprint' }, + { name: 'Bloodstone' }, + ], + }, + expected: { + hand: 'Flush', + scoringCards: [ + { rank: 'King', suit: 'Hearts', enhancement: 'lucky' }, + { rank: 'King', suit: 'Hearts', enhancement: 'lucky' }, + { rank: 'Jack', suit: 'Hearts', enhancement: 'lucky' }, + { rank: 'Ace', suit: 'Hearts', enhancement: 'lucky' }, + { rank: '6', suit: 'Hearts', enhancement: 'lucky' }, + ], + scores: [ + { score: 8904, formattedScore: '8,904', luck: 'none' }, + { score: 6275230, formattedScore: '6,275,230', luck: 'average' }, + { score: 384131132448, formattedScore: '384,131,132,448', luck: 'all' }, + ], + }, + } +} diff --git a/src/lib/types.ts b/src/lib/types.ts index 7e5d1b1..ae793aa 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -41,6 +41,7 @@ export interface Card extends Required { export interface EffectOptions { state: State score: Score + luck: Luck } export interface CardEffectOptions extends EffectOptions { @@ -73,7 +74,6 @@ export interface InitialJoker { export interface JokerDefinition { rarity: 'common' | 'uncommon' | 'rare' | 'legendary' - probability?: Probability effect?: JokerEffect indirectEffect?: JokerIndirectEffect playedCardEffect?: JokerCardEffect @@ -96,7 +96,6 @@ export interface Joker { suit?: Suit isActive: boolean rarity: 'common' | 'uncommon' | 'rare' | 'legendary' - probability?: Probability effect?: JokerEffect indirectEffect?: JokerIndirectEffect playedCardEffect?: JokerCardEffect @@ -145,9 +144,16 @@ export interface State { scoringCards: Card[] } +export type Luck = 'none' | 'average' | 'all' + +export interface ResultScore { + score: number + formattedScore: string + luck: Luck +} + export interface Result { hand: HandName scoringCards: Card[] - score: number - formattedScore: string + scores: ResultScore[] } diff --git a/src/ui/UiState.ts b/src/ui/UiState.ts index 7c70697..3296d70 100644 --- a/src/ui/UiState.ts +++ b/src/ui/UiState.ts @@ -67,12 +67,13 @@ export class UiState { } updateScore (state: State) { - const score = calculateScore(state) - log(score) + const { hand, scoringCards, scores } = calculateScore(state) + log({ hand, scoringCards, scores }) + const score = scores[0]! this.formattedScoreEl.textContent = score.formattedScore this.scoreEl.textContent = new Intl.NumberFormat('en').format(score.score) - this.playedHandEl.textContent = score.hand + this.playedHandEl.textContent = hand } /** diff --git a/src/utilities/getState.ts b/src/utilities/getState.ts index 97997c1..445d92b 100644 --- a/src/utilities/getState.ts +++ b/src/utilities/getState.ts @@ -99,7 +99,6 @@ function getJokers (initialJokers: InitialJoker[]): Joker[] { const { rarity, - probability = { numerator: 1, denominator: 1 }, effect, indirectEffect, playedCardEffect, @@ -118,7 +117,6 @@ function getJokers (initialJokers: InitialJoker[]): Joker[] { suit, isActive, rarity, - probability, effect, indirectEffect, playedCardEffect,