Skip to content

Commit 48c588b

Browse files
committed
Revert "hotfix: unwinding the peak logic."
This reverts commit e3c39d3.
1 parent e3c39d3 commit 48c588b

7 files changed

Lines changed: 81 additions & 36 deletions

File tree

___tests___/spoiler_peek.spec.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { expect, test } from "vitest";
2+
import { analyzeSeed } from "../src/modules/ImmolateWrapper";
3+
import { options } from "../src/modules/const";
4+
5+
function getAnte2BossArcanaSpoilerJokers(cardsPerAnte: number): string[] {
6+
const results = analyzeSeed(
7+
{
8+
seed: "TYTWAA1P",
9+
deck: "Plasma Deck",
10+
stake: "White Stake",
11+
gameVersion: "10106",
12+
antes: 2,
13+
cardsPerAnte,
14+
},
15+
{
16+
buys: {},
17+
sells: {},
18+
showCardSpoilers: true,
19+
unlocks: options,
20+
events: [],
21+
lockedCards: {},
22+
}
23+
) as any;
24+
25+
const packs = results?.antes?.[2]?.blinds?.bossBlind?.packs ?? [];
26+
const arcanaPacks = packs.filter((p: any) => p?.name === "Arcana");
27+
const jokerNames = arcanaPacks.flatMap((p: any) =>
28+
(p?.cards ?? [])
29+
.filter((c: any) => c?.type === "Joker")
30+
.map((c: any) => c?.name)
31+
);
32+
33+
return jokerNames;
34+
}
35+
36+
test("TYTWAA1P: Judgement spoiler does not change when Cards per Ante changes", () => {
37+
const at50 = getAnte2BossArcanaSpoilerJokers(50);
38+
const at100 = getAnte2BossArcanaSpoilerJokers(100);
39+
const at150 = getAnte2BossArcanaSpoilerJokers(150);
40+
41+
expect(at50.length).toBeGreaterThan(0);
42+
expect(at50).toEqual(at100);
43+
expect(at50).toEqual(at150);
44+
45+
expect(at50).toContain("Ice Cream");
46+
expect(at50).not.toContain("Sixth Sense");
47+
});
48+

