/
dayekb
/
vibecoding_fallout_hacking
Обзор
Документация
Войти
/
dayekb
/
vibecoding_fallout_hacking
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
script.js
525 строк
35 KB
dayekb
upload files
07 сен 2025, 08:21
07 сен 2025, 08:21
feb8e1c
Код
Авторство
О чём код?
class FalloutHackingGame { constructor() { this.difficulty = 'novice'; this.attempts = 4; this.maxAttempts = 4; this.correctPassword = ''; this.passwordList = []; this.brackets = []; this.gameState = 'menu'; // menu, playing, success, failure this.selectedWords = []; this.difficultySettings = { novice: { wordLength: 4, wordCount: 12, attempts: 4 }, advanced: { wordLength: 5, wordCount: 15, attempts: 4 }, expert: { wordLength: 6, wordCount: 18, attempts: 4 }, master: { wordLength: 7, wordCount: 20, attempts: 4 } }; this.wordLists = { 4: [ 'DOOR', 'LOCK', 'CODE', 'SAFE', 'BANK', 'CASH', 'GOLD', 'FIRE', 'WALL', 'GATE', 'PASS', 'WORD', 'TEST', 'HACK', 'BOMB', 'CORE', 'DATA', 'FILE', 'HELP', 'JAVA', 'KILL', 'LINK', 'MAIN', … [Строка слишком длинная. Вы можете скачать файл] 5: ['LOGIN', 'ADMIN', 'GUARD', 'ALERT', 'ALARM', 'BLOCK', 'CHECK', 'CRASH', 'DEBUG', 'ERROR', 'FAULT', 'FIXED', 'HACKS', 'JUMPS', 'KILLS', 'LOCKS', 'MATCH', 'PATCH', 'QUICK', 'RESET', 'SAFER', 'TRACE', 'UNLOCK', 'VALID', 'WATCH', 'YIELD', 'ZONES', 'ABORT', 'BUILD', 'CACHE', 'DIGIT', 'EMPTY', 'FOCUS', 'GUIDE', 'HOVER', 'INPUT', 'JOINT', 'KNOBS', 'LIGHT', 'MAGIC', 'NOISE', 'OUTER', 'POWER', 'QUEUE', 'RADIO', 'SCOPE', 'TOTAL', 'UNION', 'VALUE', 'WIDTH', 'YELLS', 'ZEROS', 'ABOUT', 'BOUND', 'CLEAN', 'DENSE', 'EQUAL', 'FALSE', 'GRANT', 'HANDS', 'INDEX', 'JUMBO', 'KNIFE', 'LARGE', 'MIXED', 'NORTH', 'OTHER', 'PAPER', 'QUERY', 'RANGE', 'SHEET', 'THREE', 'UNDER', 'VITAL', 'WORLD', 'YOUTH', 'ZEBRA'], 6: ['SECURE', 'SYSTEM', 'MASTER', 'BYPASS', 'CANCEL', 'CHANGE', 'CLEAR', 'CLOSED', 'DANGER', 'DELETE', 'DENIED', 'DETECT', 'ENABLE', 'ENCODE', 'EXPORT', 'FILTER', 'FINDER', 'FIXING', 'GLOBAL', 'HACKER', 'HIDDEN', 'IMPORT', 'INSERT', 'KERNEL', 'LATEST', 'LOCKED', 'LOGINS', 'MANUAL', 'MARKER', 'NUMBER', 'ONLINE', 'OPENED', 'PARSER', 'PREFIX', 'PROTECT', 'QUERIES', 'RANDOM', 'REBOOT', 'REMOVE', 'REPAIR', 'RESCAN', 'RESULT', 'RETURN', 'SAVING', 'SCANER', 'SEARCH', 'SELECT', 'SIGNAL', 'SOURCE', 'STATUS', 'STORED', 'SUPPLY', 'SWITCH', 'TARGET', 'TIMING', 'UNLOCK', 'UPDATE', 'UPLOAD', 'USERID', 'VERIFY', 'WARNER', 'WINDOW', 'WORKER', 'WRITER', 'ABOUT', 'BEFORE', 'CALLED', 'DURING', 'EVERY', 'FAMILY', 'GIVING', 'HAPPEN', 'INSIDE', 'JUNIOR', 'KINDLE', 'LITTLE', 'MOTHER', 'NEVER', 'OFFICE', 'PERSON', 'QUICK', 'REACH', 'SISTER', 'THINK', 'UNITED', 'VISION', 'WOMAN', 'YELLOW', 'ZEBRA', 'ACCEPT', 'BETTER', 'CHANGE', 'DANGER', 'EVERY', 'FATHER', 'GROUND', 'HAPPEN', 'INSIDE', 'JUNIOR', 'KINDLE', 'LITTLE', 'MOTHER', 'NEVER', 'OFFICE', 'PERSON', 'QUICK', 'REACH', 'SISTER', 'THINK', 'UNITED', 'VISION', 'WOMAN', 'YELLOW', 'ZEBRA'], 7: ['HACKING', 'TERMINAL', 'PROTOCOL', 'SECURITY', 'PASSWORD', 'FIREWALL', 'NETWORK', 'SYSTEMS', 'PROGRAM', 'COMMAND', 'CONTROL', 'ACCESS', 'BYPASS', 'CANCEL', 'CHANGED', 'CLEARED', 'CLOSING', 'DANGERS', 'DELETED', 'DENYING', 'DETECTS', 'ENABLED', 'ENCODED', 'EXPORTS', 'FILTERS', 'FINDERS', 'FIXINGS', 'GLOBALS', 'HACKERS', 'HIDDENS', 'IMPORTS', 'INSERTS', 'KERNELS', 'LATEST', 'LOCKING', 'LOGINED', 'MANUALS', 'MARKERS', 'NUMBERS', 'ONLINED', 'OPENING', 'PARSERS', 'PREFIXS', 'PROTECTS', 'QUERIES', 'RANDOMS', 'REBOOTS', 'REMOVES', 'REPAIRS', 'RESCANS', 'RESULTS', 'RETURNS', 'SAVINGS', 'SCANERS', 'SEARCHS', 'SELECTS', 'SIGNALS', 'SOURCES', 'STATUSS', 'STOREDS', 'SUPPLYS', 'SWITCHS', 'TARGETS', 'TIMINGS', 'UNLOCKS', 'UPDATES', 'UPLOADS', 'USERIDS', 'VERIFYS', 'WARNERS', 'WINDOWS', 'WORKERS', 'WRITERS', 'ABOUT', 'BEFORE', 'BETWEEN', 'CALLING', 'DURING', 'EVERY', 'FAMILY', 'GIVING', 'HAPPEN', 'INSIDE', 'JUNIOR', 'KINDLE', 'LITTLE', 'MOTHER', 'NEVER', 'OFFICE', 'PERSON', 'QUICK', 'REACH', 'SISTER', 'THINK', 'UNITED', 'VISION', 'WOMAN', 'YELLOW', 'ZEBRA', 'ACCEPT', 'BETTER', 'CHANGE', 'DANGER', 'EVERY', 'FATHER', 'GROUND', 'HAPPEN', 'INSIDE', 'JUNIOR', 'KINDLE', 'LITTLE', 'MOTHER', 'NEVER', 'OFFICE', 'PERSON', 'QUICK', 'REACH', 'SISTER', 'THINK', 'UNITED', 'VISION', 'WOMAN', 'YELLOW', 'ZEBRA'] }; this.garbageChars = '!@#$%^&*()_+-=[]{}|;:\'",./<>?~`\\|ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; // Лорные фразы для вставки в мусор this.lorePhrases = [ 'VAULT-TEC', 'RADIATION', 'NUCLEAR', 'FALLOUT', 'WAR', '2077', 'EXPERIMENT', 'OVERSIGHT', 'GECK', 'PIP-BOY', 'NUKA-COLA', 'BOTTLE-CAPS', 'SUPER-MUTANT', 'GHOUL', 'DEATHCLAW', 'BROTHERHOOD', 'ENCLAVE', 'NCR', 'LEGION', 'VAULT-DWELLER', 'WANDERER', 'SURVIVOR', 'WARRIOR', 'SCAVENGER', 'RAIDER', 'MERCHANT', 'DOCTOR', 'SCIENTIST', 'ENGINEER', 'SOLDIER', 'GUARD', 'ADMIN', 'OVERSIGHT', 'EXPERIMENT', 'CONTROL', 'GROUP', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' ]; this.bracketPairs = ['()', '[]', '{}', '<>']; this.init(); } init() { this.bindEvents(); this.newGame(); } bindEvents() { document.getElementById('newGameBtn').addEventListener('click', () => this.newGame()); document.getElementById('difficultyBtn').addEventListener('click', () => this.toggleDifficultySelector()); document.querySelectorAll('.diff-btn').forEach(btn => { btn.addEventListener('click', (e) => this.setDifficulty(e.target.dataset.diff)); }); } toggleDifficultySelector() { const selector = document.getElementById('difficultySelector'); selector.style.display = selector.style.display === 'none' ? 'flex' : 'none'; } setDifficulty(diff) { this.difficulty = diff; document.getElementById('difficulty').textContent = diff.toUpperCase(); document.querySelectorAll('.diff-btn').forEach(btn => { btn.classList.toggle('active', btn.dataset.diff === diff); }); this.toggleDifficultySelector(); this.newGame(); } newGame() { this.gameState = 'playing'; this.attempts = this.difficultySettings[this.difficulty].attempts; this.maxAttempts = this.attempts; this.selectedWords = []; this.brackets = []; this.generatePasswords(); this.renderHackingArea(); this.updateUI(); this.hideStatus(); // Временно показываем правильный пароль для отладки console.log('Правильный пароль:', this.correctPassword); console.log('Список паролей:', this.passwordList); } generatePasswords() { const settings = this.difficultySettings[this.difficulty]; const wordLength = settings.wordLength; const wordCount = settings.wordCount; // Выбираем случайные слова нужной длины const availableWords = this.wordLists[wordLength].filter(word => word.length === wordLength); this.passwordList = []; // Сначала выбираем правильный пароль this.correctPassword = availableWords[Math.floor(Math.random() * availableWords.length)]; this.passwordList.push(this.correctPassword); // Затем добавляем остальные слова for (let i = 1; i < wordCount; i++) { let randomWord; do { randomWord = availableWords[Math.floor(Math.random() * availableWords.length)]; } while (this.passwordList.includes(randomWord)); this.passwordList.push(randomWord); } // Перемешиваем список, чтобы правильный пароль не всегда был первым for (let i = this.passwordList.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [this.passwordList[i], this.passwordList[j]] = [this.passwordList[j], this.passwordList[i]]; } // Генерируем скобки this.generateBrackets(); } generateBrackets() { this.brackets = []; const bracketCount = Math.floor(Math.random() * 3) + 2; // 2-4 пары скобок for (let i = 0; i < bracketCount; i++) { const pair = this.bracketPairs[Math.floor(Math.random() * this.bracketPairs.length)]; this.brackets.push({ open: pair[0], close: pair[1], used: false, position: Math.floor(Math.random() * 1000) // Случайная позиция для размещения }); } } renderHackingArea() { const area = document.getElementById('hackingArea'); area.innerHTML = ''; // Создаем два столбца const leftColumn = document.createElement('div'); leftColumn.className = 'hacking-column'; const rightColumn = document.createElement('div'); rightColumn.className = 'hacking-column'; // Создаем строки с паролями и мусором // Разделяем строки на два столбца const leftLines = []; const rightLines = []; for (let i = 0; i < this.passwordList.length; i++) { const word = this.passwordList[i]; const wordHtml = `<span class="password-word" data-word="${word}">${word}</span>`; // Добавляем мусор вокруг слова для фиксированной длины строки const targetLength = 45; // Уменьшил длину строки const wordLength = word.length + 4; // +4 для пробелов в сепараторах const remainingLength = targetLength - wordLength; // Случайная позиция для слова в строке const maxPosition = Math.max(0, remainingLength - 5); const beforeLength = Math.floor(Math.random() * maxPosition) + 5; const afterLength = remainingLength - beforeLength; const wordWithGarbage = this.generateFixedLengthGarbage(beforeLength) + '<span class="separator"> </span>' + wordHtml + '<span class="separator"> </span>' + this.generateFixedLengthGarbage(afterLength); if (i % 2 === 0) { leftLines.push(wordWithGarbage); } else { rightLines.push(wordWithGarbage); } } // Добавляем мусорные строки в начало for (let i = 0; i < 3; i++) { leftLines.unshift(this.generateFixedLengthGarbage(45)); rightLines.unshift(this.generateFixedLengthGarbage(45)); } // Добавляем мусорные строки в конец for (let i = 0; i < 4; i++) { leftLines.push(this.generateFixedLengthGarbage(45)); rightLines.push(this.generateFixedLengthGarbage(45)); } // Заполняем левый столбец leftLines.forEach(line => { const lineDiv = document.createElement('div'); lineDiv.className = 'hacking-line'; lineDiv.innerHTML = line; leftColumn.appendChild(lineDiv); }); // Заполняем правый столбец rightLines.forEach(line => { const lineDiv = document.createElement('div'); lineDiv.className = 'hacking-line'; lineDiv.innerHTML = line; rightColumn.appendChild(lineDiv); }); // Добавляем столбцы в область area.appendChild(leftColumn); area.appendChild(rightColumn); // Вставляем скобки в мусорные строки this.insertBracketsInColumns(leftColumn, rightColumn); // Добавляем обработчики событий this.bindHackingEvents(); } insertBracketsInColumns(leftColumn, rightColumn) { // Вставляем скобки в мусорные строки обоих столбцов const columns = [leftColumn, rightColumn]; this.brackets.forEach((bracket, index) => { if (!bracket.used) { const column = columns[Math.floor(Math.random() * columns.length)]; const lines = column.querySelectorAll('.hacking-line'); // Находим мусорные строки (без паролей) const garbageLines = Array.from(lines).filter(line => !line.innerHTML.includes('password-word') ); if (garbageLines.length > 0) { const line = garbageLines[Math.floor(Math.random() * garbageLines.length)]; const content = line.innerHTML; if (content.length > 20) { // Ищем безопасные позиции для вставки скобок const safePositions = []; for (let i = 0; i < content.length - 5; i++) { if (content[i] !== '<' && content[i] !== '>') { safePositions.push(i); } } if (safePositions.length >= 2) { const openPos = safePositions[Math.floor(Math.random() * (safePositions.length - 1))]; const closePos = safePositions[Math.floor(Math.random() * (safePositions.length - 1))]; if (closePos > openPos + 2) { line.innerHTML = content.slice(0, openPos) + `<span class="bracket" data-bracket="${bracket.open}">${bracket.open}</span>` + content.slice(openPos, closePos) + `<span class="bracket" data-bracket="${bracket.close}">${bracket.close}</span>` + content.slice(closePos); console.log(`Inserted bracket pair: ${bracket.open}${bracket.close}`); } } } } } }); } generateGarbage(length) { let garbage = ''; for (let i = 0; i < length; i++) { garbage += this.garbageChars[Math.floor(Math.random() * this.garbageChars.length)]; } return garbage; } generateFixedLengthGarbage(length) { let garbage = ''; let loreInserted = false; for (let i = 0; i < length; i++) { // Иногда вставляем лорную фразу вместо мусора if (!loreInserted && Math.random() < 0.1 && i < length - 8) { const lorePhrase = this.lorePhrases[Math.floor(Math.random() * this.lorePhrases.length)]; garbage += lorePhrase; i += lorePhrase.length - 1; // Пропускаем символы фразы loreInserted = true; } else { garbage += this.garbageChars[Math.floor(Math.random() * this.garbageChars.length)]; } } return garbage; } bindHackingEvents() { // Обработчики для слов-паролей document.querySelectorAll('.password-word').forEach(word => { word.addEventListener('click', (e) => { if (this.gameState !== 'playing') return; const selectedWord = e.target.dataset.word; this.selectPassword(selectedWord, e.target); }); }); // Обработчики для скобок document.querySelectorAll('.bracket').forEach(bracket => { bracket.addEventListener('click', (e) => { if (this.gameState !== 'playing') return; const bracketChar = e.target.dataset.bracket; this.handleBracketClick(bracketChar, e.target); }); }); } selectPassword(word, element) { if (this.selectedWords.includes(word)) return; this.selectedWords.push(word); element.classList.add('selected'); this.attempts--; this.playSound('click'); if (word === this.correctPassword) { this.gameSuccess(); } else { element.classList.add('incorrect'); this.showFeedback(word); if (this.attempts <= 0) { this.gameFailure(); } } this.updateUI(); } handleBracketClick(bracketChar, element) { if (element.classList.contains('used')) return; // Определяем тип скобки const bracketPairs = { '(': ')', '[': ']', '{': '}', '<': '>' }; const expectedClose = bracketPairs[bracketChar]; if (!expectedClose) { console.log('Unknown bracket:', bracketChar); return; } console.log('Looking for pair:', bracketChar, '->', expectedClose); // Ищем соответствующую закрывающую скобку const allBrackets = document.querySelectorAll('.bracket'); let foundPair = false; for (let bracket of allBrackets) { if (bracket.dataset.bracket === expectedClose && !bracket.classList.contains('used') && bracket !== element) { // Найдена пара! console.log('Found pair!'); element.classList.add('used'); bracket.classList.add('used'); foundPair = true; break; } } if (foundPair) { this.playSound('bracket'); this.handleBracketBonus(); } else { console.log('No pair found'); this.playSound('error'); } } handleBracketBonus() { const bonus = Math.random(); if (bonus < 0.5) { // Удаляем одно неверное слово this.removeWrongPassword(); } else { // Восстанавливаем попытку if (this.attempts < this.maxAttempts) { this.attempts++; this.showStatus('ATTEMPT RESTORED!', '#00ff00'); } } this.updateUI(); } removeWrongPassword() { const wrongWords = this.passwordList.filter(word => word !== this.correctPassword && !this.selectedWords.includes(word) ); if (wrongWords.length > 0) { const wordToRemove = wrongWords[Math.floor(Math.random() * wrongWords.length)]; const element = document.querySelector(`[data-word="${wordToRemove}"]`); if (element) { element.style.opacity = '0.3'; element.style.pointerEvents = 'none'; this.showStatus('WRONG PASSWORD REMOVED!', '#00ff00'); } } } showFeedback(selectedWord) { const correct = this.correctPassword; let correctPositions = 0; let correctLetters = 0; // Подсчитываем правильные позиции for (let i = 0; i < Math.min(selectedWord.length, correct.length); i++) { if (selectedWord[i] === correct[i]) { correctPositions++; } } // Подсчитываем правильные буквы (не на своих позициях) const selectedLetters = selectedWord.split(''); const correctLettersArray = correct.split(''); for (let letter of selectedLetters) { const index = correctLettersArray.indexOf(letter); if (index !== -1) { correctLetters++; correctLettersArray.splice(index, 1); } } correctLetters -= correctPositions; // Убираем уже учтенные позиции this.showStatus( `LIKENESS: ${correctPositions} | LETTERS: ${correctLetters}`, '#00ff00' ); } gameSuccess() { this.gameState = 'success'; document.querySelector(`[data-word="${this.correctPassword}"]`).classList.add('correct'); this.showStatus('ACCESS GRANTED!', '#00ff00'); this.playSound('success'); } gameFailure() { this.gameState = 'failure'; this.showStatus('ACCESS DENIED! TERMINAL LOCKED!', '#00ff00'); this.playSound('failure'); } showStatus(message, color = '#00ff00') { const statusLine = document.getElementById('statusLine'); statusLine.textContent = '> ' + message; statusLine.style.color = color; } hideStatus() { const statusLine = document.getElementById('statusLine'); statusLine.textContent = '> READY FOR INPUT'; statusLine.style.color = '#00aa00'; } updateUI() { document.getElementById('attempts').textContent = this.attempts; document.getElementById('difficulty').textContent = this.difficulty.toUpperCase(); } playSound(type) { // Простые звуковые эффекты через Web Audio API const audioContext = new (window.AudioContext || window.webkitAudioContext)(); const oscillator = audioContext.createOscillator(); const gainNode = audioContext.createGain(); oscillator.connect(gainNode); gainNode.connect(audioContext.destination); let frequency, duration, volume; switch(type) { case 'click': frequency = 800; duration = 0.1; volume = 0.1; break; case 'bracket': frequency = 1200; duration = 0.2; volume = 0.15; break; case 'success': frequency = 1000; duration = 0.5; volume = 0.2; break; case 'failure': frequency = 200; duration = 0.8; volume = 0.2; break; case 'error': frequency = 400; duration = 0.3; volume = 0.1; break; default: frequency = 600; duration = 0.1; volume = 0.05; } oscillator.frequency.setValueAtTime(frequency, audioContext.currentTime); gainNode.gain.setValueAtTime(volume, audioContext.currentTime); gainNode.gain.exponentialRampToValueAtTime(0.01, audioContext.currentTime + duration); oscillator.start(audioContext.currentTime); oscillator.stop(audioContext.currentTime + duration); } } // Инициализация игры document.addEventListener('DOMContentLoaded', () => { new FalloutHackingGame(); });