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>Echo Chamber Escape</title>
- <style>
- * {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
- }
- body {
- background: linear-gradient(135deg, #0a0e27 0%, #1a0b2e 50%, #16213e 100%);
- color: #e0e0e0;
- font-family: 'Courier New', monospace;
- min-height: 100vh;
- display: flex;
- justify-content: center;
- align-items: center;
- overflow: hidden;
- position: relative;
- }
- body::before {
- content: '';
- position: absolute;
- width: 200%;
- height: 200%;
- background: repeating-linear-gradient(
- 0deg,
- transparent,
- transparent 2px,
- rgba(255, 0, 255, 0.03) 2px,
- rgba(255, 0, 255, 0.03) 4px
- );
- animation: scanlines 8s linear infinite;
- pointer-events: none;
- }
- @keyframes scanlines {
- 0% { transform: translateY(0); }
- 100% { transform: translateY(10px); }
- }
- .game-container {
- width: 95%;
- max-width: 1000px;
- background: rgba(10, 14, 39, 0.9);
- border: 2px solid rgba(0, 255, 255, 0.3);
- border-radius: 15px;
- padding: 30px;
- box-shadow:
- 0 0 50px rgba(0, 255, 255, 0.2),
- inset 0 0 30px rgba(255, 0, 255, 0.1);
- position: relative;
- z-index: 1;
- }
- .title {
- font-size: 2.5em;
- text-align: center;
- background: linear-gradient(45deg, #00ffff, #ff00ff, #00ffff);
- background-size: 200% 200%;
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- animation: gradient 3s ease infinite;
- margin-bottom: 20px;
- text-shadow: 0 0 30px rgba(0, 255, 255, 0.5);
- }
- @keyframes gradient {
- 0% { background-position: 0% 50%; }
- 50% { background-position: 100% 50%; }
- 100% { background-position: 0% 50%; }
- }
- .room-display {
- background: rgba(0, 0, 0, 0.5);
- border: 1px solid rgba(0, 255, 255, 0.2);
- border-radius: 10px;
- padding: 20px;
- margin-bottom: 20px;
- min-height: 150px;
- position: relative;
- overflow: hidden;
- }
- .room-name {
- color: #00ffff;
- font-size: 1.3em;
- margin-bottom: 10px;
- text-transform: uppercase;
- letter-spacing: 2px;
- }
- .room-description {
- color: #b0b0b0;
- line-height: 1.6;
- margin-bottom: 15px;
- }
- .passages-container {
- background: rgba(255, 0, 255, 0.05);
- border: 1px solid rgba(255, 0, 255, 0.2);
- border-radius: 10px;
- padding: 15px;
- margin-bottom: 20px;
- }
- .passages-label {
- color: #ff00ff;
- font-style: italic;
- margin-bottom: 10px;
- }
- .passage-buttons {
- display: flex;
- flex-wrap: wrap;
- gap: 10px;
- }
- .passage-btn {
- background: linear-gradient(135deg, rgba(0, 255, 255, 0.1), rgba(255, 0, 255, 0.1));
- border: 1px solid rgba(0, 255, 255, 0.3);
- border-radius: 8px;
- color: #00ffff;
- padding: 10px 15px;
- font-family: inherit;
- cursor: pointer;
- transition: all 0.3s;
- flex: 0 0 auto;
- min-width: 100px;
- }
- .passage-btn:hover {
- background: linear-gradient(135deg, rgba(0, 255, 255, 0.3), rgba(255, 0, 255, 0.3));
- transform: scale(1.05);
- box-shadow: 0 0 20px rgba(0, 255, 255, 0.4);
- }
- .echo-display {
- background: rgba(0, 0, 0, 0.6);
- border: 1px solid rgba(255, 0, 255, 0.2);
- border-radius: 10px;
- padding: 15px;
- margin-bottom: 20px;
- min-height: 100px;
- max-height: 200px;
- overflow-y: auto;
- position: relative;
- }
- .echo-line {
- margin: 5px 0;
- opacity: 0;
- animation: fadeInEcho 0.5s forwards;
- position: relative;
- }
- @keyframes fadeInEcho {
- 0% {
- opacity: 0;
- transform: translateX(-20px);
- }
- 100% {
- opacity: 1;
- transform: translateX(0);
- }
- }
- .original-echo {
- color: #00ffff;
- display: inline-block;
- margin-right: 10px;
- }
- .distorted-echo {
- color: #ff00ff;
- display: inline-block;
- position: relative;
- animation: glitch 2s infinite;
- }
- @keyframes glitch {
- 0%, 100% { text-shadow: 0 0 5px rgba(255, 0, 255, 0.5); }
- 25% { text-shadow: -2px 0 #ff00ff, 2px 0 #00ffff; }
- 50% { text-shadow: 2px 0 #ff00ff, -2px 0 #00ffff; }
- 75% { text-shadow: 0 0 10px rgba(255, 0, 255, 0.8); }
- }
- .echo-trail {
- position: absolute;
- color: rgba(255, 0, 255, 0.3);
- animation: trail 2s linear forwards;
- pointer-events: none;
- z-index: -1;
- }
- @keyframes trail {
- 0% {
- opacity: 0.5;
- transform: translateX(0) scale(1);
- }
- 100% {
- opacity: 0;
- transform: translateX(50px) scale(0.8);
- }
- }
- .input-section {
- display: flex;
- gap: 10px;
- }
- #command-input {
- flex: 1;
- background: rgba(0, 0, 0, 0.7);
- border: 2px solid rgba(0, 255, 255, 0.3);
- border-radius: 5px;
- color: #00ffff;
- padding: 12px;
- font-size: 1em;
- font-family: inherit;
- transition: all 0.3s;
- }
- #command-input:focus {
- outline: none;
- border-color: #00ffff;
- box-shadow: 0 0 20px rgba(0, 255, 255, 0.3);
- }
- #submit-btn {
- background: linear-gradient(45deg, #00ffff, #ff00ff);
- border: none;
- border-radius: 5px;
- color: white;
- padding: 12px 25px;
- font-size: 1em;
- font-family: inherit;
- cursor: pointer;
- transition: all 0.3s;
- text-transform: uppercase;
- letter-spacing: 1px;
- }
- #submit-btn:hover {
- transform: scale(1.05);
- box-shadow: 0 0 25px rgba(255, 0, 255, 0.5);
- }
- .status {
- text-align: center;
- margin-top: 20px;
- padding: 10px;
- background: rgba(0, 255, 255, 0.1);
- border-radius: 5px;
- color: #00ffff;
- }
- .victory, .defeat {
- position: fixed;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- background: linear-gradient(135deg, #0a0e27, #1a0b2e);
- padding: 40px;
- border-radius: 20px;
- text-align: center;
- z-index: 1000;
- display: none;
- animation: victoryPulse 1s ease-in-out;
- }
- .victory {
- border: 3px solid #00ffff;
- }
- .defeat {
- border: 3px solid #ff0000;
- }
- @keyframes victoryPulse {
- 0% { transform: translate(-50%, -50%) scale(0); }
- 50% { transform: translate(-50%, -50%) scale(1.1); }
- 100% { transform: translate(-50%, -50%) scale(1); }
- }
- .victory h2 {
- color: #00ffff;
- font-size: 2em;
- margin-bottom: 20px;
- }
- .defeat h2 {
- color: #ff0000;
- font-size: 2em;
- margin-bottom: 20px;
- }
- .help-text {
- color: #808080;
- font-size: 0.9em;
- text-align: center;
- margin-top: 15px;
- font-style: italic;
- }
- ::-webkit-scrollbar {
- width: 8px;
- }
- ::-webkit-scrollbar-track {
- background: rgba(0, 0, 0, 0.3);
- border-radius: 4px;
- }
- ::-webkit-scrollbar-thumb {
- background: linear-gradient(45deg, #00ffff, #ff00ff);
- border-radius: 4px;
- }
- </style>
- </head>
- <body>
- <div class="game-container">
- <h1 class="title">ECHO CHAMBER ESCAPE</h1>
- <div class="room-display" id="room-display">
- <div class="room-name" id="room-name">Loading...</div>
- <div class="room-description" id="room-description"></div>
- </div>
- <div class="passages-container">
- <div class="passages-label">Passages:</div>
- <div class="passage-buttons" id="passage-buttons"></div>
- </div>
- <div class="echo-display" id="echo-display">
- <div style="color: #666; text-align: center;">Your echoes will appear here...</div>
- </div>
- <div class="input-section">
- <input type="text" id="command-input" placeholder="Type a direction or command..." autofocus>
- <button id="submit-btn">ECHO</button>
- </div>
- <div class="status" id="status">
- Moves: <span id="move-count">0</span> | Rooms Explored: <span id="rooms-explored">1</span>/20
- </div>
- <div class="help-text">
- Tip: Click passages to travel, or type directions to move. Find the Victory Room to win!
- </div>
- </div>
- <div class="victory" id="victory">
- <h2>🎉 ESCAPE SUCCESSFUL! 🎉</h2>
- <p style="color: #ff00ff;">You've mastered the echoes and found freedom!</p>
- <p style="color: #00ffff;">Total moves: <span id="final-moves"></span></p>
- <button id="restart-btn" style="margin-top: 20px; padding: 10px 20px; background: linear-gradient(45deg, #00ffff, #ff00ff); border: none; border-radius: 5px; color: white; cursor: pointer;">PLAY AGAIN</button>
- </div>
- <div class="defeat" id="defeat">
- <h2>💀 TRAPPED FOREVER! 💀</h2>
- <p style="color: #ff6b6b;">The Echo Chamber has consumed you...</p>
- <p style="color: #ff0000;">Total moves: <span id="defeat-moves"></span></p>
- <button id="restart-btn-defeat" style="margin-top: 20px; padding: 10px 20px; background: linear-gradient(45deg, #ff0000, #ff6b6b); border: none; border-radius: 5px; color: white; cursor: pointer;">TRY AGAIN</button>
- </div>
- <script>
- class EchoChamberGame {
- constructor() {
- this.moves = 0;
- this.currentRoom = 'room1';
- this.echoHistory = [];
- this.visitedRooms = new Set(['room1']);
- this.victoryRoom = '';
- this.defeatRoom = '';
- // Define room properties
- this.roomNames = [
- 'The Resonant Entrance', 'The Harmonic Hallway', 'The Whispering Gallery',
- 'The Lexicon Library', 'The Echo Chamber Core', 'The Sonic Vault',
- 'The Sound Observatory', 'The Echo Crypt', 'The Resonant Void',
- 'The Final Antechamber', 'The Prism Passage', 'The Timbre Tunnel',
- 'The Cadence Cathedral', 'The Melody Maze', 'The Rhythm Ruins',
- 'The Pitch Palace', 'The Tempo Temple', 'The Dynamics Dungeon',
- 'The Fortress of Frequencies', 'The Citadel of Sound'
- ];
- this.roomDescriptions = [
- 'Crystalline walls pulse with each sound you make. The air itself seems to listen.',
- 'Echoes bounce endlessly between mirrored surfaces. Each reflection changes the sound.',
- 'Soft murmurs transform into thunderous proclamations. Silence has never been louder.',
- 'Books whisper their contents as echoes. Words float through the air like butterflies.',
- 'The heart of the maze. All sounds converge here in a symphonic chaos.',
- 'Ancient echoes are stored here, each one a key to understanding.',
- 'From here you can see the patterns of all echoes, mapped across crystalline surfaces.',
- 'Where forgotten words come to rest. The silence here is absolute, yet deafening.',
- 'A place between places. All paths converge here, yet none are visible.',
- 'The exit glimmers just beyond. One last echo stands between you and freedom.',
- 'Light refracts through sound waves, creating a rainbow of audible colors.',
- 'The walls hum with a steady rhythm that seems to guide your steps.',
- 'Vast arches amplify every whisper into a chorus of harmonic voices.',
- 'Twisting corridors create a labyrinth of sound that challenges your perception.',
- 'Broken pillars resonate with forgotten melodies from ages past.',
- 'Grand halls where pitch-perfect notes hang suspended in the air.',
- 'A sacred space where time itself seems to beat in perfect rhythm.',
- 'Caverns where volume swells and recedes like ocean tides.',
- 'Impenetrable walls that vibrate with the fundamental frequencies of existence.',
- 'The highest point in the chamber, where all sounds converge into one perfect note.'
- ];
- // Direction names for passages
- this.directions = [
- 'north', 'south', 'east', 'west', 'up', 'down',
- 'northeast', 'northwest', 'southeast', 'southwest',
- 'portal', 'tunnel', 'archway', 'corridor', 'staircase',
- 'ladder', 'bridge', 'gate', 'passage', 'doorway'
- ];
- this.distortionPatterns = [
- { pattern: /n/g, replacement: () => Math.random() > 0.5 ? 't' : 'tch' },
- { pattern: /t/g, replacement: () => Math.random() > 0.5 ? 'n' : 'th' },
- { pattern: /th/g, replacement: 'f' },
- { pattern: /s/g, replacement: () => Math.random() > 0.5 ? 'z' : 'sh' },
- { pattern: /p/g, replacement: () => Math.random() > 0.5 ? 'b' : 'pe' },
- { pattern: /k/g, replacement: () => Math.random() > 0.5 ? 'c' : 'ck' },
- { pattern: /r/g, replacement: () => Math.random() > 0.5 ? 'w' : 'rr' },
- { pattern: /l/g, replacement: () => Math.random() > 0.5 ? 'll' : 'r' },
- { pattern: /or/g, replacement: 'oh' },
- { pattern: /ea/g, replacement: () => Math.random() > 0.5 ? 'ee' : 'a' },
- { pattern: /oo/g, replacement: 'u' },
- { pattern: /ou/g, replacement: 'ow' },
- { pattern: /ing$/g, replacement: 'in\'' },
- { pattern: /ed$/g, replacement: 'id' },
- { pattern: /ly$/g, replacement: 'lee' },
- { pattern: /([aeiou])([bcdfghjklmnpqrstvwxyz])/g,
- replacement: (match, v, c) => Math.random() > 0.7 ? c + v : match }
- ];
- // Generate random room layout
- this.rooms = this.generateRandomRooms();
- this.init();
- }
- generateRandomRooms() {
- const rooms = {};
- const roomCount = 20;
- // Create rooms with random names and descriptions
- for (let i = 1; i <= roomCount; i++) {
- const roomId = `room${i}`;
- const nameIndex = Math.floor(Math.random() * this.roomNames.length);
- const descIndex = Math.floor(Math.random() * this.roomDescriptions.length);
- rooms[roomId] = {
- name: this.roomNames[nameIndex],
- description: this.roomDescriptions[descIndex],
- exits: {}
- };
- // Remove used names/descriptions to avoid duplicates
- this.roomNames.splice(nameIndex, 1);
- this.roomDescriptions.splice(descIndex, 1);
- }
- // Randomly assign victory and defeat rooms
- const roomIds = Object.keys(rooms);
- this.victoryRoom = roomIds[Math.floor(Math.random() * roomIds.length)];
- do {
- this.defeatRoom = roomIds[Math.floor(Math.random() * roomIds.length)];
- } while (this.defeatRoom === this.victoryRoom);
- // Add special properties to victory and defeat rooms
- rooms[this.victoryRoom].victory = true;
- rooms[this.victoryRoom].name = "THE VICTORY CHAMBER";
- rooms[this.victoryRoom].description = "A brilliant light washes over you. You've found the way out!";
- rooms[this.defeatRoom].defeat = true;
- rooms[this.defeatRoom].name = "THE ABYSS OF SILENCE";
- rooms[this.defeatRoom].description = "An eternal, crushing silence envelops you. All hope is lost...";
- // Create random connections between rooms
- for (let i = 0; i < roomIds.length; i++) {
- const currentRoom = roomIds[i];
- const numExits = Math.floor(Math.random() * 4) + 2; // 2-5 exits per room
- for (let j = 0; j < numExits; j++) {
- // Find a random room to connect to
- let targetRoom;
- do {
- targetRoom = roomIds[Math.floor(Math.random() * roomIds.length)];
- } while (targetRoom === currentRoom || rooms[currentRoom].exits[this.directions[j]]);
- // Use a random direction name
- const direction = this.directions[Math.floor(Math.random() * this.directions.length)];
- // Create bidirectional connection
- rooms[currentRoom].exits[direction] = targetRoom;
- // Find a different direction for the return path
- let returnDirection;
- do {
- returnDirection = this.directions[Math.floor(Math.random() * this.directions.length)];
- } while (rooms[targetRoom].exits[returnDirection]);
- rooms[targetRoom].exits[returnDirection] = currentRoom;
- }
- }
- return rooms;
- }
- init() {
- this.updateRoom();
- this.bindEvents();
- }
- bindEvents() {
- const input = document.getElementById('command-input');
- const submitBtn = document.getElementById('submit-btn');
- const restartBtn = document.getElementById('restart-btn');
- const restartBtnDefeat = document.getElementById('restart-btn-defeat');
- const processCommand = () => {
- const command = input.value.trim().toLowerCase();
- if (command) {
- this.processCommand(command);
- input.value = '';
- }
- };
- submitBtn.addEventListener('click', processCommand);
- input.addEventListener('keypress', (e) => {
- if (e.key === 'Enter') processCommand();
- });
- restartBtn.addEventListener('click', () => {
- location.reload();
- });
- restartBtnDefeat.addEventListener('click', () => {
- location.reload();
- });
- }
- clickPassage(direction) {
- const room = this.rooms[this.currentRoom];
- if (room.exits[direction]) {
- this.moves++;
- this.currentRoom = room.exits[direction];
- this.updateRoom();
- if (this.rooms[this.currentRoom].victory) {
- this.showVictory();
- } else if (this.rooms[this.currentRoom].defeat) {
- this.showDefeat();
- }
- }
- }
- distortCommand(command) {
- let distorted = command.toLowerCase();
- const iterations = Math.floor(Math.random() * 3) + 1;
- for (let i = 0; i < iterations; i++) {
- const patterns = [...this.distortionPatterns].sort(() => Math.random() - 0.5);
- patterns.slice(0, Math.floor(Math.random() * 4) + 2).forEach(({ pattern, replacement }) => {
- if (typeof replacement === 'function') {
- distorted = distorted.replace(pattern, replacement);
- } else {
- distorted = distorted.replace(pattern, replacement);
- }
- });
- }
- return distorted;
- }
- processCommand(command) {
- this.moves++;
- const distorted = this.distortCommand(command);
- this.addEcho(command, distorted);
- this.updateStatus();
- // Check if command matches any direction from current room
- const room = this.rooms[this.currentRoom];
- for (let direction in room.exits) {
- if (this.fuzzyMatch(command, direction) || command.includes(direction.substring(0, 2))) {
- this.currentRoom = room.exits[direction];
- this.updateRoom();
- if (this.rooms[this.currentRoom].victory) {
- this.showVictory();
- } else if (this.rooms[this.currentRoom].defeat) {
- this.showDefeat();
- }
- return;
- }
- }
- // If no direction matched, show a random response
- const responses = [
- 'The echo dissipates into silence...',
- 'The walls absorb your words...',
- 'Your voice returns as whispers...',
- 'The chamber hums with confusion...',
- 'Your words echo back unchanged...',
- 'The sound reverberates through the chamber...'
- ];
- this.addSystemMessage(responses[Math.floor(Math.random() * responses.length)]);
- }
- fuzzyMatch(str1, str2) {
- const threshold = 0.6;
- const longer = str1.length > str2.length ? str1 : str2;
- const shorter = str1.length > str2.length ? str2 : str1;
- if (longer.length === 0) return 1.0;
- const editDistance = this.levenshtein(longer, shorter);
- return (longer.length - editDistance) / parseFloat(longer.length) >= threshold;
- }
- levenshtein(s1, s2) {
- const costs = [];
- for (let i = 0; i <= s2.length; i++) {
- let lastValue = i;
- for (let j = 0; j <= s1.length; j++) {
- if (i === 0) costs[j] = j;
- else if (j > 0) {
- let newValue = costs[j - 1];
- if (s1.charAt(j - 1) !== s2.charAt(i - 1))
- newValue = Math.min(Math.min(newValue, lastValue), costs[j]) + 1;
- costs[j - 1] = lastValue;
- lastValue = newValue;
- }
- }
- if (i > 0) costs[s1.length] = lastValue;
- }
- return costs[s1.length];
- }
- addEcho(original, distorted) {
- const echoDisplay = document.getElementById('echo-display');
- if (echoDisplay.querySelector('[style*="color: #666"]')) {
- echoDisplay.innerHTML = '';
- }
- const echoLine = document.createElement('div');
- echoLine.className = 'echo-line';
- echoLine.innerHTML = `
- <span class="original-echo">${original}</span> →
- <span class="distorted-echo">${distorted}</span>
- `;
- for (let i = 0; i < 3; i++) {
- setTimeout(() => {
- const trail = document.createElement('span');
- trail.className = 'echo-trail';
- trail.textContent = distorted;
- trail.style.left = (150 + i * 30) + 'px';
- trail.style.top = '0';
- echoLine.appendChild(trail);
- }, i * 200);
- }
- echoDisplay.appendChild(echoLine);
- echoDisplay.scrollTop = echoDisplay.scrollHeight;
- while (echoDisplay.children.length > 10) {
- echoDisplay.removeChild(echoDisplay.firstChild);
- }
- }
- addSystemMessage(message) {
- const echoDisplay = document.getElementById('echo-display');
- const msgLine = document.createElement('div');
- msgLine.className = 'echo-line';
- msgLine.style.color = '#00ffff';
- msgLine.style.fontStyle = 'italic';
- msgLine.textContent = message;
- echoDisplay.appendChild(msgLine);
- echoDisplay.scrollTop = echoDisplay.scrollHeight;
- }
- updateRoom() {
- const room = this.rooms[this.currentRoom];
- document.getElementById('room-name').textContent = room.name;
- document.getElementById('room-description').textContent = room.description;
- // Track visited rooms
- if (!this.visitedRooms.has(this.currentRoom)) {
- this.visitedRooms.add(this.currentRoom);
- }
- // Update passage buttons
- const buttonContainer = document.getElementById('passage-buttons');
- buttonContainer.innerHTML = '';
- for (let dir in room.exits) {
- const btn = document.createElement('button');
- btn.className = 'passage-btn';
- // Capitalize first letter
- btn.textContent = dir.charAt(0).toUpperCase() + dir.slice(1);
- btn.onclick = () => this.clickPassage(dir);
- buttonContainer.appendChild(btn);
- }
- this.updateStatus();
- }
- updateStatus() {
- document.getElementById('move-count').textContent = this.moves;
- document.getElementById('rooms-explored').textContent = this.visitedRooms.size;
- }
- showVictory() {
- document.getElementById('final-moves').textContent = this.moves;
- document.getElementById('victory').style.display = 'block';
- }
- showDefeat() {
- document.getElementById('defeat-moves').textContent = this.moves;
- document.getElementById('defeat').style.display = 'block';
- }
- }
- // Start game
- window.addEventListener('DOMContentLoaded', () => {
- new EchoChamberGame();
- });
- </script>
- </body>
- </html>
Advertisement
Add Comment
Please, Sign In to add comment