<html lang="de"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> <title>HYPERSTITION: SHENZHEN <style>  * {   box-sizing: border-box;   touch-action: manipulation;  }  html, body {  width: 100%;  height: 100%;  overflow: hidden;  background: #020206;  color: #00ffcc;  font-family: 'Courier New', 'PingFang SC', 'Microsoft YaHei', monospace;  margin: 0;  padding: 6px;  display: flex;  justify-content: center;  align-items: flex-start;  user-select: none;  -webkit-user-select: none;  }    #game-wrapper {  position: relative;  width: 100%;  max-width: 380px;  display: flex;  flex-direction: column;  gap: 5px;  justify-content: flex-start;  }   /* CYBERPUNK CHINESE TITLE SCREEN */  #title-screen {  position: absolute;  top: 0; left: 0; right: 0; bottom: 0;  background: radial-gradient(circle at center, #0e051c 0%, #020208 100%);  border: 2px solid #ff0055;  box-shadow: inset 0 0 30px rgba(255, 0, 85, 0.5), 0 0 20px rgba(0, 255, 204, 0.3);  display: flex;  flex-direction: column;  justify-content: center;  align-items: center;  z-index: 500;  padding: 15px;  text-align: center;  overflow: hidden;  }   /* CRT Scanline Overlay Effect */  #title-screen::before {  content: " ";  display: block;  position: absolute;  top: 0; left: 0; bottom: 0; right: 0;  background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.35) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.05), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.05));  z-index: 2;  background-size: 100% 3px, 6px 100%;  pointer-events: none;  }   /* Watermark Chinese Characters in Background */  .title-bg-kanji {  position: absolute;  font-size: 110px;  color: rgba(255, 0, 85, 0.05);  font-weight: 900;  z-index: 1;  pointer-events: none;  line-height: 0.9;  letter-spacing: -5px;  }   .title-main-box {  z-index: 3;  border-top: 1.5px solid #00ffcc;  border-bottom: 1.5px solid #00ffcc;  padding: 12px 10px;  width: 100%;  background: rgba(8, 3, 18, 0.75);  box-shadow: 0 0 15px rgba(0, 255, 204, 0.15);  }   .title-kanji-top {  font-size: 13px;  color: #ffcc00;  letter-spacing: 5px;  text-shadow: 0 0 8px #ffcc00;  margin-bottom: 4px;  font-weight: bold;  }   .title-glitch {  font-size: 21px;  font-weight: 900;  color: #ff0055;  text-shadow: 3px 0 #00ffcc, -2px 0 #ffcc00;  letter-spacing: 2px;  line-height: 1.1;  animation: glitch 1.6s infinite alternate;  }   .title-sub {  font-size: 11px;  color: #00ffcc;  margin-top: 6px;  letter-spacing: 2px;  text-shadow: 0 0 8px #00ffcc;  font-weight: bold;  }   .title-tags {  display: flex;  gap: 6px;  margin: 12px 0 6px 0;  z-index: 3;  }   .tag-badge {  font-size: 8px;  background: #160829;  border: 1px solid #ff0055;  color: #ff0055;  padding: 2px 6px;  border-radius: 2px;  letter-spacing: 1px;  }   .title-info {  z-index: 3;  font-size: 8px;  color: #8899a6;  margin: 10px 0 18px 0;  line-height: 1.5;  border-left: 2px solid #00ffcc;  padding-left: 8px;  text-align: left;  background: rgba(0, 0, 0, 0.4);  width: 100%;  }   .start-btn {  z-index: 3;  background: #ff0055;  border: 1.5px solid #00ffcc;  color: #020208;  font-family: inherit;  font-weight: 900;  font-size: 11px;  padding: 10px 22px;  cursor: pointer;  box-shadow: 0 0 15px rgba(255, 0, 85, 0.8);  letter-spacing: 1.5px;  animation: pulse 1.2s infinite alternate;  }  .start-btn:active {  background: #00ffcc;  color: #000;  box-shadow: 0 0 20px #00ffcc;  }   /* GAME UI */  #ui-stats {  width: 100%;  display: grid;  grid-template-columns: repeat(4, 1fr);  gap: 2px;  font-weight: bold;  color: #ff0055;  font-size: 9px;  background: #08030f;  padding: 4px;  border: 1px solid #ff0055;  box-shadow: 0 0 6px rgba(255, 0, 85, 0.3);  }  #ui-stats div { text-align: center; white-space: nowrap; }    #game-container {  position: relative;  width: 100%;  }   #map {  background: #000;  border: 1.5px solid #ff0055;  box-shadow: 0 0 8px rgba(255, 0, 85, 0.25);  padding: 2px;  width: 100%;  height: 250px;  display: grid;  grid-template-columns: repeat(22, 1fr);  grid-template-rows: repeat(14, 1fr);  align-items: center;  justify-items: center;  }   .t {  width: 100%;  height: 100%;  display: flex;  align-items: center;  justify-content: center;  font-size: 11px;  font-weight: bold;  line-height: 1;  }   /* AIMING SKILL-CHECK MODAL */  #aim-modal {  display: none;  position: absolute;  top: 50%; left: 50%;  transform: translate(-50%, -50%);  width: 88%;  background: rgba(6, 2, 14, 0.95);  border: 2px solid #00ffcc;  box-shadow: 0 0 20px rgba(0, 255, 204, 0.6);  padding: 10px;  flex-direction: column;  align-items: center;  gap: 8px;  z-index: 200;  cursor: pointer;  }  #aim-title {  color: #ff0055;  font-size: 10px;  font-weight: bold;  letter-spacing: 1px;  }  #aim-bar-container {  width: 100%;  height: 22px;  background: #000;  border: 1px solid #00ffcc;  position: relative;  overflow: hidden;  }  #aim-target-zone {  position: absolute;  top: 0; bottom: 0;  background: rgba(0, 255, 204, 0.35);  border-left: 2px solid #00ffcc;  border-right: 2px solid #00ffcc;  }  #aim-cursor {  position: absolute;  top: 0; bottom: 0;  width: 4px;  background: #ff0055;  box-shadow: 0 0 8px #ff0055, 0 0 12px #ff0055;  }  #aim-instruction {  font-size: 9px;  color: #ffcc00;  font-weight: bold;  letter-spacing: 1px;  }   #shop-modal {  display: none;  position: absolute;  top: 4px; left: 4px; right: 4px; bottom: 4px;  background: rgba(4, 2, 10, 0.98);  border: 1.5px solid #ffcc00;  box-shadow: 0 0 15px rgba(255, 204, 0, 0.4);  padding: 6px;  flex-direction: column;  z-index: 100;  }  #shop-title {  color: #ffcc00;  font-size: 10px;  font-weight: bold;  text-align: center;  border-bottom: 1px dashed #ffcc00;  padding-bottom: 2px;  margin-bottom: 4px;  }  .shop-items {  display: flex;  flex-direction: column;  gap: 4px;  overflow-y: auto;  flex: 1;  }  .shop-btn {  background: #0a0a1a;  border: 1px solid #00ffcc;  color: #00ffcc;  padding: 4px 6px;  font-size: 9px;  font-family: inherit;  cursor: pointer;  text-align: left;  display: flex;  justify-content: space-between;  }  .shop-btn:active { background: #00ffcc; color: #000; }  .close-shop {  margin-top: 4px;  background: #ff0055;  color: #fff;  border: none;  padding: 5px;  font-weight: bold;  cursor: pointer;  text-align: center;  font-size: 10px;  }   #action-panel, #inventory-panel {  width: 100%;  display: flex;  gap: 3px;  }  .action-btn, .inv-slot {  flex: 1;  background: #0f0a1c;  border: 1px solid #00ffcc;  color: #ffcc00;  font-size: 9px;  padding: 5px 1px;  text-align: center;  cursor: pointer;  border-radius: 2px;  white-space: nowrap;  overflow: hidden;  text-overflow: ellipsis;  font-weight: bold;  }  .action-btn { background: #240a18; border-color: #ff0055; color: #ff0055; }  .action-btn:active, .inv-slot:active { background: #00ffcc; color: #000; }    #log {  width: 100%;  height: 42px;  background: #05020c;  border: 1px solid #222;  color: #ffcc00;  font-size: 9px;  padding: 3px 5px;  overflow-y: auto;  line-height: 1.2;  }   .controls-wrapper {  display: flex;  justify-content: center;  margin-top: 2px;  }   .controls {  display: grid;  grid-template-columns: repeat(3, 1fr);  gap: 4px;  width: 170px;  }  .btn {  background: #0f0f24;  color: #00ffcc;  border: 1px solid #00ffcc;  padding: 7px 0;  font-size: 12px;  font-weight: bold;  text-align: center;  border-radius: 3px;  cursor: pointer;  }  .btn:active { background: #00ffcc; color: #000; }    .p-player { color: #00ffcc; }  .p-psychotic { color: #ff0055; animation: blink 0.4s infinite; }  .e-triad { color: #ff3333; }  .e-ministry { color: #ffcc00; }  .e-drone { color: #ff00ff; }  .i-vendor { color: #ffcc00; text-shadow: 0 0 5px #ffcc00; }  .i-item { color: #00ff66; }  .i-exit { color: #00ffcc; text-shadow: 0 0 6px #00ffcc; font-size: 12px; }  .tile-wall { color: #3d1c3d; }  .tile-floor { color: #160f24; }  .fog-hidden { color: #000000; }  .fog-explored { color: #12081c; }  .stunned { color: #777777 !important; }   @keyframes glitch {  0% { transform: skew(0deg); }  80% { transform: skew(0deg); }  85% { transform: skew(3deg); }  90% { transform: skew(-3deg); }  100% { transform: skew(0deg); }  }   @keyframes pulse {  0% { transform: scale(1); box-shadow: 0 0 10px rgba(255, 0, 85, 0.6); }  100% { transform: scale(1.04); box-shadow: 0 0 20px rgba(255, 0, 85, 0.9); }  }   @keyframes blink { 0% { opacity: 1; } 50% { opacity: 0.2; } 100% { opacity: 1; } } <body> <div id="game-wrapper">  <div id="title-screen"> <div class="title-bg-kanji">超迷信<br>深圳 <div class="title-main-box"> <div class="title-kanji-top">【 超 迷 信 】 <div class="title-glitch">HYPERSTITION <div class="title-sub">SHENZHEN // 深圳 <div class="title-tags"> <span class="tag-badge">加速主义 <span class="tag-badge">赛博朋克 <span class="tag-badge">特区 S-01 <div class="title-info"> > SYSTEM: NEURAL INTERFACE ONLINE<br> > LOCATION: SHENZHEN SEZ [深圳特区]<br> > WARNING: 人性流失 (HUMANITY DEPLETION) <button class="start-btn" onclick="startGame()">[ 网络接入 // ACCESS ]  <div id="ui-stats"> <div id="stat-level">ZONE: S-01 <div id="stat-hp">INT: 35 <div id="stat-ram">RAM: 4/4 <div id="stat-psyche">HUM: 100% <div id="stat-food">CAL: 100% <div id="stat-ammo">AMMO: 8 <div id="stat-atk">GUN: 4 <div id="stat-cred">¥50 <div id="game-container"> <div id="map">  <div id="aim-modal" onclick="resolveShot()"> <div id="aim-title">=== ZIELERFASSUNG // LOCK-ON === <div id="aim-bar-container"> <div id="aim-target-zone"> <div id="aim-cursor"> <div id="aim-instruction">[F] / [SPACE] / TIPPE ZUM FEUERN <div id="shop-modal"> <div id="shop-title">=== SHENZHEN TAOBAO-LOOM [¥] === <div class="shop-items"> <button class="shop-btn" onclick="buyShopItem('Sheng-Stim', 35, 0)"><span>[1] Sheng-Stim (+20 Int)<span>¥35 <button class="shop-btn" onclick="buyShopItem('Synth-Baozi', 15, 0)"><span>[2] Synth-Baozi (+50% Cal)<span>¥15 <button class="shop-btn" onclick="buyShopItem('Mag-Rounds', 25, 0)"><span>[3] Kinetic-Mag (+6 Ammo)<span>¥25 <button class="shop-btn" onclick="buyShopItem('Xeno-Blade', 110, 25)"><span>[4] Xeno-Blade (+3 ATK)<span>¥110 (-25% H) <button class="shop-btn" onclick="buyShopItem('Subdermal-Weave', 110, 25)"><span>[5] Subdermal (+15 HP)<span>¥110 (-25% H) <button class="shop-btn" onclick="buyShopItem('Teleoplex-Chip', 110, 25)"><span>[6] Teleoplex (+2 RAM)<span>¥110 (-25% H) <div class="close-shop" onclick="closeShop()">TRENNEN [Ø] <div id="action-panel"> <div class="action-btn" onclick="shootNearest()">[F] KINETIK-SCHUSS <div class="action-btn" onclick="hackEnemy()">[H] OVERLOAD <div id="inventory-panel"> <div class="inv-slot" onclick="useItem(0)" id="inv-0">[1] - <div class="inv-slot" onclick="useItem(1)" id="inv-1">[2] - <div class="inv-slot" onclick="useItem(2)" id="inv-2">[3] - <div class="inv-slot" onclick="useItem(3)" id="inv-3">[4] - <div id="log"> <div class="controls-wrapper"> <div class="controls"> <div> <div class="btn" onclick="handleInput(0, -1)">▲ <div> <div class="btn" onclick="handleInput(-1, 0)">◄ <div class="btn" onclick="handleInput(0, 0)">Wait <div class="btn" onclick="handleInput(1, 0)">► <div> <div class="btn" onclick="handleInput(0, 1)">▼ <div> <script> const WIDTH = 22; const HEIGHT = 14; const MAX_INV = 4; const VISIBILITY_RADIUS = 6;  let audioCtx = null;  function initAudio() {  if (!audioCtx) {  audioCtx = new (window.AudioContext || window.webkitAudioContext)();  }  if (audioCtx.state === 'suspended') {  audioCtx.resume();  } }  function startGame() {  initAudio();  playSfx('exit');  document.getElementById('title-screen').style.display = 'none'; }  function playSfx(type) {  initAudio();  if (!audioCtx) return;   const now = audioCtx.currentTime;  const osc = audioCtx.createOscillator();  const gain = audioCtx.createGain();  osc.connect(gain);  gain.connect(audioCtx.destination);   if (type === 'move') {  osc.type = 'triangle';  osc.frequency.setValueAtTime(110, now);  osc.frequency.exponentialRampToValueAtTime(40, now + 0.04);  gain.gain.setValueAtTime(0.04, now);  gain.gain.exponentialRampToValueAtTime(0.001, now + 0.04);  osc.start(now);  osc.stop(now + 0.04);  } else if (type === 'shoot') {  osc.type = 'sawtooth';  osc.frequency.setValueAtTime(700, now);  osc.frequency.exponentialRampToValueAtTime(60, now + 0.12);  gain.gain.setValueAtTime(0.12, now);  gain.gain.exponentialRampToValueAtTime(0.001, now + 0.12);  osc.start(now);  osc.stop(now + 0.12);  } else if (type === 'hit') {  osc.type = 'square';  osc.frequency.setValueAtTime(140, now);  osc.frequency.exponentialRampToValueAtTime(30, now + 0.18);  gain.gain.setValueAtTime(0.15, now);  gain.gain.exponentialRampToValueAtTime(0.001, now + 0.18);  osc.start(now);  osc.stop(now + 0.18);  } else if (type === 'item') {  osc.type = 'square';  osc.frequency.setValueAtTime(440, now);  osc.frequency.setValueAtTime(880, now + 0.06);  gain.gain.setValueAtTime(0.08, now);  gain.gain.exponentialRampToValueAtTime(0.001, now + 0.18);  osc.start(now);  osc.stop(now + 0.18);  } else if (type === 'buy') {  osc.type = 'square';  osc.frequency.setValueAtTime(523, now);  osc.frequency.setValueAtTime(659, now + 0.06);  osc.frequency.setValueAtTime(783, now + 0.12);  gain.gain.setValueAtTime(0.08, now);  gain.gain.exponentialRampToValueAtTime(0.001, now + 0.22);  osc.start(now);  osc.stop(now + 0.22);  } else if (type === 'hack') {  osc.type = 'sawtooth';  osc.frequency.setValueAtTime(220, now);  osc.frequency.linearRampToValueAtTime(880, now + 0.08);  osc.frequency.linearRampToValueAtTime(330, now + 0.16);  gain.gain.setValueAtTime(0.1, now);  gain.gain.exponentialRampToValueAtTime(0.001, now + 0.18);  osc.start(now);  osc.stop(now + 0.18);  } else if (type === 'exit') {  // 8-Bit Chiptune Warp / Level Clear Sound  osc.type = 'square';  const notes = [261.63, 329.63, 392.00, 523.25, 659.25, 783.99, 1046.50];  const step = 0.035;  notes.forEach((freq, i) => {  osc.frequency.setValueAtTime(freq, now + i * step);  });  gain.gain.setValueAtTime(0.1, now);  gain.gain.exponentialRampToValueAtTime(0.001, now + notes.length * step);  osc.start(now);  osc.stop(now + notes.length * step);  } else if (type === 'gameover') {  osc.type = 'sawtooth';  osc.frequency.setValueAtTime(300, now);  osc.frequency.exponentialRampToValueAtTime(30, now + 0.5);  gain.gain.setValueAtTime(0.2, now);  gain.gain.exponentialRampToValueAtTime(0.001, now + 0.5);  osc.start(now);  osc.stop(now + 0.5);  } }  let player = {  x: 0, y: 0,  hp: 35, maxHp: 35,  ram: 4, maxRam: 4,  humanity: 100,  hunger: 100,  ammo: 8,  atk: 4,  creds: 50,  level: 1,  noise: 0,  inventory: ['Sheng-Stim', 'Synth-Baozi'] };  let map = []; let visibleMap = []; let exploredMap = []; let enemies = []; let items = []; let vendors = []; let exitGate = { x: 0, y: 0 }; let turnCounter = 0; let inShop = false;  // AIMING SKILL CHECK VARIABLES let isAiming = false; let aimPos = 0; let aimDir = 1; let aimSpeed = 2.5; let aimAnimFrame = null; let currentAimTargetIdx = -1;  function log(msg) {  const logBox = document.getElementById('log');  if (logBox) {  logBox.innerHTML += `> ${msg}
`;  logBox.scrollTop = logBox.scrollHeight;  } }  function initGame() {  log("SONDERWIRTSCHAFTSZONE LÄDT... NETZWERK GENERIERT.");  generateCitySector();  updateVision();  render();   document.addEventListener('keydown', e => {  initAudio();   if (isAiming) {  if (e.key === 'f' || e.key === 'F' || e.key === ' ' || e.key === 'Enter') {  resolveShot();  }  return;  }   if (inShop) {  if (e.key === 'Escape') closeShop();  return;  }   if (e.key === 'ArrowUp' || e.key === 'w') handleInput(0, -1);  if (e.key === 'ArrowDown' || e.key === 's') handleInput(0, 1);  if (e.key === 'ArrowLeft' || e.key === 'a') handleInput(-1, 0);  if (e.key === 'ArrowRight' || e.key === 'd') handleInput(1, 0);  if (e.key === ' ') handleInput(0, 0);  if (e.key === 'f' || e.key === 'F') shootNearest();  if (e.key === 'h' || e.key === 'H') hackEnemy();  if (e.key >= '1' && e.key <= '4') useItem(parseInt(e.key) - 1);  }); }  function generateCitySector() {  map = Array(HEIGHT).fill(null).map(() => Array(WIDTH).fill('▓'));  exploredMap = Array(HEIGHT).fill(null).map(() => Array(WIDTH).fill(false));  visibleMap = Array(HEIGHT).fill(null).map(() => Array(WIDTH).fill(false));  enemies = [];  items = [];  vendors = [];   let blocks = [];  let attempts = 0;    while (blocks.length < 7 && attempts < 120) {  attempts++;  let w = Math.floor(Math.random() * 3) + 3;  let h = Math.floor(Math.random() * 3) + 3;  let x = Math.floor(Math.random() * (WIDTH - w - 2)) + 1;  let y = Math.floor(Math.random() * (HEIGHT - h - 2)) + 1;   let overlap = blocks.some(b => !(x + w + 1 < b.x || x > b.x + b.w + 1 || y + h + 1 < b.y || y > b.y + b.h + 1));  if (!overlap) {  blocks.push({ x, y, w, h, center: { x: Math.floor(x + w/2), y: Math.floor(y + h/2) } });  for (let rx = x; rx < x + w; rx++) {  for (let ry = y; ry < y + h; ry++) map[ry][rx] = '·';  }  }  }   for (let i = 0; i < blocks.length; i++) {  let distances = blocks  .map((b, idx) => ({ idx, dist: Math.hypot(b.center.x - blocks[i].center.x, b.center.y - blocks[i].center.y) }))  .filter(d => d.idx !== i)  .sort((a, b) => a.dist - b.dist);   let neighbors = distances.slice(0, 2);  neighbors.forEach(n => {  let c1 = blocks[i].center;  let c2 = blocks[n.idx].center;  let currX = c1.x, currY = c1.y;    if (Math.random() < 0.5) {  while (currX !== c2.x) { map[currY][currX] = '·'; currX += currX < c2.x ? 1 : -1; }  while (currY !== c2.y) { map[currY][currX] = '·'; currY += currY < c2.y ? 1 : -1; }  } else {  while (currY !== c2.y) { map[currY][currX] = '·'; currY += currY < c2.y ? 1 : -1; }  while (currX !== c2.x) { map[currY][currX] = '·'; currX += currX < c2.x ? 1 : -1; }  }  });  }   for (let k = 0; k < 3; k++) {  let rx = Math.floor(Math.random() * (WIDTH - 6)) + 3;  let ry = Math.floor(Math.random() * (HEIGHT - 6)) + 3;  if (Math.random() < 0.5) {  for (let len = 0; len < 5; len++) { if (rx + len < WIDTH - 1) map[ry][rx + len] = '·'; }  } else {  for (let len = 0; len < 5; len++) { if (ry + len < HEIGHT - 1) map[ry + len][rx] = '·'; }  }  }   player.x = blocks[0].center.x;  player.y = blocks[0].center.y;   let sortedByDist = blocks.slice().sort((a, b) => {  let dA = Math.hypot(a.center.x - player.x, a.center.y - player.y);  let dB = Math.hypot(b.center.x - player.x, b.center.y - player.y);  return dB - dA;  });  let furthestBlock = sortedByDist[0];  exitGate = { x: furthestBlock.center.x, y: furthestBlock.center.y };   let vendorCandidates = blocks.filter(b => b !== blocks[0] && b !== furthestBlock);  if (vendorCandidates.length > 0) {  let vBlock = vendorCandidates[0];  vendors.push({ x: vBlock.center.x, y: vBlock.center.y, char: '¥' });  } else if (blocks.length > 1) {  vendors.push({ x: blocks[1].x + 1, y: blocks[1].y + 1, char: '¥' });  }   blocks.forEach((b) => {  let rand = Math.random();    let isReserved = (x, y) => (x === player.x && y === player.y) ||   (x === exitGate.x && y === exitGate.y) ||   vendors.some(v => v.x === x && v.y === y);   let enemyX = b.x + 1;  let enemyY = b.y + 1;  if (!isReserved(enemyX, enemyY) && rand > 0.3) {  let enemyType = rand < 0.6 ? 'triad' : (rand < 0.85 ? 'ministry' : 'drone');  enemies.push({  x: enemyX, y: enemyY,  type: enemyType,  char: enemyType === 'triad' ? '帮' : (enemyType === 'ministry' ? '官' : '∆'),  hp: enemyType === 'triad' ? 10 : (enemyType === 'ministry' ? 16 : 8),  atk: enemyType === 'triad' ? 4 : (enemyType === 'ministry' ? 7 : 8),  range: enemyType === 'triad' ? 1.5 : (enemyType === 'ministry' ? 4 : 6),  bounty: enemyType === 'triad' ? 25 : (enemyType === 'ministry' ? 45 : 60),  stunned: 0  });  }   let itemX = b.x + b.w - 2;  let itemY = b.y + b.h - 2;  if (!isReserved(itemX, itemY) && Math.random() > 0.35) {  let itemRand = Math.random();  let type = itemRand < 0.4 ? 'Sheng-Stim' : (itemRand < 0.7 ? 'Synth-Baozi' : 'Mag-Rounds');  let char = type === 'Sheng-Stim' ? '生' : (type === 'Synth-Baozi' ? '包' : '⌖');  items.push({ x: itemX, y: itemY, type, char });  }  }); }  function updateVision() {  for (let y = 0; y < HEIGHT; y++) {  for (let x = 0; x < WIDTH; x++) visibleMap[y][x] = false;  }   for (let angle = 0; angle < 360; angle += 5) {  let rad = angle * (Math.PI / 180);  let dx = Math.cos(rad);  let dy = Math.sin(rad);  let cx = player.x + 0.5;  let cy = player.y + 0.5;   for (let d = 0; d < VISIBILITY_RADIUS; d++) {  let tileX = Math.floor(cx);  let tileY = Math.floor(cy);   if (tileX >= 0 && tileX < WIDTH && tileY >= 0 && tileY < HEIGHT) {  visibleMap[tileY][tileX] = true;  exploredMap[tileY][tileX] = true;  if (map[tileY][tileX] === '▓') break;  }  cx += dx;  cy += dy;  }  } }  function handleInput(dx, dy) {  initAudio();  if (player.hp <= 0 || inShop || isAiming) return;   let newX = player.x + dx;  let newY = player.y + dy;   if (map[newY][newX] !== '▓') {  let enemyIdx = enemies.findIndex(e => e.x === newX && e.y === newY);  let vendorIdx = vendors.findIndex(v => v.x === newX && v.y === newY);   if (enemyIdx !== -1) {  attackEnemyMelee(enemyIdx);  } else if (vendorIdx !== -1) {  openShop();  return;  } else {  player.x = newX;  player.y = newY;  playSfx('move');  checkItems();  checkExit();  }  endTurn();  } }  function openShop() {  inShop = true;  playSfx('buy');  document.getElementById('shop-modal').style.display = 'flex';  log(`Verbindung mit Automat [¥] hergestellt.`); }  function closeShop() {  inShop = false;  document.getElementById('shop-modal').style.display = 'none';  render(); }  function buyShopItem(itemType, cost, humanityCost) {  initAudio();  if (player.creds < cost) {  log(`FEHLER: Zu wenig Yuan! (¥${cost})`);  return;  }   playSfx('buy');   if (humanityCost > 0) {  player.creds -= cost;  player.humanity = Math.max(0, player.humanity - humanityCost);   if (itemType === 'Xeno-Blade') player.atk += 3;  if (itemType === 'Subdermal-Weave') { player.maxHp += 15; player.hp += 15; }  if (itemType === 'Teleoplex-Chip') { player.maxRam += 2; player.ram += 2; }   log(`CYBERWARE: ${itemType}. Menschlichkeit: ${player.humanity}%.`);    if (player.humanity <= 30) {  log(`HYPERSTITION: Cyber-Dämon [魔]!`);  }  } else {  if (itemType === 'Mag-Rounds') {  player.creds -= cost;  player.ammo += 6;  log(`Magazin [⌖] erworben (+6 Ammo).`);  } else {  if (player.inventory.length < MAX_INV) {  player.creds -= cost;  player.inventory.push(itemType);  log(`${itemType} verstaut.`);  } else {  log(`KAUF ABGEBROCHEN: Inventar voll!`);  }  }  }  render(); }  function shootNearest() {  initAudio();  if (player.hp <= 0 || inShop || isAiming) return;  if (player.ammo <= 0) {  log(`MAGAZIN LEER!`);  return;  }   let targetIdx = -1;  let minDistance = 999;   enemies.forEach((e, idx) => {  if (visibleMap[e.y][e.x]) {  let dist = Math.hypot(e.x - player.x, e.y - player.y);  if (dist < minDistance) {  minDistance = dist;  targetIdx = idx;  }  }  });   if (targetIdx !== -1) {  currentAimTargetIdx = targetIdx;  startAimMiniGame();  } else {  log(`Kein Ziel sichtbar.`);  } }  function startAimMiniGame() {  isAiming = true;  aimPos = 0;  aimDir = 1;  aimSpeed = 2.4 + Math.random() * 1.6;   let zoneLeft = 30 + Math.floor(Math.random() * 25);  let zoneWidth = 20;   let targetZoneElem = document.getElementById('aim-target-zone');  targetZoneElem.style.left = zoneLeft + '%';  targetZoneElem.style.width = zoneWidth + '%';  targetZoneElem.dataset.min = zoneLeft;  targetZoneElem.dataset.max = zoneLeft + zoneWidth;   document.getElementById('aim-modal').style.display = 'flex';  updateAimLoop(); }  function updateAimLoop() {  if (!isAiming) return;   aimPos += aimSpeed * aimDir;  if (aimPos >= 100) {  aimPos = 100;  aimDir = -1;  } else if (aimPos <= 0) {  aimPos = 0;  aimDir = 1;  }   document.getElementById('aim-cursor').style.left = aimPos + '%';  aimAnimFrame = requestAnimationFrame(updateAimLoop); }  function resolveShot() {  if (!isAiming) return;  cancelAnimationFrame(aimAnimFrame);  isAiming = false;  document.getElementById('aim-modal').style.display = 'none';   player.ammo--;  player.noise += 3;   let targetZoneElem = document.getElementById('aim-target-zone');  let min = parseFloat(targetZoneElem.dataset.min);  let max = parseFloat(targetZoneElem.dataset.max);  let center = min + (max - min) / 2;   let e = enemies[currentAimTargetIdx];   if (!e) {  endTurn();  return;  }   if (aimPos >= min && aimPos <= max) {  let isCrit = Math.abs(aimPos - center) <= 3.5;  let bonusAtk = player.humanity <= 30 ? 6 : 0;  let dmg = player.atk + bonusAtk + Math.floor(Math.random() * 4);  if (isCrit) dmg = Math.floor(dmg * 1.6) + 4;   playSfx('shoot');  if (isCrit) {  log(`CRITICAL LOCK! [${e.char}] kritisch getroffen für ${dmg} DMG!`);  } else {  log(`TREFFER! Schuss auf [${e.char}] für ${dmg} DMG!`);  }   e.hp -= dmg;  if (e.hp <= 0) {  player.creds += e.bounty;  log(`[${e.char}] eliminiert! +¥${e.bounty}.`);  enemies.splice(currentAimTargetIdx, 1);  }  } else {  playSfx('hit');  log(`FEHLSCHUSS! Zielverfehlung (${Math.round(aimPos)}%).`);  }   endTurn(); }  function hackEnemy() {  initAudio();  if (player.ram < 2 || inShop || isAiming) {  log(`RAM ZU NIEDRIG! (2 K-RAM nötig)`);  return;  }   let targetIdx = -1;  let minDistance = 999;   enemies.forEach((e, idx) => {  if (visibleMap[e.y][e.x] && e.stunned === 0) {  let dist = Math.hypot(e.x - player.x, e.y - player.y);  if (dist < minDistance) {  minDistance = dist;  targetIdx = idx;  }  }  });   if (targetIdx !== -1) {  playSfx('hack');  player.ram -= 2;  let e = enemies[targetIdx];  e.stunned = 3;  log(`OVERCLOCK auf [${e.char}]! 3 Züge gelähmt.`);  endTurn();  } else {  log(`Kein erfassbares Ziel.`);  } }  function attackEnemyMelee(idx) {  playSfx('hit');  let e = enemies[idx];  let bonusAtk = player.humanity <= 30 ? 5 : 0;  let dmg = Math.floor(player.atk * 0.7) + bonusAtk;  e.hp -= dmg;  log(`Nahkampf auf [${e.char}] für ${dmg} DMG.`);  if (e.hp <= 0) {  player.creds += e.bounty;  log(`[${e.char}] eliminiert! +¥${e.bounty}.`);  enemies.splice(idx, 1);  } }  function useItem(slot) {  initAudio();  if (player.hp <= 0 || slot >= player.inventory.length || inShop || isAiming) return;   playSfx('item');  let item = player.inventory[slot];  if (item === 'Sheng-Stim') {  player.hp = Math.min(player.maxHp, player.hp + 20);  log(`Sheng-Stim [生] (+20 HP).`);  } else if (item === 'Synth-Baozi') {  player.hunger = Math.min(100, player.hunger + 50);  player.hp = Math.min(player.maxHp, player.hp + 5);  log(`Synth-Baozi [包] (+50% Cal).`);  }   player.inventory.splice(slot, 1);  endTurn(); }  function checkItems() {  let idx = items.findIndex(i => i.x === player.x && i.y === player.y);  if (idx !== -1) {  let item = items[idx];  playSfx('item');  if (item.type === 'Mag-Rounds') {  player.ammo += 5;  log(`Magazin [⌖] aufgesammelt (+5).`);  items.splice(idx, 1);  } else {  if (player.inventory.length < MAX_INV) {  player.inventory.push(item.type);  log(`${item.type} [${item.char}] aufgesammelt.`);  items.splice(idx, 1);  } else {  log(`Inventar voll für ${item.type}.`);  }  }  } }  function checkExit() {  if (player.x === exitGate.x && player.y === exitGate.y) {  playSfx('exit');  player.level++;  log(`ACCELERATING... Betrete Zone S-0${player.level} [门].`);  generateCitySector();  } }  function endTurn() {  turnCounter++;  updateVision();   if (turnCounter % 3 === 0 && player.ram < player.maxRam) player.ram++;   if (player.humanity <= 30 && Math.random() < 0.25) {  let psychosisEffect = Math.random();  if (psychosisEffect < 0.5) {  player.hp -= 2;  playSfx('hit');  log(`HYPERSTITION! (-2 HP).`);  } else {  player.noise += 5;  log(`TIME-LOOP-PULSE!`);  }  }   if (player.noise > 0) player.noise--;   if (turnCounter % 5 === 0 && player.hunger > 0) player.hunger--;  if (player.hunger <= 0) {  player.hp--;  playSfx('hit');  log(`METABOLISCHER KOLLAPS! -1 HP.`);  }   enemies.forEach(e => {  if (e.stunned > 0) {  e.stunned--;  return;  }   let isVisible = visibleMap[e.y][e.x];  let dist = Math.hypot(e.x - player.x, e.y - player.y);   if (isVisible || dist < player.noise) {  if (dist <= e.range) {  let dmg = Math.max(1, e.atk - Math.floor(Math.random() * 2));  player.hp -= dmg;  playSfx('hit');  log(`[${e.char}] trifft dich für ${dmg} DMG!`);  } else {  let dx = Math.sign(player.x - e.x);  let dy = Math.sign(player.y - e.y);  if (map[e.y + dy][e.x + dx] !== '▓' && !enemies.some(o => o.x === e.x + dx && o.y === e.y + dy)) {  e.x += dx;  e.y += dy;  }  }  }  });   if (player.hp <= 0) {  playSfx('gameover');  log(`FLATLINE: Vom Kapital vollständig reabsorbiert. Game Over.`);  }   render(); }  function render() {  document.getElementById('stat-level').innerText = `ZONE: S-0${player.level}`;  document.getElementById('stat-hp').innerText = `INT: ${player.hp}/${player.maxHp}`;  document.getElementById('stat-ram').innerText = `RAM: ${player.ram}/${player.maxRam}`;  document.getElementById('stat-psyche').innerText = `HUM: ${player.humanity}%`;  document.getElementById('stat-food').innerText = `CAL: ${player.hunger}%`;  document.getElementById('stat-ammo').innerText = `AMMO: ${player.ammo}`;  document.getElementById('stat-atk').innerText = `GUN: ${player.atk}`;  document.getElementById('stat-cred').innerText = `¥${player.creds}`;   for (let i = 0; i < MAX_INV; i++) {  let slot = document.getElementById(`inv-${i}`);  let name = player.inventory[i] || 'Leer';  let icon = name === 'Sheng-Stim' ? '[生]' : (name === 'Synth-Baozi' ? '[包]' : (name === 'Mag-Rounds' ? '[⌖]' : ''));  slot.innerText = `[${i+1}] ${name} ${icon}`;  }   let htmlMap = '';  for (let y = 0; y < HEIGHT; y++) {  for (let x = 0; x < WIDTH; x++) {  let isVisible = visibleMap[y][x];  let isExplored = exploredMap[y][x];   if (!isExplored) {  htmlMap += '
';  continue;  }   if (x === player.x && y === player.y) {  let pClass = player.humanity <= 30 ? 'p-psychotic' : 'p-player';  let pChar = player.humanity <= 30 ? '魔' : '@';  htmlMap += `
${pChar}
`;  } else if (x === exitGate.x && y === exitGate.y) {  htmlMap += '
';  } else {  let enemy = enemies.find(e => e.x === x && e.y === y);  let item = items.find(i => i.x === x && i.y === y);  let vendor = vendors.find(v => v.x === x && v.y === y);   if (isVisible && enemy) {  let cssClass = enemy.type === 'triad' ? 'e-triad' : (enemy.type === 'ministry' ? 'e-ministry' : 'e-drone');  if (enemy.stunned > 0) cssClass += ' stunned';  htmlMap += `
${enemy.char}
`;  } else if (isVisible && vendor) {  htmlMap += `
${vendor.char}
`;  } else if (isVisible && item) {  htmlMap += `
${item.char}
`;  } else {  let char = map[y][x];  let cssClass = isVisible ? (char === '▓' ? 'tile-wall' : 'tile-floor') : 'fog-explored';  htmlMap += `
${char}
`;  }  }  }  }  document.getElementById('map').innerHTML = htmlMap; }  initGame();