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.