';
449 | }
450 | if(line.chips !== previousChips || line.mult[0] !== previousMult[0] || line.mult[1] !== previousMult[1]) {
451 | breakdownScore = `
` +
452 | `${numberWithCommas(line.chips)}X` +
453 | `${bigNumberWithCommas(normalizeBig(line.mult))}` +
454 | `
`;
455 | previousChips = line.chips;
456 | previousMult = line.mult;
457 | }
458 | breakdownHTML += `
` +
459 | breakdownCards +
460 | `
` +
461 | line.description +
462 | `` +
463 | breakdownScore +
464 | `
`;
465 | }
466 |
467 | tabs[3].innerHTML = breakdownHTML;
468 | }
469 |
470 | function factorial(n) {
471 | let ans = 1;
472 | for(let i = 2; i <= n; i++) {
473 | ans *= i;
474 | }
475 | return ans;
476 | }
477 |
478 | function calculator() {
479 | document.body.style.cursor = 'wait';
480 |
481 | tmpBestCards = [];
482 | tmpBestHighHand = [0, 0, 0, 0, 0];
483 | tmpBestLowHand = [0, 0, 0, 0, 0];
484 | tmpTypeOfHand = 11;
485 | bestScore = false;
486 |
487 | taskID = Math.random();
488 | let possibleHands = [];
489 | let chosen = [];
490 | tmpBestJokers = [];
491 |
492 | tasks = 0;
493 |
494 | terminateThreads();
495 |
496 | if(Object.keys(playfieldJokers).length === 0) {
497 | threads[0].postMessage(['once']);
498 | tasks = 1;
499 | }
500 | else if(!optimizeJokers) {
501 | threads[0].postMessage(['dontOptimizeJokers']);
502 | tasks = 1;
503 | }
504 | else {
505 | let possibleJokers = factorial(Object.keys(playfieldJokers).length);
506 | let tasksPerThread = Math.ceil(possibleJokers / THREADS);
507 |
508 | for(let i = 0; i < THREADS; i++) {
509 | threads[i].postMessage(['optimizeJokers', i * tasksPerThread, (i + 1) * tasksPerThread]);
510 | tasks++;
511 | possibleJokers -= tasksPerThread;
512 | if(possibleJokers <= 0) {
513 | break;
514 | }
515 | }
516 | }
517 |
518 | bestJokers = Object.keys(playfieldJokers);
519 | }
520 |
521 | function numberWithCommas(x) {
522 | if(typeof x === 'object') return bigNumberWithCommas(x);
523 | if(x < 1e11) {
524 | if((Math.floor(x * 10000) / 10000) % 1 !== 0) {
525 | return Math.floor(x).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '.' + (Math.floor(Math.round((x % 1) * 10000) / 10)+'').padStart(3, 0).replace(/0+$/, '');
526 | }
527 | return Math.floor(x).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
528 | }
529 | return `${Math.floor(x/(10**Math.floor(Math.log10(x)))*10000)/10000}e${Math.floor(Math.log10(x))}`;
530 | }
531 |
532 | function bigNumberWithCommas(num, whole = false) {
533 | if(num && num[1] > 11) {
534 | return `${Math.floor(num[0] * 10000) / 10000}e${num[1]}`;
535 | }
536 |
537 | const x = num[0] * (10 ** num[1]);
538 | if((Math.floor(x * 10000) / 10000) % 1 !== 0) {
539 | if(whole) {
540 | return Math.floor(x).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
541 | }
542 | return Math.floor(x).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",") + '.' + (Math.floor(Math.round((x % 1) * 10000) / 10)+'').padStart(3, 0).replace(/0+$/, '');
543 | }
544 | return Math.floor(x).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
545 | }
546 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Balatro Calculator
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
24 |
25 |
26 |
27 |
28 |
29 | X
30 | Optimize Jokers (slow)
31 |
32 |
33 |
34 |
35 | X
36 | Optimize Hand (slow)
37 |
38 |
39 |
40 |
0/7
41 |
42 |
High Card lvl.1
43 |
5
44 |
45 | 5X1
46 |
47 |
48 |
49 |
50 |
0/8
51 |
52 |
53 |
54 | Minimize Score
55 |
56 |
57 |
58 | The Flint
59 |
60 |
61 |
62 | Can't play checked hands (The Eye)
63 |
64 |
65 |
66 | Plasma Deck
67 |
68 |
69 |
70 | Observatory
71 |
72 |
73 |
74 |

