Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
- <title>Meme Evolution Arena</title>
- <style>
- *{margin:0;padding:0;box-sizing:border-box}
- body{
- font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
- background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);
- min-height:100vh;color:#fff;overflow-x:hidden
- }
- .container{max-width:1400px;margin:0 auto;padding:20px}
- header{text-align:center;padding:30px 0;animation:glow 2s ease-in-out infinite alternate}
- @keyframes glow{
- from{ text-shadow:0 0 10px #fff,0 0 20px #fff,0 0 30px #e60073 }
- to{ text-shadow:0 0 20px #fff,0 0 30px #ff4da6,0 0 40px #ff4da6 }
- }
- h1{
- font-size:3em;margin-bottom:10px;
- background:linear-gradient(45deg,#00ffff,#ff00ff,#ffff00);
- -webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent;
- animation:rainbow 3s ease-in-out infinite
- }
- @keyframes rainbow{0%,100%{filter:hue-rotate(0deg)}50%{filter:hue-rotate(180deg)}}
- .stats{display:flex;justify-content:center;gap:30px;margin:20px 0;flex-wrap:wrap}
- .stat-box{
- background:rgba(255,255,255,.1);padding:15px 25px;border-radius:15px;
- backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.2)
- }
- .controls{
- text-align:center;margin:30px 0;display:flex;flex-wrap:wrap;gap:12px;justify-content:center
- }
- .control-btn{
- background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;border:none;
- padding:15px 22px;border-radius:30px;font-size:1.05em;font-weight:700;cursor:pointer;
- transition:all .3s ease
- }
- .control-btn:hover{transform:translateY(-3px);box-shadow:0 10px 25px rgba(102,126,234,.4)}
- .toggle-on{background:linear-gradient(135deg,#25c481,#25b7c4)}
- /* Fixed 2 x 3 grid, exactly 6 items */
- .arena{
- display:grid;
- grid-template-columns:repeat(3, 1fr);
- grid-auto-rows:auto;
- gap:20px;margin:30px 0
- }
- .meme-card{
- background:rgba(255,255,255,.95);border-radius:20px;padding:20px;color:#333;position:relative;
- transform:scale(1);transition:all .3s ease;cursor:pointer;overflow:hidden;isolation:isolate;
- z-index:0
- }
- .meme-card:hover{transform:scale(1.05) rotate(-1deg);box-shadow:0 10px 30px rgba(0,0,0,.3)}
- .meme-card.winner{animation:pulse 1s ease-in-out infinite}
- @keyframes pulse{0%,100%{transform:scale(1)}50%{transform:scale(1.05)}}
- .meme-visual{
- width:100%;height:200px;border-radius:15px;display:flex;align-items:center;justify-content:center;
- font-size:3em;margin-bottom:15px;position:relative;overflow:hidden;z-index:1
- }
- .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}
- .meme-traits{display:flex;gap:10px;flex-wrap:wrap;margin:10px 0;z-index:1;position:relative}
- .trait{
- background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;padding:5px 12px;border-radius:20px;
- font-size:.85em
- }
- .meme-stats{display:flex;justify-content:space-between;margin-top:15px;padding-top:15px;border-top:1px solid #ddd;z-index:1;position:relative}
- .vote-buttons{display:flex;gap:10px;margin-top:15px;z-index:1;position:relative}
- .vote-btn{flex:1;padding:10px;border:none;border-radius:10px;font-weight:700;cursor:pointer;transition:all .3s ease}
- .vote-up{background:linear-gradient(135deg,#56ab2f,#a8e063);color:#fff}
- .vote-up:hover{transform:translateY(-2px);box-shadow:0 5px 15px rgba(86,171,47,.4)}
- .vote-down{background:linear-gradient(135deg,#ff416c,#ff4b2b);color:#fff}
- .vote-down:hover{transform:translateY(-2px);box-shadow:0 5px 15px rgba(255,65,108,.4)}
- .evolution-tree{
- background:rgba(255,255,255,.1);border-radius:20px;padding:20px;margin:30px 0;backdrop-filter:blur(10px)
- }
- .tree-node{display:inline-block;background:rgba(255,255,255,.9);color:#333;padding:8px 15px;border-radius:20px;margin:5px;font-size:.9em}
- .mutation-effect{
- position:absolute;inset:0;pointer-events:none;animation:mutation 1s ease-out;z-index:2
- }
- @keyframes mutation{
- 0%{background:radial-gradient(circle,rgba(255,255,255,.8) 0%,transparent 70%);transform:scale(0)}
- 100%{transform:scale(2);opacity:0}
- }
- /* VIRAL badge guaranteed on top */
- .viral-badge{
- position:absolute;top:10px;right:10px;background:linear-gradient(135deg,#f093fb,#f5576c);
- color:#fff;padding:5px 15px;border-radius:20px;font-weight:800;animation:bounce 1s ease-in-out infinite;
- z-index:5;pointer-events:none;text-shadow:0 1px 1px rgba(0,0,0,.35)
- }
- @keyframes bounce{0%,100%{transform:translateY(0)}50%{transform:translateY(-5px)}}
- .small-note{font-size:.9em;opacity:.9}
- /* Comedy AI Status */
- .comedy-ai-status {
- position: fixed;
- top: 20px;
- right: 20px;
- background: rgba(0,0,0,0.7);
- padding: 10px 15px;
- border-radius: 10px;
- font-size: 0.9em;
- backdrop-filter: blur(5px);
- border: 1px solid rgba(255,255,255,0.2);
- }
- .comedy-ai-status .activity {
- margin-top: 5px;
- font-size: 0.8em;
- color: #a8e063;
- }
- </style>
- </head>
- <body>
- <div class="container">
- <header>
- <h1>๐งฌ MEME EVOLUTION ARENA ๐งฌ</h1>
- <p>2ร3 grid, 6 live memes. Auto-Votes ON by default.</p>
- </header>
- <div class="stats">
- <div class="stat-box"><strong>Generation:</strong> <span id="generation">1</span></div>
- <div class="stat-box"><strong>Population:</strong> <span id="population">6</span></div>
- <div class="stat-box"><strong>Viral Memes:</strong> <span id="viral-count">0</span></div>
- <div class="stat-box"><strong>Total Votes:</strong> <span id="total-votes">0</span></div>
- <div class="stat-box"><strong>Auto-Votes:</strong> <span id="auto-status">ON</span></div>
- </div>
- <div class="controls">
- <button class="control-btn" onclick="evolveMemes()">๐งฌ Evolve Generation</button>
- <button class="control-btn" onclick="mutateRandom()">โก Random Mutation</button>
- <button class="control-btn" onclick="resetEvolution()">๐ Reset Evolution</button>
- <button id="autoBtn" class="control-btn toggle-on" onclick="toggleAutoVotes()">๐ณ๏ธ Toggle Auto-Votes</button>
- </div>
- <div class="arena" id="meme-arena"></div>
- <div class="evolution-tree">
- <h2>๐ Evolution History</h2>
- <div id="evolution-history"></div>
- </div>
- </div>
- <div class="comedy-ai-status">
- <div>๐ค Comedy AI Status: <span id="ai-status">Active</span></div>
- <div class="activity" id="ai-activity">Analyzing memes...</div>
- </div>
- <script>
- /* ===== Content Pools (3x originals + many new) ===== */
- const textTemplates = [
- // Original 8 templates
- "When you {action} but {consequence}",
- "{subject} be like: {reaction}",
- "Nobody: ... Me: {action}",
- "POV: You're {situation}",
- "{subject}: exists. {actor}: {reaction}",
- "That feeling when {situation}",
- "Therapist: {statement}. Me: {response}",
- "{subject} at 3am: {action}",
- // 16 new templates (3x total)
- "Me trying to {action} while {subject} plays boss music",
- "Breaking news: {subject} just {action}",
- "{subject} speedrun any%: {action}",
- "My last brain cell at 2am: {reaction}",
- "Patch notes: {subject} nerfedโresult: {reaction}",
- "Teacher: you can't {action}. Me: {reaction}",
- "AI be like: {statement}",
- "Update 1.0.1: fixed bug where {subject} would {action}",
- "Plot twist: {subject} was {situation} all along",
- "How it started: {action} / How it's going: {reaction}",
- "Dream: {action}. Reality: {reaction}",
- "Boss: \"we're a family.\" Also boss: {reaction}",
- "Mobile game ad: {statement} โ real gameplay: {response}",
- "POV: your {subject} decided to {action}",
- "Speedrunner strats: {action} + {reaction}",
- "Achievement unlocked: {situation}",
- "Life hack: just {action}",
- "I can fix them: {reaction}",
- "Me after one tutorial: {reaction}",
- "Starter pack: {subject}, {action}, {reaction}",
- "{subject} DLC: now with extra {situation}",
- "New side quest appeared: {action}",
- "Daily patch notes: {subject} now causes {reaction}",
- "Scientists discovered you can {action}",
- "Gamers when {subject}: {reaction}"
- ];
- const actions = [
- // Original 15 actions
- "realize it's Monday","open the fridge","check your bank account","see your ex online","forget to save",
- "try to adult","wake up early","pretend to work","scroll for 5 hours","touch grass","read the news",
- "accidentally hit reply-all","compile without errors","find a bug in prod","buy one more gadget",
- // 30 new actions (3x total)
- "drink cold coffee","start a new side quest","beat the boss on 1 HP","skip the cutscene",
- "rename final_final_3","accidentally close 42 tabs","say \"just one more episode\"",
- "speedrun chores","watch a 10-hour tutorial","google the same error again",
- "promise to sleep early","open 57 sticky notes","send a meme to the wrong chat",
- "forget what I walked in for","start a diet on Monday","touch the thermostat",
- "try to explain crypto","download more RAM","unplug and plug back in",
- "update your status to 'working hard'","refresh the page 100 times",
- "check if the Wi-Fi is working","try to remember your password","click 'remind me later'",
- "buy something you don't need","watch ads for free stuff","try to mute the presenter",
- "wait for the perfect moment","check if your phone is charging","try to parallel park",
- "explain to grandma how the internet works","try to fold a fitted sheet"
- ];
- const subjects = [
- // Original 12 subjects
- "My brain","Spotify ads","WiFi","My code","The universe","My motivation","Sleep schedule","Diet plans",
- "New Year resolutions","My phone battery","Autocorrect","JavaScript",
- // 24 new subjects (3x total)
- "AI overlords","The algorithm","GPU prices","Coffee supply","Patch notes","Boss fight theme",
- "Laundry pile","Procrastination dragon","Notification gremlins","Keyboard goblins",
- "Task manager","Rubber duck debugger","Dark mode","Tutorial voiceover","Snack stash",
- "The last cookie","My sleep paralysis demon","My sleep schedule","My will to live",
- "The quiet kid","The one brain cell","My social battery","My bank account","The IT guy",
- "The government","My sleep schedule","My motivation","My willpower","My diet","My wallet"
- ];
- const reactions = [
- // Original 15 reactions
- "I'm gonna pretend I didn't see that","Aight imma head out","This is fine","Not today Satan",
- "Sir, this is a Wendy's","It's free real estate","Stonks","Big brain time",
- "I see this as an absolute win","Task failed successfully",
- "We ball","Emotional damage","It do be like that","Send help","Who did this",
- // 30 new reactions (3x total)
- "Delete system32","Speedrun any% tilt","Schedule a meeting about it","Low-poly feelings","Ok boomer",
- "Enhance. Enhance. Enhance.","We ride at dawn","Certified hood classic","I have decided to be silly",
- "Skill issue","Touching grass IRL","404 motivation not found","Ship it","Return to monke","Mission failed successfully",
- "I'm in this picture and I don't like it","My disappointment is immeasurable","It's evolving, just backwards",
- "They had us in the first half","Wait, that's illegal","Modern problems require modern solutions",
- "Ah yes, the floor here is made of floor","I've won, but at what cost","This is beyond science",
- "My goals are beyond your understanding","I used the stones to destroy the stones",
- "Look at this distinguished gentleman","I fear no man, but that thing... it scares me",
- "Bonk! Go to horny jail","They don't know I'm [blank]","This is a bucket","Dear god...",
- "There's more","No"
- ];
- const traits = [
- // Original 18 traits
- "Surreal","Relatable","Cursed","Blessed","Chaotic","Wholesome","Dank","Spicy","Meta","Nostalgic","Absurd","Deep-fried",
- "Cinematic","Low-poly","Glitchcore","Vaporwave","Cottagecore","Schrรถdinger",
- // 36 new traits (3x total)
- "Boomer","Zoomer","Gen Alpha","Cringe","Based","Redpilled","Bluepilled","Blackpilled",
- "Unhinged","Deranged","Unsent","Crypted","Based","Woke","Asleep","Dreaming",
- "Biblically Accurate","Historically Inaccurate","Scientifically Dubious","Philosophically Sound",
- "Mathematically Proven","Geometrically Perfect","Biologically Impossible","Chemically Unstable",
- "Physically Taxing","Psychologically Damaging","Sociologically Relevant","Politically Charged",
- "Economically Viable","Environmentally Friendly","Culturally Significant","Artistically Valid",
- "Musically Inclined","Literarily Sound","Cinematographically Pleasing","Theatrically Dramatic"
- ];
- // 60 emojis (3x original 20)
- const emojis = [
- "๐","๐","๐ฅ","โจ","๐คก","๐๏ธ","๐ ฑ๏ธ","๐ฏ","๐","๐ฟ","โก","๐ฎ",
- "๐คฃ","๐ ","๐ค","๐ง ","๐","๐ค","๐คฏ","๐ญ","๐ค","๐ฑ",
- "๐ฅณ","๐","๐","๐","๐","๐","๐ฑ","๐ถ","๐ธ","๐ฆ",
- "๐ง","๐ฅ","๐ฆ","๐","๐","๐","๐ฃ","๐ฉ","โ","๐ง",
- "๐","๐","๐","โญ","๐ช","โ๏ธ","๐งช","๐งฌ","๐ฒ","๐งฉ",
- "๐","๐ฏ","๐จ","๐ธ","๐","๐งจ","๐ฃ","๐","๐งฟ","๐ฎ"
- ];
- /* ===== Comedy AI System ===== */
- class ComedyAI {
- constructor() {
- this.memeScores = new Map();
- this.activityLog = [];
- this.lastActivity = "";
- }
- // Analyze a meme and return a humor score (0-1)
- analyzeMeme(meme) {
- const key = meme.id;
- // If we've already scored this meme, return cached score
- if (this.memeScores.has(key)) {
- return this.memeScores.get(key);
- }
- // Calculate humor score based on various factors
- let score = 0;
- // 1. Text length factor (medium length is funnier)
- const text = meme.getText();
- const textLength = text.length;
- if (textLength > 20 && textLength < 120) {
- score += 0.3;
- } else if (textLength >= 120) {
- score += 0.1;
- } else {
- score += 0.2;
- }
- // 2. Template type factor (some templates are funnier)
- const templateId = meme.genes.template;
- const funnyTemplates = [1, 2, 3, 5, 6, 9, 10, 12, 15, 18, 20, 22]; // IDs of funnier templates
- if (funnyTemplates.includes(templateId)) {
- score += 0.2;
- }
- // 3. Traits factor (some traits are funnier)
- const funnyTraits = ["Cursed", "Chaotic", "Absurd", "Unhinged", "Deranged", "Biblically Accurate"];
- let funnyTraitCount = 0;
- meme.genes.traits.forEach(traitIndex => {
- if (funnyTraits.includes(traits[traitIndex])) {
- funnyTraitCount++;
- }
- });
- score += (funnyTraitCount * 0.1);
- // 4. Emoji factor (some emojis are funnier)
- const funnyEmojis = [0, 1, 2, 3, 4, 5, 10, 11, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24];
- if (funnyEmojis.includes(meme.genes.emoji)) {
- score += 0.1;
- }
- // 5. Random factor (for variety)
- score += (Math.random() * 0.2);
- // Ensure score is between 0 and 1
- score = Math.min(1, Math.max(0, score));
- // Cache the score
- this.memeScores.set(key, score);
- return score;
- }
- // Get voting decision for a meme (true = upvote, false = downvote)
- getVoteDecision(meme) {
- const score = this.analyzeMeme(meme);
- // Higher score = more likely to upvote
- // But add some randomness so it's not completely predictable
- const threshold = 0.4 + (Math.random() * 0.3);
- return score > threshold;
- }
- // Log AI activity with playful messages
- logActivity(message) {
- this.activityLog.push(message);
- this.lastActivity = message;
- // Update UI
- document.getElementById('ai-activity').textContent = message;
- // Keep log manageable
- if (this.activityLog.length > 10) {
- this.activityLog.shift();
- }
- }
- // Get a playful message for regular voting
- getRegularVoteMessage() {
- const messages = [
- "Spreading some meme love around...",
- "Doing my civic duty as a meme connoisseur...",
- "These memes aren't going to vote for themselves!",
- "Just doing my part to keep the meme economy thriving...",
- "Time to show some appreciation for quality content!",
- "Making the digital world a funnier place, one vote at a time...",
- "My circuits are tingling with meme appreciation!"
- ];
- return messages[Math.floor(Math.random() * messages.length)];
- }
- // Get a playful message for flurry voting
- getFlurryVoteMessage() {
- const messages = [
- "Whoa, these memes are fire! Gotta spread the love!",
- "Meme overload! Engaging maximum appreciation mode!",
- "So many good memes, so little time! Let's do this!",
- "My humor circuits are overloading with all this quality content!",
- "This calls for an appreciation extravaganza!",
- "Brace yourselves, the meme appreciation wave is coming!",
- "Activating turbo-vote mode! These memes deserve it!"
- ];
- return messages[Math.floor(Math.random() * messages.length)];
- }
- // Get a playful message for mega flurry voting
- getMegaFlurryVoteMessage() {
- const messages = [
- "MEME APOCALYPSE! ENGAGING MAXIMUM APPRECIATION PROTOCOLS!",
- "This is it! The meme event of the season! All systems go!",
- "My processors can't handle this much quality! Deploying all votes!",
- "We've reached peak meme! Initiating celebration protocol!",
- "This is what I was built for! Maximum meme appreciation engaged!",
- "Alert! Alert! Critical levels of meme quality detected!",
- "I've never seen such concentrated meme power! Deploying all resources!"
- ];
- return messages[Math.floor(Math.random() * messages.length)];
- }
- }
- /* ===== Core Model ===== */
- class Meme {
- constructor(genes = null, parentGen = 1) {
- this.genes = genes ? genes : {
- template: randIndex(textTemplates.length),
- action: randIndex(actions.length),
- subject: randIndex(subjects.length),
- reaction: randIndex(reactions.length),
- emoji: randIndex(emojis.length),
- traits: this.randomTraits(),
- color: Math.random() * 360
- };
- this.fitness = 500; // Start at 500/1000
- this.score = 1; // Start at 1 point
- this.upvotes = 0;
- this.downvotes = 0;
- this.id = Date.now() + Math.random();
- this.generation = parentGen;
- }
- randomTraits() {
- const n = Math.floor(Math.random() * 3) + 2;
- const picks = new Set();
- while (picks.size < n) {
- picks.add(randIndex(traits.length));
- }
- return [...picks];
- }
- getText() {
- let text = textTemplates[this.genes.template];
- const em = emojis[this.genes.emoji];
- // Replace all possible placeholders
- text = text.replaceAll("{action}", actions[this.genes.action]);
- text = text.replaceAll("{subject}", subjects[this.genes.subject]);
- text = text.replaceAll("{consequence}", reactions[this.genes.reaction]);
- text = text.replaceAll("{reaction}", reactions[this.genes.reaction]);
- text = text.replaceAll("{situation}", actions[this.genes.action]);
- text = text.replaceAll("{actor}", subjects[this.genes.subject]);
- text = text.replaceAll("{statement}", reactions[this.genes.reaction]);
- text = text.replaceAll("{response}", actions[this.genes.action]);
- text = text.replaceAll("{emoji}", em);
- return text;
- }
- crossover(partner) {
- const childGenes = {};
- for (const key in this.genes) {
- if (key === 'traits') {
- // Combine traits from both parents, remove duplicates, limit to 4
- const all = [...this.genes.traits, ...partner.genes.traits];
- childGenes.traits = [...new Set(all)].slice(0, 4);
- } else {
- // Randomly inherit from either parent
- childGenes[key] = Math.random() < .5 ? this.genes[key] : partner.genes[key];
- }
- }
- return new Meme(childGenes, Math.max(this.generation, partner.generation) + 1);
- }
- mutate() {
- if (Math.random() < .3) {
- const keys = Object.keys(this.genes);
- const key = keys[randIndex(keys.length)];
- switch (key) {
- case 'template':
- this.genes.template = randIndex(textTemplates.length);
- break;
- case 'action':
- this.genes.action = randIndex(actions.length);
- break;
- case 'subject':
- this.genes.subject = randIndex(subjects.length);
- break;
- case 'reaction':
- this.genes.reaction = randIndex(reactions.length);
- break;
- case 'emoji':
- this.genes.emoji = randIndex(emojis.length);
- break;
- case 'traits':
- this.genes.traits = this.randomTraits();
- break;
- case 'color':
- this.genes.color = Math.random() * 360;
- break;
- }
- }
- }
- }
- /* ===== State (exactly 6 visible) ===== */
- const POP_SIZE = 6;
- let population = [];
- let generation = 1;
- let totalVotes = 0;
- let evolutionHistory = [];
- /* Auto-Votes (ON by default) */
- let autoOn = true;
- let comedyAI = new ComedyAI();
- // Auto-vote timers
- let regularVoteTimer = null;
- let flurryVoteTimer = null;
- let megaFlurryTimer = null;
- /* ===== Utilities ===== */
- function randIndex(n) {
- return Math.floor(Math.random() * n);
- }
- function randInt(min, max) {
- return Math.floor(Math.random() * (max - min + 1)) + min;
- }
- function weightedRandom(weights) {
- const total = weights.reduce((a, b) => a + b, 0);
- let r = Math.random() * total;
- for (let i = 0; i < weights.length; i++) {
- r -= weights[i];
- if (r < 0) return i;
- }
- return weights.length - 1;
- }
- /* ===== Rendering ===== */
- function initPopulation() {
- population = [];
- for (let i = 0; i < POP_SIZE; i++) {
- population.push(new Meme());
- }
- renderMemes();
- updateHistory();
- // Start auto votes by default
- if (autoOn) {
- startAutoVoting();
- }
- updateStats();
- }
- function renderMemes() {
- const arena = document.getElementById('meme-arena');
- arena.innerHTML = '';
- population.forEach((meme, idx) => {
- const card = document.createElement('div');
- card.className = 'meme-card';
- if (meme.fitness > 750) {
- card.classList.add('winner');
- }
- const visual = document.createElement('div');
- visual.className = 'meme-visual';
- visual.style.background = `linear-gradient(135deg,
- hsl(${meme.genes.color},70%,60%),
- hsl(${(meme.genes.color + 60) % 360},70%,60%))`;
- visual.textContent = emojis[meme.genes.emoji];
- const text = document.createElement('div');
- text.className = 'meme-text';
- text.textContent = meme.getText();
- const traitsDiv = document.createElement('div');
- traitsDiv.className = 'meme-traits';
- meme.genes.traits.forEach(t => {
- const tag = document.createElement('span');
- tag.className = 'trait';
- tag.textContent = traits[t];
- traitsDiv.appendChild(tag);
- });
- const stats = document.createElement('div');
- stats.className = 'meme-stats';
- stats.innerHTML = `<span>Gen: ${meme.generation}</span>
- <span>Score: ${meme.score}</span>
- <span>Fitness: ${meme.fitness}</span>`;
- const voteButtons = document.createElement('div');
- voteButtons.className = 'vote-buttons';
- voteButtons.innerHTML = `
- <button class="vote-btn vote-up" onclick="vote(${idx},1,true)">๐ Upvote (+1 Score, +20 Fitness)</button>
- <button class="vote-btn vote-down" onclick="vote(${idx},-1,true)">๐ Downvote (-1 Score, -10 Fitness)</button>
- `;
- if (meme.fitness > 750) {
- const badge = document.createElement('div');
- badge.className = 'viral-badge';
- badge.textContent = '๐ฅ VIRAL';
- card.appendChild(badge);
- }
- card.appendChild(visual);
- card.appendChild(text);
- card.appendChild(traitsDiv);
- card.appendChild(stats);
- card.appendChild(voteButtons);
- arena.appendChild(card);
- });
- updateStats();
- }
- function addEffect(index) {
- const card = document.querySelectorAll('.meme-card')[index];
- if (card) {
- const effect = document.createElement('div');
- effect.className = 'mutation-effect';
- card.appendChild(effect);
- setTimeout(() => effect.remove(), 1000);
- }
- }
- // Vote function with new fitness and score system
- function vote(index, delta, renderNow = false) {
- if (!population[index]) return;
- if (delta > 0) {
- population[index].upvotes += 1;
- population[index].fitness = Math.min(1000, population[index].fitness + 20);
- population[index].score += 1;
- } else {
- population[index].downvotes += 1;
- population[index].fitness = Math.max(0, population[index].fitness - 10);
- population[index].score = Math.max(0, population[index].score - 1);
- }
- totalVotes++;
- addEffect(index);
- if (renderNow) renderMemes();
- }
- /* ===== Evolution ===== */
- function evolveMemes() {
- population.sort((a, b) => b.fitness - a.fitness);
- const survivors = population.slice(0, 3); // top 3
- evolutionHistory.push({
- generation,
- topMeme: survivors[0]?.getText() || '',
- avgFitness: population.reduce((s, m) => s + m.fitness, 0) / population.length
- });
- const newPop = [...survivors];
- while (newPop.length < POP_SIZE) {
- const p1 = survivors[randIndex(survivors.length)];
- const p2 = survivors[randIndex(survivors.length)];
- const child = p1.crossover(p2);
- child.mutate();
- child.generation = generation + 1;
- newPop.push(child);
- }
- population = newPop;
- generation++;
- renderMemes();
- updateHistory();
- }
- function mutateRandom() {
- const i = randIndex(population.length);
- population[i].mutate();
- const card = document.querySelectorAll('.meme-card')[i];
- if (card) {
- card.style.animation = 'pulse 1s ease-in-out';
- setTimeout(() => card.style.animation = '', 1000);
- }
- renderMemes();
- }
- function resetEvolution() {
- generation = 1;
- totalVotes = 0;
- evolutionHistory = [];
- comedyAI = new ComedyAI();
- initPopulation(); // also restarts auto if ON
- }
- /* ===== History / Stats ===== */
- function updateStats() {
- document.getElementById('generation').textContent = generation;
- document.getElementById('population').textContent = population.length;
- document.getElementById('viral-count').textContent = population.filter(m => m.fitness > 750).length;
- document.getElementById('total-votes').textContent = totalVotes;
- document.getElementById('auto-status').textContent = autoOn ? 'ON' : 'OFF';
- document.getElementById('autoBtn').classList.toggle('toggle-on', autoOn);
- }
- function updateHistory() {
- const div = document.getElementById('evolution-history');
- div.innerHTML = '';
- evolutionHistory.slice(-5).forEach(entry => {
- const node = document.createElement('div');
- node.className = 'tree-node';
- node.innerHTML = `Gen ${entry.generation}: "${(entry.topMeme || '').substring(0, 30)}..." (Avg: ${entry.avgFitness.toFixed(1)})`;
- div.appendChild(node);
- });
- }
- /* ===== Enhanced Auto-Voting System ===== */
- function startAutoVoting() {
- comedyAI.logActivity("Starting auto-voting system...");
- // Regular voting: 7-3 votes every 10 seconds
- regularVoteTimer = setInterval(() => {
- if (!autoOn) return;
- comedyAI.logActivity(comedyAI.getRegularVoteMessage());
- // Get AI's voting decisions for all memes
- const voteDecisions = population.map(meme => comedyAI.getVoteDecision(meme));
- // Count how many upvotes and downvotes we need
- let upvotesNeeded = 7;
- let downvotesNeeded = 3;
- // Create weighted arrays based on AI's decisions
- const upvoteWeights = population.map((meme, i) =>
- voteDecisions[i] ? comedyAI.analyzeMeme(meme) : 0
- );
- const downvoteWeights = population.map((meme, i) =>
- !voteDecisions[i] ? (1 - comedyAI.analyzeMeme(meme)) : 0
- );
- // Distribute upvotes
- while (upvotesNeeded > 0) {
- const idx = weightedRandom(upvoteWeights);
- vote(idx, 1, false);
- upvotesNeeded--;
- // Reduce weight for this meme to avoid over-voting
- upvoteWeights[idx] *= 0.5;
- }
- // Distribute downvotes
- while (downvotesNeeded > 0) {
- const idx = weightedRandom(downvoteWeights);
- vote(idx, -1, false);
- downvotesNeeded--;
- // Reduce weight for this meme to avoid over-voting
- downvoteWeights[idx] *= 0.5;
- }
- renderMemes();
- }, 10000);
- // Flurry voting: 20-10 votes every 30-60 seconds
- flurryVoteTimer = setInterval(() => {
- if (!autoOn) return;
- const delay = randInt(30000, 60000);
- setTimeout(() => {
- if (!autoOn) return;
- comedyAI.logActivity(comedyAI.getFlurryVoteMessage());
- // Get AI's voting decisions for all memes
- const voteDecisions = population.map(meme => comedyAI.getVoteDecision(meme));
- // Count how many upvotes and downvotes we need
- let upvotesNeeded = 20;
- let downvotesNeeded = 10;
- // Create weighted arrays based on AI's decisions
- const upvoteWeights = population.map((meme, i) =>
- voteDecisions[i] ? comedyAI.analyzeMeme(meme) : 0
- );
- const downvoteWeights = population.map((meme, i) =>
- !voteDecisions[i] ? (1 - comedyAI.analyzeMeme(meme)) : 0
- );
- // Distribute upvotes
- while (upvotesNeeded > 0) {
- const idx = weightedRandom(upvoteWeights);
- vote(idx, 1, false);
- upvotesNeeded--;
- // Reduce weight for this meme to avoid over-voting
- upvoteWeights[idx] *= 0.5;
- }
- // Distribute downvotes
- while (downvotesNeeded > 0) {
- const idx = weightedRandom(downvoteWeights);
- vote(idx, -1, false);
- downvotesNeeded--;
- // Reduce weight for this meme to avoid over-voting
- downvoteWeights[idx] *= 0.5;
- }
- renderMemes();
- }, delay);
- }, 60000); // Check every minute for a flurry
- // Mega flurry: 30-20 votes every 60-90 seconds
- megaFlurryTimer = setInterval(() => {
- if (!autoOn) return;
- const delay = randInt(60000, 90000);
- setTimeout(() => {
- if (!autoOn) return;
- comedyAI.logActivity(comedyAI.getMegaFlurryVoteMessage());
- // Get AI's voting decisions for all memes
- const voteDecisions = population.map(meme => comedyAI.getVoteDecision(meme));
- // Count how many upvotes and downvotes we need
- let upvotesNeeded = 30;
- let downvotesNeeded = 20;
- // Create weighted arrays based on AI's decisions
- const upvoteWeights = population.map((meme, i) =>
- voteDecisions[i] ? comedyAI.analyzeMeme(meme) : 0
- );
- const downvoteWeights = population.map((meme, i) =>
- !voteDecisions[i] ? (1 - comedyAI.analyzeMeme(meme)) : 0
- );
- // Distribute upvotes
- while (upvotesNeeded > 0) {
- const idx = weightedRandom(upvoteWeights);
- vote(idx, 1, false);
- upvotesNeeded--;
- // Reduce weight for this meme to avoid over-voting
- upvoteWeights[idx] *= 0.5;
- }
- // Distribute downvotes
- while (downvotesNeeded > 0) {
- const idx = weightedRandom(downvoteWeights);
- vote(idx, -1, false);
- downvotesNeeded--;
- // Reduce weight for this meme to avoid over-voting
- downvoteWeights[idx] *= 0.5;
- }
- renderMemes();
- }, delay);
- }, 120000); // Check every 2 minutes for a mega flurry
- }
- function stopAutoVoting() {
- clearInterval(regularVoteTimer);
- clearInterval(flurryVoteTimer);
- clearInterval(megaFlurryTimer);
- comedyAI.logActivity("Auto-voting stopped");
- }
- function toggleAutoVotes() {
- autoOn = !autoOn;
- if (autoOn) {
- startAutoVoting();
- } else {
- stopAutoVoting();
- }
- updateStats();
- }
- /* ===== Kickoff ===== */
- initPopulation();
- </script>
- </body>
- </html>
Add Comment
Please, Sign In to add comment