XTaylorSpenceX

Mind Mirror Maze

Sep 20th, 2025
79
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
HTML 37.74 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>Mirror Mind Maze - Navigate Your Reflections</title>
  7.     <style>
  8.         * {
  9.             margin: 0;
  10.             padding: 0;
  11.             box-sizing: border-box;
  12.         }
  13.         body {
  14.             background: linear-gradient(135deg, #0a0a0a, #1a0033, #0a0a0a);
  15.             color: #fff;
  16.             font-family: 'Courier New', monospace;
  17.             overflow: hidden;
  18.             height: 100vh;
  19.             display: flex;
  20.             justify-content: center;
  21.             align-items: center;
  22.             position: relative;
  23.         }
  24.         body::before {
  25.             content: '';
  26.             position: absolute;
  27.             inset: 0;
  28.             background:
  29.                 radial-gradient(circle at 20% 50%, rgba(255, 0, 255, 0.1), transparent 50%),
  30.                 radial-gradient(circle at 80% 50%, rgba(0, 255, 255, 0.1), transparent 50%);
  31.             animation: pulse 8s ease-in-out infinite;
  32.             pointer-events: none;
  33.         }
  34.         @keyframes pulse {
  35.             0%, 100% { opacity: 0.3; }
  36.             50% { opacity: 0.6; }
  37.         }
  38.         #gameContainer {
  39.             position: relative;
  40.             width: 800px;
  41.             height: 600px;
  42.             border: 2px solid rgba(255, 255, 255, 0.2);
  43.             box-shadow:
  44.                 0 0 50px rgba(255, 0, 255, 0.5),
  45.                 inset 0 0 50px rgba(0, 255, 255, 0.2);
  46.             background: rgba(0, 0, 0, 0.8);
  47.         }
  48.         #maze {
  49.             position: absolute;
  50.             width: 100%;
  51.             height: 100%;
  52.             overflow: hidden;
  53.         }
  54.         .wall {
  55.             position: absolute;
  56.             background: linear-gradient(45deg, #2a2a3a, #1a1a2a);
  57.             border: 1px solid rgba(255, 255, 255, 0.1);
  58.             box-shadow:
  59.                 inset 0 0 10px rgba(0, 0, 0, 0.5),
  60.                 0 0 5px rgba(100, 100, 200, 0.3);
  61.         }
  62.         .mirror-wall {
  63.             background: linear-gradient(135deg,
  64.                 rgba(255, 255, 255, 0.1),
  65.                 rgba(200, 200, 255, 0.05),
  66.                 rgba(255, 255, 255, 0.1));
  67.             backdrop-filter: blur(5px);
  68.             border: 1px solid rgba(255, 255, 255, 0.3);
  69.             box-shadow:
  70.                 inset 0 0 20px rgba(255, 255, 255, 0.2),
  71.                 0 0 15px rgba(100, 200, 255, 0.4);
  72.             animation: shimmer 3s linear infinite;
  73.         }
  74.         @keyframes shimmer {
  75.             0% { filter: brightness(1) hue-rotate(0deg); }
  76.             50% { filter: brightness(1.2) hue-rotate(10deg); }
  77.             100% { filter: brightness(1) hue-rotate(0deg); }
  78.         }
  79.         .player {
  80.             position: absolute;
  81.             width: 20px;
  82.             height: 20px;
  83.             background: radial-gradient(circle, #00ffff, #0088ff);
  84.             border-radius: 50%;
  85.             box-shadow:
  86.                 0 0 20px #00ffff,
  87.                 0 0 40px #00ffff,
  88.                 inset 0 0 10px rgba(255, 255, 255, 0.5);
  89.             z-index: 10;
  90.             transition: none;
  91.         }
  92.         .reflection {
  93.             position: absolute;
  94.             width: 20px;
  95.             height: 20px;
  96.             border-radius: 50%;
  97.             opacity: 0.7;
  98.             transition: all 0.3s ease;
  99.             pointer-events: none;
  100.             z-index: 5;
  101.         }
  102.         .reflection.type-1 {
  103.             background: radial-gradient(circle, #ff00ff, #8800ff);
  104.             box-shadow:
  105.                 0 0 15px #ff00ff,
  106.                 0 0 30px #ff00ff;
  107.             animation: float 2s ease-in-out infinite;
  108.         }
  109.         .reflection.type-2 {
  110.             background: radial-gradient(circle, #ffff00, #ff8800);
  111.             box-shadow:
  112.                 0 0 15px #ffff00,
  113.                 0 0 30px #ffaa00;
  114.             animation: float 2s ease-in-out infinite reverse;
  115.         }
  116.         .reflection.type-3 {
  117.             background: radial-gradient(circle, #00ff00, #00ff88);
  118.             box-shadow:
  119.                 0 0 15px #00ff00,
  120.                 0 0 30px #00ff00;
  121.             animation: rotate 3s linear infinite;
  122.         }
  123.         @keyframes float {
  124.             0%, 100% { transform: translateY(0); }
  125.             50% { transform: translateY(-5px); }
  126.         }
  127.         @keyframes rotate {
  128.             0% { transform: rotate(0deg); }
  129.             100% { transform: rotate(360deg); }
  130.         }
  131.         .goal {
  132.             position: absolute;
  133.             width: 30px;
  134.             height: 30px;
  135.             background: radial-gradient(circle, #fff, #00ffff, transparent);
  136.             border-radius: 50%;
  137.             box-shadow:
  138.                 0 0 30px #00ffff,
  139.                 0 0 60px #00ffff,
  140.                 inset 0 0 20px rgba(255, 255, 255, 0.8);
  141.             animation: goalPulse 1.5s ease-in-out infinite;
  142.             z-index: 3;
  143.         }
  144.         @keyframes goalPulse {
  145.             0%, 100% { transform: scale(1); opacity: 0.8; }
  146.             50% { transform: scale(1.2); opacity: 1; }
  147.         }
  148.         .power-up {
  149.             position: absolute;
  150.             width: 20px;
  151.             height: 20px;
  152.             box-shadow:
  153.                 0 0 20px currentColor,
  154.                 0 0 40px currentColor,
  155.                 inset 0 0 10px rgba(255, 255, 255, 0.5);
  156.             animation: goalPulse 1.5s ease-in-out infinite;
  157.             z-index: 3;
  158.         }
  159.         .power-up.life-up {
  160.             background: radial-gradient(circle, #ff0000, #ff8800);
  161.         }
  162.         .power-up.speed-boost {
  163.             background: radial-gradient(circle, #ffff00, #ffaa00);
  164.         }
  165.         .power-up.plus-reflections {
  166.             background: radial-gradient(circle, #ff00ff, #8800ff);
  167.         }
  168.         .power-up.minus-reflections {
  169.             background: radial-gradient(circle, #00ff00, #00ff88);
  170.         }
  171.         .power-up.invisibility {
  172.             background: radial-gradient(circle, #0000ff, #0088ff);
  173.         }
  174.         .power-up.teleport {
  175.             background: radial-gradient(circle, #ff00ff, #ff88ff);
  176.         }
  177.         .power-up.shield {
  178.             background: radial-gradient(circle, #00ffff, #00aaff);
  179.         }
  180.         #ui {
  181.             position: absolute;
  182.             top: 20px;
  183.             left: 20px;
  184.             font-size: 14px;
  185.             color: #00ffff;
  186.             text-shadow: 0 0 10px #00ffff;
  187.             z-index: 100;
  188.         }
  189.         #message {
  190.             position: absolute;
  191.             top: 50%;
  192.             left: 50%;
  193.             transform: translate(-50%, -50%);
  194.             font-size: 24px;
  195.             color: #fff;
  196.             text-align: center;
  197.             text-shadow: 0 0 20px currentColor;
  198.             z-index: 1000;
  199.             display: none;
  200.             animation: messageGlow 1s ease-in-out;
  201.         }
  202.         @keyframes messageGlow {
  203.             0% { opacity: 0; transform: translate(-50%, -50%) scale(0.5); }
  204.             50% { opacity: 1; transform: translate(-50%, -50%) scale(1.1); }
  205.             100% { opacity: 1; transform: translate(-50%, -50%) scale(1); }
  206.         }
  207.         #controls {
  208.             position: absolute;
  209.             bottom: 20px;
  210.             left: 50%;
  211.             transform: translateX(-50%);
  212.             text-align: center;
  213.             color: rgba(255, 255, 255, 0.6);
  214.             font-size: 12px;
  215.         }
  216.         .particle {
  217.             position: absolute;
  218.             width: 2px;
  219.             height: 2px;
  220.             background: #fff;
  221.             border-radius: 50%;
  222.             pointer-events: none;
  223.             animation: particleFade 1s ease-out forwards;
  224.         }
  225.         @keyframes particleFade {
  226.             0% {
  227.                 opacity: 1;
  228.                 transform: translate(0, 0) scale(1);
  229.             }
  230.             100% {
  231.                 opacity: 0;
  232.                 transform: translate(var(--dx), var(--dy)) scale(0);
  233.             }
  234.         }
  235.         .danger-pulse {
  236.             animation: dangerPulse 0.5s ease-in-out infinite;
  237.         }
  238.         @keyframes dangerPulse {
  239.             0%, 100% { box-shadow: 0 0 20px #ff0000, 0 0 40px #ff0000; }
  240.             50% { box-shadow: 0 0 40px #ff0000, 0 0 80px #ff0000; }
  241.         }
  242.         .invisible {
  243.             opacity: 0.5;
  244.         }
  245.         .speed-boost {
  246.             animation: speedGlow 0.5s ease-in-out infinite;
  247.         }
  248.         @keyframes speedGlow {
  249.             0%, 100% { box-shadow: 0 0 20px #ffff00, 0 0 40px #ffff00; }
  250.             50% { box-shadow: 0 0 40px #ffff00, 0 0 80px #ffff00; }
  251.         }
  252.     </style>
  253. </head>
  254. <body>
  255.     <div id="gameContainer">
  256.         <div id="maze"></div>
  257.         <div id="ui">
  258.             <div>Level: <span id="level">1</span></div>
  259.             <div>Moves: <span id="moves">0</span></div>
  260.             <div>Reflections: <span id="reflectionCount">0</span></div>
  261.             <div style="color: #ff6666;">Lives: <span id="lives">3</span></div>
  262.         </div>
  263.         <div id="message"></div>
  264.         <div id="controls">
  265.             Use ARROW KEYS or WASD to move | R to restart level<br>
  266.             <span style="color: #ff6666;">Get surrounded by 2 reflections and lose!</span>
  267.         </div>
  268.     </div>
  269.     <script>
  270.         class MirrorMindMaze {
  271.             constructor() {
  272.                 this.maze = document.getElementById('maze');
  273.                 this.level = 1;
  274.                 this.moves = 0;
  275.                 this.lives = 3;
  276.                 this.playerPos = { x: 1, y: 1 };
  277.                 this.goalPos = { x: 18, y: 13 };
  278.                 this.powerUps = [];
  279.                 this.activePowerUps = new Set();
  280.                 this.reflections = [];
  281.                 this.extraReflections = [];
  282.                 this.reflectionModifier = 0;
  283.                 this.moveHistory = [];
  284.                 this.gridSize = 20;
  285.                 this.cols = 40;
  286.                 this.rows = 30;
  287.                 this.walls = [];
  288.                 this.mirrorWalls = [];
  289.                 this.isMoving = false;
  290.                 this.player = null;
  291.                 this.goal = null;
  292.                
  293.                 this.init();
  294.             }
  295.             init() {
  296.                 this.setupMaze();
  297.                 this.createPlayer();
  298.                 this.createGoal();
  299.                 this.createPowerUps();
  300.                 this.setupControls();
  301.                 this.updateUI();
  302.             }
  303.             setupMaze() {
  304.                 // Clear maze
  305.                 this.maze.innerHTML = '';
  306.                 this.walls = [];
  307.                 this.mirrorWalls = [];
  308.                 this.powerUps = [];
  309.                 this.activePowerUps.clear();
  310.                
  311.                 // Generate maze layout
  312.                 const mazeLayout = this.level === 1 ?
  313.                     this.generateLevel1() :
  314.                     this.generateProceduralLevel();
  315.                
  316.                 // Create walls
  317.                 mazeLayout.forEach(wall => {
  318.                     const wallEl = document.createElement('div');
  319.                     wallEl.className = wall.mirror ? 'wall mirror-wall' : 'wall';
  320.                     wallEl.style.left = wall.x * this.gridSize + 'px';
  321.                     wallEl.style.top = wall.y * this.gridSize + 'px';
  322.                     wallEl.style.width = wall.width * this.gridSize + 'px';
  323.                     wallEl.style.height = wall.height * this.gridSize + 'px';
  324.                     this.maze.appendChild(wallEl);
  325.                    
  326.                     if (wall.mirror) {
  327.                         this.mirrorWalls.push(wall);
  328.                     } else {
  329.                         this.walls.push(wall);
  330.                     }
  331.                 });
  332.             }
  333.             generateLevel1() {
  334.                 const layout = [];
  335.                
  336.                 // Outer walls
  337.                 layout.push({ x: 0, y: 0, width: this.cols, height: 1, mirror: false });
  338.                 layout.push({ x: 0, y: this.rows - 1, width: this.cols, height: 1, mirror: false });
  339.                 layout.push({ x: 0, y: 0, width: 1, height: this.rows, mirror: false });
  340.                 layout.push({ x: this.cols - 1, y: 0, width: 1, height: this.rows, mirror: false });
  341.                
  342.                 // Level 1 specific pattern
  343.                 layout.push({ x: 5, y: 5, width: 10, height: 1, mirror: true });
  344.                 layout.push({ x: 10, y: 10, width: 1, height: 8, mirror: true });
  345.                 layout.push({ x: 20, y: 5, width: 1, height: 10, mirror: true });
  346.                 layout.push({ x: 25, y: 15, width: 8, height: 1, mirror: true });
  347.                
  348.                 // Regular walls
  349.                 layout.push({ x: 15, y: 2, width: 1, height: 8, mirror: false });
  350.                 layout.push({ x: 5, y: 20, width: 15, height: 1, mirror: false });
  351.                 layout.push({ x: 30, y: 8, width: 1, height: 12, mirror: false });
  352.                
  353.                 // No power-ups in level 1
  354.                 this.powerUps = [];
  355.                
  356.                 return layout;
  357.             }
  358.             generateProceduralLevel() {
  359.                 const layout = [];
  360.                
  361.                 // Outer walls
  362.                 layout.push({ x: 0, y: 0, width: this.cols, height: 1, mirror: false });
  363.                 layout.push({ x: 0, y: this.rows - 1, width: this.cols, height: 1, mirror: false });
  364.                 layout.push({ x: 0, y: 0, width: 1, height: this.rows, mirror: false });
  365.                 layout.push({ x: this.cols - 1, y: 0, width: 1, height: this.rows, mirror: false });
  366.                
  367.                 // Calculate complexity based on level
  368.                 const mirrorCount = Math.min(3 + this.level, 12);
  369.                 const wallCount = Math.min(5 + Math.floor(this.level / 2), 15);
  370.                
  371.                 // Place random starting position
  372.                 this.playerPos = {
  373.                     x: 1 + Math.floor(Math.random() * 5),
  374.                     y: 1 + Math.floor(Math.random() * 5)
  375.                 };
  376.                
  377.                 // Place goal far from start
  378.                 this.goalPos = {
  379.                     x: this.cols - 2 - Math.floor(Math.random() * 5),
  380.                     y: this.rows - 2 - Math.floor(Math.random() * 5)
  381.                 };
  382.                
  383.                 // Generate mirror walls
  384.                 for (let i = 0; i < mirrorCount; i++) {
  385.                    const isHorizontal = Math.random() > 0.5;
  386.                     let wall;
  387.                     if (isHorizontal) {
  388.                         wall = {
  389.                             x: 3 + Math.floor(Math.random() * (this.cols - 10)),
  390.                             y: 3 + Math.floor(Math.random() * (this.rows - 6)),
  391.                             width: 4 + Math.floor(Math.random() * 8),
  392.                             height: 1,
  393.                             mirror: true
  394.                         };
  395.                     } else {
  396.                         wall = {
  397.                             x: 3 + Math.floor(Math.random() * (this.cols - 6)),
  398.                             y: 3 + Math.floor(Math.random() * (this.rows - 10)),
  399.                             width: 1,
  400.                             height: 4 + Math.floor(Math.random() * 8),
  401.                             mirror: true
  402.                         };
  403.                     }
  404.                     if (!this.wallBlocksPosition(wall, this.playerPos) &&
  405.                        !this.wallBlocksPosition(wall, this.goalPos)) {
  406.                        layout.push(wall);
  407.                     }
  408.                 }
  409.                
  410.                 // Generate regular walls
  411.                 for (let i = 0; i < wallCount; i++) {
  412.                    const isHorizontal = Math.random() > 0.5;
  413.                     let wall;
  414.                     if (isHorizontal) {
  415.                         wall = {
  416.                             x: 2 + Math.floor(Math.random() * (this.cols - 8)),
  417.                             y: 2 + Math.floor(Math.random() * (this.rows - 4)),
  418.                             width: 3 + Math.floor(Math.random() * 6),
  419.                             height: 1,
  420.                             mirror: false
  421.                         };
  422.                     } else {
  423.                         wall = {
  424.                             x: 2 + Math.floor(Math.random() * (this.cols - 4)),
  425.                             y: 2 + Math.floor(Math.random() * (this.rows - 8)),
  426.                             width: 1,
  427.                             height: 3 + Math.floor(Math.random() * 6),
  428.                             mirror: false
  429.                         };
  430.                     }
  431.                     if (!this.wallBlocksPosition(wall, this.playerPos) &&
  432.                        !this.wallBlocksPosition(wall, this.goalPos)) {
  433.                        layout.push(wall);
  434.                     }
  435.                 }
  436.                
  437.                 // Generate power-ups: 1-4 per level, spaced out
  438.                 this.powerUps = [];
  439.                 const powerUpTypes = [
  440.                     'life-up', 'speed-boost', 'plus-reflections', 'minus-reflections',
  441.                     'invisibility', 'teleport', 'shield'
  442.                 ];
  443.                 const numPowerUps = (this.level % 5 === 0 || this.level % 5 === 1) ? 1 + Math.floor(Math.random() * 2) : 3 + Math.floor(Math.random() * 2); // 1-2 or 3-4
  444.                 const selectedTypes = powerUpTypes.sort(() => 0.5 - Math.random()).slice(0, numPowerUps);
  445.                
  446.                 selectedTypes.forEach(type => {
  447.                     let attempts = 0;
  448.                     let pos;
  449.                     do {
  450.                         pos = {
  451.                             x: 2 + Math.floor(Math.random() * (this.cols - 4)),
  452.                             y: 2 + Math.floor(Math.random() * (this.rows - 4))
  453.                         };
  454.                         attempts++;
  455.                     } while ((this.wallBlocksPositionAny(layout, pos) ||
  456.                               this.powerUps.some(p => p.pos.x === pos.x && p.pos.y === pos.y) ||
  457.                              (pos.x === this.playerPos.x && pos.y === this.playerPos.y) ||
  458.                              (pos.x === this.goalPos.x && pos.y === this.goalPos.y)) && attempts < 100);
  459.                    
  460.                     if (attempts < 100) {
  461.                        this.powerUps.push({ type, pos, element: null });
  462.                    }
  463.                });
  464.              
  465.                return layout;
  466.            }
  467.            wallBlocksPositionAny(walls, pos) {
  468.                return walls.some(wall => this.wallBlocksPosition(wall, pos));
  469.             }
  470.             wallBlocksPosition(wall, pos) {
  471.                 return pos.x >= wall.x && pos.x < wall.x + wall.width &&
  472.                       pos.y >= wall.y && pos.y < wall.y + wall.height;
  473.             }
  474.             createPlayer() {
  475.                 if (this.player) {
  476.                     this.player.remove();
  477.                 }
  478.                
  479.                 this.player = document.createElement('div');
  480.                 this.player.className = 'player';
  481.                 this.updatePlayerPosition();
  482.                 this.maze.appendChild(this.player);
  483.             }
  484.             createGoal() {
  485.                 if (this.goal) {
  486.                     this.goal.remove();
  487.                 }
  488.                
  489.                 this.goal = document.createElement('div');
  490.                 this.goal.className = 'goal';
  491.                 this.goal.style.left = this.goalPos.x * this.gridSize - 5 + 'px';
  492.                 this.goal.style.top = this.goalPos.y * this.gridSize - 5 + 'px';
  493.                 this.maze.appendChild(this.goal);
  494.             }
  495.             createPowerUps() {
  496.                 this.powerUps.forEach(powerUp => {
  497.                     if (powerUp.element) {
  498.                         powerUp.element.remove();
  499.                     }
  500.                     const el = document.createElement('div');
  501.                     el.className = `power-up ${powerUp.type}`;
  502.                     el.style.left = powerUp.pos.x * this.gridSize + 'px';
  503.                     el.style.top = powerUp.pos.y * this.gridSize + 'px';
  504.                     this.maze.appendChild(el);
  505.                     powerUp.element = el;
  506.                 });
  507.             }
  508.             updatePlayerPosition() {
  509.                 if (this.player) {
  510.                     this.player.style.left = this.playerPos.x * this.gridSize + 'px';
  511.                     this.player.style.top = this.playerPos.y * this.gridSize + 'px';
  512.                    
  513.                     this.createParticles(this.playerPos.x * this.gridSize + 10, this.playerPos.y * this.gridSize + 10);
  514.                 }
  515.             }
  516.             createParticles(x, y) {
  517.                 for (let i = 0; i < 5; i++) {
  518.                    const particle = document.createElement('div');
  519.                    particle.className = 'particle';
  520.                    particle.style.left = x + 'px';
  521.                    particle.style.top = y + 'px';
  522.                    particle.style.setProperty('--dx', (Math.random() - 0.5) * 30 + 'px');
  523.                    particle.style.setProperty('--dy', (Math.random() - 0.5) * 30 + 'px');
  524.                    this.maze.appendChild(particle);
  525.                    setTimeout(() => particle.remove(), 1000);
  526.                 }
  527.             }
  528.             setupControls() {
  529.                 document.addEventListener('keydown', (e) => {
  530.                     if (this.isMoving) return;
  531.                    
  532.                     let dx = 0, dy = 0;
  533.                    
  534.                     switch(e.key.toLowerCase()) {
  535.                         case 'arrowup':
  536.                         case 'w':
  537.                             dy = -1;
  538.                             break;
  539.                         case 'arrowdown':
  540.                         case 's':
  541.                             dy = 1;
  542.                             break;
  543.                         case 'arrowleft':
  544.                         case 'a':
  545.                             dx = -1;
  546.                             break;
  547.                         case 'arrowright':
  548.                         case 'd':
  549.                             dx = 1;
  550.                             break;
  551.                         case 'r':
  552.                             this.resetLevel();
  553.                             return;
  554.                     }
  555.                    
  556.                     if (dx !== 0 || dy !== 0) {
  557.                         this.movePlayer(dx, dy);
  558.                     }
  559.                 });
  560.             }
  561.             movePlayer(dx, dy) {
  562.                 let steps = this.activePowerUps.has('speed-boost') ? 2 : 1;
  563.                 for (let step = 0; step < steps; step++) {
  564.                    const newX = this.playerPos.x + dx;
  565.                    const newY = this.playerPos.y + dy;
  566.                  
  567.                    if (this.checkCollision(newX, newY)) {
  568.                        break;
  569.                    }
  570.                  
  571.                    this.moves++;
  572.                    this.moveHistory.push({ dx, dy, time: Date.now() });
  573.                  
  574.                    this.playerPos.x = newX;
  575.                    this.playerPos.y = newY;
  576.                    this.updatePlayerPosition();
  577.                  
  578.                    this.updateReflections(dx, dy);
  579.                  
  580.                    if (this.checkSurrounded()) {
  581.                        if (this.activePowerUps.has('shield')) {
  582.                            this.activePowerUps.delete('shield');
  583.                            this.showMessage('Shield blocked surround!');
  584.                        } else {
  585.                            this.loseLife();
  586.                            return;
  587.                        }
  588.                    }
  589.                  
  590.                    if (this.checkGoal()) {
  591.                        this.levelComplete();
  592.                        return;
  593.                    }
  594.                  
  595.                    this.checkPowerUps();
  596.                  
  597.                }
  598.              
  599.                this.updateUI();
  600.                this.isMoving = false;
  601.            }
  602.            checkCollision(x, y) {
  603.                if (x < 1 || x >= this.cols - 1 || y < 1 || y >= this.rows - 1) return true;
  604.                
  605.                 for (const wall of [...this.walls, ...this.mirrorWalls]) {
  606.                     if (x >= wall.x && x < wall.x + wall.width && y >= wall.y && y < wall.y + wall.height) return true;
  607.                 }
  608.                
  609.                 for (const reflection of this.reflections) {
  610.                     if (reflection.x === x && reflection.y === y) {
  611.                        const typeColors = { 1: 'Purple', 2: 'Orange', 3: 'Green' };
  612.                         this.showMessage(`Blocked by ${typeColors[reflection.type]} reflection!`);
  613.                         console.log(`Collision: Player at (${x},${y}) hit ${typeColors[reflection.type]} at (${reflection.x},${reflection.y})`);
  614.                         return true;
  615.                     }
  616.                 }
  617.                
  618.                 return false;
  619.             }
  620.             updateReflections(dx, dy) {
  621.                 document.querySelectorAll('.reflection').forEach(r => r.remove());
  622.                 this.reflections = [];
  623.                
  624.                 let baseReflections = Math.min(5 + Math.floor(this.level / 2), 8) + this.reflectionModifier;
  625.                 baseReflections = Math.max(0, baseReflections);
  626.                
  627.                 this.mirrorWalls.forEach((mirror, index) => {
  628.                     const reflectionsPerMirror = Math.min(1 + Math.floor(this.level / 3), 3);
  629.                    
  630.                     for (let i = 0; i < reflectionsPerMirror && this.reflections.length < baseReflections; i++) {
  631.                        const type = ((index + i) % 3) + 1;
  632.                        let refX = mirror.width > mirror.height ? this.playerPos.x + (i - 1) * 2 : 2 * mirror.x - this.playerPos.x;
  633.                         let refY = mirror.width > mirror.height ? 2 * mirror.y - this.playerPos.y : this.playerPos.y + (i - 1) * 2;
  634.                        
  635.                         const delay = this.moveHistory[Math.max(0, this.moveHistory.length - 3)];
  636.                         if (delay) {
  637.                             if (type === 1) {
  638.                                 refX += delay.dx;
  639.                                 refY += delay.dy;
  640.                             } else if (type === 2) {
  641.                                 refX -= delay.dx;
  642.                                 refY -= delay.dy;
  643.                             }
  644.                         }
  645.                         if (type === 3) {
  646.                             refX += Math.floor(Math.sin(Date.now() / 1000 + i) * 2);
  647.                             refY += Math.floor(Math.cos(Date.now() / 1000 + i) * 2);
  648.                         }
  649.                        
  650.                         if (this.activePowerUps.has('invisibility')) {
  651.                             // Invert direction to path away
  652.                             refX -= (this.playerPos.x - refX) / 2;
  653.                             refY -= (this.playerPos.y - refY) / 2;
  654.                         } else {
  655.                             // Normal attract
  656.                             refX += (this.playerPos.x - refX) / 4; // Slight pull towards player
  657.                             refY += (this.playerPos.y - refY) / 4;
  658.                         }
  659.                        
  660.                         // Add slight random movement like Pac-Man ghosts
  661.                         const randomDx = Math.floor(Math.random() * 3 - 1);
  662.                         const randomDy = Math.floor(Math.random() * 3 - 1);
  663.                         refX += randomDx;
  664.                         refY += randomDy;
  665.                        
  666.                         refX = Math.round(Math.max(1, Math.min(this.cols - 2, refX)));
  667.                         refY = Math.round(Math.max(1, Math.min(this.rows - 2, refY)));
  668.                        
  669.                         let valid = true;
  670.                         for (const wall of [...this.walls, ...this.mirrorWalls]) {
  671.                             if (refX >= wall.x && refX < wall.x + wall.width && refY >= wall.y && refY < wall.y + wall.height) {
  672.                                valid = false;
  673.                                 break;
  674.                             }
  675.                         }
  676.                        
  677.                         if (valid) {
  678.                             const reflection = document.createElement('div');
  679.                             reflection.className = `reflection type-${type}`;
  680.                             reflection.style.left = refX * this.gridSize + 'px';
  681.                             reflection.style.top = refY * this.gridSize + 'px';
  682.                             this.maze.appendChild(reflection);
  683.                             this.reflections.push({ x: refX, y: refY, type });
  684.                             if (type === 2) console.log(`Orange at (${refX}, ${refY})`);
  685.                         }
  686.                     }
  687.                 });
  688.                
  689.                 // Add persistent extra reflections (static)
  690.                 this.extraReflections.forEach(extra => {
  691.                     // Add slight random to extras too for consistency
  692.                     extra.x += Math.floor(Math.random() * 3 - 1);
  693.                     extra.y += Math.floor(Math.random() * 3 - 1);
  694.                     extra.x = Math.round(Math.max(1, Math.min(this.cols - 2, extra.x)));
  695.                     extra.y = Math.round(Math.max(1, Math.min(this.rows - 2, extra.y)));
  696.                    
  697.                     const reflection = document.createElement('div');
  698.                     reflection.className = `reflection type-${extra.type}`;
  699.                     reflection.style.left = extra.x * this.gridSize + 'px';
  700.                     reflection.style.top = extra.y * this.gridSize + 'px';
  701.                     this.maze.appendChild(reflection);
  702.                     this.reflections.push(extra);
  703.                 });
  704.                
  705.                 document.getElementById('reflectionCount').textContent = this.reflections.length;
  706.             }
  707.             checkSurrounded() {
  708.                 let adjacent = 0;
  709.                 const positions = [
  710.                     { x: this.playerPos.x - 1, y: this.playerPos.y },
  711.                     { x: this.playerPos.x + 1, y: this.playerPos.y },
  712.                     { x: this.playerPos.x, y: this.playerPos.y - 1 },
  713.                     { x: this.playerPos.x, y: this.playerPos.y + 1 },
  714.                     { x: this.playerPos.x - 1, y: this.playerPos.y - 1 },
  715.                     { x: this.playerPos.x + 1, y: this.playerPos.y - 1 },
  716.                     { x: this.playerPos.x - 1, y: this.playerPos.y + 1 },
  717.                     { x: this.playerPos.x + 1, y: this.playerPos.y + 1 }
  718.                 ];
  719.                
  720.                 for (const pos of positions) {
  721.                     for (const ref of this.reflections) {
  722.                         if (Math.round(ref.x) === pos.x && Math.round(ref.y) === pos.y) {
  723.                            adjacent++;
  724.                             break;
  725.                         }
  726.                     }
  727.                 }
  728.                
  729.                 if (adjacent >= 1 && this.player) this.player.classList.add('danger-pulse');
  730.                 else if (this.player) this.player.classList.remove('danger-pulse');
  731.                
  732.                 return adjacent >= 2;
  733.             }
  734.             loseLife() {
  735.                 this.lives--;
  736.                 if (this.lives < 0) {
  737.                    this.gameOver();
  738.                } else {
  739.                    this.showMessage(`Surrounded! Lives: ${this.lives}`);
  740.                    setTimeout(() => this.resetLevel(), 2000);
  741.                 }
  742.             }
  743.             gameOver() {
  744.                 this.showMessage('Game Over! Press R to restart');
  745.                 this.level = 1;
  746.                 this.lives = 3;
  747.                 setTimeout(() => this.resetLevel(), 3000);
  748.             }
  749.             checkGoal() {
  750.                 return this.playerPos.x === this.goalPos.x && this.playerPos.y === this.goalPos.y;
  751.             }
  752.             checkPowerUps() {
  753.                 this.powerUps = this.powerUps.filter(powerUp => {
  754.                     if (this.playerPos.x === powerUp.pos.x && this.playerPos.y === powerUp.pos.y) {
  755.                        this.activatePowerUp(powerUp.type);
  756.                         powerUp.element.remove();
  757.                         return false;
  758.                     }
  759.                     return true;
  760.                 });
  761.             }
  762.             activatePowerUp(type) {
  763.                 this.activePowerUps.add(type);
  764.                 let message = '';
  765.                 switch (type) {
  766.                     case 'life-up':
  767.                         this.lives++;
  768.                         message = 'Life Up! +1 Life';
  769.                         break;
  770.                     case 'speed-boost':
  771.                         this.player.classList.add('speed-boost');
  772.                         message = 'Speed Boost! x2 Speed';
  773.                         break;
  774.                     case 'plus-reflections':
  775.                         for (let i = 0; i < 2; i++) {
  776.                            this.addRandomReflection();
  777.                        }
  778.                        message = '+2 Reflections!';
  779.                        break;
  780.                    case 'minus-reflections':
  781.                        if (this.extraReflections.length > 0) {
  782.                             const idx = Math.floor(Math.random() * this.extraReflections.length);
  783.                             this.extraReflections.splice(idx, 1);
  784.                         } else {
  785.                             this.reflectionModifier -= 1;
  786.                         }
  787.                         message = '-1 Reflection!';
  788.                         break;
  789.                     case 'invisibility':
  790.                         this.player.classList.add('invisible');
  791.                         message = 'Invisibility! Reflections Flee';
  792.                         break;
  793.                     case 'teleport':
  794.                         this.teleportPlayer();
  795.                         message = 'Teleport! Warped';
  796.                         this.activePowerUps.delete('teleport'); // One-time
  797.                         break;
  798.                     case 'shield':
  799.                         message = 'Shield! Blocks One Surround';
  800.                         break;
  801.                 }
  802.                 this.showMessage(message);
  803.                 this.updateUI();
  804.             }
  805.             addRandomReflection() {
  806.                 let refX, refY, attempts = 0;
  807.                 do {
  808.                     refX = 1 + Math.floor(Math.random() * (this.cols - 2));
  809.                     refY = 1 + Math.floor(Math.random() * (this.rows - 2));
  810.                     attempts++;
  811.                 } while (this.checkCollision(refX, refY) && attempts < 100);
  812.                
  813.                 if (attempts < 100) {
  814.                    const type = Math.floor(Math.random() * 3) + 1;
  815.                    this.extraReflections.push({ x: refX, y: refY, type });
  816.                }
  817.            }
  818.            teleportPlayer() {
  819.                let newX, newY, attempts = 0;
  820.                do {
  821.                    newX = 1 + Math.floor(Math.random() * (this.cols - 2));
  822.                    newY = 1 + Math.floor(Math.random() * (this.rows - 2));
  823.                    attempts++;
  824.                } while (this.checkCollision(newX, newY) && attempts < 100);
  825.              
  826.                if (attempts < 100) {
  827.                    this.playerPos.x = newX;
  828.                    this.playerPos.y = newY;
  829.                    this.updatePlayerPosition();
  830.                }
  831.            }
  832.            levelComplete() {
  833.                this.showMessage(`Level ${this.level} Complete!`);
  834.                setTimeout(() => {
  835.                     this.level++;
  836.                     this.nextLevel();
  837.                 }, 2000);
  838.             }
  839.             nextLevel() {
  840.                 this.moves = 0;
  841.                 this.moveHistory = [];
  842.                 this.reflections = [];
  843.                 this.extraReflections = [];
  844.                 this.reflectionModifier = 0;
  845.                 this.activePowerUps.clear();
  846.                 this.isMoving = false;
  847.                
  848.                 this.setupMaze();
  849.                 this.createPlayer();
  850.                 this.createGoal();
  851.                 this.createPowerUps();
  852.                 this.updateUI();
  853.                
  854.                 document.getElementById('message').style.display = 'none';
  855.             }
  856.             resetLevel() {
  857.                 this.moves = 0;
  858.                 this.moveHistory = [];
  859.                 this.reflections = [];
  860.                 this.extraReflections = [];
  861.                 this.reflectionModifier = 0;
  862.                 this.activePowerUps.clear();
  863.                 this.isMoving = false;
  864.                
  865.                 if (this.level === 1) {
  866.                     this.playerPos = { x: 1, y: 1 };
  867.                     this.goalPos = { x: 18, y: 13 };
  868.                 }
  869.                
  870.                 this.setupMaze();
  871.                 this.createPlayer();
  872.                 this.createGoal();
  873.                 this.createPowerUps();
  874.                 this.updateUI();
  875.                
  876.                 document.getElementById('message').style.display = 'none';
  877.             }
  878.             showMessage(text) {
  879.                 const message = document.getElementById('message');
  880.                 message.textContent = text;
  881.                 message.style.display = 'block';
  882.                 if (!text.includes('Game Over')) {
  883.                     setTimeout(() => message.style.display = 'none', 1500);
  884.                 }
  885.             }
  886.             updateUI() {
  887.                 document.getElementById('level').textContent = this.level;
  888.                 document.getElementById('moves').textContent = this.moves;
  889.                 document.getElementById('reflectionCount').textContent = this.reflections.length;
  890.                 document.getElementById('lives').textContent = this.lives;
  891.             }
  892.         }
  893.         const game = new MirrorMindMaze();
  894.     </script>
  895. </body>
  896. </html>
  897.  
Advertisement
Add Comment
Please, Sign In to add comment