75 |
76 |
77 |
78 |
79 |
82 |
83 |
84 |
85 | -
86 | 1
87 | +
88 | Count
89 | 1
90 |
91 |
92 |
93 |
94 | -
95 | 0
96 | +
97 | Value
98 | 0
99 |
100 |
101 |
102 |
103 | Search
104 |
105 |
106 |
107 |
122 |
123 |
124 |
125 |
126 |
127 | -
128 | 1
129 | +
130 | Count
131 | 1
132 |
133 |
134 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 | -
188 | 0
189 | +
190 | Value
191 | 0
192 |
193 |
194 |
195 |
196 | -
197 | 0
198 | +
199 | Sell
200 | 0
201 |
202 |
203 |
218 |
219 |
220 |
221 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
--------------------------------------------------------------------------------
/structured-data.jsonld:
--------------------------------------------------------------------------------
1 | {
2 | "@context": "http://schema.org",
3 | "@type": "VideoGame",
4 | "name": "Balatro Calculator",
5 | "description": "Calculate the score of any Balatro hand",
6 | "gameItem": [
7 | {
8 | "@type": "Thing",
9 | "name": "Joker",
10 | "description": "+4 Mult"
11 | },
12 | {
13 | "@type": "Thing",
14 | "name": "Chaos the Clown",
15 | "description": "1 free Reroll per shop"
16 | },
17 | {
18 | "@type": "Thing",
19 | "name": "Jolly Joker",
20 | "description": "+8 Mult if played hand contains a Pair"
21 | },
22 | {
23 | "@type": "Thing",
24 | "name": "Zany Joker",
25 | "description": "+12 Mult if played hand contains a Three of a Kind"
26 | },
27 | {
28 | "@type": "Thing",
29 | "name": "Mad Joker",
30 | "description": "+10 Mult if played hand contains a Two Pair"
31 | },
32 | {
33 | "@type": "Thing",
34 | "name": "Crazy Joker",
35 | "description": "+12 Mult if played hand contains a Straight"
36 | },
37 | {
38 | "@type": "Thing",
39 | "name": "Droll Joker",
40 | "description": "+10 Mult if played hand contains a Flush"
41 | },
42 | {
43 | "@type": "Thing",
44 | "name": "Half Joker",
45 | "description": "+20 Mult if played hand contains 3 or fewer cards"
46 | },
47 | {
48 | "@type": "Thing",
49 | "name": "Merry Andy",
50 | "description": "+3 discards, -1 hand size"
51 | },
52 | {
53 | "@type": "Thing",
54 | "name": "Stone Joker",
55 | "description": "This Joker gains +25 Chips for each Stone Card in your full deck (Currently +0 Chips)"
56 | },
57 | {
58 | "@type": "Thing",
59 | "name": "Juggler",
60 | "description": "+1 hand size"
61 | },
62 | {
63 | "@type": "Thing",
64 | "name": "Drunkard",
65 | "description": "+1 discard"
66 | },
67 | {
68 | "@type": "Thing",
69 | "name": "Acrobat",
70 | "description": "X3 Mult on final hand of round (Currently inactive)"
71 | },
72 | {
73 | "@type": "Thing",
74 | "name": "Sock and Buskin",
75 | "description": "Retrigger all played face cards"
76 | },
77 | {
78 | "@type": "Thing",
79 | "name": "Mime",
80 | "description": "Retrigger all card held in hand abilities"
81 | },
82 | {
83 | "@type": "Thing",
84 | "name": "Credit Card",
85 | "description": "Go up to -$20 in debt"
86 | },
87 | {
88 | "@type": "Thing",
89 | "name": "Greedy Joker",
90 | "description": "Played cards with Diamond suit give +3 Mult when scored"
91 | },
92 | {
93 | "@type": "Thing",
94 | "name": "Lusty Joker",
95 | "description": "Played cards with Heart suit give +3 Mult when scored"
96 | },
97 | {
98 | "@type": "Thing",
99 | "name": "Wrathful Joker",
100 | "description": "Played cards with Spade suit give +3 Mult when scored"
101 | },
102 | {
103 | "@type": "Thing",
104 | "name": "Gluttonous Joker",
105 | "description": "Played cards with Club suit give +3 Mult when scored"
106 | },
107 | {
108 | "@type": "Thing",
109 | "name": "Troubadour",
110 | "description": "+2 hand size, -1 hands per round"
111 | },
112 | {
113 | "@type": "Thing",
114 | "name": "Banner",
115 | "description": "+30 Chips for each remaining discard (Currently +0 Chips)"
116 | },
117 | {
118 | "@type": "Thing",
119 | "name": "Mystic Summit",
120 | "description": "+15 Mult when 0 discards remaining (Currently inactive)"
121 | },
122 | {
123 | "@type": "Thing",
124 | "name": "Marble Joker",
125 | "description": "Adds one Stone card to deck when Blind is selected"
126 | },
127 | {
128 | "@type": "Thing",
129 | "name": "Loyalty Card",
130 | "description": "X4 Mult every 6 hands played (0 remaining)"
131 | },
132 | {
133 | "@type": "Thing",
134 | "name": "Hack",
135 | "description": "Retrigger each played 2, 3, 4, or 5"
136 | },
137 | {
138 | "@type": "Thing",
139 | "name": "Misprint",
140 | "description": "+0 - +23 Mult"
141 | },
142 | {
143 | "@type": "Thing",
144 | "name": "Steel Joker",
145 | "description": "This Joker gains X0.2 Mult for each Steel Card in your full deck (Currently X1 Mult)"
146 | },
147 | {
148 | "@type": "Thing",
149 | "name": "Raised Fist",
150 | "description": "Adds double the rank of lowest card held in hand to Mult"
151 | },
152 | {
153 | "@type": "Thing",
154 | "name": "Golden Joker",
155 | "description": "Earn $4 at end of round"
156 | },
157 | {
158 | "@type": "Thing",
159 | "name": "Blueprint",
160 | "description": "Copies ability of Joker to the right"
161 | },
162 | {
163 | "@type": "Thing",
164 | "name": "Glass Joker",
165 | "description": "This Joker gains X0.75 Mult for every Glass Card that is destroyed (Currently X1 Mult)"
166 | },
167 | {
168 | "@type": "Thing",
169 | "name": "Scary Face",
170 | "description": "Played face cards give +30 Chips when scored"
171 | },
172 | {
173 | "@type": "Thing",
174 | "name": "Abstract Joker",
175 | "description": "+3 Mult for each Joker card (Currently +0 Mult)"
176 | },
177 | {
178 | "@type": "Thing",
179 | "name": "Delayed Gratification",
180 | "description": "Earn $2 per discard if no discards are used by end of the round"
181 | },
182 | {
183 | "@type": "Thing",
184 | "name": "Golden Ticket",
185 | "description": "Played Gold cards earn $4 when scored"
186 | },
187 | {
188 | "@type": "Thing",
189 | "name": "Pareidolia",
190 | "description": "All cards are considered Face cards"
191 | },
192 | {
193 | "@type": "Thing",
194 | "name": "Cartomancer",
195 | "description": "Create a Tarot card when Blind is selected (Must have room)"
196 | },
197 | {
198 | "@type": "Thing",
199 | "name": "Even Steven",
200 | "description": "Played cards with even rank give +4 Mult when scored (10, 8, 6, 4, 2)"
201 | },
202 | {
203 | "@type": "Thing",
204 | "name": "Odd Todd",
205 | "description": "Played cards with odd rank give +31 Chips when scored (A, 9, 7, 5, 3)"
206 | },
207 | {
208 | "@type": "Thing",
209 | "name": "Wee Joker",
210 | "description": "This Joker gains +8 Chips when each played 2 is scored (Currently +0 Chips)"
211 | },
212 | {
213 | "@type": "Thing",
214 | "name": "Business Card",
215 | "description": "Played Face cards have a 1 in 2 chance to give $2 when scored"
216 | },
217 | {
218 | "@type": "Thing",
219 | "name": "Supernova",
220 | "description": "Adds the number of times poker hand has been played to Mult (Currently +0 Mult)"
221 | },
222 | {
223 | "@type": "Thing",
224 | "name": "Mr. Bones",
225 | "description": "Prevents Death if chips scored are at least 25% of required chips self destructs"
226 | },
227 | {
228 | "@type": "Thing",
229 | "name": "Seeing Double",
230 | "description": "X2 Mult if played hand has a scoring Club card and a scoring card of any other suit"
231 | },
232 | {
233 | "@type": "Thing",
234 | "name": "The Duo",
235 | "description": "X2 Mult if played hand contains a Pair"
236 | },
237 | {
238 | "@type": "Thing",
239 | "name": "The Trio",
240 | "description": "X3 Mult if played hand contains a Three of a Kind"
241 | },
242 | {
243 | "@type": "Thing",
244 | "name": "The Family",
245 | "description": "X4 Mult if played hand contains a Four of a Kind"
246 | },
247 | {
248 | "@type": "Thing",
249 | "name": "The Order",
250 | "description": "X3 Mult if played hand contains a Straight"
251 | },
252 | {
253 | "@type": "Thing",
254 | "name": "The Tribe",
255 | "description": "X2 Mult if played hand contains a Flush"
256 | },
257 | {
258 | "@type": "Thing",
259 | "name": "8 Ball",
260 | "description": "1 in 4 chance for each played 8 to create a Tarot card when scored (Must have room)"
261 | },
262 | {
263 | "@type": "Thing",
264 | "name": "Fibonacci",
265 | "description": "Each plaed Ace, 2, 3, 5, or 8 gives +8 Mult when scored"
266 | },
267 | {
268 | "@type": "Thing",
269 | "name": "Joker Stencil",
270 | "description": "X1 Mult for each empty Joker slot Joker stencil included (Currently X1)"
271 | },
272 | {
273 | "@type": "Thing",
274 | "name": "Space Joker",
275 | "description": "1 in 4 chane to upgrade level of played poker hand"
276 | },
277 | {
278 | "@type": "Thing",
279 | "name": "Matador",
280 | "description": "Earn $8 if played hand triggers the Boss Blind ability"
281 | },
282 | {
283 | "@type": "Thing",
284 | "name": "Ceremonial Dagger",
285 | "description": "When Blind is selected, destroy Joker to the right and permanently add double its sell value to this Mult (Currently +0 Mult)"
286 | },
287 | {
288 | "@type": "Thing",
289 | "name": "Showman",
290 | "description": "Joker, Tarot, Planet, and Spectral cards may appear multiple times"
291 | },
292 | {
293 | "@type": "Thing",
294 | "name": "Fortune Teller",
295 | "description": "+1 Mult per Tarot card used this run (Currently 0)"
296 | },
297 | {
298 | "@type": "Thing",
299 | "name": "Hit the Road",
300 | "description": "This Joker gains X0.5 Mult per discarded Jack this round (Currently X1)"
301 | },
302 | {
303 | "@type": "Thing",
304 | "name": "Swashbuckler",
305 | "description": "Adds the sell value of all other owned Jokers to Mult"
306 | },
307 | {
308 | "@type": "Thing",
309 | "name": "Flower Pot",
310 | "description": "X3 Mult if poker hand contains a Diamond card, Club card, Heart card, and Spade card"
311 | },
312 | {
313 | "@type": "Thing",
314 | "name": "Ride the Bus",
315 | "description": "This Joker gains +1 Mult per consecutive hand played without a scoring face card (Currently +0)"
316 | },
317 | {
318 | "@type": "Thing",
319 | "name": "Shoot the Moon",
320 | "description": "+13 Mult for each Queen held in hand"
321 | },
322 | {
323 | "@type": "Thing",
324 | "name": "Scholar",
325 | "description": "Played Aces give +20 Chips and +4 Mult when scored"
326 | },
327 | {
328 | "@type": "Thing",
329 | "name": "Smeared Joker",
330 | "description": "Heart and Diamond count as the same suit, Spade and Club count as the same suit"
331 | },
332 | {
333 | "@type": "Thing",
334 | "name": "Oops! All 6s",
335 | "description": "Double all listed probabilities (ex: 1 in 3 -> 2 in 3)"
336 | },
337 | {
338 | "@type": "Thing",
339 | "name": "Four Fingers",
340 | "description": "All Flushes and Straights can be made with 4 cards"
341 | },
342 | {
343 | "@type": "Thing",
344 | "name": "Gros Michel",
345 | "description": "+15 Mult 1 in 6 chance this card is destroyed at the end of the round"
346 | },
347 | {
348 | "@type": "Thing",
349 | "name": "Stuntman",
350 | "description": "+250 Chips, -2 hand size"
351 | },
352 | {
353 | "@type": "Thing",
354 | "name": "Hanging Chad",
355 | "description": "Retrigger first played card used in scoring 2 additional times"
356 | },
357 | {
358 | "@type": "Thing",
359 | "name": "Driver's License",
360 | "description": "X3 Mult if you have at least 16 Enhanced cards in your full deck (Currently 0)"
361 | },
362 | {
363 | "@type": "Thing",
364 | "name": "Invisible Joker",
365 | "description": "After 2 rounds, sell this card to duplicate a random Joker (Currently 0/2)"
366 | },
367 | {
368 | "@type": "Thing",
369 | "name": "Astronomer",
370 | "description": "All Planet cards and Celestial Packs in the shop are free"
371 | },
372 | {
373 | "@type": "Thing",
374 | "name": "Burnt Joker",
375 | "description": "Upgrade the level of the first discarded poker hand each round"
376 | },
377 | {
378 | "@type": "Thing",
379 | "name": "Dusk",
380 | "description": "Retrigger all played cards in final hand of round (Currently inactive)"
381 | },
382 | {
383 | "@type": "Thing",
384 | "name": "Throwback",
385 | "description": "X0.25 Mult for each Blind skipped this run (Currently X1 Mult)"
386 | },
387 | {
388 | "@type": "Thing",
389 | "name": "The Idol",
390 | "description": "Each played 2 of Hearts gives X2 Mult when scored Card changes every round"
391 | },
392 | {
393 | "@type": "Thing",
394 | "name": "Brainstorm",
395 | "description": "Copies the ability of the leftmost Joker"
396 | },
397 | {
398 | "@type": "Thing",
399 | "name": "Satellite",
400 | "description": "Earn $1 at the end of round per unique Planet card used this run (Currently $0)"
401 | },
402 | {
403 | "@type": "Thing",
404 | "name": "Rough Gem",
405 | "description": "Played cards with Diamond suit earn $1 when scored"
406 | },
407 | {
408 | "@type": "Thing",
409 | "name": "Bloodstone",
410 | "description": "1 in 2 chance for played cards with Heart suit to give X1.5 Mult when scored"
411 | },
412 | {
413 | "@type": "Thing",
414 | "name": "Arrowhead",
415 | "description": "Played cards with Spade suit give +50 Chips when scored"
416 | },
417 | {
418 | "@type": "Thing",
419 | "name": "Onyx Agate",
420 | "description": "Played cards with Club suit give +7 Mult when scored"
421 | },
422 | {
423 | "@type": "Thing",
424 | "name": "Canio",
425 | "description": "Gains X1 Mult when a face card is destroyed (Currently X1 Mult)"
426 | },
427 | {
428 | "@type": "Thing",
429 | "name": "Triboulet",
430 | "description": "Played Kings and Queens each give X2 Mult when scored"
431 | },
432 | {
433 | "@type": "Thing",
434 | "name": "Yorick",
435 | "description": "This Joker gains X1 Mult every 23 [23] cards discarded (Currently X1 Mult)"
436 | },
437 | {
438 | "@type": "Thing",
439 | "name": "Chicot",
440 | "description": "Disables effect of every Boss Blind"
441 | },
442 | {
443 | "@type": "Thing",
444 | "name": "Perkeo",
445 | "description": "Creates a Negative copy of 1 random consumable card in your possession at the end of the shop"
446 | },
447 | {
448 | "@type": "Thing",
449 | "name": "Certificate",
450 | "description": "When round begins, add a random playing card with a random seal to your hand"
451 | },
452 | {
453 | "@type": "Thing",
454 | "name": "Bootstraps",
455 | "description": "+2 Mult for every $5 you have (Currently +0 Mult)"
456 | },
457 | {
458 | "@type": "Thing",
459 | "name": "Egg",
460 | "description": "Gains $3 of sell value at end of round"
461 | },
462 | {
463 | "@type": "Thing",
464 | "name": "Burglar",
465 | "description": "When Blind is selected, gain +3 Hands and lose all discards"
466 | },
467 | {
468 | "@type": "Thing",
469 | "name": "Blackboard",
470 | "description": "X3 Mult if all cards held in hand are Spade or Club"
471 | },
472 | {
473 | "@type": "Thing",
474 | "name": "Runner",
475 | "description": "Gains +15 Chips if played hand contains a Straight (Currently +0 Chips)"
476 | },
477 | {
478 | "@type": "Thing",
479 | "name": "Ice Cream",
480 | "description": "+100 Chips -5 Chips for every hand played"
481 | },
482 | {
483 | "@type": "Thing",
484 | "name": "DNA",
485 | "description": "If first hand of round has only 1 card, add a permanent copy to deck and draw it to hand"
486 | },
487 | {
488 | "@type": "Thing",
489 | "name": "Splash",
490 | "description": "Every played card counts in scoring"
491 | },
492 | {
493 | "@type": "Thing",
494 | "name": "Blue Joker",
495 | "description": "+2 Chips for each remaining card in Deck (Currently +104 Chips)"
496 | },
497 | {
498 | "@type": "Thing",
499 | "name": "Sixth Sense",
500 | "description": "If first hand of round is a single 6, destroy it and create a Spectral card (Must have room)"
501 | },
502 | {
503 | "@type": "Thing",
504 | "name": "Constellation",
505 | "description": "This Joker gains X0.1 Mult per Planet card used (Currently X1 Mult)"
506 | },
507 | {
508 | "@type": "Thing",
509 | "name": "Hiker",
510 | "description": "Every played card permanently gains +5 Chips when scored"
511 | },
512 | {
513 | "@type": "Thing",
514 | "name": "Faceless Joker",
515 | "description": "Earn $5 if 3 or more face cards are discarded at the same time"
516 | },
517 | {
518 | "@type": "Thing",
519 | "name": "Green Joker",
520 | "description": "+1 Mult per hand played -1 Mult per discard (Currently +0 Mult)"
521 | },
522 | {
523 | "@type": "Thing",
524 | "name": "Superposition",
525 | "description": "Create a Tarot card if poker hand contains an Ace and a Straight (Must have room)"
526 | },
527 | {
528 | "@type": "Thing",
529 | "name": "To Do List",
530 | "description": "Earn $4 if poker hand is a Pair, poker hand changes at end of round"
531 | },
532 | {
533 | "@type": "Thing",
534 | "name": "Cavendish",
535 | "description": "X3 Mult 1 in 1000 chance this card is destroy at end of round"
536 | },
537 | {
538 | "@type": "Thing",
539 | "name": "Card Sharp",
540 | "description": "X3 Mult if played poker hand has already been played this round (Currently inactive)"
541 | },
542 | {
543 | "@type": "Thing",
544 | "name": "Red Card",
545 | "description": "This Joker gains +3 Mult when any Booster Pack is skipped (Currently +0 Mult)"
546 | },
547 | {
548 | "@type": "Thing",
549 | "name": "Madness",
550 | "description": "When Small Blind or Big Blind is selected, gain X0.5 Mult and destroy a random Joker (Currently X1 Mult)"
551 | },
552 | {
553 | "@type": "Thing",
554 | "name": "Square Joker",
555 | "description": "This Joker gains +4 Chips if played hand has exactly 4 card (Currently +0 Chips)"
556 | },
557 | {
558 | "@type": "Thing",
559 | "name": "Séance",
560 | "description": "If poker hand is a Straight Flush, craeate a random Spectral card (Must have room)"
561 | },
562 | {
563 | "@type": "Thing",
564 | "name": "Riff-raff",
565 | "description": "When Blind is selected, create 2 Common Jokers (Must have room)"
566 | },
567 | {
568 | "@type": "Thing",
569 | "name": "Vampire",
570 | "description": "This Joker gains X0.1 Mult per scoring Enhanced card played, removes card Enhancement (Currently X1 Mult)"
571 | },
572 | {
573 | "@type": "Thing",
574 | "name": "Shortcut",
575 | "description": "Allows Straights to be made with gaps of 1 rank (ex: 10 8 6 5 3)"
576 | },
577 | {
578 | "@type": "Thing",
579 | "name": "Hologram",
580 | "description": "This Joker gains X0.25 Mult per playing card added to your deck (Currently X1 Mult)"
581 | },
582 | {
583 | "@type": "Thing",
584 | "name": "Vagabond",
585 | "description": "Create a Tarot card if hand is played with $4 or less"
586 | },
587 | {
588 | "@type": "Thing",
589 | "name": "Baron",
590 | "description": "Each King held in hand gives X1.5 Mult"
591 | },
592 | {
593 | "@type": "Thing",
594 | "name": "Cloud 9",
595 | "description": "Earn $1 for each 9 in your full deck at end of round (Currently $0)"
596 | },
597 | {
598 | "@type": "Thing",
599 | "name": "Rocket",
600 | "description": "Earn $1 at end of round. Gains $2 when Boss Blind is defeated"
601 | },
602 | {
603 | "@type": "Thing",
604 | "name": "Obelisk",
605 | "description": "This Joker gains X0.2 Mult per consecutive hand played without playing your must played poker hand (Currently X1 Mult)"
606 | },
607 | {
608 | "@type": "Thing",
609 | "name": "Midas Mask",
610 | "description": "All played face cards become Gold cards when scored"
611 | },
612 | {
613 | "@type": "Thing",
614 | "name": "Luchador",
615 | "description": "Sell this card to disable the current Boss Blind"
616 | },
617 | {
618 | "@type": "Thing",
619 | "name": "Photograph",
620 | "description": "First played face card gives X2 Mult when scored"
621 | },
622 | {
623 | "@type": "Thing",
624 | "name": "Gift Card",
625 | "description": "Add $1 of sell value to every Joker and Consumable card at end of round"
626 | },
627 | {
628 | "@type": "Thing",
629 | "name": "Turtle Bean",
630 | "description": "+5 hand size, reduces by 1 every round"
631 | },
632 | {
633 | "@type": "Thing",
634 | "name": "Erosion",
635 | "description": "+4 Mult for each card below 52 in your full deck (Currently +0)"
636 | },
637 | {
638 | "@type": "Thing",
639 | "name": "Reserved Parking",
640 | "description": "Each face card held in hand has a 1 in 2 chance to give $1"
641 | },
642 | {
643 | "@type": "Thing",
644 | "name": "Mail-In Rebate",
645 | "description": "Earn $5 for each discarded 2, rank changes every round"
646 | },
647 | {
648 | "@type": "Thing",
649 | "name": "To the Moon",
650 | "description": "Earn an extra $1 of interest for every $5 you have at end of round"
651 | },
652 | {
653 | "@type": "Thing",
654 | "name": "Hallucination",
655 | "description": "1 in 2 chance to create a Tarot card when any Booster Pack is opened (Must have room)"
656 | },
657 | {
658 | "@type": "Thing",
659 | "name": "Sly Joker",
660 | "description": "+50 Chips if played hand contains a Pair"
661 | },
662 | {
663 | "@type": "Thing",
664 | "name": "Wily Joker",
665 | "description": "+100 Chips if played hand contains a Three of a Kind"
666 | },
667 | {
668 | "@type": "Thing",
669 | "name": "Clever Joker",
670 | "description": "+80 Chips if played hand contains a Two Pair"
671 | },
672 | {
673 | "@type": "Thing",
674 | "name": "Devious Joker",
675 | "description": "+100 Chips if played hand contains a Straight"
676 | },
677 | {
678 | "@type": "Thing",
679 | "name": "Crafty Joker",
680 | "description": "+80 Chips if played hand contains a Flush"
681 | },
682 | {
683 | "@type": "Thing",
684 | "name": "Lucky Cat",
685 | "description": "This Joker gains X0.25 Mult each time a Lucky card successfully triggers (currently X1 Mult)"
686 | },
687 | {
688 | "@type": "Thing",
689 | "name": "Baseball Card",
690 | "description": "Uncommon Jokers each give X1.5 Mult"
691 | },
692 | {
693 | "@type": "Thing",
694 | "name": "Bull",
695 | "description": "+2 Chips for each dollar you have (Currently +0 Chips)"
696 | },
697 | {
698 | "@type": "Thing",
699 | "name": "Diet Cola",
700 | "description": "Sell this card to create a free Double Tag"
701 | },
702 | {
703 | "@type": "Thing",
704 | "name": "Trading Card",
705 | "description": "If first discard of round has only 1 card, destroy it and earn $3"
706 | },
707 | {
708 | "@type": "Thing",
709 | "name": "Flash Card",
710 | "description": "This Joker gains +2 Mult per reroll in the shop (Currently +0 Mult)"
711 | },
712 | {
713 | "@type": "Thing",
714 | "name": "Popcorn",
715 | "description": "+20 Mult -4 Mult per round played"
716 | },
717 | {
718 | "@type": "Thing",
719 | "name": "Ramen",
720 | "description": "X2 Mult, loses X0.01 Mult per card discarded"
721 | },
722 | {
723 | "@type": "Thing",
724 | "name": "Seltzer",
725 | "description": "Retrigger all cards played for the next 10 hands"
726 | },
727 | {
728 | "@type": "Thing",
729 | "name": "Spare Trousers",
730 | "description": "Gain +2 Mult if played hand contains a Two Pair (Currently +0 Mult)"
731 | },
732 | {
733 | "@type": "Thing",
734 | "name": "Campfire",
735 | "description": "This Joker gains X0.25 Mult for each card sold, resets when Boss Blind is defeated (Currently X1 Mult)"
736 | },
737 | {
738 | "@type": "Thing",
739 | "name": "Smiley Face",
740 | "description": "Played face cards give +5 Mult when scored"
741 | },
742 | {
743 | "@type": "Thing",
744 | "name": "Ancient Joker",
745 | "description": "Each played card with Heart suit gives X1.5 Mult when scored suit changes at end of round"
746 | },
747 | {
748 | "@type": "Thing",
749 | "name": "Walkie Talkie",
750 | "description": "Each played 10 or 4 gives +10 Chips and +4 Mult when scored"
751 | },
752 | {
753 | "@type": "Thing",
754 | "name": "Castle",
755 | "description": "This Joker gains +3 Chips per discarded Heart card, suit changes every round (Currently +0 Chips)"
756 | }
757 | ]
758 | }
759 |
--------------------------------------------------------------------------------
/main.js:
--------------------------------------------------------------------------------
1 | const menuBtns = [
2 | document.getElementById('JokersBtn'),
3 | document.getElementById('CardsBtn'),
4 | document.getElementById('HandsBtn'),
5 | document.getElementById('BreakdownBtn'),
6 | document.getElementById('ModifyJokerBtn'),
7 | ];
8 |
9 | const tabs = [
10 | document.getElementById('Jokers'),
11 | document.getElementById('Cards'),
12 | document.getElementById('Hands'),
13 | document.getElementById('Breakdown'),
14 | document.getElementById('ModifyJoker'),
15 | ];
16 |
17 | let searchVal = '';
18 |
19 | for(let i = 0; i < menuBtns.length; i++) {
20 | menuBtns[i].addEventListener('click', changeTab(i));
21 | tabs[i].style.display = "none";
22 | }
23 |
24 | let revertToTab = 0;
25 | let modifyingJoker = false;
26 | let modifyingJokerValue = 0;
27 |
28 | let modifyingJokerValTxt = document.getElementById('modValue');
29 | let modifyingJokerValueDiv = document.getElementById('modifyJokerValue');
30 | let modifyingJokerValDiv = document.getElementById('modifyJokerVal');
31 | let modifyingJokerSellValDiv = document.getElementById('modifyJokerSellVal');
32 | let modifyJokerDiv = document.getElementById('modifyJoker');
33 | let highContrastDiv = document.getElementById('highContrastBtn');
34 |
35 | function changeTab(tab) {
36 | return () => {
37 | revertToTab = tab === 4 ? revertToTab : tab;
38 | for(let i = 0; i < menuBtns.length; i++) {
39 | menuBtns[i].classList.remove('active');
40 | tabs[i].style.display = "none";
41 | }
42 | menuBtns[tab].classList.add('active');
43 | tabs[tab].style.display = "block";
44 |
45 | modifyingJoker = false;
46 | }
47 | }
48 |
49 | changeTab(0)();
50 |
51 | const hands = [
52 | {
53 | name: "Flush Five",
54 | planet: "Eris",
55 | mult: 16,
56 | chips: 160,
57 | s_mult: 16,
58 | s_chips: 160,
59 | l_mult: 3,
60 | l_chips: 50
61 | },
62 | {
63 | name: "Flush House",
64 | planet: "Ceres",
65 | mult: 14,
66 | chips: 140,
67 | s_mult: 14,
68 | s_chips: 140,
69 | l_mult: 4,
70 | l_chips: 40
71 | },
72 | {
73 | name: "Five of a Kind",
74 | planet: "Planet X",
75 | mult: 12,
76 | chips: 120,
77 | s_mult: 12,
78 | s_chips: 120,
79 | l_mult: 3,
80 | l_chips: 35
81 | },
82 | {
83 | name: "Straight Flush",
84 | planet: "Neptune",
85 | mult: 8,
86 | chips: 100,
87 | s_mult: 8,
88 | s_chips: 100,
89 | l_mult: 4,
90 | l_chips: 40
91 | },
92 | {
93 | name: "Four of a Kind",
94 | planet: "Mars",
95 | mult: 7,
96 | chips: 60,
97 | s_mult: 7,
98 | s_chips: 60,
99 | l_mult: 3,
100 | l_chips: 30
101 | },
102 | {
103 | name: "Full House",
104 | planet: "Earth",
105 | mult: 4,
106 | chips: 40,
107 | s_mult: 4,
108 | s_chips: 40,
109 | l_mult: 2,
110 | l_chips: 25
111 | },
112 | {
113 | name: "Flush",
114 | planet: "Jupiter",
115 | mult: 4,
116 | chips: 35,
117 | s_mult: 4,
118 | s_chips: 35,
119 | l_mult: 2,
120 | l_chips: 15
121 | },
122 | {
123 | name: "Straight",
124 | planet: "Saturn",
125 | mult: 4,
126 | chips: 30,
127 | s_mult: 4,
128 | s_chips: 30,
129 | l_mult: 3,
130 | l_chips: 30
131 | },
132 | {
133 | name: "Three of a Kind",
134 | planet: "Venus",
135 | mult: 3,
136 | chips: 30,
137 | s_mult: 3,
138 | s_chips: 30,
139 | l_mult: 2,
140 | l_chips: 20
141 | },
142 | {
143 | name: "Two Pair",
144 | planet: "Uranus",
145 | mult: 2,
146 | chips: 20,
147 | s_mult: 2,
148 | s_chips: 20,
149 | l_mult: 1,
150 | l_chips: 20
151 | },
152 | {
153 | name: "Pair",
154 | planet: "Mercury",
155 | mult: 2,
156 | chips: 10,
157 | s_mult: 2,
158 | s_chips: 10,
159 | l_mult: 1,
160 | l_chips: 15
161 | },
162 | {
163 | name: "High Card",
164 | planet: "Pluto",
165 | mult: 1,
166 | chips: 5,
167 | s_mult: 1,
168 | s_chips: 5,
169 | l_mult: 1,
170 | l_chips: 10
171 | }
172 | ];
173 |
174 | const handColors = [
175 | '#efefef',
176 | '#95acff',
177 | '#65efaf',
178 | '#fae37e',
179 | '#ffc052',
180 | '#f87d75',
181 | '#caa0ef'
182 | ];
183 |
184 | const handLevels = document.getElementById('hands');
185 | const consumables = document.getElementById('consumables');
186 |
187 | function incrementLevel(inc, handIndex) {
188 | const hand = hands[handIndex];
189 | const div = document.getElementById(hand.id);
190 | hand.level += inc;
191 | if(hand.level < 0) hand.level = 0;
192 | hand.mult = Math.max(1, hand.s_mult + (hand.level-1) * hand.l_mult);
193 | hand.chips = Math.max(0, hand.s_chips + (hand.level-1) * hand.l_chips);
194 | div.children[2].innerText = 'lvl.'+hand.level;
195 | div.children[2].style.backgroundColor = hand.level === 1 ? handColors[0] : handColors[((Math.ceil(Math.abs(hand.level)/6)*6+hand.level+4)%6)+1];
196 | div.children[4].children[0].innerText = numberWithCommas(hand.chips);
197 | div.children[4].children[1].innerText = numberWithCommas(hand.mult);
198 |
199 | redrawPlayfield();
200 | }
201 |
202 | function incrementPlanet(inc, handIndex) {
203 | const hand = hands[handIndex];
204 | const div = document.getElementById('planets-' + hand.id);
205 | hand.planets += inc;
206 | if(hand.planets < 0 || inc === 0) hand.planets = 0;
207 | div.children[3].innerText = hand.planets;
208 |
209 | redrawPlayfield();
210 | }
211 |
212 | function setPlanet(handIndex) {
213 | const hand = hands[handIndex];
214 | const div = document.getElementById('planets-' + hand.id);
215 | let willBlur = false;
216 |
217 | if(div.children[3].innerText.indexOf('\n') >= 0) {
218 | div.children[3].innerText = div.children[3].innerText.replace(/[\r\n]/g, '');
219 | willBlur = true;
220 | }
221 | if(1 * div.children[3].innerText > 0) {
222 | hand.planets = Math.round(1 * div.children[3].innerText);
223 | }
224 | else {
225 | hand.planets = 0;
226 | }
227 |
228 | if(willBlur) div.children[3].blur();
229 |
230 | redrawPlayfield();
231 | }
232 |
233 | function setLevel(handIndex) {
234 | const hand = hands[handIndex];
235 | const div = document.getElementById(hand.id);
236 | let willBlur = false;
237 |
238 | if(div.children[2].innerText.indexOf('\n') >= 0) {
239 | div.children[2].innerText = div.children[2].innerText.replace(/[\r\n]/g, '');
240 | willBlur = true;
241 | }
242 | if(1 * div.children[2].innerText > 0) {
243 | hand.level = Math.round(1 * div.children[2].innerText);
244 | }
245 | else {
246 | hand.level = 0;
247 | }
248 |
249 | hand.mult = Math.max(1, hand.s_mult + (hand.level-1) * hand.l_mult);
250 | hand.chips = Math.max(0, hand.s_chips + (hand.level-1) * hand.l_chips);
251 | div.children[2].style.backgroundColor = hand.level === 1 ? handColors[0] : handColors[((Math.ceil(Math.abs(hand.level)/6)*6+hand.level+4)%6)+1];
252 | div.children[4].children[0].innerText = numberWithCommas(hand.chips);
253 | div.children[4].children[1].innerText = numberWithCommas(hand.mult);
254 |
255 | if(willBlur) div.children[2].blur();
256 |
257 | redrawPlayfield();
258 | }
259 |
260 | function setPlayed(handIndex) {
261 | const hand = hands[handIndex];
262 | const div = document.getElementById(hand.id);
263 | let willBlur = false;
264 |
265 | if(div.children[1].children[0].innerText.indexOf('\n') >= 0) {
266 | div.children[1].children[0].innerText = div.children[1].children[0].innerText.replace(/[\r\n]/g, '');
267 | willBlur = true;
268 | }
269 |
270 | if(1 * div.children[1].children[0].innerText > 0) {
271 | hand.played = Math.round(1 * div.children[1].children[0].innerText);
272 | }
273 | else {
274 | hand.played = 0;
275 | }
276 |
277 | if(willBlur) div.children[1].children[0].blur();
278 |
279 | redrawPlayfield();
280 | }
281 |
282 | function removeLvlText (handIndex) {
283 | const hand = hands[handIndex];
284 | const div = document.getElementById(hand.id);
285 | div.children[2].innerText = hand.level;
286 |
287 | selectAll(div.children[2])
288 | }
289 |
290 | function selectAll(div) {
291 | const selection = window.getSelection();
292 | const range = document.createRange();
293 | range.selectNodeContents(div);
294 | selection.removeAllRanges();
295 | selection.addRange(range);
296 | }
297 |
298 | function addLvlText(handIndex) {
299 | const hand = hands[handIndex];
300 | const div = document.getElementById(hand.id);
301 | div.children[2].innerText = 'lvl.'+hand.level;
302 | }
303 |
304 | const jokerValueHTML = document.getElementById('jokerVal');
305 | let jokerValue = 0;
306 |
307 | const jokerCountHTML = document.getElementById('jokerCnt');
308 | let jokerCount = 1;
309 |
310 | const cardCountHTML = document.getElementById('cardCnt');
311 | let cardCount = 1;
312 |
313 | function incrementJokerValue(inc) {
314 | jokerValue += inc;
315 | if(inc === 0) {
316 | jokerValue = 0;
317 | }
318 | jokerValueHTML.innerText = jokerValue;
319 | jredrawCards();
320 | }
321 |
322 | function setJokerValue() {
323 | let willBlur = false;
324 |
325 | if(jokerValueHTML.innerText.indexOf('\n') >= 0) {
326 | jokerValueHTML.innerText = jokerValueHTML.innerText.replace(/[\r\n]/g, '');
327 | willBlur = true;
328 | }
329 | if(!isNaN(jokerValueHTML.innerText)) {
330 | jokerValue = Math.round(jokerValueHTML.innerText * 1);
331 | }
332 | else {
333 | jokerValue = 0;
334 | }
335 |
336 | if(willBlur) {
337 | jokerValueHTML.blur();
338 | jokerValueHTML.innerText = jokerValue;
339 | }
340 |
341 | jredrawCards();
342 | }
343 |
344 | function incrementJokerCount(inc) {
345 | jokerCount += inc;
346 | if(inc === 0) {
347 | jokerCount = 1;
348 | }
349 | jokerCountHTML.innerText = Math.max(1, jokerCount);
350 | }
351 |
352 | function setJokerCount() {
353 | console.log(jokerCountHTML.innerText);
354 | let willBlur = false;
355 |
356 | if(jokerCountHTML.innerText.indexOf('\n') >= 0) {
357 | jokerCountHTML.innerText = jokerCountHTML.innerText.replace(/[\r\n]/g, '');
358 | willBlur = true;
359 | }
360 | if(!isNaN(jokerCountHTML.innerText)) {
361 | jokerCount = Math.max(1, Math.round(jokerCountHTML.innerText * 1));
362 | }
363 | else {
364 | jokerCount = 1;
365 | }
366 |
367 | if(willBlur) {
368 | jokerCountHTML.blur();
369 | jokerCountHTML.innerText = jokerCount;
370 | }
371 | }
372 |
373 | function incrementCardCount(inc) {
374 | cardCount += inc;
375 | if(inc === 0) {
376 | cardCount = 1;
377 | }
378 | cardCountHTML.innerText = Math.max(1, cardCount);
379 | }
380 |
381 | function setCardCount() {
382 | console.log(cardCountHTML.innerText);
383 | let willBlur = false;
384 |
385 | if(cardCountHTML.innerText.indexOf('\n') >= 0) {
386 | cardCountHTML.innerText = cardCountHTML.innerText.replace(/[\r\n]/g, '');
387 | willBlur = true;
388 | }
389 | if(!isNaN(cardCountHTML.innerText)) {
390 | cardCount = Math.max(1, Math.round(cardCountHTML.innerText * 1));
391 | }
392 | else {
393 | cardCount = 1;
394 | }
395 |
396 | if(willBlur) {
397 | cardCountHTML.blur();
398 | cardCountHTML.innerText = cardCount;
399 | }
400 | }
401 |
402 | handLevels.innerHTML = '';
403 |
404 | for(let i = 0; i < hands.length; i++) {
405 | hands[i].level = 1;
406 | hands[i].planets = 0;
407 | hands[i].id = hands[i].name.replace(/ /g,'');
408 | hands[i].played = 0;
409 | hands[i].playedThisRound = 0;
410 | handLevels.innerHTML += `
411 |
412 |
#0
413 |
lvl.1
414 |
${hands[i].name}
415 |
416 | ${hands[i].chips}X${hands[i].mult}
417 |
418 |
`;
419 |
420 | consumables.innerHTML += `
421 |
-
422 |
0
423 |
+
424 |
0
425 |
${hands[i].planet}
${hands[i].name}
426 |
`;
427 | }
428 |
429 | const modifiers = {
430 | foil: false,
431 | holographic: false,
432 | polychrome: false,
433 | stone: false,
434 | increment: false,
435 | mult: false,
436 | wild: false,
437 | chance: false,
438 | glass: false,
439 | steel: false,
440 | gold: false,
441 | double: false,
442 | disabled: false
443 | };
444 |
445 | let modifierString = ', url(assets/Enhancers.png) -71px 0px';
446 | let modifierPostString = '';
447 |
448 | let modifierClass = '';
449 |
450 | const jmodifiers = {
451 | foil: false,
452 | holographic: false,
453 | polychrome: false,
454 | disabled: false
455 | };
456 |
457 | function jtoggleCardModifier(name) {
458 | if(('foil holographic polychrome disabled'.indexOf(name) >= 0) && !jmodifiers[name]) {
459 | jmodifiers.foil = false;
460 | jmodifiers.holographic = false;
461 | jmodifiers.polychrome = false;
462 | jmodifiers.disabled = false;
463 | }
464 | jmodifiers[name] = !jmodifiers[name];
465 |
466 | jredrawCards();
467 | }
468 |
469 | function setModifierString() {
470 | modifierClass = '';
471 |
472 | if(modifiers.stone) {
473 | modifierString = ', url(assets/Enhancers.png) 142px 0';
474 | }
475 | else if(modifiers.increment) {
476 | modifierString = ', url(assets/Enhancers.png) -71px -95px';
477 | }
478 | else if(modifiers.mult) {
479 | modifierString = ', url(assets/Enhancers.png) -142px -95px';
480 | }
481 | else if(modifiers.wild) {
482 | modifierString = ', url(assets/Enhancers.png) -213px -95px';
483 | }
484 | else if(modifiers.chance) {
485 | modifierString = ', url(assets/Enhancers.png) -284px -95px';
486 | }
487 | else if(modifiers.glass) {
488 | modifierString = ', url(assets/Enhancers.png) -355px -95px';
489 | }
490 | else if(modifiers.steel) {
491 | modifierString = ', url(assets/Enhancers.png) -426px -95px';
492 | }
493 | else if(modifiers.gold) {
494 | modifierString = ', url(assets/Enhancers.png) 71px 0px';
495 | }
496 | else {
497 | modifierString = ', url(assets/Enhancers.png) -71px 0px';
498 | }
499 |
500 | if(modifiers.double) {
501 | modifierPostString = 'url(assets/Enhancers.png) 142px 95px, ';
502 | }
503 | else {
504 | modifierPostString = 'url(assets/Jokers.png) 0px -855px, ';
505 | }
506 |
507 | if(modifiers.foil) {
508 | modifierPostString += 'url(assets/Editions.png) -71px 0, ';
509 | }
510 | else if(modifiers.holographic) {
511 | modifierPostString += 'url(assets/Editions.png) -142px 0, ';
512 | }
513 | else if(modifiers.polychrome) {
514 | modifierClass = ' polychrome';
515 | modifierPostString += 'url(assets/Editions.png) -213px 0, ';
516 | }
517 | else if(modifiers.disabled) {
518 | modifierPostString += 'url(assets/Editions.png) 71px 0, ';
519 | }
520 | }
521 |
522 | function toggleCardModifier(name) {
523 | if(('gold stone increment mult wild chance glass steel'.indexOf(name) >= 0) && !modifiers[name]) {
524 | modifiers.stone = false;
525 | modifiers.increment = false;
526 | modifiers.mult = false;
527 | modifiers.wild = false;
528 | modifiers.chance = false;
529 | modifiers.glass = false;
530 | modifiers.steel = false;
531 | modifiers.gold = false;
532 | }
533 |
534 | if(('foil holographic polychrome disabled'.indexOf(name) >= 0) && !modifiers[name]) {
535 | modifiers.foil = false;
536 | modifiers.holographic = false;
537 | modifiers.polychrome = false;
538 | modifiers.disabled = false;
539 | }
540 | modifiers[name] = !modifiers[name];
541 |
542 | setModifierString();
543 |
544 | redrawCards();
545 | }
546 |
547 | const cardsDiv = document.getElementById('cards');
548 | const jcardsDiv = document.getElementById('jokers');
549 |
550 | let highContrast = window.localStorage.hc === '1';
551 | if(highContrast) {
552 | highContrastDiv.innerText = 'X';
553 | }
554 |
555 | function cardString(i, j, hc = 0) {
556 | if(modifiers.stone) {
557 | return `${modifierClass}" style="background: ` +
558 | `${modifierPostString}${modifierString.slice(2)}"`;
559 | }
560 | else {
561 | return `${modifierClass}" style="background: ` +
562 | `${modifierPostString}url(assets/8BitDeck${(hc === 2 || (hc === 0 && highContrast))?'_opt2':''}.png) ` +
563 | `-${71*j}px -${95*i}px${modifierString}"`;
564 | }
565 | }
566 |
567 | function redrawCards() {
568 | let txt = '';
569 | for(let i = 0; i < 4; i++) {
570 | txt += '
';
571 | for(let j = 0; j < 13; j++) {
572 | txt += `
`;
573 | }
574 | txt += '
';
575 | }
576 | cardsDiv.innerHTML = txt;
577 | }
578 |
579 | function toggleContrast() {
580 | highContrast = !highContrast;
581 | window.localStorage.setItem('hc', highContrast?1:0);
582 | if(highContrast) {
583 | highContrastDiv.innerText = 'X';
584 | }
585 | else {
586 | highContrastDiv.innerHTML = ' ';
587 | }
588 |
589 | redrawCards();
590 | redrawPlayfieldHTML();
591 | }
592 |
593 | document.getElementById('highContrastBtn').addEventListener('click', toggleContrast);
594 |
595 | function jokerString(i, j, modifiers) {
596 | let jmodifierClass = '';
597 |
598 | let jmodifierString = 'url(assets/Jokers.png) 0px -855px, ';
599 | let jmodifierPostString = '';
600 |
601 | if(modifiers.foil) {
602 | jmodifierPostString = 'url(assets/Editions.png) -71px 0, ';
603 | }
604 | else if(modifiers.holographic) {
605 | jmodifierPostString = 'url(assets/Editions.png) -142px 0, ';
606 | }
607 | else if(modifiers.polychrome) {
608 | jmodifierClass = ' polychrome';
609 | jmodifierPostString = 'url(assets/Editions.png) -213px 0, ';
610 | }
611 | else if(modifiers.disabled) {
612 | jmodifierPostString = 'url(assets/Editions.png) 71px 0, ';
613 | }
614 | else {
615 | jmodifierPostString = '';
616 | }
617 |
618 | switch(`${i},${j}`) {
619 | case '8,3': jmodifierString = `url(assets/Jokers.png) -${71*3}px -${95*9}px, `; break;
620 | case '8,4': jmodifierString = `url(assets/Jokers.png) -${71*4}px -${95*9}px, `; break;
621 | case '8,5': jmodifierString = `url(assets/Jokers.png) -${71*5}px -${95*9}px, `; break;
622 | case '8,6': jmodifierString = `url(assets/Jokers.png) -${71*6}px -${95*9}px, `; break;
623 | case '8,7': jmodifierString = `url(assets/Jokers.png) -${71*7}px -${95*9}px, `; break;
624 | case '12,4': jmodifierString = `url(assets/Jokers.png) -${71*2}px -${95*9}px, `; break;
625 | }
626 | return `${jmodifierClass}" style="mask-position: -${71*j}px -${95*i}px; background: ${jmodifierPostString}${jmodifierString}url(assets/Jokers.png) -${71*j}px -${95*i}px"`;
627 | }
628 |
629 | function jredrawCards() {
630 | let txt = '
';
631 | let count = 0;
632 | for(let i = 0; i < 16; i++) {
633 | if(i === 9) {i++;}
634 | for(let j = 0; j < 10; j++) {
635 | const title = (jokerTexts.length > i && jokerTexts[i].length > j) ? jokerTexts[i][j][0] : 'WIP';
636 | const description = (jokerTexts.length > i && jokerTexts[i].length > j) ? eval('`' + jokerTexts[i][j][1] + '`') : 'WIP';
637 | if(title.toLowerCase().indexOf(searchVal.toLowerCase()) >= 0 || description.replace(/\<[^\>]+\>/g,'').toLowerCase().indexOf(searchVal.toLowerCase()) >= 0) {
638 | txt += `
`;
642 | count++;
643 | if(count >= 10) {
644 | count = 0;
645 | txt += '
';
646 | }
647 | }
648 | }
649 | }
650 | txt += '
';
651 | jcardsDiv.innerHTML = txt;
652 | }
653 |
654 | redrawCards();
655 | jredrawCards();
656 |
657 | const jokerAreaDiv = document.getElementById('jokerArea');
658 | const bestPlayDiv = document.getElementById('bestPlay');
659 | const cardsInHandDiv = document.getElementById('cardsInHand');
660 |
661 | const jokerLimitDiv = document.getElementById('jokerLimit');
662 | const handLimitDiv = document.getElementById('handLimit');
663 |
664 | let playfieldCards = {};
665 |
666 | function updateTooltips() {
667 | for(let joker in playfieldJokers) {
668 | let i = playfieldJokers[joker].type[0];
669 | let j = playfieldJokers[joker].type[1];
670 | let jokerValue = playfieldJokers[joker].value;
671 | playfieldJokers[joker].tooltip = (jokerTexts.length > i && jokerTexts[i].length > j) ? [jokerTexts[i][j][0], eval('`' + jokerTexts[i][j][1] + '`')] : ['WIP', 'WIP'];
672 | }
673 | }
674 |
675 | function addJoker(i, j, sell = false) {
676 | for(let k = 0; k < jokerCount; k++) {
677 | let id = 'j'+(Math.random()+'').slice(2);
678 | while(playfieldJokers.hasOwnProperty(id)) {
679 | id = 'j'+(Math.random()+'').slice(2);
680 | }
681 |
682 | playfieldJokers[id] = {
683 | id,
684 | type: [i, j],
685 | modifiers: {...jmodifiers},
686 | value: jokerValue,
687 | sell: sell !== false ? sell : Math.floor((jokerPrice[i][j] + ((jmodifiers.foil || jmodifiers.holographic || jmodifiers.polychrome) ? 1 : 0)) / 2),
688 | string: jokerString(i, j, jmodifiers),
689 | tooltip: (jokerTexts.length > i && jokerTexts[i].length > j) ? [jokerTexts[i][j][0], eval('`' + jokerTexts[i][j][1] + '`')] : ['WIP', 'WIP']
690 | };
691 | }
692 |
693 | jokerLimitDiv.innerText = Object.keys(playfieldJokers).length;
694 |
695 | if(Object.keys(playfieldJokers).length >= 8 && optimizeJokers) {
696 | toggleJoker();
697 | }
698 |
699 | updateTooltips();
700 | redrawPlayfield();
701 | }
702 |
703 | function removeJoker(id) {
704 | delete playfieldJokers[id];
705 |
706 | jokerLimitDiv.innerText = Object.keys(playfieldJokers).length;
707 |
708 | updateTooltips();
709 | redrawPlayfield();
710 |
711 | changeTab(revertToTab)();
712 | }
713 |
714 | function addCard(i, j) {
715 | for(let k = 0; k < cardCount; k++) {
716 | let id = ((j === 10 && !modifiers.stone) ? (!modifiers.steel ? '993' : '992') : '') + (''+j).padStart(2, 0)+(4-i)+Object.keys(modifiers).map(a=>modifiers[a]?'1':'0').join('');
717 | while(playfieldCards.hasOwnProperty(id)) {
718 | id += '#';
719 | }
720 |
721 | playfieldCards[id] = {
722 | id,
723 | type: [(i + 3) % 4, j],
724 | modifiers: {...modifiers},
725 | string: cardString((i + 3) % 4, j, 1),
726 | HCString: cardString((i + 3) % 4, j, 2),
727 | };
728 | }
729 |
730 | handLimitDiv.innerText = Object.keys(playfieldCards).length;
731 |
732 | if(Object.keys(playfieldCards).length >= 9 && optimizeJokers) {
733 | toggleCard();
734 | }
735 |
736 | redrawPlayfield();
737 | }
738 |
739 | function removeCard(id) {
740 | if(bestHand.indexOf(id) >= 0) {
741 | bestHand.splice(bestHand.indexOf(id), 1);
742 | }
743 |
744 | delete playfieldCards[id];
745 |
746 | handLimitDiv.innerText = Object.keys(playfieldCards).length;
747 |
748 | redrawPlayfield();
749 | }
750 |
751 | function redrawPlayfield() {
752 | calculator();
753 | }
754 |
755 | function redrawPlayfieldHTML() {
756 | compileHand();
757 |
758 | let txt = '';
759 | for(let id of bestJokers) {
760 | txt += `
`;
774 | }
775 | jokerAreaDiv.innerHTML = txt;
776 |
777 | txt = '';
778 | for(let id of bestHand) {
779 | txt += `
`;
789 | }
790 | bestPlayDiv.innerHTML = txt;
791 |
792 | txt = '';
793 |
794 | let lowestCards = [];
795 |
796 | for(let id of Object.keys(playfieldCards).sort().reverse()) {
797 | if(bestHand.indexOf(id) >= 0) continue;
798 | if(id.indexOf('99') !== 0) continue;
799 | txt += `
`;
805 | }
806 |
807 | // if Raised Fist, move the lowest cards to the left
808 | if(Object.keys(playfieldJokers).reduce((a,b) => a || (playfieldJokers[b].type[0] === 2 && playfieldJokers[b].type[1] === 8 && !playfieldJokers[b].modifiers.disabled), false)) {
809 | let lowest = 100;
810 | let isQueen = true;
811 | let type = 0;
812 | for(let card in playfieldCards) {
813 | if(!playfieldCards[card].modifiers.stone && bestHand.indexOf(card) < 0) {
814 | if(lowest > cardValues[playfieldCards[card].type[1]] + (playfieldCards[card].type[1] === QUEEN ? 10 : 0)) {
815 | isQueen = playfieldCards[card].type[1] === QUEEN;
816 | lowest = cardValues[playfieldCards[card].type[1]] + (isQueen ? 10 : 0);
817 | lowestCards = [card];
818 | type = playfieldCards[card].type[1];
819 | }
820 | else if(lowest === cardValues[playfieldCards[card].type[1]]) {
821 | lowestCards.push(card);
822 | }
823 | }
824 | }
825 |
826 | let index = 0;
827 | let highScore = 0;
828 | for(let i = 0; i < lowestCards.length; i++) {
829 | const card = lowestCards[i];
830 | if(!playfieldCards[card].modifiers.disabled) {
831 | let thisScore = 1;
832 | if(playfieldCards[card].modifiers.steel) {
833 | thisScore += 2;
834 | }
835 | if(playfieldCards[card].modifiers.double) {
836 | thisScore += 4;
837 | }
838 | if(thisScore > highScore) {
839 | highScore = thisScore;
840 | index = i;
841 | }
842 | }
843 | }
844 |
845 | ignoreCard = -1;
846 |
847 | // only add cards if there is a valid lowest card
848 | if(lowest > 0 && lowest < 100 && !isQueen) {
849 | ignoreCard = lowestCards[index];
850 |
851 | for(let id of Object.keys(playfieldCards).sort().reverse()) {
852 | if(lowestCards.indexOf(id) < 0) continue;
853 | if(id === ignoreCard) continue;
854 | if(id.indexOf('99') === 0) continue;
855 | txt += `
`;
861 | }
862 |
863 | txt += `
`;
869 | }
870 | //console.log(txt);
871 | }
872 |
873 | for(let id of Object.keys(playfieldCards).sort().reverse()) {
874 | if(bestHand.indexOf(id) >= 0) continue;
875 | if(lowestCards.indexOf(id) >= 0) continue;
876 | if(id.indexOf('99') === 0) continue;
877 | txt += `
`;
883 | }
884 | cardsInHandDiv.innerHTML = txt;
885 | }
886 |
887 | function moveJokerLeft(id) {
888 | if(optimizeJokers) toggleJoker();
889 | const index = bestJokers.indexOf(id);
890 | if(index > 0) {
891 | bestJokers.splice(index, 1);
892 | bestJokers.splice(index - 1, 0, id);
893 | }
894 | let newPlayfield = {};
895 | for(joker of bestJokers) {
896 | newPlayfield[joker] = playfieldJokers[joker];
897 | }
898 | playfieldJokers = newPlayfield;
899 | redrawPlayfield();
900 | }
901 |
902 | function moveJokerRight(id) {
903 | let index = bestJokers.indexOf(id);
904 | if(index < bestJokers.length) {
905 | bestJokers.splice(index, 1);
906 | bestJokers.splice(index + 1, 0, id);
907 | }
908 | let newPlayfield = {};
909 | for(let i = 0; i < bestJokers.length; i++) {
910 | let joker = bestJokers[i];
911 | newPlayfield[joker] = playfieldJokers[joker];
912 | }
913 | playfieldJokers = newPlayfield;
914 |
915 | if(optimizeJokers) {
916 | toggleJoker();
917 | }
918 | else {
919 | redrawPlayfield();
920 | }
921 | }
922 |
923 | function moveHandCardLeft(id) {
924 | if(optimizeCards) toggleCard();
925 | let index = bestHand.indexOf(id);
926 | if(index > 0) {
927 | bestHand.splice(index, 1);
928 | bestHand.splice(index - 1, 0, id);
929 | }
930 | redrawPlayfield();
931 | }
932 | function moveHandCardRight(id) {
933 | if(optimizeCards) toggleCard();
934 | let index = bestHand.indexOf(id);
935 | if(index < bestHand.length) {
936 | bestHand.splice(index, 1);
937 | bestHand.splice(index + 1, 0, id);
938 | }
939 | redrawPlayfield();
940 | }
941 |
942 | function moveHandCardDown(id) {
943 | if(optimizeCards) toggleCard();
944 | bestHand.splice(bestHand.indexOf(id), 1);
945 | redrawPlayfield();
946 | }
947 |
948 | function moveCardUp(id) {
949 | if(optimizeCards) toggleCard();
950 | if(bestHand.length < 5) {
951 | bestHand.push(id);
952 | }
953 | redrawPlayfield();
954 | }
955 |
956 | const searchDiv = document.getElementById('SearchVal');
957 |
958 | function searchJoker() {
959 | searchVal = searchDiv.value;
960 | jredrawCards();
961 | }
962 |
963 | let modifyTab = changeTab(4);
964 |
965 | function modifyJoker(id) {
966 | modifyTab();
967 | modifyingJoker = id;
968 | modifyingJokerValDiv.innerText = playfieldJokers[modifyingJoker].value;
969 | modifyingJokerSellValDiv.innerText = playfieldJokers[modifyingJoker].sell;
970 |
971 | const type = playfieldJokers[modifyingJoker].type;
972 | if(jokerTexts[type[0]][type[1]][2]) {
973 | modifyingJokerValueDiv.style.display = 'inline-block';
974 | modifyingJokerValTxt.innerText = jokerTexts[type[0]][type[1]][2];
975 | }
976 | else {
977 | modifyingJokerValueDiv.style.display = 'none';
978 | }
979 |
980 | updateModifyingJoker();
981 | }
982 |
983 | function updateModifyingJoker() {
984 | if(!playfieldJokers.hasOwnProperty(modifyingJoker)) return;
985 |
986 | modifyJokerDiv.innerHTML = `
308) {
138 | return b;
139 | }
140 | return [
141 | a / powersOfTen[b[1] + 323] + b[0],
142 | b[1]
143 | ];
144 | }
145 |
146 | function bigTimes(a, b) {
147 | const tempM = a * b[0];
148 |
149 | if(tempM > 1e13) {
150 | const tempE = Math.floor(Math.log10(Math.abs(tempM))) + 13;
151 |
152 | return [
153 | tempM / powersOfTen[tempE + 323],
154 | b[1] + tempE
155 | ];
156 | }
157 | else {
158 | return [
159 | tempM,
160 | b[1]
161 | ];
162 | }
163 | }
164 |
165 | function bigBigAdd(a, b) {
166 | if(b[1] > a[1]) {
167 | const diff = b[1] - a[1];
168 | if(diff >= 309) {
169 | return b;
170 | }
171 | return [
172 | a[0] / powersOfTen[diff + 323] + b[0],
173 | b[1]
174 | ];
175 | }
176 | else {
177 | const diff = a[1] - b[1];
178 | if(diff >= 309) {
179 | return a;
180 | }
181 | return [
182 | b[0] / powersOfTen[diff + 323] + a[0],
183 | a[1]
184 | ];
185 | }
186 | }
187 |
188 | function bigBigTimes(a, b) {
189 | return [
190 | a[0] * b[0],
191 | a[1] + b[1]
192 | ];
193 | }
194 |
195 | function normalizeBig(b) {
196 | const tempE = Math.floor(Math.log10(Math.abs(b[0])));
197 |
198 | return [
199 | b[0] / powersOfTen[tempE + 323],
200 | b[1] + tempE
201 | ];
202 | }
203 |
204 | /*
205 | brute-force order of operations:
206 |
207 | - compileJokers()
208 | - all combinations of joker order
209 | - compileJokerOrder()
210 | - all combinations of cards played
211 | - compileCards()
212 | - all combinations of cards played order
213 | - simulate()
214 | */
215 |
216 | class Hand {
217 | hands = [];
218 | jokersExtraValue = [];
219 | jokerRarities = [];
220 |
221 | randomMode = 0;
222 | chips = 0;
223 | mult = [1, 0]; // big-float
224 |
225 | chanceMultiplier = 1;
226 |
227 | FourFingers = false; // straights/flushes with 4 cards
228 | Shortcut = false; // straights can skip numbers
229 | Pareidolia = false; // all cards are faces
230 | SmearedJoker = false; // hearts = diamonds, clubs = spades
231 | Splash = false; // every card is counted in scoring
232 |
233 | hasVampire = false;
234 | Vampire = false;
235 | BaseballCard = 0;
236 |
237 | RaisedFist = false;
238 |
239 | MidasMaskas = false;
240 |
241 | compiledValues = [];
242 |
243 | handType = 11;
244 | involvedCards = [];
245 |
246 | hasPair = false;
247 | hasTwoPair = false;
248 | hasThreeOfAKind = false;
249 | hasFourOfAKind = false;
250 | hasStraight = false;
251 | hasFlush = false;
252 |
253 | compiledChips = 0;
254 | compiledMult = [1, 0];
255 |
256 | compiledInHandPlusMult = [0, 0];
257 | compiledInHandTimesMult = [1, 0];
258 | cardCast = [];
259 | cardExtraExtraChips = [];
260 |
261 | actualCardsInHand = [];
262 |
263 | constructor({
264 | cards = [],
265 | cardsInHand = [],
266 | jokers = [],
267 | hands = false,
268 | TheFlint = false,
269 | TheEye = false,
270 | PlasmaDeck = false,
271 | Observatory = false
272 | } = {}) {
273 | this.cards = cards;
274 | this.cardsInHand = cardsInHand;
275 | this.jokers = jokers;
276 | if(hands) {
277 | this.hands = hands;
278 | }
279 | else {
280 | for(let i = 0; i < handChips.length; i++) {
281 | this.hands.push([
282 | 1, // level
283 | 0, // planets
284 | 0, // played
285 | 0, // played this round
286 | ]);
287 | }
288 | }
289 | this.TheFlint = TheFlint;
290 | this.TheEye = TheEye;
291 | this.PlasmaDeck = PlasmaDeck;
292 | this.Observatory = Observatory;
293 | }
294 |
295 | triggerJoker(joker, j) {
296 | if(joker[JOKER_DISABLED]) return;
297 |
298 | if(joker[EDITION] === FOIL) {
299 | this.chips += 50;
300 | }
301 | else if(joker[EDITION] === HOLOGRAPHIC) {
302 | this.mult = bigAdd(10, this.mult);
303 | }
304 |
305 | switch(joker[JOKER]) {
306 | case 0:
307 | // Joker
308 | this.mult = bigAdd(4, this.mult);
309 | break;
310 | case 2:
311 | // Jolly Joker
312 | if(this.hasPair) {
313 | this.mult = bigAdd(8, this.mult);
314 | }
315 | break;
316 | case 3:
317 | // Zany Joker
318 | if(this.hasThreeOfAKind) {
319 | this.mult = bigAdd(12, this.mult);
320 | }
321 | break;
322 | case 4:
323 | // Mad Joker
324 | if(this.hasTwoPair) {
325 | this.mult = bigAdd(10, this.mult);
326 | }
327 | break;
328 | case 5:
329 | // Crazy Joker
330 | if(this.hasStraight) {
331 | this.mult = bigAdd(12, this.mult);
332 | }
333 | break;
334 | case 6:
335 | // Droll Joker
336 | if(this.hasFlush) {
337 | this.mult = bigAdd(10, this.mult);
338 | }
339 | break;
340 | case 7:
341 | // Half Joker
342 | if(this.cards.length <= 3) {
343 | this.mult = bigAdd(20, this.mult);
344 | }
345 | break;
346 | case 12:
347 | // Acrobat
348 | if(joker[VALUE] !== 0) {
349 | this.mult = bigTimes(3, this.mult);
350 | }
351 | break;
352 | case 22:
353 | // Mystic Summit
354 | if(joker[VALUE] !== 0) {
355 | this.mult = bigAdd(15, this.mult);
356 | }
357 | break;
358 | case 24:
359 | // Loyalty Card
360 | if(joker[VALUE] === 0) {
361 | this.mult = bigTimes(4, this.mult);
362 | }
363 | break;
364 | case 26:
365 | // Misprint
366 | switch(this.randomMode) {
367 | case 0:
368 | this.mult = bigAdd(23, this.mult);
369 | break;
370 | case 2:
371 | this.mult = bigAdd(Math.floor(Math.random() * 24), this.mult);
372 | break;
373 | }
374 | break;
375 | case 27:
376 | // Steel Joker
377 | this.mult = bigTimes(this.compiledValues[j], this.mult);
378 | break;
379 | case 31:
380 | // Glass Joker
381 | this.mult = bigTimes(this.compiledValues[j], this.mult);
382 | break;
383 | case 33:
384 | // Abstract Joker
385 | this.mult = bigAdd(this.jokers.length * 3, this.mult);
386 | break;
387 | case 42:
388 | // Supernova
389 | this.mult = bigAdd(this.hands[this.typeOfHand][PLAYED] + 1, this.mult);
390 | break;
391 | case 44:
392 | // Seeing Double
393 | if(this.compiledValues[j]) {
394 | this.mult = bigTimes(2, this.mult);
395 | }
396 | break;
397 | case 45:
398 | // The Duo
399 | if(this.hasPair) {
400 | this.mult = bigTimes(2, this.mult);
401 | }
402 | break;
403 | case 46:
404 | // The Trio
405 | if(this.hasThreeOfAKind) {
406 | this.mult = bigTimes(3, this.mult);
407 | }
408 | break;
409 | case 47:
410 | // The Family
411 | if(this.hasFourOfAKind) {
412 | this.mult = bigTimes(4, this.mult);
413 | }
414 | break;
415 | case 48:
416 | // The Order
417 | if(this.hasStraight) {
418 | this.mult = bigTimes(3, this.mult);
419 | }
420 | break;
421 | case 49:
422 | // The Tribe
423 | if(this.hasFlush) {
424 | this.mult = bigTimes(2, this.mult);
425 | }
426 | break;
427 | case 52:
428 | // Joker Stencil
429 | this.mult = bigTimes(1 + joker[VALUE], this.mult);
430 | break;
431 | case 55:
432 | // Ceremonial Dagger
433 | this.mult = bigAdd(joker[VALUE], this.mult);
434 | break;
435 | case 57:
436 | // Fortune Teller
437 | this.mult = bigAdd(joker[VALUE], this.mult);
438 | break;
439 | case 58:
440 | // Hit the Road
441 | this.mult = bigTimes(1 + joker[VALUE] * 0.5, this.mult);
442 | break;
443 | case 59:
444 | // Swashbuckler
445 | this.mult = bigAdd(this.compiledValues[j], this.mult);
446 | break;
447 | case 60:
448 | // Flower Pot
449 | if(this.compiledValues[j]) {
450 | this.mult = bigTimes(3, this.mult);
451 | }
452 | break;
453 | case 61:
454 | // Ride the Bus
455 | this.mult = bigAdd(this.compiledValues[j], this.mult);
456 | break;
457 | case 67:
458 | // Gros Michel
459 | this.mult = bigAdd(15, this.mult);
460 | break;
461 | case 70:
462 | // Driver's License
463 | if(joker[VALUE] >= 16) {
464 | this.mult = bigTimes(3, this.mult);
465 | }
466 | break;
467 | case 75:
468 | // Throwback
469 | this.mult = bigTimes(1 + joker[VALUE] * 0.25, this.mult);
470 | break;
471 | case 83:
472 | // Canio
473 | this.mult = bigTimes(1 + joker[VALUE], this.mult);
474 | break;
475 | case 85:
476 | // Yorick
477 | this.mult = bigTimes(joker[VALUE], this.mult);
478 | break;
479 | case 89:
480 | // Bootstraps
481 | this.mult = bigAdd(joker[VALUE] * 2, this.mult);
482 | break;
483 | case 102:
484 | // Blackboard
485 | if(this.compiledValues[j]) {
486 | this.mult = bigTimes(3, this.mult);
487 | }
488 | break;
489 | case 109:
490 | // Constellation
491 | this.mult = bigTimes(1 + joker[VALUE] / 10, this.mult);
492 | break;
493 | case 112:
494 | // Green Joker
495 | this.mult = bigAdd(1 + joker[VALUE], this.mult);
496 | break;
497 | case 115:
498 | // Cavendish
499 | this.mult = bigTimes(3, this.mult);
500 | break;
501 | case 116:
502 | // Card Sharp
503 | if(this.hands[this.typeOfHand][PLAYED_THIS_ROUND]) {
504 | this.mult = bigTimes(3, this.mult);
505 | }
506 | break;
507 | case 117:
508 | // Red Card
509 | this.mult = bigAdd(joker[VALUE] * 3, this.mult);
510 | break;
511 | case 118:
512 | // Madness
513 | this.mult = bigTimes(1 + joker[VALUE] * 0.5, this.mult);
514 | break;
515 | case 122:
516 | // Vampire
517 | this.mult = bigTimes(1 + this.compiledValues[j] / 10, this.mult);
518 | break;
519 | case 124:
520 | // Hologram
521 | this.mult = bigTimes(1 + joker[VALUE] * 0.25, this.mult);
522 | break;
523 | case 129:
524 | // Obelisk
525 | this.mult = bigTimes(this.compiledValues[j], this.mult);
526 | break;
527 | case 135:
528 | // Erosion
529 | this.mult = bigAdd(joker[VALUE] * 4, this.mult);
530 | break;
531 | case 145:
532 | // Lucky Cat
533 | this.mult = bigTimes(1 + (joker[VALUE] + this.jokersExtraValue[j]) / 4, this.mult);
534 | break;
535 | case 147:
536 | // Bull
537 | this.chips += 2 * joker[VALUE] + this.jokersExtraValue[j];
538 | break;
539 | case 150:
540 | // Flash Card
541 | this.mult = bigAdd(joker[VALUE] * 2, this.mult);
542 | break;
543 | case 151:
544 | // Popcorn
545 | this.mult = bigAdd(20 - joker[VALUE] * 4, this.mult);
546 | break;
547 | case 152:
548 | // Ramen
549 | this.mult = bigTimes(2 - joker[VALUE] / 100, this.mult);
550 | break;
551 | case 154:
552 | // Spare Trousers
553 | if(this.hasTwoPair) {
554 | this.compiledValues[j] = 1;
555 | this.mult = bigAdd(2 + joker[VALUE] * 2, this.mult);
556 | }
557 | else {
558 | this.mult = bigAdd(joker[VALUE] * 2, this.mult);
559 | }
560 | break;
561 | case 155:
562 | // Campfire
563 | this.mult = bigTimes(1 + joker[VALUE] * 0.25, this.mult);
564 | break;
565 | }
566 |
567 | if(joker[EDITION] === POLYCHROME) {
568 | this.mult = bigTimes(1.5, this.mult);
569 | }
570 | }
571 |
572 | triggerCard(card, retrigger = false) {
573 | if(card[CARD_DISABLED]) return;
574 | const notStone = card[ENHANCEMENT] !== STONE;
575 |
576 | if(notStone || this.hasVampire) {
577 | this.chips += cardValues[card[RANK]] + card[EXTRA_CHIPS] + card[EXTRA_EXTRA_CHIPS];
578 | }
579 |
580 | let luckyMult = 0;
581 | let luckyMoney = 0;
582 | let luckyTriggers = 0;
583 |
584 | if(!this.hasVampire) {
585 | switch(card[ENHANCEMENT]) {
586 | case BOUNS:
587 | this.chips += 30;
588 | break;
589 | case MULT:
590 | this.mult = bigAdd(4, this.mult);
591 | break;
592 | case GLASS:
593 | this.mult = bigTimes(2, this.mult);
594 | break;
595 | case STONE:
596 | this.chips += 50;
597 | break;
598 | case LUCKY:
599 | let triggered = false;
600 | switch(this.randomMode) {
601 | case 0:
602 | this.mult = bigAdd(20, this.mult);
603 | luckyMult++;
604 | luckyMoney++;
605 | luckyTriggers++;
606 | break;
607 | case 1:
608 | if(this.chanceMultiplier >= 5) {
609 | this.mult = bigAdd(20, this.mult);
610 | luckyMult++;
611 | triggered = true;
612 | }
613 | if(this.chanceMultiplier >= 20) {
614 | luckyMoney++;
615 | triggered = true;
616 | }
617 | if(triggered) {
618 | luckyTriggers++;
619 | }
620 | break;
621 | case 2:
622 | if(Math.random() < 0.2 * this.chanceMultiplier) {
623 | this.mult = bigAdd(20, this.mult);
624 | luckyMult++;
625 | triggered = true;
626 | }
627 | if(Math.random() < 1/15 * this.chanceMultiplier) {
628 | luckyMoney++;
629 | triggered = true;
630 | }
631 | if(triggered) {
632 | luckyTriggers++;
633 | }
634 | break;
635 | }
636 | break;
637 | }
638 | }
639 |
640 | switch(card[EDITION]) {
641 | case FOIL:
642 | this.chips += 50;
643 | break;
644 | case HOLOGRAPHIC:
645 | this.mult = bigAdd(10, this.mult);
646 | break;
647 | case POLYCHROME:
648 | this.mult = bigTimes(1.5, this.mult);
649 | break;
650 | }
651 |
652 | const isFace = this.Pareidolia || (notStone && card[RANK] >= JACK && card[RANK] <= KING);
653 |
654 | if(notStone) {
655 | for(let j = 0; j < this.jokers.length; j++) {
656 | const joker = this.jokers[j];
657 | if(joker[JOKER_DISABLED]) continue;
658 | switch(joker[JOKER]) {
659 | case 16:
660 | // Greedy Joker
661 | if(card[SUIT] === DIAMONDS || (this.SmearedJoker && card[SUIT] === HEARTS)) {
662 | this.mult = bigAdd(3, this.mult);
663 | }
664 | else if(card[SUIT] === true) {
665 | this.mult = bigAdd(3, this.mult);
666 | }
667 | break;
668 | case 17:
669 | // Lusty Joker
670 | if(card[SUIT] === HEARTS || (this.SmearedJoker && card[SUIT] === DIAMONDS)) {
671 | this.mult = bigAdd(3, this.mult);
672 | }
673 | else if(card[SUIT] === true) {
674 | this.mult = bigAdd(3, this.mult);
675 | }
676 | break;
677 | case 18:
678 | // Wrathful Joker
679 | if(card[SUIT] === SPADES || (this.SmearedJoker && card[SUIT] === CLUBS)) {
680 | this.mult = bigAdd(3, this.mult);
681 | }
682 | else if(card[SUIT] === true) {
683 | this.mult = bigAdd(3, this.mult);
684 | }
685 | break;
686 | case 19:
687 | // Gluttonous Joker
688 | if(card[SUIT] === CLUBS || (this.SmearedJoker && card[SUIT] === SPADES)) {
689 | this.mult = bigAdd(3, this.mult);
690 | }
691 | else if(card[SUIT] === true) {
692 | this.mult = bigAdd(3, this.mult);
693 | }
694 | break;
695 | case 32:
696 | // Scary Face
697 | if(isFace) {
698 | this.chips += 30;
699 | }
700 | break;
701 | case 38:
702 | // Even Steven
703 | if(card[RANK] % 2 === 0 && card[RANK] <= _10) {
704 | this.mult = bigAdd(4, this.mult);
705 | }
706 | break;
707 | case 39:
708 | // Odd Todd
709 | if((card[RANK] % 2 === 1 && card[RANK] <= _9) || card[RANK] === ACE) {
710 | this.chips += 31;
711 | }
712 | break;
713 | case 40:
714 | // Wee Joker
715 | if(card[RANK] === _2) {
716 | this.chips += 8;
717 | }
718 | break;
719 | case 51:
720 | // Fibonacci
721 | if(card[RANK] === ACE || card[RANK] === _8 || card[RANK] === _5 || card[RANK] === _3 || card[RANK] === _2) {
722 | this.mult = bigAdd(8, this.mult);
723 | }
724 | break;
725 | case 63:
726 | // Scholar
727 | if(card[RANK] === ACE) {
728 | this.chips += 20;
729 | this.mult = bigAdd(4, this.mult);
730 | }
731 | break;
732 | case 76:
733 | // The Idol
734 | if(card[SUIT] === Math.abs(joker[VALUE]) % 4 && card[RANK] === Math.floor(Math.abs(joker[VALUE]) / 4) % 13) {
735 | this.mult = bigTimes(2, this.mult);
736 | }
737 | break;
738 | case 80:
739 | // Bloodstone
740 | if(card[SUIT] === HEARTS || (this.SmearedJoker && card[SUIT] === DIAMONDS)) {
741 | switch(this.randomMode) {
742 | case 0:
743 | this.mult = bigTimes(1.5, this.mult);
744 | break;
745 | case 1:
746 | if(this.chanceMultiplier >= 2) {
747 | this.mult = bigTimes(1.5, this.mult);
748 | }
749 | break;
750 | case 2:
751 | if(Math.random() < 1/2 * this.chanceMultiplier) {
752 | this.mult = bigTimes(1.5, this.mult);
753 | }
754 | break;
755 | }
756 | }
757 | else if(card[SUIT] === true) {
758 | switch(this.randomMode) {
759 | case 0:
760 | this.mult = bigTimes(1.5, this.mult);
761 | break;
762 | case 1:
763 | if(this.chanceMultiplier >= 2) {
764 | this.mult = bigTimes(1.5, this.mult);
765 | }
766 | break;
767 | case 2:
768 | if(Math.random() < 1/2 * this.chanceMultiplier) {
769 | this.mult = bigTimes(1.5, this.mult);
770 | }
771 | break;
772 | }
773 | }
774 | break;
775 | case 81:
776 | // Arrowhead
777 | if(card[SUIT] === SPADES || (this.SmearedJoker && card[SUIT] === CLUBS)) {
778 | this.chips += 50;
779 | }
780 | else if(card[SUIT] === true) {
781 | this.chips += 50;
782 | }
783 | break;
784 | case 82:
785 | // Onyx Agate
786 | if(card[SUIT] === CLUBS || (this.SmearedJoker && card[SUIT] === SPADES)) {
787 | this.mult = bigAdd(7, this.mult);
788 | }
789 | else if(card[SUIT] === true) {
790 | this.mult = bigAdd(7, this.mult);
791 | }
792 | break;
793 | case 84:
794 | // Triboulet
795 | if(card[RANK] === KING || card[RANK] === QUEEN) {
796 | this.mult = bigTimes(2, this.mult);
797 | }
798 | break;
799 | case 110:
800 | // Hiker
801 | card[EXTRA_EXTRA_CHIPS] += 5;
802 | break;
803 | case 132:
804 | // Photograph
805 | if(isFace && (this.jokersExtraValue[j] === card || this.jokersExtraValue[j] === 0)) {
806 | this.jokersExtraValue[j] = card;
807 | this.mult = bigTimes(2, this.mult);
808 | }
809 | break;
810 | case 145:
811 | // Lucky Cat
812 | this.jokersExtraValue[j] += luckyTriggers;
813 | break;
814 | case 147:
815 | // Bull
816 | this.jokersExtraValue[j] += luckyMoney * 40;
817 | break;
818 | case 156:
819 | // Smiley Face
820 | if(isFace) {
821 | this.mult = bigAdd(5, this.mult);
822 | }
823 | break;
824 | case 157:
825 | // Ancient Joker
826 | if(card[ENHANCEMENT] === WILD || (this.SmearedJoker ? card[SUIT] % 2 === Math.abs(joker[VALUE]) % 2 : card[SUIT] === Math.abs(joker[VALUE]) % 4)) {
827 | this.mult = bigTimes(1.5, this.mult);
828 | }
829 | break;
830 | case 158:
831 | // Walkie Talkie
832 | if(card[RANK] === _4 || card[RANK] === _10) {
833 | this.chips += 10;
834 | this.mult = bigAdd(4, this.mult);
835 | }
836 | break;
837 | }
838 | }
839 | }
840 | else if(isFace) {
841 | for(let j = 0; j < this.jokers.length; j++) {
842 | const joker = this.jokers[j];
843 | if(joker[JOKER_DISABLED]) continue;
844 | switch(joker[JOKER]) {
845 | case 32:
846 | // Scary Face
847 | this.chips += 30;
848 | break;
849 | case 110:
850 | // Hiker
851 | card[EXTRA_EXTRA_CHIPS] += 5;
852 | break;
853 | case 132:
854 | // Photograph
855 | if(this.jokersExtraValue[j] === card || this.jokersExtraValue[j] === 0) {
856 | this.jokersExtraValue[j] = card;
857 | this.mult = bigTimes(2, this.mult);
858 | }
859 | break;
860 | case 156:
861 | // Smiley Face
862 | this.mult = bigAdd(5, this.mult);
863 | break;
864 | }
865 | }
866 | }
867 | else {
868 | for(let j = 0; j < this.jokers.length; j++) {
869 | const joker = this.jokers[j];
870 | if(joker[JOKER_DISABLED]) continue;
871 | switch(joker[JOKER]) {
872 | case 110:
873 | // Hiker
874 | card[EXTRA_EXTRA_CHIPS] += 4;
875 | break;
876 | }
877 | }
878 | }
879 |
880 | // retriggers
881 | if(!retrigger) {
882 | if(card[SEAL] === RED_SEAL) {
883 | this.triggerCard(card, true);
884 | }
885 |
886 | for(let j = 0; j < this.jokers.length; j++) {
887 | const joker = this.jokers[j];
888 | if(joker[JOKER_DISABLED]) continue;
889 | switch(joker[JOKER]) {
890 | case 13:
891 | // Sock and Buskin
892 | if(isFace) {
893 | this.triggerCard(card, true);
894 | }
895 | break;
896 | case 25:
897 | // Hack
898 | if(card[RANK] <= _5) {
899 | this.triggerCard(card, true);
900 | }
901 | break;
902 | case 69:
903 | // Hanging Chad
904 | if(this.jokersExtraValue[j] === 0) {
905 | this.jokersExtraValue[j]++;
906 | this.triggerCard(card, true);
907 | this.triggerCard(card, true);
908 | }
909 | break;
910 | case 74:
911 | // Dusk
912 | if(joker[VALUE] !== 0) {
913 | this.triggerCard(card, true);
914 | }
915 | break;
916 | case 153:
917 | // Seltzer
918 | this.triggerCard(card, true);
919 | break;
920 | }
921 | }
922 | }
923 | }
924 |
925 | triggerCardInHand(card, retrigger = false) {
926 | if(card[CARD_DISABLED]) return;
927 |
928 | // apply steel cards
929 | if(card[ENHANCEMENT] === STEEL && !card[CARD_DISABLED]) {
930 | this.compiledInHandPlusMult = bigTimes(1.5, this.compiledInHandPlusMult);
931 | this.compiledInHandTimesMult = bigTimes(1.5, this.compiledInHandTimesMult);
932 | }
933 |
934 | for(let j = 0; j < this.jokers.length; j++) {
935 | const joker = this.jokers[j];
936 | if(joker[JOKER_DISABLED]) continue;
937 | switch (joker[JOKER]) {
938 | case 28:
939 | // Raised Fist
940 | if(card === this.compiledValues[j] && card[ENHANCEMENT] !== STONE) {
941 | this.compiledInHandPlusMult = bigAdd(2 * (card[RANK] === ACE ? 11 : Math.min(10, card[RANK] + 2)), this.compiledInHandPlusMult);
942 | }
943 | break;
944 | case 62:
945 | // Shoot the Moon
946 | if(card[RANK] === QUEEN && card[ENHANCEMENT] !== STONE) {
947 | this.compiledInHandPlusMult = bigAdd(13, this.compiledInHandPlusMult);
948 | }
949 | break;
950 | case 126:
951 | // Baron
952 | if(card[RANK] === KING && card[ENHANCEMENT] !== STONE) {
953 | this.compiledInHandPlusMult = bigTimes(1.5, this.compiledInHandPlusMult);
954 | this.compiledInHandTimesMult = bigTimes(1.5, this.compiledInHandTimesMult);
955 | }
956 | break;
957 | }
958 | }
959 |
960 | // retriggers
961 | if(!retrigger) {
962 | if(card[SEAL] === RED_SEAL) {
963 | this.triggerCardInHand(card, true);
964 | }
965 |
966 | for(let j = 0; j < this.jokers.length; j++) {
967 | const joker = this.jokers[j];
968 | if(joker[JOKER_DISABLED]) continue;
969 | switch(joker[JOKER]) {
970 | case 14:
971 | this.triggerCardInHand(card, true);
972 | break;
973 | }
974 | }
975 | }
976 | }
977 |
978 | getTypeOfHand() {
979 | // ES2019 apparently mandates stable sort
980 | const sortedCards = this.cards.filter(a => a[ENHANCEMENT] !== STONE).sort((a, b) => b[RANK] - a[RANK]);
981 |
982 | let flush = [];
983 |
984 | let straight = false;
985 |
986 | if(sortedCards.length >= (this.FourFingers ? 4 : 5)) {
987 | const lines = [
988 | [sortedCards[0]],
989 | [sortedCards[1]],
990 | ];
991 | if(this.FourFingers) {
992 | lines.push([sortedCards[2]]);
993 | }
994 |
995 | for(let i = 1; i < sortedCards.length; i++) {
996 | for(let l = 0; l < lines.length; l++) {
997 | const val = lines[l][lines[l].length - 1][RANK];
998 | if(sortedCards[i][RANK] + 1 === val) {
999 | lines.push([...lines[l], sortedCards[i]]);
1000 | }
1001 | else if(this.Shortcut && sortedCards[i][RANK] + 2 === val) {
1002 | lines.push([...lines[l], sortedCards[i]]);
1003 | }
1004 | }
1005 | }
1006 |
1007 | for(let i = 0; i < sortedCards.length; i++) {
1008 | for(let l = 0; l < lines.length; l++) {
1009 | const val = lines[l][lines[l].length - 1][RANK];
1010 | if(val === _2 && sortedCards[i][0] === ACE) {
1011 | lines.push([...lines[l], sortedCards[i]]);
1012 | }
1013 | else if(this.Shortcut && val === _3 && sortedCards[i][0] === ACE) {
1014 | lines.push([...lines[l], sortedCards[i]]);
1015 | }
1016 | }
1017 | }
1018 |
1019 | let flushes = [
1020 | [],[],[],[]
1021 | ];
1022 |
1023 | for(let c = 0; c < this.cards.length; c++) {
1024 | const card = this.cards[c];
1025 | for(let i = 0; i < 4; i++) {
1026 | if(card[ENHANCEMENT] !== STONE && (card[ENHANCEMENT] === WILD || (this.SmearedJoker ? card[SUIT] % 2 == i : card[SUIT] === i))) {
1027 | flushes[i].push(card);
1028 | }
1029 | }
1030 | }
1031 |
1032 | for(let i = 0; i < flushes.length; i++) {
1033 | if(flushes[i].length > flush.length) {
1034 | flush = flushes[i];
1035 | }
1036 | }
1037 |
1038 | if(lines[lines.length - 1].length >= (this.FourFingers ? 4 : 5)) {
1039 | straight = lines[lines.length - 1];
1040 | }
1041 | }
1042 |
1043 | if(flush.length < (this.FourFingers ? 4 : 5)) flush = false;
1044 |
1045 | if(flush) {
1046 | this.hasFlush = true;
1047 | }
1048 |
1049 | if(straight) {
1050 | this.hasStraight = true;
1051 | }
1052 |
1053 | if(sortedCards.length >= 4 && (
1054 | sortedCards[0][RANK] === sortedCards[3][RANK] ||
1055 | (sortedCards.length >= 5 && sortedCards[1][RANK] === sortedCards[4][RANK])
1056 | )) {
1057 | this.hasPair = true;
1058 | this.hasThreeOfAKind = true;
1059 | this.hasFourOfAKind = true;
1060 | }
1061 | else if(sortedCards.length >= 3 && (
1062 | (sortedCards[0][RANK] === sortedCards[1][RANK] && sortedCards[1][RANK] === sortedCards[2][RANK]) ||
1063 | (sortedCards.length >= 4 && (
1064 | (sortedCards[1][RANK] === sortedCards[2][RANK] && sortedCards[2][RANK] === sortedCards[3][RANK]) ||
1065 | (sortedCards.length >= 5 && sortedCards[2][RANK] === sortedCards[3][RANK] && sortedCards[3][RANK] === sortedCards[4][RANK])
1066 | )))) {
1067 | this.hasPair = true;
1068 | this.hasThreeOfAKind = true;
1069 | }
1070 | else if(sortedCards.length >= 2 &&
1071 | (sortedCards[0][RANK] === sortedCards[1][RANK] ||
1072 | (sortedCards.length >= 3 &&
1073 | (sortedCards[1][RANK] === sortedCards[2][RANK] ||
1074 | (sortedCards.length >= 4 &&
1075 | (sortedCards[2][RANK] === sortedCards[3][RANK] ||
1076 | (sortedCards.length >= 5 && sortedCards[3][RANK] === sortedCards[4][RANK])
1077 | )))))) {
1078 | this.hasPair = true;
1079 | }
1080 |
1081 | if(sortedCards.length >= 4) {
1082 | if(sortedCards[0][RANK] === sortedCards[1][RANK]) {
1083 | if(sortedCards[2][RANK] === sortedCards[3][RANK]) {
1084 | this.hasTwoPair = true;
1085 | }
1086 | if(sortedCards.length >= 5 && sortedCards[3][RANK] === sortedCards[4][RANK]) {
1087 | this.hasTwoPair = true;
1088 | }
1089 | }
1090 | if(sortedCards.length >= 5 && sortedCards[1][RANK] === sortedCards[2][RANK] && sortedCards[3][RANK] === sortedCards[4][RANK]) {
1091 | this.hasTwoPair = true;
1092 | }
1093 | }
1094 |
1095 | // flush five
1096 | if(flush && sortedCards.length === 5 && sortedCards[0][RANK] === sortedCards[4][RANK]) {
1097 | return [FLUSH_FIVE, this.cards];
1098 | }
1099 |
1100 | // flush house
1101 | if(flush && sortedCards.length === 5 && sortedCards[0][RANK] === sortedCards[1][RANK] && sortedCards[3][RANK] === sortedCards[4][RANK] && (sortedCards[1][RANK] === sortedCards[2][RANK] || sortedCards[2][RANK] === sortedCards[3][RANK])) {
1102 | return [FLUSH_HOUSE, this.cards];
1103 | }
1104 |
1105 | // five of a kind
1106 | if(sortedCards.length === 5 && sortedCards[0][RANK] === sortedCards[4][RANK]) {
1107 | return [FIVE_OF_A_KIND, this.cards];
1108 | }
1109 |
1110 | // straight flush
1111 | if(straight && flush) {
1112 | return [STRAIGHT_FLUSH, [...new Set([...straight, ...flush])]];
1113 | }
1114 |
1115 | // four of a kind
1116 | if(sortedCards.length >= 4) {
1117 | if(sortedCards[0][RANK] === sortedCards[3][RANK]) {
1118 | return [FOUR_OF_A_KIND, [
1119 | sortedCards[0],
1120 | sortedCards[1],
1121 | sortedCards[2],
1122 | sortedCards[3]
1123 | ]];
1124 | }
1125 | if(sortedCards.length >= 5 && sortedCards[1][RANK] === sortedCards[4][RANK]) {
1126 | return [FOUR_OF_A_KIND, [
1127 | sortedCards[1],
1128 | sortedCards[2],
1129 | sortedCards[3],
1130 | sortedCards[4]
1131 | ]];
1132 | }
1133 | }
1134 |
1135 | // full house
1136 | if(sortedCards.length === 5 && sortedCards[0][RANK] === sortedCards[1][RANK] && sortedCards[3][RANK] === sortedCards[4][RANK] && (sortedCards[1][RANK] === sortedCards[2][RANK] || sortedCards[2][RANK] === sortedCards[3][RANK])) {
1137 | return [FULL_HOUSE, this.cards];
1138 | }
1139 |
1140 | // flush
1141 | if(flush) {
1142 | return [FLUSH, flush];
1143 | }
1144 |
1145 | // straight
1146 | if(straight) {
1147 | return [STRAIGHT, straight];
1148 | }
1149 |
1150 | // three of a kind
1151 | if(sortedCards.length >= 3) {
1152 | if(sortedCards[0][RANK] === sortedCards[1][RANK] && sortedCards[1][RANK] === sortedCards[2][RANK]) {
1153 | return [THREE_OF_A_KIND, [sortedCards[0], sortedCards[1], sortedCards[2]]];
1154 | }
1155 | if(sortedCards.length >= 4) {
1156 | if(sortedCards[1][RANK] === sortedCards[2][RANK] && sortedCards[2][RANK] === sortedCards[3][RANK]) {
1157 | return [THREE_OF_A_KIND, [sortedCards[1], sortedCards[2], sortedCards[3]]];
1158 | }
1159 | if(sortedCards.length >= 5 && sortedCards[2][RANK] === sortedCards[3][RANK] && sortedCards[3][RANK] === sortedCards[4][RANK]) {
1160 | return [THREE_OF_A_KIND, [sortedCards[2], sortedCards[3], sortedCards[4]]];
1161 | }
1162 | }
1163 | }
1164 |
1165 | // two pair
1166 | if(sortedCards.length >= 4) {
1167 | if(sortedCards[0][RANK] === sortedCards[1][RANK]) {
1168 | if(sortedCards[2][RANK] === sortedCards[3][RANK]) {
1169 | return [TWO_PAIR, [sortedCards[0], sortedCards[1], sortedCards[2], sortedCards[3]]];
1170 | }
1171 | if(sortedCards.length >= 5 && sortedCards[3][RANK] === sortedCards[4][RANK]) {
1172 | return [TWO_PAIR, [sortedCards[0], sortedCards[1], sortedCards[3], sortedCards[4]]];
1173 | }
1174 | }
1175 | if(sortedCards.length >= 5 && sortedCards[1][RANK] === sortedCards[2][RANK] && sortedCards[3][RANK] === sortedCards[4][RANK]) {
1176 | return [TWO_PAIR, [sortedCards[1], sortedCards[2], sortedCards[3], sortedCards[4]]];
1177 | }
1178 | }
1179 |
1180 | // pair
1181 | if(sortedCards.length >= 2) {
1182 | if(sortedCards[0][RANK] === sortedCards[1][RANK]) {
1183 | return [PAIR, [sortedCards[0], sortedCards[1]]];
1184 | }
1185 | if(sortedCards.length >= 3) {
1186 | if(sortedCards[1][RANK] === sortedCards[2][RANK]) {
1187 | return [PAIR, [sortedCards[1], sortedCards[2]]];
1188 | }
1189 | if(sortedCards.length >= 4) {
1190 | if(sortedCards[2][RANK] === sortedCards[3][RANK]) {
1191 | return [PAIR, [sortedCards[2], sortedCards[3]]];
1192 | }
1193 | if(sortedCards.length >= 5 && sortedCards[3][RANK] === sortedCards[4][RANK]) {
1194 | return [PAIR, [sortedCards[3], sortedCards[4]]];
1195 | }
1196 | }
1197 | }
1198 | }
1199 |
1200 | // none
1201 | if(sortedCards.length === 0) {
1202 | return [HIGH_CARD, []];
1203 | }
1204 |
1205 | // high-card
1206 | return [HIGH_CARD, [sortedCards[0]]];
1207 | }
1208 |
1209 | // knowledge of joker order and cards-played (not their order)
1210 | compileCards() {
1211 | this.hasPair = false;
1212 | this.hasTwoPair = false;
1213 | this.hasThreeOfAKind = false;
1214 | this.hasFourOfAKind = false;
1215 | this.hasStraight = false;
1216 | this.hasFlush = false;
1217 |
1218 | this.Vampire = false;
1219 |
1220 | this.compiledChips = 0;
1221 | this.compiledMult = [1, 0];
1222 |
1223 | this.compiledInHandPlusMult = [0, 0];
1224 | this.compiledInHandTimesMult = [1, 0];
1225 |
1226 | if(this.actualCardsInHand.length === 0) {
1227 | this.actualCardsInHand = this.cardsInHand.slice();
1228 | }
1229 | else {
1230 | this.cardsInHand = this.actualCardsInHand.slice();
1231 | }
1232 |
1233 | this.lowestCard = false;
1234 |
1235 | for(let c = 0; c < this.cards.length; c++) {
1236 | if(this.cards[c][ENHANCEMENT] === WILD) {
1237 | this.cards[c][SUIT] = true;
1238 | }
1239 | }
1240 |
1241 | // get hand type
1242 | [this.typeOfHand, this.involvedCards] = this.getTypeOfHand();
1243 |
1244 | if(this.Splash) {
1245 | this.involvedCards = this.cards;
1246 | }
1247 |
1248 | if(this.typeOfHand >= 0) {
1249 | this.compiledChips = handChips[this.typeOfHand][0] + handChips[this.typeOfHand][2] * (this.hands[this.typeOfHand][LEVEL] - 1);
1250 | this.compiledMult = [handChips[this.typeOfHand][1] + handChips[this.typeOfHand][3] * (this.hands[this.typeOfHand][LEVEL] - 1), 0];
1251 |
1252 | if(this.TheFlint) {
1253 | this.compiledChips /= 2;
1254 | this.compiledMult[0] /= 2;
1255 | }
1256 | }
1257 |
1258 | // resolve jokers that require knowledge of hand
1259 | for(let j = 0; j < this.jokers.length; j++) {
1260 | const joker = this.jokers[j];
1261 | if(joker[JOKER_DISABLED]) continue;
1262 |
1263 | const oldCompiledValue = this.compiledValues[j];
1264 | this.compiledValues[j] = 0;
1265 |
1266 | switch(joker[JOKER]) {
1267 | case 9:
1268 | // Stone Joker
1269 | this.compiledChips += joker[VALUE] * 25;
1270 | if(this.hasVampire) {
1271 | for(let c = 0; c < this.involvedCards.length; c++) {
1272 | if(this.involvedCards[c][ENHANCEMENT] === STONE) {
1273 | this.compiledChips -= 25;
1274 | }
1275 | }
1276 | }
1277 | break;
1278 | case 21:
1279 | // Banner
1280 | this.compiledChips += joker[VALUE] * 30;
1281 | break;
1282 | case 27:
1283 | // Steel Joker
1284 | if(this.hasVampire) {
1285 | let amount = joker[VALUE];
1286 | for(let c = 0; c < this.involvedCards.length; c++) {
1287 | if(this.involvedCards[c][ENHANCEMENT] === STEEL) {
1288 | amount++;
1289 | }
1290 | }
1291 | this.compiledValues[j] = 1 + (joker[VALUE] - amount) * 0.2;
1292 | }
1293 | else {
1294 | this.compiledValues[j] = 1 + joker[VALUE] * 0.2;
1295 | }
1296 | break;
1297 | case 28:
1298 | // Raised Fist
1299 | // find lowest card
1300 | let lowest = 100;
1301 | let lowestCards = [];
1302 | for(let c = 0; c < this.cardsInHand.length; c++) {
1303 | const card = this.cardsInHand[c];
1304 | if(card[ENHANCEMENT] !== STONE) {
1305 | if(lowest > card[RANK]) {
1306 | lowest = card[RANK];
1307 | lowestCards = [card];
1308 | }
1309 | else if(lowest === card[RANK]) {
1310 | lowestCards.push(card);
1311 | }
1312 | }
1313 | }
1314 |
1315 | if(lowestCards.length > 0) {
1316 | this.compiledValues[j] = lowestCards[lowestCards.length - 1];
1317 | }
1318 | break;
1319 | case 31:
1320 | // Glass Joker
1321 | if(this.hasVampire) {
1322 | let amount = joker[VALUE];
1323 | for(let c = 0; c < this.cards.length; c++) {
1324 | if(this.cards[c][ENHANCEMENT] === GLASS) {
1325 | switch(this.randomMode) {
1326 | case 0:
1327 | amount++;
1328 | break;
1329 | case 1:
1330 | if(this.chanceMultiplier >= 4) {
1331 | amount++;
1332 | }
1333 | break;
1334 | case 2:
1335 | if(Math.random() < 0.25 * this.chanceMultiplier) {
1336 | amount++;
1337 | }
1338 | break;
1339 | }
1340 | }
1341 | }
1342 | this.compiledValues[j] = 1 + (joker[VALUE] - amount) * 0.75;
1343 | }
1344 | else {
1345 | this.compiledValues[j] = 1 + joker[VALUE] * 0.75;
1346 | }
1347 | break;
1348 | case 40:
1349 | // Wee Joker
1350 | this.compiledChips += joker[VALUE] * 8;
1351 | break;
1352 | case 44:
1353 | // Seeing Double
1354 | if(this.SmearedJoker) {
1355 | let club = 0;
1356 | let nonClub = 0;
1357 | for(let c = 0; c < this.involvedCards.length; c++) {
1358 | if(this.involvedCards[c][CARD_DISABLED]) continue;
1359 | if(this.involvedCards[c][ENHANCEMENT] === STONE) continue;
1360 | if(this.involvedCards[c][ENHANCEMENT] === WILD ||
1361 | this.involvedCards[c][SUIT] === CLUBS ||
1362 | this.involvedCards[c][SUIT] === SPADES) {
1363 | club++;
1364 | }
1365 | else {
1366 | nonClub++;
1367 | }
1368 | }
1369 |
1370 | if(club > 0 && (club > 1 || nonClub > 0)) {
1371 | this.compiledValues[j] = true;
1372 | }
1373 | }
1374 | else {
1375 | let club = false;
1376 | let nonClub = false;
1377 | let wildC = 0;
1378 | for(let c = 0; c < this.involvedCards.length; c++) {
1379 | if(this.involvedCards[c][CARD_DISABLED]) continue;
1380 | if(this.involvedCards[c][ENHANCEMENT] === STONE) continue;
1381 | if(this.involvedCards[c][ENHANCEMENT] === WILD) {
1382 | wildC++;
1383 | }
1384 | else if(this.involvedCards[c][SUIT] === CLUBS) {
1385 | club = true;
1386 | }
1387 | else {
1388 | nonClub = true;
1389 | }
1390 | }
1391 | for(let i = 0; i < wildC; i++) {
1392 | if(!club) club = true;
1393 | else nonClub = true;
1394 | }
1395 |
1396 | if(club && nonClub) {
1397 | this.compiledValues[j] = true;
1398 | }
1399 | }
1400 | break;
1401 | case 60:
1402 | // Flower Pot
1403 | let hearts = 0;
1404 | let diamonds = 0;
1405 | let clubs = 0;
1406 | let spades = 0;
1407 | let wild = 0;
1408 | for(let c = 0; c < this.involvedCards.length; c++) {
1409 | if(this.involvedCards[c][CARD_DISABLED] && this.involvedCards[c][ENHANCEMENT] === WILD) continue;// seems to be a bug in balatro itself, remove when fixed?
1410 | if(this.involvedCards[c][ENHANCEMENT] !== STONE) {
1411 | if(this.involvedCards[c][ENHANCEMENT] === WILD && !this.involvedCards[c][CARD_DISABLED]) {
1412 | wild++;
1413 | }
1414 | else if(this.involvedCards[c][SUIT] === HEARTS) {
1415 | hearts = 1;
1416 | }
1417 | else if(this.involvedCards[c][SUIT] === DIAMONDS) {
1418 | diamonds = 1;
1419 | }
1420 | else if(this.involvedCards[c][SUIT] === CLUBS) {
1421 | clubs = 1;
1422 | }
1423 | else if(this.involvedCards[c][SUIT] === SPADES) {
1424 | spades = 1;
1425 | }
1426 | }
1427 | }
1428 | if(hearts + diamonds + clubs + spades + wild >= 4) {
1429 | this.compiledValues[j] = true;
1430 | }
1431 | break;
1432 | case 61:
1433 | // Ride the Bus
1434 | if(!this.Pareidolia) {
1435 | let playedFace = false;
1436 | for(let c = 0; c < this.involvedCards.length; c++) {
1437 | if(this.involvedCards[c][CARD_DISABLED]) continue;
1438 | if(this.involvedCards[c][ENHANCEMENT] !== STONE && this.involvedCards[c][RANK] >= JACK && this.involvedCards[c][RANK] <= KING) {
1439 | playedFace = true;
1440 | break;
1441 | }
1442 | }
1443 | if(!playedFace) {
1444 | this.compiledValues[j] = joker[VALUE] + 1;
1445 | }
1446 | }
1447 | break;
1448 | case 68:
1449 | // Stuntman
1450 | this.compiledChips += 250;
1451 | break;
1452 | case 102:
1453 | // Blackboard
1454 | let allBlack = true;
1455 | for(let c = 0; c < this.cardsInHand.length; c++) {
1456 | if(this.cardsInHand[c][ENHANCEMENT] === STONE || (this.cardsInHand[c][ENHANCEMENT] !== WILD && (this.cardsInHand[c][SUIT] === HEARTS || this.cardsInHand[c][SUIT] === DIAMONDS))) {
1457 | allBlack = false;
1458 | break;
1459 | }
1460 | }
1461 | if(allBlack) {
1462 | this.compiledValues[j] = true;
1463 | }
1464 | break;
1465 | case 103:
1466 | // Runner
1467 | if(this.hasStraight) {
1468 | this.compiledChips += 15 * (joker[VALUE] + 1);
1469 | }
1470 | else {
1471 | this.compiledChips += 15 * joker[VALUE];
1472 | }
1473 | break;
1474 | case 104:
1475 | // Ice Cream
1476 | this.compiledChips += 100 - 5 * joker[VALUE];
1477 | break;
1478 | case 105:
1479 | // DNA
1480 | if(this.cards.length === 1) {
1481 | this.cardsInHand.push(this.cards[0]);
1482 | }
1483 | break;
1484 | case 107:
1485 | //Blue joker
1486 | this.compiledChips += 104 + 2 * joker[VALUE];
1487 | break;
1488 | case 119:
1489 | // Square Joker
1490 | if(this.cards.length === 4) {
1491 | this.compiledChips += 4 * (joker[VALUE] + 1);
1492 | }
1493 | else {
1494 | this.compiledChips += 4 * joker[VALUE];
1495 | }
1496 | break;
1497 | case 122:
1498 | // Vampire
1499 | this.compiledValues[j] = joker[VALUE];
1500 | if(this.Vampire) {
1501 | break;
1502 | }
1503 | this.Vampire = true;
1504 | for(let c = 0; c < this.involvedCards.length; c++) {
1505 | const card = this.involvedCards[c];
1506 | if((this.MidasMaskas && card[RANK] >= JACK && card[RANK] <= KING) || (this.MidasMaskas && this.Pareidolia)) {
1507 | this.compiledValues[j]++;
1508 | }
1509 | else {
1510 | if(card[ENHANCEMENT] > 0) {
1511 | this.compiledValues[j]++;
1512 | }
1513 | }
1514 | }
1515 | break;
1516 | case 129:
1517 | // Obelisk
1518 | let mostPlayed = 0;
1519 | for(let h = 0; h < this.hands.length; h++) {
1520 | if(this.hands[h][PLAYED] > mostPlayed) {
1521 | mostPlayed = this.hands[h][PLAYED];
1522 | }
1523 | }
1524 | if(this.hands[this.typeOfHand][PLAYED] === mostPlayed) {
1525 | this.compiledValues[j] = 1;
1526 | }
1527 | else {
1528 | this.compiledValues[j] = 1 + (joker[VALUE] + 1) / 5;
1529 | }
1530 | break;
1531 | case 140:
1532 | // Sly Joker
1533 | if(this.hasPair) {
1534 | this.compiledChips += 50;
1535 | }
1536 | break;
1537 | case 141:
1538 | // Wily Joker
1539 | if(this.hasThreeOfAKind) {
1540 | this.compiledChips += 100;
1541 | }
1542 | break;
1543 | case 142:
1544 | // Clever Joker
1545 | if(this.hasTwoPair && !this.hasFourOfAKind) {
1546 | this.compiledChips += 80;
1547 | }
1548 | break;
1549 | case 143:
1550 | // Devious Joker
1551 | if(this.hasStraight) {
1552 | this.compiledChips += 100;
1553 | }
1554 | break;
1555 | case 144:
1556 | // Crafty Joker
1557 | if(this.hasFlush) {
1558 | this.compiledChips += 80;
1559 | }
1560 | break;
1561 | case 159:
1562 | // Castle
1563 | this.compiledChips += joker[VALUE] * 3;
1564 | break;
1565 | default:
1566 | this.compiledValues[j] = oldCompiledValue;
1567 | }
1568 | }
1569 |
1570 | // Blueprint or Brainstorm compiled value
1571 | for(let j = 0; j < this.actualJokers.length; j++) {
1572 | const joker = this.actualJokers[j];
1573 | if(joker[JOKER_DISABLED]) continue;
1574 |
1575 | switch(joker[JOKER]) {
1576 | case 30:
1577 | case 77:
1578 | // Blueprint
1579 | this.compiledValues[j] = this.compiledValues[this.cardCast[j]];
1580 | break;
1581 | }
1582 | }
1583 |
1584 | // trigger cards-in-hand
1585 | for(let c = 0; c < this.cardsInHand.length; c++) {
1586 | this.triggerCardInHand(this.cardsInHand[c]);
1587 | }
1588 | }
1589 |
1590 | // knowledge of joker order, not cards-played
1591 | compileJokerOrder() {
1592 | this.jokerRarities = [];
1593 | this.compiledValues = [];
1594 | this.cardCast = [];
1595 |
1596 | this.BaseballCard = 0;
1597 |
1598 | this.actualJokers = this.jokers.map(a => a.slice());
1599 |
1600 | // resolve jokers that are card but not joker order agnostic
1601 | for(let j = 0; j < this.jokers.length; j++) {
1602 | const joker = this.jokers[j];
1603 |
1604 | this.compiledValues.push(0);
1605 | this.jokerRarities.push(jokerRarity[this.actualJokers[j][JOKER]]);
1606 |
1607 | if(joker[JOKER_DISABLED]) continue;
1608 |
1609 | let resolved = false;
1610 | switch(joker[JOKER]) {
1611 | case 30:
1612 | // resolve Blueprint
1613 | if(j + 1 < this.jokers.length) {
1614 | let at = j + 1;
1615 | let t = 0;
1616 | while(!resolved && t++ < this.jokers.length) {
1617 | switch(this.jokers[at][JOKER]) {
1618 | case 30:
1619 | if(at + 1 < this.jokers.length) {
1620 | at++;
1621 | }
1622 | break;
1623 | case 77:
1624 | if(at !== 0 && this.jokers[0][0] !== 77) {
1625 | at = 0;
1626 | }
1627 | break;
1628 | default:
1629 | resolved = true;
1630 | }
1631 | }
1632 | if(resolved) {
1633 | this.jokers[j][JOKER] = this.jokers[at][JOKER];
1634 | this.jokers[j][VALUE] = this.jokers[at][VALUE];
1635 | this.jokers[j][JOKER_DISABLED] = this.jokers[at][JOKER_DISABLED];
1636 | this.cardCast[j] = at;
1637 | j--;
1638 | this.compiledValues.pop();
1639 | this.jokerRarities.pop();
1640 | }
1641 | }
1642 | break;
1643 | case 59:
1644 | // resolve Swashbuckler
1645 | for(let k = 0; k < this.jokers.length; k++) {
1646 | if(k == j){
1647 | continue;
1648 | }
1649 | this.compiledValues[j] += this.jokers[k][SELL_VALUE];
1650 | }
1651 | break;
1652 | case 77:
1653 | // resolve Brainstorm
1654 | if(j > 0 && this.jokers[0][0] !== 77) {
1655 | let at = 0;
1656 | let t = 0;
1657 | while(!resolved && t++ < this.jokers.length) {
1658 | switch(this.jokers[at][JOKER]) {
1659 | case 30:
1660 | if(at + 1 < this.jokers.length) {
1661 | at++;
1662 | }
1663 | break;
1664 | case 77:
1665 | if(at !== 0 && this.jokers[0][0] !== 77) {
1666 | at = 0;
1667 | }
1668 | break;
1669 | default:
1670 | resolved = true;
1671 | }
1672 | }
1673 | if(resolved) {
1674 | this.jokers[j][JOKER] = this.jokers[at][JOKER];
1675 | this.jokers[j][VALUE] = this.jokers[at][VALUE];
1676 | this.jokers[j][JOKER_DISABLED] = this.jokers[at][JOKER_DISABLED];
1677 | this.cardCast[j] = at;
1678 | j--;
1679 | this.compiledValues.pop();
1680 | this.jokerRarities.pop();
1681 | }
1682 | }
1683 | break;
1684 | case 146:
1685 | // Baseball Card
1686 | this.BaseballCard++;
1687 | break;
1688 | }
1689 | }
1690 | }
1691 |
1692 | // knowledge of jokers, not joker order or cards-played
1693 | compileJokers() {
1694 | // set standard values; probability modifier (Oops! All 6s), vampire, etc.
1695 |
1696 | // set global variables' default values
1697 | this.actualCardsInHand = [];
1698 |
1699 | this.chanceMultiplier = 1;
1700 |
1701 | this.FourFingers = false;
1702 | this.Shortcut = false;
1703 | this.Pareidolia = false;
1704 | this.SmearedJoker = false;
1705 |
1706 | this.RaisedFist = false;
1707 | this.Splash = false;
1708 | this.MidasMaskas = false;
1709 |
1710 | this.hasVampire = false;
1711 |
1712 | // resolve joker global effects that are card and joker order agnostic
1713 | for(let j = 0; j < this.jokers.length; j++) {
1714 | const joker = this.jokers[j];
1715 | if(joker[JOKER_DISABLED]) continue;
1716 | switch(joker[JOKER]) {
1717 | case 28:
1718 | this.RaisedFist = true;
1719 | break;
1720 | case 36:
1721 | this.Pareidolia = true;
1722 | break;
1723 | case 64:
1724 | this.SmearedJoker = true;
1725 | break;
1726 | case 65:
1727 | this.chanceMultiplier *= 2;
1728 | break;
1729 | case 66:
1730 | this.FourFingers = true;
1731 | break;
1732 | case 106:
1733 | this.Splash = true;
1734 | break;
1735 | case 122:
1736 | this.hasVampire = true;
1737 | break;
1738 | case 123:
1739 | this.Shortcut = true;
1740 | break;
1741 | case 130:
1742 | this.MidasMaskas = true;
1743 | break;
1744 | }
1745 | }
1746 | }
1747 |
1748 | compileAll() {
1749 | this.compileJokers();
1750 | this.compileJokerOrder();
1751 | this.compileCards();
1752 | }
1753 |
1754 | // simulate what wasn't compiled
1755 | simulate() {
1756 | this.chips = this.compiledChips;
1757 | this.mult = [this.compiledMult[0], this.compiledMult[1]];
1758 | this.jokersExtraValue = [];
1759 |
1760 | if(this.TheEye && this.hands[this.typeOfHand][PLAYED_THIS_ROUND]) {
1761 | return [1, -10, 0, [0,0]];
1762 | }
1763 |
1764 | for(let j = 0; j < this.jokers.length; j++) {
1765 | this.jokersExtraValue.push(0);
1766 | }
1767 |
1768 | // score cards
1769 | for(let c = 0; c < this.cards.length; c++) {
1770 | const card = this.cards[c];
1771 | card[EXTRA_EXTRA_CHIPS] = 0;
1772 |
1773 | if(card[ENHANCEMENT] === STONE || this.involvedCards.indexOf(card) >= 0) {
1774 | this.triggerCard(card);
1775 | }
1776 | else {
1777 | for(let j = 0; j < this.jokers.length; j++) {
1778 | const joker = this.jokers[j];
1779 | if(joker[JOKER_DISABLED]) continue;
1780 | switch(joker[JOKER]) {
1781 | // Hanging Chad
1782 | case 69:
1783 | this.jokersExtraValue[j]++;
1784 | break;
1785 | }
1786 | }
1787 | }
1788 | }
1789 |
1790 | // score cards-in-hand
1791 | this.mult = bigBigTimes(this.compiledInHandTimesMult, this.mult);
1792 | this.mult = bigBigAdd(this.compiledInHandPlusMult, this.mult);
1793 |
1794 | // score jokers
1795 | for(let j = 0; j < this.jokers.length; j++) {
1796 | this.triggerJoker(this.jokers[j], j);
1797 |
1798 | if(this.BaseballCard && this.jokerRarities[j] === 2 && !this.jokers[j][JOKER_DISABLED]) {
1799 | for(let i = 0; i < this.BaseballCard; i++) {
1800 | this.mult = bigTimes(1.5, this.mult);
1801 | }
1802 | }
1803 | }
1804 |
1805 | // Observatory
1806 | if(this.Observatory) {
1807 | const ObservatoryScore = this.hands[this.typeOfHand][PLANETS];
1808 | this.mult = bigTimes(1.5 ** ObservatoryScore, this.mult);
1809 | }
1810 |
1811 | if(this.PlasmaDeck) {
1812 | this.mult = bigAdd(this.chips, this.mult);
1813 | this.mult = bigTimes(0.5, this.mult);
1814 |
1815 | if(this.mult[1] === 0) {
1816 | this.mult[0] = Math.floor(this.mult[0]);
1817 | }
1818 | return [...normalizeBig(bigBigTimes(this.mult, this.mult)), normalizeBig(this.mult), normalizeBig(this.mult)];
1819 | }
1820 |
1821 | return [...normalizeBig(bigTimes(this.chips, this.mult)), this.chips, normalizeBig(this.mult)];
1822 | }
1823 |
1824 | simulateBestHand() {
1825 | this.randomMode = 0;
1826 | return this.simulate();
1827 | }
1828 |
1829 | simulateWorstHand() {
1830 | this.randomMode = 1;
1831 | return this.simulate();
1832 | }
1833 |
1834 | simulateRandomHand() {
1835 | this.randomMode = 2;
1836 | return this.simulate();
1837 | }
1838 | };
1839 |
--------------------------------------------------------------------------------