src/modules/ImmolateWrapper/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ export function analyzeSeed(settings: AnalyzeSettings, analyzeOptions: AnalyzeOp
544544
const shopItem = engine.nextShopItem(ante);
545545
const spoilerSource = engine.hasSpoilersMap[shopItem.item.name];
546546
if (engine.hasSpoilers && spoilerSource) {
547-
const joker: JokerData = engine.nextJoker(spoilerSource, ante, true);
547+
const joker: JokerData = engine.peekJoker(spoilerSource, ante, true);
548548
result.queue.push(
549549
engineWrapper.makeGameCard(joker)
550550
)
@@ -560,7 +560,7 @@ export function analyzeSeed(settings: AnalyzeSettings, analyzeOptions: AnalyzeOp
560560
if (analyzeOptions && analyzeOptions?.showCardSpoilers) {
561561
if (itemsWithSpoilers.includes(result.queue[i].name as SpoilableItems)) {
562562
// @ts-expect-error reports types dont match.
563-
result.queue[i] = Pack.PackCardToCard(engine.nextJoker(spoilerSources[itemsWithSpoilers.indexOf(result.queue[i].name)], ante, false), 'Joker')
563+
result.queue[i] = Pack.PackCardToCard(engine.peekJoker(spoilerSources[itemsWithSpoilers.indexOf(result.queue[i].name)], ante, false), 'Joker')
564564
}
565565
}
566566
if (analyzeOptions && analyzeOptions.buys[key]) {
@@ -671,7 +671,7 @@ export function analyzeSeed(settings: AnalyzeSettings, analyzeOptions: AnalyzeOp
671671
const spoilerSource = engine.hasSpoilersMap[card.name];
672672
// @ts-ignore
673673
if (engine.hasSpoilers && spoilerSource) {
674-
card = engine.nextJoker(spoilerSource, ante, true)
674+
card = engine.peekJoker(spoilerSource, ante, true)
675675
}
676676
const generatedCard = engineWrapper.makeGameCard(card);
677677
// @ts-ignore

src/modules/balatrots/BalatroAnalyzer.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ export class BalatroAnalyzer {
238238

239239
if (this.hasSpoilers && isSpoilable) {
240240
const spoilerSource = this.hasSpoilersMap[card.name as SpoilableItems];
241-
const joker = game.nextJoker(spoilerSource, this.result.ante, true);
241+
const joker = game.peekJoker(spoilerSource, this.result.ante, true);
242242
BalatroAnalyzer.getSticker(joker);
243243
card = joker
244244
run.addJoker(card.joker.name);
@@ -257,7 +257,7 @@ export class BalatroAnalyzer {
257257
const spoilerSource = Object.keys(this.hasSpoilersMap)
258258
.includes(shopItem.item.name);
259259
if (this.hasSpoilers && spoilerSource) {
260-
const joker: JokerData = game.nextJoker(this.hasSpoilersMap[shopItem.item.name as SpoilableItems], ante, true);
260+
const joker: JokerData = game.peekJoker(this.hasSpoilersMap[shopItem.item.name as SpoilableItems], ante, true);
261261
run.addJoker(joker.joker.getName());
262262
BalatroAnalyzer.getSticker(joker);
263263
this.result.addItemToShopQueue(joker);
@@ -323,7 +323,7 @@ export class BalatroAnalyzer {
323323
if (item === "The Soul") {
324324
run.hasTheSoul = true;
325325
}
326-
const joker = game.nextJoker(spoilerSource, this.result.ante, true);
326+
const joker = game.peekJoker(spoilerSource, this.result.ante, true);
327327
run.addJoker(joker.joker.getName());
328328
const sticker = BalatroAnalyzer.getSticker(joker);
329329
options.add(new Option(joker.joker, new ItemImpl(sticker)));

src/modules/balatrots/Cache.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,4 @@ export class Cache {
7474
}
7575
this.nodes.set(key, value);
7676
}
77-
}
77+
}

src/modules/balatrots/Game.ts

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,11 @@ export class Game extends Lock {
346346
this.hasSpoilers = false;
347347
}
348348

349+
private withCacheState<T>(fn: () => T): T {
350+
// Roll back only the keys mutated during `fn` (cheap), instead of copying the whole cache.
351+
return this.cache.withRollback(fn);
352+
}
353+
349354
private getNode(id: string) {
350355
let c = this.cache.getNode(id);
351356

@@ -653,6 +658,14 @@ export class Game extends Lock {
653658
return new JokerData(joker, rarity, edition, stickers);
654659
}
655660

661+
/**
662+
* Returns what `nextJoker(...)` would return, but does NOT advance RNG/cache state.
663+
* Intended for spoiler/peek UI.
664+
*/
665+
peekJoker(source: QueueNames, ante: number, hasStickers: boolean): JokerData {
666+
return this.withCacheState(() => this.nextJoker(source, ante, hasStickers));
667+
}
668+
656669
getShopInstance(): ShopInstance {
657670
let tarotRate = 4;
658671
let planetRate = 4;
@@ -1031,7 +1044,7 @@ export class Game extends Lock {
10311044
const item = (card as ItemImpl).getName();
10321045
const spoilerSource = this.hasSpoilersMap[item];
10331046
if (this.hasSpoilers) {
1034-
return this.nextJoker(spoilerSource, ante, false)
1047+
return this.peekJoker(spoilerSource, ante, false)
10351048
}
10361049
return card as Card;
10371050
}
@@ -1132,18 +1145,18 @@ item wheel_of_fortune_edition(instance* inst) {
11321145
}
11331146
return (value + this.hashedSeed) / 2;
11341147
}
1135-
static get CARDS_ABANDONED(): Array<Card> {
1148+
static get CARDS_ABANDONED(): Card[] {
11361149
// Abandoned Deck: 40 cards, no face cards (J, Q, K).
11371150
return this.CARDS.filter(c => {
11381151
const name = c.getName();
11391152
return !name.includes("_J") && !name.includes("_Q") && !name.includes("_K");
11401153
}).map(c => new Card(c.getName() as PlayingCard));
11411154
}
11421155

1143-
static get CARDS_CHECKERED(): Array<Card> {
1156+
static get CARDS_CHECKERED(): Card[] {
11441157
// Checkered Deck: 52 cards (Hearts/Spades only).
11451158
return this.CARDS.map(c => {
1146-
const name = c.getName();
1159+
const name = c.getName() as string;
11471160
const rank = name.split("_")[1];
11481161
const suit = name.split("_")[0];
11491162
let newSuit = suit;
@@ -1156,9 +1169,9 @@ item wheel_of_fortune_edition(instance* inst) {
11561169
/**
11571170
* Returns a fully shuffled deck for the given ante and round index (1, 2, or 3).
11581171
*/
1159-
private getShuffledDeck(ante: number, round: number = 1): Array<Card> {
1172+
private getShuffledDeck(ante: number, round: number = 1): Card[] {
11601173
const deckType = this.params.getDeck().name;
1161-
let cards: Array<Card>;
1174+
let cards: Card[];
11621175

11631176
switch (deckType) {
11641177
case deckNames[DeckType.ABANDONED_DECK]:
@@ -1168,7 +1181,7 @@ item wheel_of_fortune_edition(instance* inst) {
11681181
cards = Game.CARDS_CHECKERED;
11691182
break;
11701183
case deckNames[DeckType.ERRATIC_DECK]: {
1171-
const randomizedCards: Array<Card> = [];
1184+
const randomizedCards: Card[] = [];
11721185
for(let i = 0; i < 52; i++){
11731186
const card = this.randchoice_simple(RandomQueueNames.R_Erratic, Game.CARDS);
11741187
randomizedCards.push(new Card(card.getName() as PlayingCard));
@@ -1185,7 +1198,7 @@ item wheel_of_fortune_edition(instance* inst) {
11851198

11861199
for (let i = cards.length - 1; i >= 1; i--) {
11871200
const j = rng.randint(1, i + 1) -1;
1188-
const temp = cards[i];
1201+
let temp = cards[i];
11891202
cards[i] = cards[j];
11901203
cards[j] = temp;
11911204

@@ -1202,29 +1215,13 @@ item wheel_of_fortune_edition(instance* inst) {
12021215
* @param round The round index within the ante (1, 2, or 3) (default 1)
12031216
* @param count Number of cards to draw (default 8)
12041217
*/
1205-
getDeckDraw(ante: number, round: number = 1, count: number = 8): Array<Card> {
1218+
getDeckDraw(ante: number, round: number = 1, count: number = 8): Card[] {
12061219
const deck = this.getShuffledDeck(ante, round);
12071220
return deck.slice(0, count);
12081221
}
12091222

1210-
getStartingDeckDraw(count = 8, sort: 'rank' | 'suit' = 'rank'): Array<Card> {
1223+
getStartingDeckDraw(): Card[] {
12111224
// pifreak loves you!
1212-
const hand = this.getDeckDraw(1, 1, count);
1213-
if (sort === 'rank') {
1214-
return hand.sort((a, b) => {
1215-
const rankA = parseInt(a.getName().split('_')[1]);
1216-
const rankB = parseInt(b.getName().split('_')[1]);
1217-
return rankA - rankB;
1218-
});
1219-
}
1220-
else {
1221-
const suitOrder: Record<string, number> = { 'C': 1, 'D': 2, 'H': 3, 'S': 4 };
1222-
return hand.sort((a, b) => {
1223-
const suitA = a.getName().split('_')[0];
1224-
const suitB = b.getName().split('_')[0];
1225-
return suitOrder[suitA] - suitOrder[suitB];
1226-
});
1227-
}
1225+
return this.getDeckDraw(1, 1, 8);
12281226
}
12291227
}
1230-

src/modules/balatrots/Lock.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,4 @@ export class Lock implements ILock {
151151
if (ante == 5) this.unlock("The Serpent");
152152
if (ante == 6) this.unlock("The Ox");
153153
}
154-
}
154+
}

src/modules/balatrots/struct/InstanceParams.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,4 @@ export class InstanceParams {
7070
setVouchers(vouchers: Set<Voucher>): void {
7171
this.vouchers = vouchers;
7272
}
73-
}
73+
}

0 commit comments

Comments
 (0)