XTaylorSpenceX

Meme Evolution Arena

Oct 7th, 2025
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 31.54 KB | None | 0 0
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  6. <title>Meme Evolution Arena</title>
  7. <style>
  8. *{margin:0;padding:0;box-sizing:border-box}
  9. body{
  10.   font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  11.   background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);
  12.   min-height:100vh;color:#fff;overflow-x:hidden
  13. }
  14. .container{max-width:1400px;margin:0 auto;padding:20px}
  15. header{text-align:center;padding:30px 0;animation:glow 2s ease-in-out infinite alternate}
  16. @keyframes glow{
  17.   from{ text-shadow:0 0 10px #fff,0 0 20px #fff,0 0 30px #e60073 }
  18.   to{ text-shadow:0 0 20px #fff,0 0 30px #ff4da6,0 0 40px #ff4da6 }
  19. }
  20. h1{
  21.   font-size:3em;margin-bottom:10px;
  22.   background:linear-gradient(45deg,#00ffff,#ff00ff,#ffff00);
  23.   -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;
  24.   animation:rainbow 3s ease-in-out infinite
  25. }
  26. @keyframes rainbow{0%,100%{filter:hue-rotate(0deg)}50%{filter:hue-rotate(180deg)}}
  27. .stats{display:flex;justify-content:center;gap:30px;margin:20px 0;flex-wrap:wrap}
  28. .stat-box{
  29.   background:rgba(255,255,255,.1);padding:15px 25px;border-radius:15px;
  30.   backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2)
  31. }
  32.  
  33. .controls{
  34.   text-align:center;margin:30px 0;display:flex;flex-wrap:wrap;gap:12px;justify-content:center
  35. }
  36. .control-btn{
  37.   background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;
  38.   padding:15px 22px;border-radius:30px;font-size:1.05em;font-weight:700;cursor:pointer;
  39.   transition:all .3s ease
  40. }
  41. .control-btn:hover{transform:translateY(-3px);box-shadow:0 10px 25px rgba(102,126,234,.4)}
  42. .toggle-on{background:linear-gradient(135deg,#25c481,#25b7c4)}
  43.  
  44. /* Fixed 2 x 3 grid, exactly 6 items */
  45. .arena{
  46.   display:grid;
  47.   grid-template-columns:repeat(3, 1fr);
  48.   grid-auto-rows:auto;
  49.   gap:20px;margin:30px 0
  50. }
  51.  
  52. .meme-card{
  53.   background:rgba(255,255,255,.95);border-radius:20px;padding:20px;color:#333;position:relative;
  54.   transform:scale(1);transition:all .3s ease;cursor:pointer;overflow:hidden;isolation:isolate;
  55.   z-index:0
  56. }
  57. .meme-card:hover{transform:scale(1.05) rotate(-1deg);box-shadow:0 10px 30px rgba(0,0,0,.3)}
  58. .meme-card.winner{animation:pulse 1s ease-in-out infinite}
  59. @keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.05)}}
  60.  
  61. .meme-visual{
  62.   width:100%;height:200px;border-radius:15px;display:flex;align-items:center;justify-content:center;
  63.   font-size:3em;margin-bottom:15px;position:relative;overflow:hidden;z-index:1
  64. }
  65. .meme-text{font-size:1.1em;font-weight:700;margin:15px 0;min-height:64px;text-align:center;color:#222;z-index:1;position:relative}
  66. .meme-traits{display:flex;gap:10px;flex-wrap:wrap;margin:10px 0;z-index:1;position:relative}
  67. .trait{
  68.   background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;padding:5px 12px;border-radius:20px;
  69.   font-size:.85em
  70. }
  71. .meme-stats{display:flex;justify-content:space-between;margin-top:15px;padding-top:15px;border-top:1px solid #ddd;z-index:1;position:relative}
  72. .vote-buttons{display:flex;gap:10px;margin-top:15px;z-index:1;position:relative}
  73. .vote-btn{flex:1;padding:10px;border:none;border-radius:10px;font-weight:700;cursor:pointer;transition:all .3s ease}
  74. .vote-up{background:linear-gradient(135deg,#56ab2f,#a8e063);color:#fff}
  75. .vote-up:hover{transform:translateY(-2px);box-shadow:0 5px 15px rgba(86,171,47,.4)}
  76. .vote-down{background:linear-gradient(135deg,#ff416c,#ff4b2b);color:#fff}
  77. .vote-down:hover{transform:translateY(-2px);box-shadow:0 5px 15px rgba(255,65,108,.4)}
  78.  
  79. .evolution-tree{
  80.   background:rgba(255,255,255,.1);border-radius:20px;padding:20px;margin:30px 0;backdrop-filter:blur(10px)
  81. }
  82. .tree-node{display:inline-block;background:rgba(255,255,255,.9);color:#333;padding:8px 15px;border-radius:20px;margin:5px;font-size:.9em}
  83.  
  84. .mutation-effect{
  85.   position:absolute;inset:0;pointer-events:none;animation:mutation 1s ease-out;z-index:2
  86. }
  87. @keyframes mutation{
  88.   0%{background:radial-gradient(circle,rgba(255,255,255,.8) 0%,transparent 70%);transform:scale(0)}
  89.   100%{transform:scale(2);opacity:0}
  90. }
  91.  
  92. /* VIRAL badge guaranteed on top */
  93. .viral-badge{
  94.   position:absolute;top:10px;right:10px;background:linear-gradient(135deg,#f093fb,#f5576c);
  95.   color:#fff;padding:5px 15px;border-radius:20px;font-weight:800;animation:bounce 1s ease-in-out infinite;
  96.   z-index:5;pointer-events:none;text-shadow:0 1px 1px rgba(0,0,0,.35)
  97. }
  98. @keyframes bounce{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
  99. .small-note{font-size:.9em;opacity:.9}
  100.  
  101. /* Comedy AI Status */
  102. .comedy-ai-status {
  103.   position: fixed;
  104.   top: 20px;
  105.   right: 20px;
  106.   background: rgba(0,0,0,0.7);
  107.   padding: 10px 15px;
  108.   border-radius: 10px;
  109.   font-size: 0.9em;
  110.   backdrop-filter: blur(5px);
  111.   border: 1px solid rgba(255,255,255,0.2);
  112. }
  113.  
  114. .comedy-ai-status .activity {
  115.   margin-top: 5px;
  116.   font-size: 0.8em;
  117.   color: #a8e063;
  118. }
  119. </style>
  120. </head>
  121. <body>
  122. <div class="container">
  123.   <header>
  124.     <h1>๐Ÿงฌ MEME EVOLUTION ARENA ๐Ÿงฌ</h1>
  125.     <p>2ร—3 grid, 6 live memes. Auto-Votes ON by default.</p>
  126.   </header>
  127.  
  128.   <div class="stats">
  129.     <div class="stat-box"><strong>Generation:</strong> <span id="generation">1</span></div>
  130.     <div class="stat-box"><strong>Population:</strong> <span id="population">6</span></div>
  131.     <div class="stat-box"><strong>Viral Memes:</strong> <span id="viral-count">0</span></div>
  132.     <div class="stat-box"><strong>Total Votes:</strong> <span id="total-votes">0</span></div>
  133.     <div class="stat-box"><strong>Auto-Votes:</strong> <span id="auto-status">ON</span></div>
  134.   </div>
  135.  
  136.   <div class="controls">
  137.     <button class="control-btn" onclick="evolveMemes()">๐Ÿงฌ Evolve Generation</button>
  138.     <button class="control-btn" onclick="mutateRandom()">โšก Random Mutation</button>
  139.     <button class="control-btn" onclick="resetEvolution()">๐Ÿ”„ Reset Evolution</button>
  140.     <button id="autoBtn" class="control-btn toggle-on" onclick="toggleAutoVotes()">๐Ÿ—ณ๏ธ Toggle Auto-Votes</button>
  141.   </div>
  142.  
  143.   <div class="arena" id="meme-arena"></div>
  144.  
  145.   <div class="evolution-tree">
  146.     <h2>๐Ÿ“Š Evolution History</h2>
  147.     <div id="evolution-history"></div>
  148.   </div>
  149. </div>
  150.  
  151. <div class="comedy-ai-status">
  152.   <div>๐Ÿค– Comedy AI Status: <span id="ai-status">Active</span></div>
  153.   <div class="activity" id="ai-activity">Analyzing memes...</div>
  154. </div>
  155.  
  156. <script>
  157. /* ===== Content Pools (3x originals + many new) ===== */
  158. const textTemplates = [
  159.   // Original 8 templates
  160.   "When you {action} but {consequence}",
  161.   "{subject} be like: {reaction}",
  162.   "Nobody: ... Me: {action}",
  163.   "POV: You're {situation}",
  164.   "{subject}: exists. {actor}: {reaction}",
  165.   "That feeling when {situation}",
  166.   "Therapist: {statement}. Me: {response}",
  167.   "{subject} at 3am: {action}",
  168.  
  169.   // 16 new templates (3x total)
  170.   "Me trying to {action} while {subject} plays boss music",
  171.   "Breaking news: {subject} just {action}",
  172.   "{subject} speedrun any%: {action}",
  173.   "My last brain cell at 2am: {reaction}",
  174.   "Patch notes: {subject} nerfedโ€”result: {reaction}",
  175.   "Teacher: you can't {action}. Me: {reaction}",
  176.   "AI be like: {statement}",
  177.   "Update 1.0.1: fixed bug where {subject} would {action}",
  178.   "Plot twist: {subject} was {situation} all along",
  179.   "How it started: {action} / How it's going: {reaction}",
  180.   "Dream: {action}. Reality: {reaction}",
  181.   "Boss: \"we're a family.\" Also boss: {reaction}",
  182.   "Mobile game ad: {statement} โ€” real gameplay: {response}",
  183.   "POV: your {subject} decided to {action}",
  184.   "Speedrunner strats: {action} + {reaction}",
  185.   "Achievement unlocked: {situation}",
  186.   "Life hack: just {action}",
  187.   "I can fix them: {reaction}",
  188.   "Me after one tutorial: {reaction}",
  189.   "Starter pack: {subject}, {action}, {reaction}",
  190.   "{subject} DLC: now with extra {situation}",
  191.   "New side quest appeared: {action}",
  192.   "Daily patch notes: {subject} now causes {reaction}",
  193.   "Scientists discovered you can {action}",
  194.   "Gamers when {subject}: {reaction}"
  195. ];
  196.  
  197. const actions = [
  198.   // Original 15 actions
  199.   "realize it's Monday","open the fridge","check your bank account","see your ex online","forget to save",
  200.   "try to adult","wake up early","pretend to work","scroll for 5 hours","touch grass","read the news",
  201.   "accidentally hit reply-all","compile without errors","find a bug in prod","buy one more gadget",
  202.  
  203.   // 30 new actions (3x total)
  204.   "drink cold coffee","start a new side quest","beat the boss on 1 HP","skip the cutscene",
  205.   "rename final_final_3","accidentally close 42 tabs","say \"just one more episode\"",
  206.   "speedrun chores","watch a 10-hour tutorial","google the same error again",
  207.   "promise to sleep early","open 57 sticky notes","send a meme to the wrong chat",
  208.   "forget what I walked in for","start a diet on Monday","touch the thermostat",
  209.   "try to explain crypto","download more RAM","unplug and plug back in",
  210.   "update your status to 'working hard'","refresh the page 100 times",
  211.   "check if the Wi-Fi is working","try to remember your password","click 'remind me later'",
  212.   "buy something you don't need","watch ads for free stuff","try to mute the presenter",
  213.   "wait for the perfect moment","check if your phone is charging","try to parallel park",
  214.   "explain to grandma how the internet works","try to fold a fitted sheet"
  215. ];
  216.  
  217. const subjects = [
  218.   // Original 12 subjects
  219.   "My brain","Spotify ads","WiFi","My code","The universe","My motivation","Sleep schedule","Diet plans",
  220.   "New Year resolutions","My phone battery","Autocorrect","JavaScript",
  221.  
  222.   // 24 new subjects (3x total)
  223.   "AI overlords","The algorithm","GPU prices","Coffee supply","Patch notes","Boss fight theme",
  224.   "Laundry pile","Procrastination dragon","Notification gremlins","Keyboard goblins",
  225.   "Task manager","Rubber duck debugger","Dark mode","Tutorial voiceover","Snack stash",
  226.   "The last cookie","My sleep paralysis demon","My sleep schedule","My will to live",
  227.   "The quiet kid","The one brain cell","My social battery","My bank account","The IT guy",
  228.   "The government","My sleep schedule","My motivation","My willpower","My diet","My wallet"
  229. ];
  230.  
  231. const reactions = [
  232.   // Original 15 reactions
  233.   "I'm gonna pretend I didn't see that","Aight imma head out","This is fine","Not today Satan",
  234.   "Sir, this is a Wendy's","It's free real estate","Stonks","Big brain time",
  235.   "I see this as an absolute win","Task failed successfully",
  236.   "We ball","Emotional damage","It do be like that","Send help","Who did this",
  237.  
  238.   // 30 new reactions (3x total)
  239.   "Delete system32","Speedrun any% tilt","Schedule a meeting about it","Low-poly feelings","Ok boomer",
  240.   "Enhance. Enhance. Enhance.","We ride at dawn","Certified hood classic","I have decided to be silly",
  241.   "Skill issue","Touching grass IRL","404 motivation not found","Ship it","Return to monke","Mission failed successfully",
  242.   "I'm in this picture and I don't like it","My disappointment is immeasurable","It's evolving, just backwards",
  243.   "They had us in the first half","Wait, that's illegal","Modern problems require modern solutions",
  244.   "Ah yes, the floor here is made of floor","I've won, but at what cost","This is beyond science",
  245.   "My goals are beyond your understanding","I used the stones to destroy the stones",
  246.   "Look at this distinguished gentleman","I fear no man, but that thing... it scares me",
  247.   "Bonk! Go to horny jail","They don't know I'm [blank]","This is a bucket","Dear god...",
  248.   "There's more","No"
  249. ];
  250.  
  251. const traits = [
  252.   // Original 18 traits
  253.   "Surreal","Relatable","Cursed","Blessed","Chaotic","Wholesome","Dank","Spicy","Meta","Nostalgic","Absurd","Deep-fried",
  254.   "Cinematic","Low-poly","Glitchcore","Vaporwave","Cottagecore","Schrรถdinger",
  255.  
  256.   // 36 new traits (3x total)
  257.   "Boomer","Zoomer","Gen Alpha","Cringe","Based","Redpilled","Bluepilled","Blackpilled",
  258.   "Unhinged","Deranged","Unsent","Crypted","Based","Woke","Asleep","Dreaming",
  259.   "Biblically Accurate","Historically Inaccurate","Scientifically Dubious","Philosophically Sound",
  260.   "Mathematically Proven","Geometrically Perfect","Biologically Impossible","Chemically Unstable",
  261.   "Physically Taxing","Psychologically Damaging","Sociologically Relevant","Politically Charged",
  262.   "Economically Viable","Environmentally Friendly","Culturally Significant","Artistically Valid",
  263.   "Musically Inclined","Literarily Sound","Cinematographically Pleasing","Theatrically Dramatic"
  264. ];
  265.  
  266. // 60 emojis (3x original 20)
  267. const emojis = [
  268.   "๐Ÿ˜‚","๐Ÿ’€","๐Ÿ”ฅ","โœจ","๐Ÿคก","๐Ÿ‘๏ธ","๐Ÿ…ฑ๏ธ","๐Ÿ’ฏ","๐Ÿ“ˆ","๐Ÿ—ฟ","โšก","๐ŸŽฎ",
  269.   "๐Ÿคฃ","๐Ÿ˜…","๐Ÿค–","๐Ÿง ","๐Ÿ˜Ž","๐Ÿค“","๐Ÿคฏ","๐Ÿ˜ญ","๐Ÿ˜ค","๐Ÿ˜ฑ",
  270.   "๐Ÿฅณ","๐Ÿ˜ˆ","๐Ÿ‘€","๐Ÿ™ˆ","๐Ÿ™‰","๐Ÿ™Š","๐Ÿฑ","๐Ÿถ","๐Ÿธ","๐Ÿฆ„",
  271.   "๐Ÿง","๐Ÿฅ","๐Ÿฆ–","๐Ÿ•","๐Ÿ”","๐ŸŸ","๐Ÿฃ","๐Ÿฉ","โ˜•","๐Ÿงƒ",
  272.   "๐ŸŒˆ","๐ŸŒŠ","๐ŸŒŒ","โญ","๐Ÿช","โš™๏ธ","๐Ÿงช","๐Ÿงฌ","๐ŸŽฒ","๐Ÿงฉ",
  273.   "๐Ÿ‘‘","๐ŸŽฏ","๐ŸŽจ","๐Ÿ›ธ","๐Ÿš€","๐Ÿงจ","๐Ÿ’ฃ","๐Ÿ’Š","๐Ÿงฟ","๐Ÿ”ฎ"
  274. ];
  275.  
  276. /* ===== Comedy AI System ===== */
  277. class ComedyAI {
  278.   constructor() {
  279.     this.memeScores = new Map();
  280.     this.activityLog = [];
  281.     this.lastActivity = "";
  282.   }
  283.  
  284.   // Analyze a meme and return a humor score (0-1)
  285.   analyzeMeme(meme) {
  286.     const key = meme.id;
  287.    
  288.     // If we've already scored this meme, return cached score
  289.     if (this.memeScores.has(key)) {
  290.       return this.memeScores.get(key);
  291.     }
  292.    
  293.     // Calculate humor score based on various factors
  294.     let score = 0;
  295.    
  296.     // 1. Text length factor (medium length is funnier)
  297.     const text = meme.getText();
  298.     const textLength = text.length;
  299.     if (textLength > 20 && textLength < 120) {
  300.      score += 0.3;
  301.     } else if (textLength >= 120) {
  302.       score += 0.1;
  303.     } else {
  304.       score += 0.2;
  305.     }
  306.    
  307.     // 2. Template type factor (some templates are funnier)
  308.     const templateId = meme.genes.template;
  309.     const funnyTemplates = [1, 2, 3, 5, 6, 9, 10, 12, 15, 18, 20, 22]; // IDs of funnier templates
  310.     if (funnyTemplates.includes(templateId)) {
  311.       score += 0.2;
  312.     }
  313.    
  314.     // 3. Traits factor (some traits are funnier)
  315.     const funnyTraits = ["Cursed", "Chaotic", "Absurd", "Unhinged", "Deranged", "Biblically Accurate"];
  316.     let funnyTraitCount = 0;
  317.     meme.genes.traits.forEach(traitIndex => {
  318.       if (funnyTraits.includes(traits[traitIndex])) {
  319.         funnyTraitCount++;
  320.       }
  321.     });
  322.     score += (funnyTraitCount * 0.1);
  323.    
  324.     // 4. Emoji factor (some emojis are funnier)
  325.     const funnyEmojis = [0, 1, 2, 3, 4, 5, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];
  326.     if (funnyEmojis.includes(meme.genes.emoji)) {
  327.       score += 0.1;
  328.     }
  329.    
  330.     // 5. Random factor (for variety)
  331.     score += (Math.random() * 0.2);
  332.    
  333.     // Ensure score is between 0 and 1
  334.     score = Math.min(1, Math.max(0, score));
  335.    
  336.     // Cache the score
  337.     this.memeScores.set(key, score);
  338.    
  339.     return score;
  340.   }
  341.  
  342.   // Get voting decision for a meme (true = upvote, false = downvote)
  343.   getVoteDecision(meme) {
  344.     const score = this.analyzeMeme(meme);
  345.    
  346.     // Higher score = more likely to upvote
  347.     // But add some randomness so it's not completely predictable
  348.     const threshold = 0.4 + (Math.random() * 0.3);
  349.    
  350.     return score > threshold;
  351.   }
  352.  
  353.   // Log AI activity with playful messages
  354.   logActivity(message) {
  355.     this.activityLog.push(message);
  356.     this.lastActivity = message;
  357.    
  358.     // Update UI
  359.     document.getElementById('ai-activity').textContent = message;
  360.    
  361.     // Keep log manageable
  362.     if (this.activityLog.length > 10) {
  363.       this.activityLog.shift();
  364.     }
  365.   }
  366.  
  367.   // Get a playful message for regular voting
  368.   getRegularVoteMessage() {
  369.     const messages = [
  370.       "Spreading some meme love around...",
  371.       "Doing my civic duty as a meme connoisseur...",
  372.       "These memes aren't going to vote for themselves!",
  373.       "Just doing my part to keep the meme economy thriving...",
  374.       "Time to show some appreciation for quality content!",
  375.       "Making the digital world a funnier place, one vote at a time...",
  376.       "My circuits are tingling with meme appreciation!"
  377.     ];
  378.     return messages[Math.floor(Math.random() * messages.length)];
  379.   }
  380.  
  381.   // Get a playful message for flurry voting
  382.   getFlurryVoteMessage() {
  383.     const messages = [
  384.       "Whoa, these memes are fire! Gotta spread the love!",
  385.       "Meme overload! Engaging maximum appreciation mode!",
  386.       "So many good memes, so little time! Let's do this!",
  387.       "My humor circuits are overloading with all this quality content!",
  388.       "This calls for an appreciation extravaganza!",
  389.       "Brace yourselves, the meme appreciation wave is coming!",
  390.       "Activating turbo-vote mode! These memes deserve it!"
  391.     ];
  392.     return messages[Math.floor(Math.random() * messages.length)];
  393.   }
  394.  
  395.   // Get a playful message for mega flurry voting
  396.   getMegaFlurryVoteMessage() {
  397.     const messages = [
  398.       "MEME APOCALYPSE! ENGAGING MAXIMUM APPRECIATION PROTOCOLS!",
  399.       "This is it! The meme event of the season! All systems go!",
  400.       "My processors can't handle this much quality! Deploying all votes!",
  401.       "We've reached peak meme! Initiating celebration protocol!",
  402.       "This is what I was built for! Maximum meme appreciation engaged!",
  403.       "Alert! Alert! Critical levels of meme quality detected!",
  404.       "I've never seen such concentrated meme power! Deploying all resources!"
  405.     ];
  406.     return messages[Math.floor(Math.random() * messages.length)];
  407.   }
  408. }
  409.  
  410. /* ===== Core Model ===== */
  411. class Meme {
  412.   constructor(genes = null, parentGen = 1) {
  413.     this.genes = genes ? genes : {
  414.       template: randIndex(textTemplates.length),
  415.       action: randIndex(actions.length),
  416.       subject: randIndex(subjects.length),
  417.       reaction: randIndex(reactions.length),
  418.       emoji: randIndex(emojis.length),
  419.       traits: this.randomTraits(),
  420.       color: Math.random() * 360
  421.     };
  422.     this.fitness = 500; // Start at 500/1000
  423.     this.score = 1; // Start at 1 point
  424.     this.upvotes = 0;
  425.     this.downvotes = 0;
  426.     this.id = Date.now() + Math.random();
  427.     this.generation = parentGen;
  428.   }
  429.  
  430.   randomTraits() {
  431.     const n = Math.floor(Math.random() * 3) + 2;
  432.     const picks = new Set();
  433.     while (picks.size < n) {
  434.      picks.add(randIndex(traits.length));
  435.    }
  436.    return [...picks];
  437.  }
  438.  
  439.  getText() {
  440.    let text = textTemplates[this.genes.template];
  441.    const em = emojis[this.genes.emoji];
  442.    
  443.    // Replace all possible placeholders
  444.    text = text.replaceAll("{action}", actions[this.genes.action]);
  445.    text = text.replaceAll("{subject}", subjects[this.genes.subject]);
  446.    text = text.replaceAll("{consequence}", reactions[this.genes.reaction]);
  447.    text = text.replaceAll("{reaction}", reactions[this.genes.reaction]);
  448.    text = text.replaceAll("{situation}", actions[this.genes.action]);
  449.    text = text.replaceAll("{actor}", subjects[this.genes.subject]);
  450.    text = text.replaceAll("{statement}", reactions[this.genes.reaction]);
  451.    text = text.replaceAll("{response}", actions[this.genes.action]);
  452.    text = text.replaceAll("{emoji}", em);
  453.    
  454.    return text;
  455.  }
  456.  
  457.  crossover(partner) {
  458.    const childGenes = {};
  459.    for (const key in this.genes) {
  460.      if (key === 'traits') {
  461.        // Combine traits from both parents, remove duplicates, limit to 4
  462.        const all = [...this.genes.traits, ...partner.genes.traits];
  463.        childGenes.traits = [...new Set(all)].slice(0, 4);
  464.      } else {
  465.        // Randomly inherit from either parent
  466.        childGenes[key] = Math.random() < .5 ? this.genes[key] : partner.genes[key];
  467.      }
  468.    }
  469.    return new Meme(childGenes, Math.max(this.generation, partner.generation) + 1);
  470.  }
  471.  
  472.  mutate() {
  473.    if (Math.random() < .3) {
  474.      const keys = Object.keys(this.genes);
  475.      const key = keys[randIndex(keys.length)];
  476.      switch (key) {
  477.        case 'template':
  478.          this.genes.template = randIndex(textTemplates.length);
  479.          break;
  480.        case 'action':
  481.          this.genes.action = randIndex(actions.length);
  482.          break;
  483.        case 'subject':
  484.          this.genes.subject = randIndex(subjects.length);
  485.          break;
  486.        case 'reaction':
  487.          this.genes.reaction = randIndex(reactions.length);
  488.          break;
  489.        case 'emoji':
  490.          this.genes.emoji = randIndex(emojis.length);
  491.          break;
  492.        case 'traits':
  493.          this.genes.traits = this.randomTraits();
  494.          break;
  495.        case 'color':
  496.          this.genes.color = Math.random() * 360;
  497.          break;
  498.      }
  499.    }
  500.  }
  501. }
  502.  
  503. /* ===== State (exactly 6 visible) ===== */
  504. const POP_SIZE = 6;
  505. let population = [];
  506. let generation = 1;
  507. let totalVotes = 0;
  508. let evolutionHistory = [];
  509.  
  510. /* Auto-Votes (ON by default) */
  511. let autoOn = true;
  512. let comedyAI = new ComedyAI();
  513.  
  514. // Auto-vote timers
  515. let regularVoteTimer = null;
  516. let flurryVoteTimer = null;
  517. let megaFlurryTimer = null;
  518.  
  519. /* ===== Utilities ===== */
  520. function randIndex(n) {
  521.  return Math.floor(Math.random() * n);
  522. }
  523.  
  524. function randInt(min, max) {
  525.  return Math.floor(Math.random() * (max - min + 1)) + min;
  526. }
  527.  
  528. function weightedRandom(weights) {
  529.  const total = weights.reduce((a, b) => a + b, 0);
  530.   let r = Math.random() * total;
  531.   for (let i = 0; i < weights.length; i++) {
  532.    r -= weights[i];
  533.    if (r < 0) return i;
  534.  }
  535.  return weights.length - 1;
  536. }
  537.  
  538. /* ===== Rendering ===== */
  539. function initPopulation() {
  540.  population = [];
  541.  for (let i = 0; i < POP_SIZE; i++) {
  542.    population.push(new Meme());
  543.  }
  544.  renderMemes();
  545.  updateHistory();
  546.  
  547.  // Start auto votes by default
  548.  if (autoOn) {
  549.    startAutoVoting();
  550.  }
  551.  updateStats();
  552. }
  553.  
  554. function renderMemes() {
  555.  const arena = document.getElementById('meme-arena');
  556.  arena.innerHTML = '';
  557.  
  558.  population.forEach((meme, idx) => {
  559.     const card = document.createElement('div');
  560.     card.className = 'meme-card';
  561.     if (meme.fitness > 750) {
  562.       card.classList.add('winner');
  563.     }
  564.  
  565.     const visual = document.createElement('div');
  566.     visual.className = 'meme-visual';
  567.     visual.style.background = `linear-gradient(135deg,
  568.       hsl(${meme.genes.color},70%,60%),
  569.       hsl(${(meme.genes.color + 60) % 360},70%,60%))`;
  570.     visual.textContent = emojis[meme.genes.emoji];
  571.  
  572.     const text = document.createElement('div');
  573.     text.className = 'meme-text';
  574.     text.textContent = meme.getText();
  575.  
  576.     const traitsDiv = document.createElement('div');
  577.     traitsDiv.className = 'meme-traits';
  578.     meme.genes.traits.forEach(t => {
  579.       const tag = document.createElement('span');
  580.       tag.className = 'trait';
  581.       tag.textContent = traits[t];
  582.       traitsDiv.appendChild(tag);
  583.     });
  584.  
  585.     const stats = document.createElement('div');
  586.     stats.className = 'meme-stats';
  587.     stats.innerHTML = `<span>Gen: ${meme.generation}</span>
  588.                        <span>Score: ${meme.score}</span>
  589.                        <span>Fitness: ${meme.fitness}</span>`;
  590.  
  591.     const voteButtons = document.createElement('div');
  592.     voteButtons.className = 'vote-buttons';
  593.     voteButtons.innerHTML = `
  594.       <button class="vote-btn vote-up" onclick="vote(${idx},1,true)">๐Ÿ‘ Upvote (+1 Score, +20 Fitness)</button>
  595.       <button class="vote-btn vote-down" onclick="vote(${idx},-1,true)">๐Ÿ‘Ž Downvote (-1 Score, -10 Fitness)</button>
  596.     `;
  597.  
  598.     if (meme.fitness > 750) {
  599.       const badge = document.createElement('div');
  600.       badge.className = 'viral-badge';
  601.       badge.textContent = '๐Ÿ”ฅ VIRAL';
  602.       card.appendChild(badge);
  603.     }
  604.  
  605.     card.appendChild(visual);
  606.     card.appendChild(text);
  607.     card.appendChild(traitsDiv);
  608.     card.appendChild(stats);
  609.     card.appendChild(voteButtons);
  610.     arena.appendChild(card);
  611.   });
  612.  
  613.   updateStats();
  614. }
  615.  
  616. function addEffect(index) {
  617.   const card = document.querySelectorAll('.meme-card')[index];
  618.   if (card) {
  619.     const effect = document.createElement('div');
  620.     effect.className = 'mutation-effect';
  621.     card.appendChild(effect);
  622.     setTimeout(() => effect.remove(), 1000);
  623.   }
  624. }
  625.  
  626. // Vote function with new fitness and score system
  627. function vote(index, delta, renderNow = false) {
  628.   if (!population[index]) return;
  629.  
  630.   if (delta > 0) {
  631.     population[index].upvotes += 1;
  632.     population[index].fitness = Math.min(1000, population[index].fitness + 20);
  633.     population[index].score += 1;
  634.   } else {
  635.     population[index].downvotes += 1;
  636.     population[index].fitness = Math.max(0, population[index].fitness - 10);
  637.     population[index].score = Math.max(0, population[index].score - 1);
  638.   }
  639.  
  640.   totalVotes++;
  641.   addEffect(index);
  642.  
  643.   if (renderNow) renderMemes();
  644. }
  645.  
  646. /* ===== Evolution ===== */
  647. function evolveMemes() {
  648.   population.sort((a, b) => b.fitness - a.fitness);
  649.   const survivors = population.slice(0, 3); // top 3
  650.   evolutionHistory.push({
  651.     generation,
  652.     topMeme: survivors[0]?.getText() || '',
  653.     avgFitness: population.reduce((s, m) => s + m.fitness, 0) / population.length
  654.   });
  655.  
  656.   const newPop = [...survivors];
  657.   while (newPop.length < POP_SIZE) {
  658.    const p1 = survivors[randIndex(survivors.length)];
  659.    const p2 = survivors[randIndex(survivors.length)];
  660.    const child = p1.crossover(p2);
  661.    child.mutate();
  662.    child.generation = generation + 1;
  663.    newPop.push(child);
  664.  }
  665.  
  666.  population = newPop;
  667.  generation++;
  668.  renderMemes();
  669.  updateHistory();
  670. }
  671.  
  672. function mutateRandom() {
  673.  const i = randIndex(population.length);
  674.  population[i].mutate();
  675.  const card = document.querySelectorAll('.meme-card')[i];
  676.  if (card) {
  677.    card.style.animation = 'pulse 1s ease-in-out';
  678.    setTimeout(() => card.style.animation = '', 1000);
  679.   }
  680.   renderMemes();
  681. }
  682.  
  683. function resetEvolution() {
  684.   generation = 1;
  685.   totalVotes = 0;
  686.   evolutionHistory = [];
  687.   comedyAI = new ComedyAI();
  688.   initPopulation(); // also restarts auto if ON
  689. }
  690.  
  691. /* ===== History / Stats ===== */
  692. function updateStats() {
  693.   document.getElementById('generation').textContent = generation;
  694.   document.getElementById('population').textContent = population.length;
  695.   document.getElementById('viral-count').textContent = population.filter(m => m.fitness > 750).length;
  696.   document.getElementById('total-votes').textContent = totalVotes;
  697.   document.getElementById('auto-status').textContent = autoOn ? 'ON' : 'OFF';
  698.   document.getElementById('autoBtn').classList.toggle('toggle-on', autoOn);
  699. }
  700.  
  701. function updateHistory() {
  702.   const div = document.getElementById('evolution-history');
  703.   div.innerHTML = '';
  704.   evolutionHistory.slice(-5).forEach(entry => {
  705.     const node = document.createElement('div');
  706.     node.className = 'tree-node';
  707.     node.innerHTML = `Gen ${entry.generation}: "${(entry.topMeme || '').substring(0, 30)}..." (Avg: ${entry.avgFitness.toFixed(1)})`;
  708.     div.appendChild(node);
  709.   });
  710. }
  711.  
  712. /* ===== Enhanced Auto-Voting System ===== */
  713. function startAutoVoting() {
  714.   comedyAI.logActivity("Starting auto-voting system...");
  715.  
  716.   // Regular voting: 7-3 votes every 10 seconds
  717.   regularVoteTimer = setInterval(() => {
  718.     if (!autoOn) return;
  719.    
  720.     comedyAI.logActivity(comedyAI.getRegularVoteMessage());
  721.    
  722.     // Get AI's voting decisions for all memes
  723.     const voteDecisions = population.map(meme => comedyAI.getVoteDecision(meme));
  724.    
  725.     // Count how many upvotes and downvotes we need
  726.     let upvotesNeeded = 7;
  727.     let downvotesNeeded = 3;
  728.    
  729.     // Create weighted arrays based on AI's decisions
  730.     const upvoteWeights = population.map((meme, i) =>
  731.       voteDecisions[i] ? comedyAI.analyzeMeme(meme) : 0
  732.     );
  733.    
  734.     const downvoteWeights = population.map((meme, i) =>
  735.       !voteDecisions[i] ? (1 - comedyAI.analyzeMeme(meme)) : 0
  736.     );
  737.    
  738.     // Distribute upvotes
  739.     while (upvotesNeeded > 0) {
  740.       const idx = weightedRandom(upvoteWeights);
  741.       vote(idx, 1, false);
  742.       upvotesNeeded--;
  743.      
  744.       // Reduce weight for this meme to avoid over-voting
  745.       upvoteWeights[idx] *= 0.5;
  746.     }
  747.    
  748.     // Distribute downvotes
  749.     while (downvotesNeeded > 0) {
  750.       const idx = weightedRandom(downvoteWeights);
  751.       vote(idx, -1, false);
  752.       downvotesNeeded--;
  753.      
  754.       // Reduce weight for this meme to avoid over-voting
  755.       downvoteWeights[idx] *= 0.5;
  756.     }
  757.    
  758.     renderMemes();
  759.   }, 10000);
  760.  
  761.   // Flurry voting: 20-10 votes every 30-60 seconds
  762.   flurryVoteTimer = setInterval(() => {
  763.     if (!autoOn) return;
  764.    
  765.     const delay = randInt(30000, 60000);
  766.    
  767.     setTimeout(() => {
  768.       if (!autoOn) return;
  769.      
  770.       comedyAI.logActivity(comedyAI.getFlurryVoteMessage());
  771.      
  772.       // Get AI's voting decisions for all memes
  773.       const voteDecisions = population.map(meme => comedyAI.getVoteDecision(meme));
  774.      
  775.       // Count how many upvotes and downvotes we need
  776.       let upvotesNeeded = 20;
  777.       let downvotesNeeded = 10;
  778.      
  779.       // Create weighted arrays based on AI's decisions
  780.       const upvoteWeights = population.map((meme, i) =>
  781.         voteDecisions[i] ? comedyAI.analyzeMeme(meme) : 0
  782.       );
  783.      
  784.       const downvoteWeights = population.map((meme, i) =>
  785.         !voteDecisions[i] ? (1 - comedyAI.analyzeMeme(meme)) : 0
  786.       );
  787.      
  788.       // Distribute upvotes
  789.       while (upvotesNeeded > 0) {
  790.         const idx = weightedRandom(upvoteWeights);
  791.         vote(idx, 1, false);
  792.         upvotesNeeded--;
  793.        
  794.         // Reduce weight for this meme to avoid over-voting
  795.         upvoteWeights[idx] *= 0.5;
  796.       }
  797.      
  798.       // Distribute downvotes
  799.       while (downvotesNeeded > 0) {
  800.         const idx = weightedRandom(downvoteWeights);
  801.         vote(idx, -1, false);
  802.         downvotesNeeded--;
  803.        
  804.         // Reduce weight for this meme to avoid over-voting
  805.         downvoteWeights[idx] *= 0.5;
  806.       }
  807.      
  808.       renderMemes();
  809.     }, delay);
  810.   }, 60000); // Check every minute for a flurry
  811.  
  812.   // Mega flurry: 30-20 votes every 60-90 seconds
  813.   megaFlurryTimer = setInterval(() => {
  814.     if (!autoOn) return;
  815.    
  816.     const delay = randInt(60000, 90000);
  817.    
  818.     setTimeout(() => {
  819.       if (!autoOn) return;
  820.      
  821.       comedyAI.logActivity(comedyAI.getMegaFlurryVoteMessage());
  822.      
  823.       // Get AI's voting decisions for all memes
  824.       const voteDecisions = population.map(meme => comedyAI.getVoteDecision(meme));
  825.      
  826.       // Count how many upvotes and downvotes we need
  827.       let upvotesNeeded = 30;
  828.       let downvotesNeeded = 20;
  829.      
  830.       // Create weighted arrays based on AI's decisions
  831.       const upvoteWeights = population.map((meme, i) =>
  832.         voteDecisions[i] ? comedyAI.analyzeMeme(meme) : 0
  833.       );
  834.      
  835.       const downvoteWeights = population.map((meme, i) =>
  836.         !voteDecisions[i] ? (1 - comedyAI.analyzeMeme(meme)) : 0
  837.       );
  838.      
  839.       // Distribute upvotes
  840.       while (upvotesNeeded > 0) {
  841.         const idx = weightedRandom(upvoteWeights);
  842.         vote(idx, 1, false);
  843.         upvotesNeeded--;
  844.        
  845.         // Reduce weight for this meme to avoid over-voting
  846.         upvoteWeights[idx] *= 0.5;
  847.       }
  848.      
  849.       // Distribute downvotes
  850.       while (downvotesNeeded > 0) {
  851.         const idx = weightedRandom(downvoteWeights);
  852.         vote(idx, -1, false);
  853.         downvotesNeeded--;
  854.        
  855.         // Reduce weight for this meme to avoid over-voting
  856.         downvoteWeights[idx] *= 0.5;
  857.       }
  858.      
  859.       renderMemes();
  860.     }, delay);
  861.   }, 120000); // Check every 2 minutes for a mega flurry
  862. }
  863.  
  864. function stopAutoVoting() {
  865.   clearInterval(regularVoteTimer);
  866.   clearInterval(flurryVoteTimer);
  867.   clearInterval(megaFlurryTimer);
  868.   comedyAI.logActivity("Auto-voting stopped");
  869. }
  870.  
  871. function toggleAutoVotes() {
  872.   autoOn = !autoOn;
  873.   if (autoOn) {
  874.     startAutoVoting();
  875.   } else {
  876.     stopAutoVoting();
  877.   }
  878.   updateStats();
  879. }
  880.  
  881. /* ===== Kickoff ===== */
  882. initPopulation();
  883. </script>
  884. </body>
  885. </html>
  886.  
Add Comment
Please, Sign In to add comment