PageSourceSearch

https://swallja.art/swalljasgambit.js?v=1.0

js swallja.art collected 2026-10-08 07:40:41 UTC 20,146 bytes, 759 lines download raw bytes

1
2$(document).ready(function() {
3  // Initialize game state variables
4  let player = { class: "", score: { Risk: 0, Reward: 0, Stability: 0 }, rounds: [] };
5  let classes = {
6    Banker: { initialScore: { Risk: -2, Reward: 0, Stability: 2 } },
7    Pepe: { initialScore: { Risk: 2, Reward: 2, Stability: -2 } },
8    Wojak: { initialScore: { Risk: -1, Reward: -1, Stability: 3 } }
9  };
10  let cards = [
11    {
12      title: "Buy Bitcoin",
13      effect: {
14        Risk: 2,
15        Reward: 2,
16        Stability: -1
17      }
18    },
19    {
20      title: "Sell Bitcoin",
21      effect: {
22        Risk: -2,
23        Reward: 0,
24        Stability: 1
25      }
26    },
27    {
28      title: "Buy into a Shitcoin Hype",
29      effect: {
30        Risk: 3,
31        Reward: 5,
32        Stability: -5
33      }
34    },
35    {
36      title: "Buy Gold (lmao)",
37      effect: {
38        Risk: -1,
39        Reward: -1,
40        Stability: 3
41      }
42    },
43    {
44      title: "Donate to a Cause",
45      effect: {
46        Risk: 0,
47        Reward: 2,
48        Stability: 1
49      }
50    },
51    {
52      title: "Invest in a Shady ICO",
53      effect: {
54        Risk: 4,
55        Reward: 5,
56        Stability: -5
57      }
58    },
59    {
60      title: "Get Involved in Crypto Twitter Drama",
61      effect: {
62        Risk: 2,
63        Reward: 0,
64        Stability: -3
65      }
66    },
67    {
68      title: "Start a Blockchain Startup",
69      effect: {
70        Risk: 4,
71        Reward: 4,
72        Stability: -3
73      }
74    },
75    {
76      title: "Get Married to a Crypto Skeptic",
77      effect: {
78        Risk: 1,
79        Reward: 0,
80        Stability: -1
81      }
82    },
83    {
84      title: "Invite Satoshi Nakamoto to a Family BBQ",
85      effect: {
86        Risk: -2,
87        Reward: 3,
88        Stability: 2
89      }
90    },
91    {
92      title: "Be the Keynote Speaker at a Blockchain Conference",
93      effect: {
94        Risk: 0,
95        Reward: 2,
96        Stability: 1
97      }
98    },
99    {
100      title: "Join a DAO",
101      effect: {
102        Risk: 1,
103        Reward: 1,
104        Stability: 0
105      }
106    },
107    {
108      title: "Take a Hike, Leave Crypto Behind",
109      effect: {
110        Risk: -3,
111        Reward: -3,
112        Stability: 5
113      }
114    },
115    {
116      title: "Face a Scam Accusation",
117      effect: {
118        Risk: 4,
119        Reward: -4,
120        Stability: -5
121      }
122    },
123    {
124      title: "Get Doxxed",
125      effect: {
126        Risk: 5,
127        Reward: -2,
128        Stability: -5
129      }
130    },
131    {
132      title: "Have a Romantic Dinner with Vitalik Buterin",
133      effect: {
134        Risk: -1,
135        Reward: 4,
136        Stability: 1
137      }
138    },
139    {
140      title: "Start a Meme Coin",
141      effect: {
142        Risk: 3,
143        Reward: 5,
144        Stability: -3
145      }
146    },
147    {
148      title: "Go to Therapy for Crypto Addiction",
149      effect: {
150        Risk: -1,
151        Reward: -1,
152        Stability: 7
153      }
154    },
155    {
156      title: "The SEC Chair Follows You on Twitter",
157      effect: {
158        Risk: 3,
159        Reward: 2,
160        Stability: -3
161      }
162    },
163    {
164      title: "Create a Pepe the Frog NFT",
165      effect: {
166        Risk: 1,
167        Reward: 7,
168        Stability: -1
169      }
170    },
171    {
172      title: "Elon Musk Retweet",
173      effect: {
174        Risk: 2,
175        Reward: 5,
176        Stability: -3
177      }
178    },
179    {
180      title: "Create Anon Troll Account",
181      effect: {
182        Risk: 0,
183        Reward: -2,
184        Stability: -1
185      }
186    },
187    {
188      title: "Name Your Pet 'Wojak' ",
189      effect: {
190        Risk: 1,
191        Reward: 1,
192        Stability: -1
193      }
194    },
195    {
196      title: "Touch Grass",
197      effect: {
198        Risk: -2,
199        Reward: 0,
200        Stability: 4
201      }
202    },
203    {
204      title: "Start a Yoga Routine for Better Trade Discipline",
205      effect: {
206        Risk: -2,
207        Reward: 2,
208        Stability: 3
209      }
210    },
211    {
212      title: "Start Blog About Crypto Ethics",
213      effect: {
214        Risk: 0,
215        Reward: 1,
216        Stability: 1
217      }
218    },
219    {
220      title: "Fall in Love with an AI",
221      effect: {
222        Risk: 1,
223        Reward: 3,
224        Stability: -2
225      }
226    },
227    {
228      title: "Do Nothing",
229      effect: {
230        Risk: 0,
231        Reward: 0,
232        Stability: 1
233      }
234    },
235    {
236      title: "Become a Spokesperson for an L2",
237      effect: {
238        Risk: -1,
239        Reward: 1,
240        Stability: 3
241      }
242    },
243    {
244      title: "Give Away All Your Crypto in a Fit of Existential Despair",
245      effect: {
246        Risk: -5,
247        Reward: -5,
248        Stability: 0
249      }
250    },
251    {
252      title: "Start a Nihilistic Crypto Philosophy Blog",
253      effect: {
254        Risk: 3,
255        Reward: 1,
256        Stability: -1
257      }
258    },
259    {
260      title: "Announce You Are Leaving Social Media",
261      effect: {
262        Risk: 0,
263        Reward: 0,
264        Stability: 0
265      }
266    },
267    {
268      title: "Accidentally Send 10 BTC to a Scam Address",
269      effect: {
270        Risk: 5,
271        Reward: -5,
272        Stability: -5
273      }
274    },
275    {
276      title: "Fall in Love with an anon",
277      effect: {
278        Risk: 4,
279        Reward: 0,
280        Stability: -2
281      }
282    },
283    {
284      title: "Have a Heated Argument About Crypto at Thanksgiving",
285      effect: {
286        Risk: 2,
287        Reward: -2,
288        Stability: -2
289      }
290    },
291    {
292      title: "Move Back in with Your Parents",
293      effect: {
294        Risk: 3,
295        Reward: -2,
296        Stability: 1
297      }
298    },
299    {
300      title: "Oops, got CANCELLED",
301      effect: {
302        Risk: 1,
303        Reward: -5,
304        Stability: -3
305      }
306    },
307    {
308      title: "Start a Crypto Fund with Your Inheritance",
309      effect: {
310        Risk: 4,
311        Reward: 3,
312        Stability: -2
313      }
314    },
315    {
316      title: "Convince Your Partner to Go 50/50 in a Shitcoin",
317      effect: {
318        Risk: 5,
319        Reward: 5,
320        Stability: -3
321      }
322    },
323    {
324      title: "Have a Mid-Crypto-Life Crisis",
325      effect: {
326        Risk: 3,
327        Reward: -3,
328        Stability: -3
329      }
330    },
331    {
332      title: "Quit Your Day Job to Become a Full-Time Crypto Artist",
333      effect: {
334        Risk: 4,
335        Reward: 2,
336        Stability: -4
337      }
338    },
339    {
340      title: "Reject All Material Possessions, Including Crypto",
341      effect: {
342        Risk: -5,
343        Reward: -5,
344        Stability: 5
345      }
346    }
347  ];
348
349  let currentCards = [];
350  let gameRound = 0;
351  let maxRounds = 10;
352  let heartbeatInterval;
353  let countdownInterval;
354  let gamesPlayed = 0;
355  let diceLeft = 10; // 10 dice for 10 decisions
356
357  // Audio elements and Web Audio API
358  let gameMusic = document.getElementById("game-music");
359  let audioContext;
360  let isAudioInitialized = false;
361
362  // Initialize Web Audio API
363  function initAudio() {
364    if (!isAudioInitialized) {
365      audioContext = new (window.AudioContext || window.webkitAudioContext)();
366      isAudioInitialized = true;
367    }
368  }
369
370  // Sound effect functions using Web Audio API
371  function playClickSound() {
372    if (!audioContext) return;
373
374    const oscillator = audioContext.createOscillator();
375    const gainNode = audioContext.createGain();
376
377    oscillator.connect(gainNode);
378    gainNode.connect(audioContext.destination);
379
380    oscillator.frequency.setValueAtTime(800, audioContext.currentTime);
381    oscillator.frequency.exponentialRampToValueAtTime(400, audioContext.currentTime + 0.1);
382
383    gainNode.gain.setValueAtTime(0.3, audioContext.currentTime);
384    gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.1);
385
386    oscillator.start(audioContext.currentTime);
387    oscillator.stop(audioContext.currentTime + 0.1);
388  }
389
390  function startHeartbeat() {
391    // Calculate time for this round (10, 9, 8, ... down to 1)
392    let currentTimeLimit = Math.max(1, 11 - gameRound);
393    let timeLeft = currentTimeLimit * 1000; // Convert to milliseconds
394    let startTime = Date.now();
395
396    $('#rollDice').addClass('time-bomb-active');
397    $('#gameContainer').addClass('noise-active');
398
399    // Update timer display every 50ms for smooth countdown
400    heartbeatInterval = setInterval(() => {
401      let elapsed = Date.now() - startTime;
402      timeLeft = Math.max(0, (currentTimeLimit * 1000) - elapsed);
403
404      // Update button text with millisecond precision
405      let seconds = Math.floor(timeLeft / 1000);
406      let milliseconds = timeLeft % 1000;
407      $('#rollDice').text(`ROLL DICE (${seconds}.${milliseconds.toString().padStart(3, '0')}s)`);
408
409      // Update visual intensity based on time left
410      let intensity = 1 - (timeLeft / (currentTimeLimit * 1000));
411      $('#rollDice').css('--time-intensity', intensity);
412
413      // Pulse the heart icon
414      $('#heartIcon').animate({fontSize: '28px'}, 100).animate({fontSize: '24px'}, 100);
415
416      // Play heartbeat sound with increasing frequency as time runs out
417      if (audioContext && timeLeft % 500 === 0) { // Every half second
418        const oscillator = audioContext.createOscillator();
419        const gainNode = audioContext.createGain();
420
421        oscillator.connect(gainNode);
422        gainNode.connect(audioContext.destination);
423
424        let frequency = 60 + (intensity * 40); // Increases as time runs out
425        oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime);
426        oscillator.frequency.exponentialRampToValueAtTime(frequency + 20, audioContext.currentTime + 0.1);
427
428        gainNode.gain.setValueAtTime(0.2, audioContext.currentTime);
429        gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + 0.2);
430
431        oscillator.start(audioContext.currentTime);
432        oscillator.stop(audioContext.currentTime + 0.2);
433      }
434
435      if (timeLeft <= 0) {
436        // Time's up! Force a random choice
437        clearInterval(heartbeatInterval);
438        $('#rollDice').removeClass('time-bomb-active').css('--time-intensity', 0).text('TIME FORCED YOUR HAND');
439        $('#gameContainer').removeClass('noise-active');
440
441        // Apply guaranteed risk cost for not rolling dice
442        player.score.Risk += 3;
443        $('#gameOutput').append(`<p><span class="risk-text">+3 Risk</span> penalty for not rolling dice!</p>`);
444
445        // Show the message on button for 2 seconds
446        setTimeout(() => {
447          // Force random card choice
448          let randomCard = Math.floor(Math.random() * 2);
449          chooseCard(randomCard);
450        }, 2000);
451      }
452    }, 50);
453  }
454
455  function stopHeartbeat() {
456    if (heartbeatInterval) {
457      clearInterval(heartbeatInterval);
458    }
459    $('#rollDice').removeClass('time-bomb-active').css('--time-intensity', 0).text('ROLL DICE FOR NEXT DECISION');
460    $('#gameContainer').removeClass('noise-active');
461  }
462
463  // Add click sound to all buttons
464  $('button').on('click', playClickSound);
465
466  // Define a function to handle the initialization of the game
467  function initializeGame() {
468    $('#startGame').click(function() {
469      initAudio();
470      playClickSound();
471      $(this).hide();
472      $('#classChoice').show();
473
474      // Start background music
475      if (gameMusic) {
476        gameMusic.volume = 0.5;
477        gameMusic.play().catch(e => console.log('Game music failed:', e));
478      }
479    });
480
481    $('#classBanker, #classPepe, #classWojak').click(function() {
482      playClickSound();
483      let chosenClass = $(this).attr('id').replace('class', '');
484      startGame(chosenClass);
485    });
486
487    $('#card1, #card2').click(function() {
488      playClickSound();
489      let cardIndex = $(this).is('#card1') ? 0 : 1;
490      chooseCard(cardIndex);
491    });
492
493    $('#rollDice').click(function() {
494      playClickSound();
495      rollDice();
496    });
497
498    // Play Again button click
499    $('#playAgain').click(function() {
500      playClickSound();
501      resetGame();
502    });
503  }
504
505  function startGame(chosenClass) {
506    player.class = chosenClass;
507    player.score = { ...classes[chosenClass].initialScore };
508    player.rounds = [];
509    gameRound = 0;
510    diceLeft = 10; // Reset to 10 dice for 10 decisions
511
512    $('#classChoice').hide();
513    $('#gameOutput').html(`<p>Welcome, ${chosenClass}! Your journey begins...</p>`);
514
515    updateDisplay();
516    playRound();
517  }
518
519  function playRound() {
520    if (gameRound >= maxRounds) {
521      endGame();
522      return;
523    }
524
525    gameRound++;
526
527    // Select two random cards
528    currentCards = [];
529    let usedIndices = [];
530
531    for (let i = 0; i < 2; i++) {
532      let randomIndex;
533      do {
534        randomIndex = Math.floor(Math.random() * cards.length);
535      } while (usedIndices.includes(randomIndex));
536
537      usedIndices.push(randomIndex);
538      currentCards.push(cards[randomIndex]);
539    }
540
541    // Display cards
542    $('#card1').text(currentCards[0].title);
543    $('#card2').text(currentCards[1].title);
544    $('#cardChoice').show();
545    $('#rollDice').hide();
546
547    $('#gameOutput').append(`<p><strong>Round ${gameRound}:</strong> Choose your path...</p>`);
548  }
549
550  function chooseCard(cardIndex) {
551    let chosenCard = currentCards[cardIndex];
552
553    // Apply card effects
554    player.score.Risk += chosenCard.effect.Risk;
555    player.score.Reward += chosenCard.effect.Reward;
556    player.score.Stability += chosenCard.effect.Stability;
557
558    player.rounds.push({
559      round: gameRound,
560      card: chosenCard.title,
561      effect: chosenCard.effect
562    });
563
564    $('#gameOutput').append(`<p>You chose: ${chosenCard.title}</p>`);
565
566    // Format effect with colors
567    let effectText = `<p>Effect: `;
568    effectText += `<span class="risk-text">Risk ${chosenCard.effect.Risk >= 0 ? '+' : ''}${chosenCard.effect.Risk}</span>, `;
569    effectText += `<span class="reward-text">Reward ${chosenCard.effect.Reward >= 0 ? '+' : ''}${chosenCard.effect.Reward}</span>, `;
570    effectText += `<span class="stability-text">Stability ${chosenCard.effect.Stability >= 0 ? '+' : ''}${chosenCard.effect.Stability}</span>`;
571    effectText += `</p>`;
572
573    $('#gameOutput').append(effectText);
574
575    $('#cardChoice').hide();
576    $('#rollDice').show();
577
578    updateDisplay();
579
580    // Start heartbeat when dice is available
581    startHeartbeat();
582  }
583
584  function rollDice() {
585    if (diceLeft <= 0) {
586      $('#gameOutput').append(`<p><span class="risk-text">No dice left!</span></p>`);
587      return;
588    }
589
590    // Prevent multiple clicks and disable button
591    stopHeartbeat();
592    $('#rollDice').prop('disabled', true).text('LOADING DECISIONS...');
593
594    // Use one die
595    diceLeft--;
596    updateDiceDisplay();
597
598    let diceRoll = Math.floor(Math.random() * 6) + 1;
599
600    // Apply dice modifier with higher scale
601    let riskModifier = Math.round((diceRoll - 3.5) * 1.0); // -3 to +3 for higher impact
602    player.score.Risk += riskModifier;
603
604    let diceText = `<p>Dice rolled: ${diceRoll} `;
605    if (riskModifier !== 0) {
606      diceText += `(<span class="risk-text">Risk ${riskModifier >= 0 ? '+' : ''}${riskModifier}</span>)`;
607    } else {
608      diceText += `(No modifier)`;
609    }
610    diceText += `</p>`;
611
612    $('#gameOutput').append(diceText);
613    $('#gameOutput').append(`<p>---</p>`);
614
615    updateDisplay();
616
617    // Re-enable button and continue
618    setTimeout(() => {
619      $('#rollDice').prop('disabled', false).text('ROLL DICE FOR NEXT DECISION');
620      playRound();
621    }, 1500);
622  }
623
624  function updateDisplay() {
625    // Update score display with color coding
626    let scoreHtml = `<span class="risk-text">Risk: ${player.score.Risk}</span> `;
627    scoreHtml += `<span class="reward-text">Reward: ${player.score.Reward}</span> `;
628    scoreHtml += `<span class="stability-text">Stability: ${player.score.Stability}</span>`;
629    $('#scoreDisplay').html(scoreHtml);
630
631    // Auto-scroll game output to bottom
632    $('#gameOutput').scrollTop($('#gameOutput')[0].scrollHeight);
633  }
634
635  function updateDiceDisplay() {
636    let diceDisplay = '';
637    for (let i = 0; i < diceLeft; i++) {
638      diceDisplay += '🎲';
639    }
640    $('#diceDisplay').html(diceDisplay);
641  }
642
643  function generateNarrativeSummary() {
644    let narrative = `As a ${player.class}, your journey through the crypto chaos was `;
645
646    // Analyze the journey based on scores and decisions
647    let riskLevel = player.score.Risk;
648    let rewardLevel = player.score.Reward;
649    let stabilityLevel = player.score.Stability;
650
651    // Count decision types
652    let riskCount = 0, rewardCount = 0, stabilityCount = 0;
653    player.rounds.forEach(round => {
654      if (round.effect.Risk > round.effect.Reward && round.effect.Risk > round.effect.Stability) riskCount++;
655      else if (round.effect.Reward > round.effect.Risk && round.effect.Reward > round.effect.Stability) rewardCount++;
656      else stabilityCount++;
657    });
658
659    // Generate personality assessment
660    if (riskCount > rewardCount && riskCount > stabilityCount) {
661      narrative += "defined by bold, dangerous moves. You lived on the edge, ";
662    } else if (rewardCount > riskCount && rewardCount > stabilityCount) {
663      narrative += "focused on maximum gains. You chased the rewards, ";
664    } else {
665      narrative += "marked by cautious, steady choices. You played it safe, ";
666    }
667
668    // Add outcome context
669    if (riskLevel > 8) {
670      narrative += "embracing chaos until it nearly consumed you. ";
671    } else if (riskLevel < -3) {
672      narrative += "avoiding danger at every turn. ";
673    } else {
674      narrative += "balancing on the knife's edge. ";
675    }
676
677    if (rewardLevel > 10) {
678      narrative += "Your hunger for profit knew no bounds. ";
679    } else if (rewardLevel < -5) {
680      narrative += "Wealth slipped through your fingers like sand. ";
681    }
682
683    if (stabilityLevel > 8) {
684      narrative += "Through it all, you maintained your composure like a zen master.";
685    } else if (stabilityLevel < -8) {
686      narrative += "Stability became a foreign concept as chaos reigned supreme.";
687    }
688
689    // Add philosophical ending based on class and outcome
690    if (player.class === "Pepe") {
691      narrative += " The memes chose their champion well.";
692    } else if (player.class === "Wojak") {
693      narrative += " Your feels guided you through the darkness.";
694    } else if (player.class === "Banker") {
695      narrative += " Traditional wisdom met digital revolution.";
696    }
697
698    return narrative;
699  }
700
701  function endGame() {
702    stopHeartbeat();
703
704    // Increment games played for timer progression
705    gamesPlayed++;
706
707    let totalScore = player.score.Risk + player.score.Reward + player.score.Stability;
708    let outcome = '';
709
710    if (totalScore > 15) {
711      outcome = 'CRYPTO LEGEND! You mastered the gambit!';
712    } else if (totalScore > 5) {
713      outcome = 'Solid player! You survived the crypto chaos.';
714    } else if (totalScore > -5) {
715      outcome = 'Middle ground. Not bad, not great.';
716    } else {
717      outcome = 'REKT! The gambit got the better of you.';
718    }
719
720    let narrativeSummary = generateNarrativeSummary();
721
722    $('#gameOutput').append(`<p><strong>=== GAME OVER ===</strong></p>`);
723    $('#gameOutput').append(`<p>Final Score: ${totalScore}</p>`);
724    $('#gameOutput').append(`<p>${outcome}</p>`);
725    $('#gameOutput').append(`<p>Class: ${player.class}</p>`);
726    $('#gameOutput').append(`<p><strong>Your Journey:</strong></p>`);
727    $('#gameOutput').append(`<p><em>${narrativeSummary}</em></p>`);
728    $('#gameOutput').append(`<p>Thanks for playing Swallja's Gambit!</p>`);
729
730    // Completely hide and disable all game controls
731    $('#rollDice').hide().prop('disabled', true);
732    $('#cardChoice').hide();
733    $('#card1, #card2').prop('disabled', true);
734    $('#playAgain').show();
735  }
736
737  // Reset game state
738  function resetGame() {
739    stopHeartbeat(); // Make sure all timers are stopped
740
741    $('#gameOutput').empty();
742    $('#scoreDisplay').empty();
743    $('#diceDisplay').html('🎲🎲🎲🎲🎲🎲🎲🎲🎲🎲'); // 10 dice emojis
744
745    player = { class: "", score: { Risk: 0, Reward: 0, Stability: 0 }, rounds: [] };
746    gameRound = 0;
747    diceLeft = 10;
748
749    // Re-enable all controls
750    $('#rollDice').prop('disabled', false).text('ROLL DICE FOR NEXT DECISION').removeClass('time-bomb-active');
751    $('#card1, #card2').prop('disabled', false);
752    $('#cardChoice').hide();
753    $('#playAgain').hide();
754    $('#startGame').show();
755  }
756
757  // Call the initializeGame function to set up the event listeners
758  initializeGame();
759});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.