### Полный исправленный и доработанный код симулятора `space_adventure_3d.rb` ```ruby #!/usr/bin/env ruby # encoding: utf-8 require 'json' class SpaceAdventure3D SAVE_FILE = 'savegame.json' # Константы меню и сообщений MAIN_MENU = { '1' => 'Проверить курс (показать координаты)', '2' => 'Переместиться в сектор (X Y Z)', '3' => 'Исследовать текущий сектор', '4' => 'Поговорить с ИИ‑помощником «Эхо‑3D»', '5' => 'Проверить инвентарь', '6' => 'Сохранить игру', '7' => 'Посетить космический рынок', '8' => 'Выйти из игры', 'give_credits' => '[ОТЛАДКА] Начислить 8 888 888 888 CR' } def initialize load_game || reset_game end def reset_game @position = { x: 0, y: 0, z: 0 } @health = 100 @fuel = 100 @credits = 50 @crystals = 0 @inventory = [] @game_over = false @sector_map = {} @level = 1 @target = { x: 5, y: -3, z: 2 } @ship = :phoenix @shield_active = false end def load_game if File.exist?(SAVE_FILE) data = JSON.parse(File.read(SAVE_FILE)) @position = data['position'] @health = data['health'] @fuel = data['fuel'] @credits = data['credits'] @crystals = data['crystals'] || 0 @inventory = data['inventory'] @sector_map = data['sector_map'] @level = data['level'] @target = data['target'] @ship = data['ship'] || :phoenix @shield_active = data['shield_active'] || false puts "✅ Игра загружена!" return true end false end def save_game data = { position: @position, health: @health, fuel: @fuel, credits: @credits, crystals: @crystals, inventory: @inventory, sector_map: @sector_map, level: @level, target: @target, ship: @ship, shield_active: @shield_active } File.write(SAVE_FILE, JSON.generate(data)) puts "💾 Игра сохранена!" end def show_status puts "\n! + "≪! * 40 puts "СОСТОЯНИЕ КОРАБЛЯ (3D) | Уровень: #{@level} | Корабль: #{ship_name(@ship)}" puts "Позиция: X=#{@position[:x]}, Y=#{@position[:y]}, Z=#{@position[:z]}" puts "Цель: X=#{@target[:x]}, Y=#{@target[:y]}, Z=#{@target[:z]}" puts "Здоровье: #{@health}%" puts "Топливо: #{@fuel} ед." puts "Кредиты: #{@credits} CR" puts "Кристаллы: #{@crystals} 🔮" puts "Инвентарь: #{@inventory.empty? ? 'пусто' : @inventory.join(', ')}" puts "Куполообразная защита: #{@shield_active ? 'активна' : 'не активна'}" puts "Исследовано секторов: #{@sector_map.size}" distance = calc_distance(@position, @target) puts "До цели: #{distance.round(1)} ед." puts "≫! * 40 end def ship_name(symbol) { phoenix: 'Феникс‑3D', warrior: 'Воин‑X', scout: 'Скаут‑Z' }[symbol] || 'Неизвестный' end def calc_distance(a, b) Math.sqrt((a[:x] - b[:x])**2 + (a[:y] - b[:y])**2 + (a[:z] - b[:z])**2) end def prompt print "\n▸ " gets.chomp.downcase end def display_menu puts "\nЧто вы хотите сделать?" MAIN_MENU.each { |key, label| puts "#{key}. #{label}" } end def show_mini_map # Простая мини‑карта: показываем соседние сектора (±1 по каждой оси) puts "\n🗺 МИНИ‑КАРТА (видимая область: ±1 от текущей позиции)" (-1..1).each do |dz| (-1..1).each do |dy| line = [] (-1..1).each do |dx| abs_x = @position[:x] + dx abs_y = @position[:y] + dy abs_z = @position[:z] + dz key = "#{abs_x}-#{abs_y}-#{abs_z}" if abs_x == @position[:x] && abs_y == @position[:y] && abs_z == @position[:z] line << "[*]" # текущая позиция elsif @sector_map[key] line << "[.]" # исследованный сектор else line << "[...]" # неисследованный end end puts line.join(" ") end end end def explore_sector(pos) key = "#{pos[:x]}-#{pos[:y]}-#{pos[:z]}" if @sector_map[key] puts "Этот сектор уже исследован. Ничего нового." return end puts "\n🔍 Вы активируете 3D‑сенсоры для сканирования сектора…" sleep 0.5 event = rand(1..7) case event when 1 credits_gain = rand(20..50) @credits += credits_gain puts "✓ Найден контейнер с данными! +#{credits_gain} CR." when 2 if @inventory.include?('щит‑прототип') puts "Вы использовали «щит‑прототип» — атака отражена!" else damage = rand(15..30) @health -= damage puts "⚠️ Пиратский корабль атаковал! -#{damage}% здоровья." check_game_over end when 3 puts "Вы обнаружили древний артефакт! Добавляете в инвентарь: «гипер‑компас»." @inventory << 'гипер‑компас' when 4 puts "В глубинах сектора мерцает энергетический кристалл! +25 ед. топлива." @fuel += 25 when 5 puts "Сектор пуст. Тишина космоса…" when 6 super_bonus = 888_888 @credits += super_bonus puts "🌟 РЕДКИЙ НАХОД! Вы обнаружили заброшенный торговый хаб! +#{super_bonus} CR!" when 7 crystals_gain = rand(5..15) @crystals += crystals_gain puts "🔮 В секторе мерцают загадочные кристаллы! +#{crystals_gain} 🔮 кристаллов." end @sector_map[key] = true end def check_game_over if @health <= 0 puts "💀 Ваше судно повреждено! Игра окончена." @game_over = true end end def ai_dialog_3d responses = [ "Эхо‑3D: Капитан, я фиксирую аномалии в секторе #{@position[:x]},#{@position[:y]},#{@position[:z]}. Будьте бдительны.", "Эхо‑3D: Топливо на уровне #{@fuel} ед. Рекомендую пополнить запасы.", "Эхо‑3D: До цели осталось #{calc_distance(@position, @target).round(1)} единиц. Курс верный.", "Эхо‑3D: В вашем инвентаре #{@inventory.size} предметов. Проверьте их состояние.", "Эхо‑3D: Кредиты: #{@credits