文字游戏

· · 个人记录

#include <iostream>
#include <vector>
#include <string>
#include <map> // 用于物品栏和职业数据
#include <deque> // 用于消息日志
#include <algorithm> // 用于 min/max, find_if, random_shuffle
#include <chrono> // 用于线程暂停
#include <thread> // 用于线程暂停
#include <cstdlib> // For rand(), srand()
#include <ctime>   // For time()
#include <functional> // For std::function in Upgrade struct
#include <fstream> // For file I/O (save/load)
#include <limits> // For numeric_limits in file I/O
#include <cmath> // For sqrt() and pow() in map generation

// Windows 特定头文件
#include <conio.h> // _getch() - Kept for specific "press any key" prompt, but not for general action input.
#include <windows.h> // SetConsoleCursorInfo, SetConsoleCursorPosition, SetConsoleTextAttribute, GetAsyncKeyState, COORD, SetConsoleScreenBufferSize, SetConsoleWindowInfo

// 定义快捷键宏
// getAsyncKeyState 是非阻塞的,每次循环都会检查按键状态
#define zxb(VK_NONAME) ((GetAsyncKeyState(VK_NONAME) & 0x8000) ? 1 : 0)

using namespace std;

// --- 控制台工具函数 ---
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); // 全局控制台句柄

void hide() {
    CONSOLE_CURSOR_INFO cursor_info = {1, 0};
    SetConsoleCursorInfo(hConsole, &cursor_info);
}

void gotoxy(int x, int y) {
    COORD pos = {(SHORT)x, (SHORT)y};
    SetConsoleCursorPosition(hConsole, pos);
}

enum Color {
    black = 0, blue = 1, green = 2, cyan = 3, red = 4, magenta = 5,
    yellow = 6, white = 7, gray = 8, light_blue = 9, light_green = 10,
    light_cyan = 11, light_red = 12, light_magenta = 13, light_yellow = 14,
    bright_white = 15
};

void set_color(int color) {
    SetConsoleTextAttribute(hConsole, color);
}

// 清空指定区域
void clear_area(int x1, int y1, int x2, int y2) {
    for (int y = y1; y <= y2; ++y) {
        gotoxy(x1, y);
        for (int x_char = x1; x_char <= x2; ++x_char) { // Iterate character by character
            cout << " ";
        }
    }
}

// --- 游戏常量和全局变量 ---
const int MAP_COLS = 40, MAP_ROWS = 20; // 地图尺寸 MAP_COLS:宽 MAP_ROWS:高
const int UI_OFFSET_X = MAP_COLS * 2 + 4; // 侧边栏起始X坐标
const int SIDEBAR_WIDTH = 35; // 侧边栏可用的宽度 (字符数)
const int NUM_FLOORS = 6; // 总共的楼层数

// 新增:最大等级常量
const int MAX_LEVEL = 51; 

// 玩家状态
int x_pos, y_pos; // 玩家在地图上的坐标,x代表行(y轴),y代表列(x轴)
int x_pos_last, y_pos_last; // 用于记录上一步的位置 (无尽模式中防卡住)
int player_class; // 1:战士 2:游侠 3:法师 4:mwh
int level = 1, experience = 0; // 等级,经验
int current_hp; // 当前生命值
int gold = 10; // 金币
int skill_cooldown = 0; // 技能冷却时间

// --- 新增:一次性物品状态 ---
bool power_potion_active = false; // 力量药水效果是否激活
bool defense_potion_active = false; // 坚韧药水效果是否激活

int have_sword = 0; // 当前装备的武器索引 (指向 all_weapons 中的一个)
int have_armor = 0; // 当前装备的防具索引 (指向 all_armors 中的一个)

int current_floor = 1; // 当前所在楼层 (1到NUM_FLOORS)
int max_unlocked_floor = 1; // 玩家能解锁的最高楼层

int game_phase = 1; // 游戏轮次
int best_phase = 1; // 最高游戏轮次记录

// --- 新增:无尽模式相关变量 ---
bool is_in_endless_mode = false; // 标记玩家是否在无尽模式中
int endless_current_floor = 1;   // 无尽模式的当前层数
int endless_max_floor = 1;       // 玩家达到过的最高无尽层数

// 用于从无尽模式返回
int stored_normal_floor;
int stored_normal_x, stored_normal_y;

// 无尽模式的地图和状态
vector<string> endless_map;
bool endless_boss_defeated_this_floor = false;

// --- 新增:星徽之力数据结构 ---
struct StarPower {
    int id; // 唯一的ID,用于识别
    string name;
    string description;
};

vector<StarPower> all_star_powers; // 存储所有可用的星徽之力
int current_star_power_id = -1; // 玩家当前拥有的星徽ID,-1代表没有

// --- 妙具系统: 新增妙具数据结构 ---
struct Gadget {
    int id;
    string name;
    string description;
    int max_uses; // 每层可用的最大次数
};

vector<Gadget> all_gadgets; // 存储所有可用的妙具
int current_gadget_id = -1; // 玩家当前拥有的妙具ID,-1代表没有
int gadget_current_uses = 0; // 当前妙具的剩余使用次数

// 等级相关属性数据 (索引0不用,实际从1级开始)
// 经验需求调整,确保游戏有足够长度,现在支持到MAX_LEVEL
int XP_REQUIRED[] = {
    0, 50, 120, 220, 350, 520, 750, 1000, 1300, 1700,
    2200, 2800, 3500, 4300, 5200, 6200, 7325, 8600, 10050, 11700,
    13575, 15700, 18090, 20755, 23700, 26935, 30475, 34330, 38515, 43045,
    47935, 53200, 58855, 64915, 71395, 78310, 85675, 93505, 101815, 110620,
    119935, 129775, 140155, 151090, 162595, 174685, 187375, 200680, 214615, 229195,
    244435, 9999999
};

// --- 职业数据结构 ---
struct ClassStats {
    string name;
    string skill_name;
    int skill_cooldown_base; // 技能基础冷却时间
    vector<int> max_hp_per_level;
    vector<int> base_attack_per_level;
    vector<int> base_defense_per_level;

    // 默认构造函数,用于 map 插入时初始化空向量
    ClassStats() : skill_cooldown_base(0) {
        max_hp_per_level.resize(MAX_LEVEL + 1); // 预留MAX_LEVEL+1个空间
        base_attack_per_level.resize(MAX_LEVEL + 1);
        base_defense_per_level.resize(MAX_LEVEL + 1);
    }
};
map<int, ClassStats> class_definitions; // 存储所有职业的数据

// --- 物品词条(Affix)与装备数据 ---
struct Affix {
    string name;
    int tier; // 1:普通, 2:稀有, 3:史诗
    string description; // 描述中包含具体数值
};
vector<Affix> all_affixes; // 存储所有词条模板

// Helper functions to categorize affixes (NEW)
bool is_weapon_affix_type(const Affix& affix) {
    // 列出所有武器词条的名称
    return (affix.name == "暴击+" || affix.name == "吸血" || affix.name == "穿甲" ||
            affix.name == "破碎一击" || affix.name == "经验加成" || affix.name == "财富掠夺" ||
            affix.name == "剧毒之刃" || affix.name == "致残打击");
}

bool is_armor_affix_type(const Affix& affix) {
    // 列出所有护甲词条的名称
    return (affix.name == "生命+" || affix.name == "韧性" || affix.name == "反伤" ||
            affix.name == "再生" || affix.name == "毒抗");
}

struct Weapon {
    string name;
    int initial_damage; // Lv0时的基础伤害
    int cost;
    int level = 0;        // 武器自身等级
    int initial_affix_slots; // Lv0时的基础词条插槽数
    vector<Affix> affixes; // 实际持有的词条

    // 根据等级计算当前伤害和词条槽数
    int get_current_damage() const {
        return initial_damage + level * 5; // 每升一级增加5点伤害
    }
    int get_current_affix_slots() const {
        // 固定词条武器(例如神圣之剑、混沌战斧)的词条槽数是固定的
        if (name == "神圣之剑" || name == "混沌战斧") {
            return initial_affix_slots;
        }
        return initial_affix_slots + level; // 每升一级增加1个槽位
    }

    // 构造函数,用于创建武器实例
    Weapon(const string& n, int i_dmg, int c, int i_slots, const vector<Affix>& fixed_aff = {})
        : name(n), initial_damage(i_dmg), cost(c), level(0), initial_affix_slots(i_slots) {
        if (!fixed_aff.empty()) {
            affixes = fixed_aff; // 对于固定词条武器,直接复制
        }
    }
    // 默认构造函数,用于序列化/反序列化时使用,不进行自动初始化
    Weapon() : name(""), initial_damage(0), cost(0), level(0), initial_affix_slots(0) {}
};

// 全局武器模板列表 (不会被存档/读档内容直接覆盖,只作为蓝本)
vector<Weapon> global_weapon_templates;

// all_weapons 现在存储的是玩家实际拥有的武器实例列表
// have_sword 索引到这个列表中的某个元素
vector<Weapon> all_weapons; 

// --- 护甲数据结构 ---
struct Armor {
    string name;
    int initial_defense_bonus; // Lv0时的基础防御
    int cost;
    int level = 0;             // 护甲自身等级
    int initial_affix_slots;   // Lv0时的基础词条插槽数
    vector<Affix> affixes;     // 实际持有的词条

    // 根据等级计算当前防御和词条槽数
    int get_current_defense() const {
        return initial_defense_bonus + level * 2; // 每升一级增加2点防御
    }
    int get_current_affix_slots() const {
        // 固定词条护甲(例如神圣之盾、混沌胸甲)的词条槽数是固定的
        if (name == "神圣之盾" || name == "混沌胸甲") {
            return initial_affix_slots;
        }
        return initial_affix_slots + level; // 每升一级增加1个槽位
    }

    // 构造函数,用于创建护甲实例
    Armor(const string& n, int i_def, int c, int i_slots, const vector<Affix>& fixed_aff = {})
        : name(n), initial_defense_bonus(i_def), cost(c), level(0), initial_affix_slots(i_slots) {
        if (!fixed_aff.empty()) {
            affixes = fixed_aff; // 对于固定词条护甲,直接复制
        }
    }
    // 默认构造函数,用于序列化/反序列化时使用
    Armor() : name(""), initial_defense_bonus(0), cost(0), level(0), initial_affix_slots(0) {}
};

// 全局护甲模板列表
vector<Armor> global_armor_templates;

// all_armors 存储玩家实际拥有的护甲实例列表
// have_armor 索引到这个列表中的某个元素
vector<Armor> all_armors;

// 怪物数据
enum MonsterType {
    GOBLIN, SPIDER, // Floor 1
    BEAST, SKELETON, // Floor 2
    DEMON_GUARD, ZOMBIE, // Floor 3
    SHADOW_BEAST, WIZARD_APPRENTICE, // Floor 4
    ELITE_GUARD, FIRE_DEMON, // Floor 5
    VOID_RAVAGER, ANCIENT_GUARDIAN, // Floor 6
    BOSS_GOBLIN_KING, BOSS_MINOTAUR, BOSS_NECROMANCER, BOSS_DRAGON_SPAWN, BOSS_FINAL, BOSS_LORD_OF_CHAOS // Bosses
};

struct Monster {
    string name;
    int max_hp;
    int attack;
    int defense;
    int xp_reward;
    int gold_reward;
    MonsterType type; // 怪物类型,用于判断特殊能力
    int floor; // 怪物出现的楼层
};

vector<Monster> all_monster_templates_base; // 存储怪物原始模板数据 (未缩放)
vector<Monster> current_monster_templates;  // 存储当前轮次调整后的怪物数据 (已缩放)

// 从当前怪物模板中获取特定类型的怪物
Monster get_monster_template(MonsterType type) {
    for (const auto& m : current_monster_templates) {
        if (m.type == type) {
            return m;
        }
    }
    return current_monster_templates[0]; // Fallback to Goblin
}

// 获取当前楼层的小怪
Monster get_random_monster_for_floor(int floor, bool is_strong = false) {
    vector<Monster> available_monsters;
    for (const auto& m : current_monster_templates) {
        if (m.floor == floor && m.type < BOSS_GOBLIN_KING) { // 过滤掉Boss
            available_monsters.push_back(m);
        }
    }
    if (available_monsters.empty()) return current_monster_templates[0]; // Fallback to Goblin

    // 对于第六层,所有小怪都应该很强,可以有逻辑偏向
    if (floor == 6 && available_monsters.size() > 1 && is_strong) {
        // 尝试返回第二种怪物,通常更强
        return available_monsters[1];
    } else if (available_monsters.size() > 1 && is_strong && rand() % 2 == 0) {
        // 非第六层,但is_strong,则有50%几率返回列表中第二种怪物(如果有的话)
        return available_monsters[1];
    }

    return available_monsters[rand() % available_monsters.size()];
}

// 物品栏 (键:物品名称,值:数量)
map<string, int> inventory;

// 消息日志
deque<string> message_log;
int g_message_log_start_y = 0; // Global variable to track where message log starts dynamically

// --- 地图数据 ---
// 原始地图模板 (用于重置)
vector<string> initial_maps[NUM_FLOORS];
// 当前地图状态 (会被修改)
vector<string> current_maps[NUM_FLOORS];

// 每层传送门进入时的默认位置 (x, y)
pair<int, int> floor_entrance_coords[NUM_FLOORS + 1] = {
    {0,0}, // 占位符,索引从1开始
    {1, 1}, // Floor 1 entry
    {1, 1}, // Floor 2 entry
    {1, 1}, // Floor 3 entry
    {1, 1}, // Floor 4 entry
    {1, 1},  // Floor 5 entry
    {1, 1}   // Floor 6 entry
};

// 追踪每层Boss是否已被击败
bool boss_defeated[NUM_FLOORS + 1];

// --- 角色强化数据 ---
struct Upgrade {
    string name;
    int level = 0; // 升级等级
    int base_cost; // 基础费用
    function<void()> apply_effect; // 升级效果
};
vector<Upgrade> upgrades;

// --- 前置声明 ---
void print_tile(char j);
void print_message_log(); // Declared to be used by add_message
void add_message(string s);

// Helper function to get combined affix descriptions (NEW)
vector<string> get_combined_affix_descriptions(const vector<Affix>& affixes);

// UI Print functions (modified to be dynamic or use new global y)
int get_total_attack(int battle_bonus_atk = 0); // 新增:计算总攻击力
int get_total_defense(int battle_bonus_def = 0); // 新增:计算总防御力
int get_total_max_hp(); // 新增:计算总生命值上限
int print_player_stats_panel_lines(int start_y_panel); // New helper for player stats
int print_equipped_items_details(int start_y_panel); // Modified signature to print both weapon and armor
int print_star_power_status(int start_y_panel); // 新增:打印星徽之力
int print_gadget_status(int start_y_panel); // --- 妙具系统: 新增前置声明 ---
void print_floor_boss_status(int start_y_panel); // New helper for floor/boss
void refresh_ui(); 

int print_weapon_details(const Weapon& w, int start_y, const string& prefix = ""); // Modified to return next_y
int print_armor_details(const Armor& a, int start_y, const string& prefix = ""); // New: print armor details

void check_level_up();
void start_battle(Monster monster_template);
void game_over();
void update_game_state();
void enter_shop();
void choose_class();
void load_initial_maps(); // 加载地图模板
void reset_player_progression(); // 重置玩家状态(用于游戏重开)
void reset_map_and_boss_status(); // 重置地图和Boss(用于新轮次或重开)
void reset_game_state(); // 完整的游戏重置
void enter_portal(); 
void initialize_class_data();
void initialize_monster_templates(); // 初始化怪物数据并根据轮次缩放
void initialize_item_templates_and_affixes(); // 初始化武器/护甲模板和词条数据 (填充 global_weapon_templates, global_armor_templates, all_affixes)
void initialize_star_powers(); // 新增:初始化星徽之力
void initialize_gadgets(); // --- 妙具系统: 新增前置声明 ---
void initialize_base_templates(); // 新增:整合所有基础模板初始化
void initialize_upgrades();  // 初始化升级系统
void enter_forging_hut();   // 锻造小屋函数
void on_final_boss_defeated(); // 最终Boss击败处理
void reroll_affixes(Weapon& w); // 武器词条重铸
void reroll_armor_affixes(Armor& a); // 护甲词条重铸

// New: Weapon Upgrade
void upgrade_weapon(int weapon_idx);
// New: Armor Upgrade
void upgrade_armor(int armor_idx);

// New: Save/Load functions
void save_game(const string& filename = "save.txt");
void load_game(const string& filename = "save.txt");

// New: Endless Mode functions
void generate_endless_map(int floor_level);
Monster get_endless_monster(int floor_level, char tile_type);

// --- 妙具系统: 更新战斗辅助函数的前置声明 ---
void perform_basic_attack(int& monster_current_hp, const Monster& monster_template, vector<string>& battle_log, bool& monster_stunned_ref,
                          bool& monster_poisoned_status_ref, int& monster_poison_duration_status_ref, int& monster_poison_damage_per_turn_status_ref,
                          bool& monster_crippled_status_ref, int& monster_cripple_duration_status_ref, int& monster_cripple_attack_reduction_ref,
                          float player_attack_multiplier, float monster_stat_multiplier);

void perform_skill_attack(int& monster_current_hp, const Monster& monster_template, vector<string>& battle_log, bool& monster_stunned_ref,
                          float player_attack_multiplier, float monster_stat_multiplier);

// --- 游戏简介函数 (New) ---
void display_game_intro() {
    system("cls");
    set_color(light_yellow);
    gotoxy(25, 3);
    cout << "--- 欢迎来到文字地牢! ---";

    set_color(white);
    gotoxy(10, 6);
    cout << "你是一名勇敢的冒险者,踏入充满危险的地牢深处。";
    gotoxy(10, 7);
    cout << "这里布满了各种可怕的怪物、陷阱,但也隐藏着稀有的宝藏。";
    gotoxy(10, 9);
    cout << "你的目标是不断探索,击败强大的敌人,提升自身能力,";
    gotoxy(10, 10);
    cout << "最终征服所有楼层的挑战,并在更高的轮次中证明自己!";

    set_color(light_cyan);
    gotoxy(10, 12);
    cout << "====== 游戏指南 ======";
    set_color(white);
    gotoxy(10, 14);
    cout << "移动: W (上), A (左), S (下), D (右)";
    gotoxy(10, 15);
    cout << "战斗: 进入怪物格 ('怪'/'兽'/'王'/'英') 自动触发";
    gotoxy(10, 16);
    cout << "物品: H (使用生命药水), F (使用职业技能), G (使用妙具)";
    gotoxy(10, 17);
    cout << "特殊地点: ";
    set_color(light_cyan); cout << "店"; set_color(white); cout << " (商店), ";
    set_color(bright_white); cout << "锻"; set_color(white); cout << " (锻造小屋), ";
    set_color(light_yellow); cout << "门"; set_color(white); cout << " (传送门)";
    gotoxy(10, 18);
    cout << "保存/读取: P (保存), L (读取)";
    gotoxy(10, 19);
    cout << "退出游戏: Esc";

    set_color(light_green);
    gotoxy(20, 22);
    cout << "按 [空格键] 开始你的冒险...";

    while (!zxb(VK_SPACE)) { 
        this_thread::sleep_for(chrono::milliseconds(50)); 
    }
    while (zxb(VK_SPACE)); // Debounce

    system("cls"); // 清屏,准备进入职业选择界面
}

// --- 游戏功能实现 ---

// 打印单个地图图块
void print_tile(char j) {
    if (j == '#') {
        set_color(gray);
        cout << "墙";
    } else if (j == '.') {
        set_color(white);
        cout << ". ";
    } else if (j == 'D') {
        set_color(light_yellow);
        cout << "门"; // 传送门
    } else if (j == 'H') {
        set_color(light_red);
        cout << "药"; // 药水
    } else if (j == 'T') {
        set_color(yellow);
        cout << "宝"; // 宝箱
    } else if (j == 'm') {
        set_color(green);
        cout << "怪"; // 普通小怪
    } else if (j == 'G') {
        set_color(red);
        cout << "兽"; // 强力小怪
    } else if (j == 'S') {
        set_color(light_cyan);
        cout << "店"; // 商店
    } else if (j == 'F') { // 新增锻造小屋
        set_color(bright_white);
        cout << "锻"; // 锻造小屋
    } else if (j == 'B') {
        set_color(light_magenta);
        cout << "王"; // Boss
    } else if (j == 'U') { // 新增:下一层入口
        set_color(light_magenta);
        cout << "往";
    } else if (j == 'R') { // 新增:回归门
        set_color(light_cyan);
        cout << "归";
    } else if (j == 'E') { // 新增:精英怪
        set_color(light_magenta);
        cout << "英";
    } else {
        cout << "  "; // 未知字符或空白
    }
}

// 专门用于打印消息日志 (Uses global g_message_log_start_y)
void print_message_log() {
    clear_area(UI_OFFSET_X, g_message_log_start_y, UI_OFFSET_X + SIDEBAR_WIDTH, g_message_log_start_y + 9); // Max 9 messages + 1 title
    set_color(light_yellow);
    gotoxy(UI_OFFSET_X, g_message_log_start_y);
    cout << "------ 消息日志 ------";
    set_color(white);
    int current_log_y = g_message_log_start_y + 1; // Messages start after title
    for (const string& msg : message_log) {
        gotoxy(UI_OFFSET_X, current_log_y++);
        cout << msg;
    }
}

// 添加消息到日志并显示
void add_message(string s) {
    message_log.push_back(s);
    if (message_log.size() > 9) { // 最多保留9条消息
        message_log.pop_front();
    }
    print_message_log(); // Update the log display immediately
}

// Helper function to get combined affix descriptions (NEW)
vector<string> get_combined_affix_descriptions(const vector<Affix>& affixes) {
    map<string, int> affix_counts;
    for (const auto& affix : affixes) {
        affix_counts[affix.name]++;
    }

    vector<string> combined_descriptions;
    for (const auto& pair : affix_counts) {
        string name = pair.first;
        int count = pair.second;
        string desc_line_base = ""; // This will be the base description for the affix, ignoring count for a moment

        // Find the base description from all_affixes
        for (const auto& original_affix : all_affixes) {
            if (original_affix.name == name) {
                desc_line_base = original_affix.description;
                break;
            }
        }

        string desc_line;
        if (name == "暴击+") {
            desc_line = "增加 " + to_string(count * 10) + "% 的暴击几率。";
        } else if (name == "吸血") {
            desc_line = "每次攻击造成伤害的 " + to_string(count * 10) + "% 转化为生命。";
        } else if (name == "穿甲") {
            desc_line = "攻击时无视敌人 " + to_string(count * 5) + " 点防御。";
        } else if (name == "破碎一击") {
            desc_line = "攻击时有 " + to_string(min(85, count * 15)) + "% 几率击晕敌人一回合。"; // Apply stun cap
        }
        else if (name == "经验加成") {
            desc_line = "击败怪物时额外获得 " + to_string(count * 15) + "% 经验。";
        } else if (name == "财富掠夺") {
            desc_line = "击败怪物时额外获得 " + to_string(count * 15) + "% 金币。";
        } else if (name == "剧毒之刃") {
            desc_line = "攻击时有 " + to_string(min(100, count * 25)) + "% 几率使敌人中毒。"; // Cap at 100%
        } else if (name == "致残打击") {
            desc_line = "攻击时有 " + to_string(min(100, count * 20)) + "% 几率降低敌人攻击力。"; // Cap at 100%
        }
        else if (name == "生命+") {
            desc_line = "增加生命上限 " + to_string(count * 10) + " 点。";
        } else if (name == "韧性") {
            desc_line = "受到伤害时有 " + to_string(min(85, count * 15)) + "% 几率减少50%伤害。"; // Cap at 85%
        } else if (name == "反伤") {
            desc_line = "受到伤害时反弹 " + to_string(min(85, count * 20)) + "% 伤害给攻击者。"; // Cap at 85%
        } else if (name == "再生") {
            desc_line = "每回合开始时回复 " + to_string(count * 5) + " 点生命值。";
        } else if (name == "毒抗") {
            desc_line = "减少受到的中毒伤害 " + to_string(count * 25) + "%。";
        }
        else {
            // Fallback for any other affixes that might be added later
            desc_line = name + ": " + desc_line_base;
            if (count > 1) { // If multiple, indicate count
                 desc_line = "(x" + to_string(count) + ") " + desc_line;
            }
        }
        combined_descriptions.push_back(desc_line);
    }
    return combined_descriptions;
}

// 打印地图
void print_map() {
    // 使用无尽地图如果处于无尽模式
    vector<string>& map_to_print = is_in_endless_mode ? endless_map : current_maps[current_floor - 1];

    set_color(white);
    clear_area(0, 0, MAP_COLS * 2, MAP_ROWS - 1);
    for (int i = 0; i < MAP_ROWS; i++) {
        string current_map_row = map_to_print[i]; // 使用正确的地图数据
        gotoxy(0, i);
        for (char tile : current_map_row) {
            print_tile(tile);
        }
    }
}

// --- 新增:获取玩家总攻击力 ---
int get_total_attack(int battle_bonus_atk) { // 新增一个可选参数
    int total_atk = class_definitions[player_class].base_attack_per_level[level] + all_weapons[have_sword].get_current_damage();

    // 应用泰坦之力效果
    if (current_star_power_id == 3) {
        total_atk = static_cast<int>(total_atk * 1.10);
    }

    return total_atk + battle_bonus_atk; // 返回时加上战斗中的临时加成
}

// --- 新增:获取玩家总防御力 ---
int get_total_defense(int battle_bonus_def) { // 新增一个可选参数
    int total_def = class_definitions[player_class].base_defense_per_level[level] + all_armors[have_armor].get_current_defense();

    // 应用泰坦之力效果
    if (current_star_power_id == 3) {
        total_def = static_cast<int>(total_def * 1.10);
    }

    return total_def + battle_bonus_def; // 返回时加上战斗中的临时加成
}

// 获取玩家总生命上限(包含护甲词条)
int get_total_max_hp() {
    int base_hp = class_definitions[player_class].max_hp_per_level[level];
    int bonus_hp_from_affixes = 0;
    for (const auto& affix : all_armors[have_armor].affixes) {
        if (affix.name == "生命+") {
            bonus_hp_from_affixes += 10; // 每个“生命+”词条增加10点生命
        }
    }
    int total_hp = base_hp + bonus_hp_from_affixes;

    // --- 新增:应用泰坦之力效果 ---
    if (current_star_power_id == 3) {
        total_hp = static_cast<int>(total_hp * 1.10);
    }
    // --- 结束新增 ---

    return total_hp;
}

// Helper: Prints player stats, returns next Y
int print_player_stats_panel_lines(int start_y_panel) {
    int current_y = start_y_panel;

    set_color(white);
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "职业: " << class_definitions[player_class].name << " (等级 " << level << ")";
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "经验: " << experience << "/" << XP_REQUIRED[level];
    gotoxy(UI_OFFSET_X, current_y++);
    set_color(light_green);
    cout << "生命: " << current_hp << "/" << get_total_max_hp(); // 使用新的总生命上限函数
    gotoxy(UI_OFFSET_X, current_y++);
    set_color(light_red);
    cout << "攻击: " << get_total_attack(); // 不传入参数,显示基础攻击
    set_color(white);
    cout << " (" << class_definitions[player_class].base_attack_per_level[level] << "+" << all_weapons[have_sword].get_current_damage() << ")";
    gotoxy(UI_OFFSET_X, current_y++);
    set_color(cyan);
    cout << "防御: " << get_total_defense(); // 不传入参数,显示基础防御
    set_color(white);
    cout << " (" << class_definitions[player_class].base_defense_per_level[level] << "+" << all_armors[have_armor].get_current_defense() << ")";
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "金币: " << gold << " G";

    // --- 修改:显示所有一次性物品 ---
    clear_area(UI_OFFSET_X, current_y, UI_OFFSET_X + SIDEBAR_WIDTH, current_y + 6); 

    gotoxy(UI_OFFSET_X, current_y++);
    cout << "生命药水: " << inventory["生命药水"] << " (非战斗按'H')";
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "力量药水: " << inventory["力量药水"] << " (战斗中使用)";
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "坚韧药水: " << inventory["坚韧药水"] << " (战斗中使用)";
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "火焰炸弹: " << inventory["火焰炸弹"] << " (战斗中使用)";
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "麻痹卷轴: " << inventory["麻痹卷轴"] << " (战斗中使用)";
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "烟雾弹  : " << inventory["烟雾弹"]   << " (战斗中使用)";

    gotoxy(UI_OFFSET_X, current_y++);
    cout << "技能: " << class_definitions[player_class].skill_name << " (按'F') ";
    if (skill_cooldown == 0) {
        set_color(light_green);
        cout << "[准备就绪]";
    } else {
        set_color(gray);
        cout << "[冷却中:" << skill_cooldown << "]";
    }
    set_color(white);
    return current_y;
}

// Helper: Prints current floor and boss status, fixed at bottom
void print_floor_boss_status(int start_y_panel) {
    if (is_in_endless_mode) {
        int current_y = start_y_panel;
        set_color(light_magenta);
        gotoxy(UI_OFFSET_X, current_y++);
        cout << "无尽模式: 第 " << endless_current_floor << " 层 (最高 " << endless_max_floor << ")";
        gotoxy(UI_OFFSET_X, current_y++);
        if (!endless_boss_defeated_this_floor) {
             set_color(light_red);
             cout << "本层守护者: 未击败  ";
        } else {
            set_color(light_green);
            cout << "本层守护者: 已击败  ";
        }
        set_color(white);
        return;
    }

    int current_y = start_y_panel;
    set_color(white);
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "当前楼层: " << current_floor << " / " << NUM_FLOORS << " (轮次: " << game_phase << ")         ";
    gotoxy(UI_OFFSET_X, current_y++);
    if (current_floor <= NUM_FLOORS && !boss_defeated[current_floor]) {
         set_color(light_red);
         cout << "本层Boss: 未击败  ";
    } else if (current_floor <= NUM_FLOORS && boss_defeated[current_floor]) {
        set_color(light_green);
        cout << "本层Boss: 已击败  ";
    }
    set_color(white);
}

// 打印当前装备武器和护甲的详细信息,包含词条换行 (Modified signature and logic)
int print_equipped_items_details(int start_y_panel) {
    set_color(white); // Ensure color is white for this section

    int current_y = start_y_panel; // Start from the passed Y

    // 武器信息
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "武器: " << all_weapons[have_sword].name << " (Lv." << all_weapons[have_sword].level << ")";

    // 打印合并后的武器词条名称 (例如: [暴击+] (x2) [吸血])
    map<string, int> weapon_affix_counts;
    for (const auto& affix : all_weapons[have_sword].affixes) {
        weapon_affix_counts[affix.name]++;
    }

    string current_weapon_affix_name_line = "  词条: ";
    if (!weapon_affix_counts.empty()) {
        for (const auto& pair : weapon_affix_counts) {
            string affix_text = "[" + pair.first + "]";
            if (pair.second > 1) {
                affix_text += " (x" + to_string(pair.second) + ")";
            }
            // Check if current affix plus next would exceed sidebar width
            if (current_weapon_affix_name_line.length() + affix_text.length() + 1 > SIDEBAR_WIDTH) { 
                gotoxy(UI_OFFSET_X, current_y++); // Increment Y for new line
                cout << current_weapon_affix_name_line; // Print current accumulated line
                current_weapon_affix_name_line = "        " + affix_text; // Start new line with indent
            } else {
                current_weapon_affix_name_line += " " + affix_text; // Append to current line
            }
        }
        gotoxy(UI_OFFSET_X, current_y++); // Print the last accumulated line of affix names
        cout << current_weapon_affix_name_line;
    } else {
        gotoxy(UI_OFFSET_X, current_y++);
        cout << current_weapon_affix_name_line << "[无]";
    }

    // 打印汇总后的武器词条描述
    vector<string> combined_weapon_affix_descs = get_combined_affix_descriptions(all_weapons[have_sword].affixes);
    if (!combined_weapon_affix_descs.empty()) {
        for (const string& desc : combined_weapon_affix_descs) {
            gotoxy(UI_OFFSET_X, current_y++);
            cout << "    - " << desc; // Indent combined descriptions
        }
    }
    current_y++; // 武器和护甲之间的间隙

    // 护甲信息
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "防具: " << all_armors[have_armor].name << " (Lv." << all_armors[have_armor].level << ")";

    // 打印合并后的护甲词条名称
    map<string, int> armor_affix_counts;
    for (const auto& affix : all_armors[have_armor].affixes) {
        armor_affix_counts[affix.name]++;
    }

    string current_armor_affix_name_line = "  词条: ";
    if (!armor_affix_counts.empty()) {
        for (const auto& pair : armor_affix_counts) {
            string affix_text = "[" + pair.first + "]";
            if (pair.second > 1) {
                affix_text += " (x" + to_string(pair.second) + ")";
            }
            if (current_armor_affix_name_line.length() + affix_text.length() + 1 > SIDEBAR_WIDTH) { 
                gotoxy(UI_OFFSET_X, current_y++);
                cout << current_armor_affix_name_line;
                current_armor_affix_name_line = "        " + affix_text;
            } else {
                current_armor_affix_name_line += " " + affix_text;
            }
        }
        gotoxy(UI_OFFSET_X, current_y++);
        cout << current_armor_affix_name_line;
    } else {
        gotoxy(UI_OFFSET_X, current_y++);
        cout << current_armor_affix_name_line << "[无]";
    }

    // 打印汇总后的护甲词条描述
    vector<string> combined_armor_affix_descs = get_combined_affix_descriptions(all_armors[have_armor].affixes);
    if (!combined_armor_affix_descs.empty()) {
        for (const string& desc : combined_armor_affix_descs) {
            gotoxy(UI_OFFSET_X, current_y++);
            cout << "    - " << desc;
        }
    }

    return current_y; // Return the next available Y coordinate
}

// --- 新增:打印星徽之力状态 ---
int print_star_power_status(int start_y_panel) {
    if (current_star_power_id == -1) {
        return start_y_panel; // 如果没有星徽,什么也不打印,直接返回
    }

    int current_y = start_y_panel;
    StarPower current_power;
    for(const auto& sp : all_star_powers) {
        if (sp.id == current_star_power_id) {
            current_power = sp;
            break;
        }
    }

    set_color(light_magenta);
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "星徽之力: [" << current_power.name << "]";
    set_color(white);
    gotoxy(UI_OFFSET_X, current_y++);
    // 简单的换行处理
    string desc = "  效果: " + current_power.description;
    if (desc.length() > SIDEBAR_WIDTH) {
        cout << desc.substr(0, SIDEBAR_WIDTH);
        gotoxy(UI_OFFSET_X, current_y++);
        cout << "  " << desc.substr(SIDEBAR_WIDTH);
    } else {
        cout << desc;
    }

    return current_y + 1; // 返回下一个可用的Y坐标,留出一些间隙
}

// --- 妙具系统: 新增打印妙具状态函数 ---
int print_gadget_status(int start_y_panel) {
    if (current_gadget_id == -1) {
        return start_y_panel; // 如果没有妙具,不打印
    }

    int current_y = start_y_panel;
    Gadget current_gadget;
    for(const auto& g : all_gadgets) {
        if (g.id == current_gadget_id) {
            current_gadget = g;
            break;
        }
    }

    set_color(light_cyan); // 使用不同的颜色以区分
    gotoxy(UI_OFFSET_X, current_y++);
    cout << "妙具: [" << current_gadget.name << "]";
    set_color(white);
    gotoxy(UI_OFFSET_X, current_y++);
    // 简单的换行处理
    string desc = "  效果: " + current_gadget.description;
    if (desc.length() > SIDEBAR_WIDTH) {
        cout << desc.substr(0, SIDEBAR_WIDTH);
        gotoxy(UI_OFFSET_X, current_y++);
        cout << "  " << desc.substr(SIDEBAR_WIDTH);
    } else {
        cout << desc;
    }

    gotoxy(UI_OFFSET_X, current_y++);
    set_color(light_yellow);
    cout << "  剩余次数: " << gadget_current_uses << " / " << current_gadget.max_uses << " (战斗按'G')";

    return current_y + 1; // 返回下一个可用的Y坐标
}

// 打印主界面 (包含地图和状态栏)
void refresh_ui() {
    print_map();

    // Clear entire sidebar area for redraw, to ensure no old text lingers
    clear_area(UI_OFFSET_X, 0, UI_OFFSET_X + SIDEBAR_WIDTH, MAP_ROWS + 9 + 25); // Adjusted height for more dynamic content

    set_color(gray);
    for (int i = 0; i < MAP_ROWS + 25; i++) { // Separator still spans map height + more
        gotoxy((MAP_COLS << 1), i);
        cout << "|";
    }
    set_color(white); // Reset color after separator

    int current_sidebar_y = 1; // Start for first section content

    // Section 1: Top Banner
    gotoxy(UI_OFFSET_X, current_sidebar_y++);
    set_color(light_yellow);
    cout << "--- 文字地牢探险 ---";
    set_color(white);

    // Section 2: Player Stats Panel
    current_sidebar_y = print_player_stats_panel_lines(current_sidebar_y); // Returns next Y

    // Section 3: Equipped Items Details (dynamic height)
    current_sidebar_y = print_equipped_items_details(current_sidebar_y); // Call new function

    // 新增:打印星徽之力
    current_sidebar_y = print_star_power_status(current_sidebar_y);

    // --- 妙具系统: 调用打印函数 ---
    current_sidebar_y = print_gadget_status(current_sidebar_y);

    // Section 4: Message Log (fixed height, dynamic start Y)
    g_message_log_start_y = current_sidebar_y; // Set global Y for message log
    print_message_log(); // Call message log print (it uses g_message_log_start_y)
    current_sidebar_y += 10; // Advance Y by 10 (1 for title, 9 for messages)

    // Section 5: Current Floor and Boss Status (fixed height, dynamic start Y)
    print_floor_boss_status(current_sidebar_y);

    set_color(white); // Reset to default color at the end
}

// 打印武器详细信息 (用于商店和锻造小屋) (Modified to return next_y)
int print_weapon_details(const Weapon& w, int start_y, const string& prefix) {
    // Clear a larger area sufficient for weapon details AND all affix descriptions
    clear_area(4, start_y, 4 + SIDEBAR_WIDTH + 30, start_y + 25); // Extend clear area significantly
    set_color(white);

    int current_y_internal = start_y; // Use an internal tracker

    gotoxy(4, current_y_internal++);
    set_color(white);
    cout << prefix << "名称: " << w.name << " (Lv." << w.level << ")";
    gotoxy(4, current_y_internal++);
    set_color(light_red);
    cout << prefix << "伤害: " << w.get_current_damage();
    gotoxy(4, current_y_internal++);
    set_color(cyan);
    cout << prefix << "初始词条槽位: " << w.initial_affix_slots;
    gotoxy(4, current_y_internal++);
    set_color(light_green);
    cout << prefix << "当前词条槽位: " << w.get_current_affix_slots();
    gotoxy(4, current_y_internal++);
    set_color(yellow);
    cout << prefix << "出售价格: " << w.cost / 2 << " G";
    gotoxy(4, current_y_internal++);
    set_color(white);

    // 打印合并后的武器词条名称 (例如: [暴击+] (x2) [吸血])
    map<string, int> affix_counts;
    for (const auto& affix : w.affixes) {
        affix_counts[affix.name]++;
    }
    string current_affix_name_line_detail = prefix + "词条: ";
    if (!affix_counts.empty()) {
        for (const auto& pair : affix_counts) {
            string affix_text = "[" + pair.first + "]";
            if (pair.second > 1) {
                affix_text += " (x" + to_string(pair.second) + ")";
            }
            if (current_affix_name_line_detail.length() + affix_text.length() + 1 > SIDEBAR_WIDTH) { 
                gotoxy(4, current_y_internal++);
                cout << current_affix_name_line_detail;
                current_affix_name_line_detail = prefix + "      " + affix_text; // 缩进新行
            } else {
                current_affix_name_line_detail += " " + affix_text;
            }
        }
        gotoxy(4, current_y_internal++); // Print the last accumulated affix names line
        cout << current_affix_name_line_detail;
    } else {
        gotoxy(4, current_y_internal++);
        cout << current_affix_name_line_detail << "[无]";
    }

    // 打印汇总后的词条描述
    vector<string> combined_affix_descs = get_combined_affix_descriptions(w.affixes);
    if (!combined_affix_descs.empty()) {
        for (const string& desc : combined_affix_descs) {
            gotoxy(4, current_y_internal++);
            cout << prefix << "  - " << desc;
        }
    }
    return current_y_internal;
}

// 打印护甲详细信息 (用于商店和锻造小屋)
int print_armor_details(const Armor& a, int start_y, const string& prefix) {
    // Clear a larger area sufficient for armor details AND all affix descriptions
    clear_area(4, start_y, 4 + SIDEBAR_WIDTH + 30, start_y + 25); 
    set_color(white);

    int current_y_internal = start_y;

    gotoxy(4, current_y_internal++);
    set_color(white);
    cout << prefix << "名称: " << a.name << " (Lv." << a.level << ")";
    gotoxy(4, current_y_internal++);
    set_color(cyan);
    cout << prefix << "防御: " << a.get_current_defense();
    gotoxy(4, current_y_internal++);
    set_color(cyan);
    cout << prefix << "初始词条槽位: " << a.initial_affix_slots;
    gotoxy(4, current_y_internal++);
    set_color(light_green);
    cout << prefix << "当前词条槽位: " << a.get_current_affix_slots();
    gotoxy(4, current_y_internal++);
    set_color(yellow);
    cout << prefix << "出售价格: " << a.cost / 2 << " G";
    gotoxy(4, current_y_internal++);
    set_color(white);

    // 打印合并后的护甲词条名称
    map<string, int> affix_counts;
    for (const auto& affix : a.affixes) {
        affix_counts[affix.name]++;
    }
    string current_affix_name_line_detail = prefix + "词条: ";
    if (!affix_counts.empty()) {
        for (const auto& pair : affix_counts) {
            string affix_text = "[" + pair.first + "]";
            if (pair.second > 1) {
                affix_text += " (x" + to_string(pair.second) + ")";
            }
            if (current_affix_name_line_detail.length() + affix_text.length() + 1 > SIDEBAR_WIDTH) { 
                gotoxy(4, current_y_internal++);
                cout << current_affix_name_line_detail;
                current_affix_name_line_detail = prefix + "      " + affix_text; // 缩进新行
            } else {
                current_affix_name_line_detail += " " + affix_text;
            }
        }
        gotoxy(4, current_y_internal++); // Print the last accumulated affix names line
        cout << current_affix_name_line_detail;
    } else {
        gotoxy(4, current_y_internal++);
        cout << current_affix_name_line_detail << "[无]";
    }

    // 打印汇总后的词条描述
    vector<string> combined_affix_descs = get_combined_affix_descriptions(a.affixes);
    if (!combined_affix_descs.empty()) {
        for (const string& desc : combined_affix_descs) {
            gotoxy(4, current_y_internal++);
            cout << prefix << "  - " << desc;
        }
    }
    return current_y_internal;
}

// 处理宝箱内容
void open_treasure_chest() {
    // --- 新增:无尽模式下有几率获得星徽之力 ---
    if (is_in_endless_mode && (rand() % 100 < 10)) { // 10% 的几率
        int new_power_idx = rand() % all_star_powers.size();
        StarPower found_power = all_star_powers[new_power_idx];

        if (current_star_power_id == -1) { // 玩家没有星徽,直接获得
            current_star_power_id = found_power.id;
            add_message("你从宝箱中感应到一股神秘力量!");
            add_message("获得了星徽之力: [" + found_power.name + "]!");
        } else { // 玩家已有星徽,需要选择
            // 找到当前星徽
            StarPower current_power;
            for(const auto& sp : all_star_powers) {
                if (sp.id == current_star_power_id) {
                    current_power = sp;
                    break;
                }
            }

            system("cls");
            gotoxy(25, 2); set_color(light_magenta); cout << "--- 星徽抉择 ---";
            set_color(white);

            gotoxy(10, 5); cout << "你发现了一个新的星徽之力,但你只能同时拥有一个。";

            gotoxy(10, 8); set_color(light_cyan); cout << "你当前拥有的星徽:";
            set_color(white);
            gotoxy(12, 10); cout << "名称: " << current_power.name;
            gotoxy(12, 11); cout << "效果: " << current_power.description;

            gotoxy(10, 14); set_color(light_yellow); cout << "新发现的星徽:";
            set_color(white);
            gotoxy(12, 16); cout << "名称: " << found_power.name;
            gotoxy(12, 17); cout << "效果: " << found_power.description;

            gotoxy(10, 20); cout << "请选择: [1] 替换为新的星徽 (" << found_power.name << ")";
            gotoxy(10, 21); cout << "         [2] 保留现有的星徽 (" << current_power.name << ")";

            bool choice_made = false;
            while (!choice_made) {
                if (zxb('1')) {
                    add_message("你吸收了新的力量,替换了旧的星徽!");
                    add_message("新星徽: [" + found_power.name + "] 已激活。");
                    current_star_power_id = found_power.id;
                    choice_made = true;
                    while(zxb('1'));
                } else if (zxb('2')) {
                    add_message("你决定保留现有的力量,放弃了新的星徽。");
                    choice_made = true;
                    while(zxb('2'));
                }
                this_thread::sleep_for(chrono::milliseconds(50));
            }
            system("cls");
            refresh_ui();
            gotoxy(y_pos << 1, x_pos); set_color(bright_white); cout << "入";
        }
        // 获得星徽之力后,宝箱的常规奖励不再触发
        current_maps[current_floor - 1][x_pos][y_pos] = '.';
        if(is_in_endless_mode) endless_map[x_pos][y_pos] = '.';
        return;
    }
    // --- 妙具系统: 在无尽宝箱中获得妙具 ---
    else if (is_in_endless_mode && (rand() % 100 < 6)) { // 6% 的几率获得妙具
        int new_gadget_idx = rand() % all_gadgets.size();
        Gadget found_gadget = all_gadgets[new_gadget_idx];

        if (current_gadget_id == -1) { // 玩家没有妙具,直接获得
            current_gadget_id = found_gadget.id;
            gadget_current_uses = found_gadget.max_uses;
            add_message("你从宝箱中发现一个奇妙的装置!");
            add_message("获得了妙具: [" + found_gadget.name + "]!");
        } else { // 玩家已有妙具,需要选择
            Gadget current_gadget;
            for(const auto& g : all_gadgets) {
                if (g.id == current_gadget_id) {
                    current_gadget = g;
                    break;
                }
            }

            system("cls");
            gotoxy(25, 2); set_color(light_cyan); cout << "--- 妙具抉择 ---";
            set_color(white);

            gotoxy(10, 5); cout << "你发现了一个新的妙具,但你只能同时携带一个。";

            gotoxy(10, 8); set_color(light_green); cout << "你当前携带的妙具:";
            set_color(white);
            gotoxy(12, 10); cout << "名称: " << current_gadget.name;
            gotoxy(12, 11); cout << "效果: " << current_gadget.description;
            gotoxy(12, 12); cout << "次数: " << gadget_current_uses << " / " << current_gadget.max_uses;

            gotoxy(10, 15); set_color(light_yellow); cout << "新发现的妙具:";
            set_color(white);
            gotoxy(12, 17); cout << "名称: " << found_gadget.name;
            gotoxy(12, 18); cout << "效果: " << found_gadget.description;
            gotoxy(12, 19); cout << "次数: " << found_gadget.max_uses << " / " << found_gadget.max_uses;

            gotoxy(10, 22); cout << "请选择: [1] 替换为新的妙具 (" << found_gadget.name << ")";
            gotoxy(10, 23); cout << "         [2] 保留现有的妙具 (" << current_gadget.name << ")";

            bool choice_made = false;
            while (!choice_made) {
                if (zxb('1')) {
                    add_message("你装备了新的妙具,替换了旧的!");
                    add_message("新妙具: [" + found_gadget.name + "] 已准备就绪。");
                    current_gadget_id = found_gadget.id;
                    gadget_current_uses = found_gadget.max_uses; // 新妙具次数充满
                    choice_made = true;
                    while(zxb('1'));
                } else if (zxb('2')) {
                    add_message("你决定保留现有的装置,放弃了新的妙具。");
                    choice_made = true;
                    while(zxb('2'));
                }
                this_thread::sleep_for(chrono::milliseconds(50));
            }
            system("cls");
            refresh_ui();
            gotoxy(y_pos << 1, x_pos); set_color(bright_white); cout << "入";
        }
        // 获得妙具后,宝箱的常规奖励不再触发
        current_maps[current_floor - 1][x_pos][y_pos] = '.';
        if(is_in_endless_mode) endless_map[x_pos][y_pos] = '.';
        return;
    }

    int loot_type = rand() % 100; // 0-99

    // --- 新增:无尽模式奖励调整 ---
    float endless_bonus_multiplier = 1.0f;
    if (is_in_endless_mode) {
        endless_bonus_multiplier = 1.0f + (endless_current_floor * 0.1f);
    }
    // --- 结束新增 ---

    if (loot_type < 30) { // 30% 几率获得金币
        // --- 修改金币获取公式 ---
        int amount = rand() % 20 + 10 * current_floor * game_phase;
        amount = static_cast<int>(amount * endless_bonus_multiplier); // 应用无尽模式加成
        gold += amount;
        add_message("你打开宝箱,获得了 " + to_string(amount) + " 金币!");
    } else if (loot_type < 65) { // 35% 几率获得武器或护甲
        bool is_weapon = rand() % 2;

        // --- 修改装备等级公式 ---
        int floor_factor = is_in_endless_mode ? (endless_current_floor / 2) : current_floor;
        int max_weapon_template_idx = min((int)global_weapon_templates.size() - 1, floor_factor + game_phase + 2);
        max_weapon_template_idx = max(0, max_weapon_template_idx);

        int max_armor_template_idx = min((int)global_armor_templates.size() - 1, floor_factor + game_phase + 2);
        max_armor_template_idx = max(0, max_armor_template_idx);

        if (is_weapon) {
            int weapon_template_idx = rand() % (max_weapon_template_idx + 1); // 随机获得一种武器模板索引
            // 创建新的武器实例,其level默认为0,affixes会在构造时根据initial_affix_slots生成
            Weapon new_weapon_instance = global_weapon_templates[weapon_template_idx]; // 从模板复制
            new_weapon_instance.level = rand() % 2; // 宝箱获得的武器可能是Lv0或Lv1

            // 重新为这个新实例生成词条
            // 对于固定词条的武器,不重新生成词条
            if (!(new_weapon_instance.name == "神圣之剑" || new_weapon_instance.name == "混沌战斧")) {
                new_weapon_instance.affixes.clear();
                for (int i = 0; i < new_weapon_instance.get_current_affix_slots(); ++i) {
                     vector<Affix> pool;
                     for (const auto& affix_template : all_affixes) {
                         // 武器词条:只选择武器词条,且级别不超过武器等级+1
                         if (affix_template.tier <= new_weapon_instance.level + 1 &&
                             is_weapon_affix_type(affix_template)) { 
                             pool.push_back(affix_template);
                         }
                     }
                     if (!pool.empty()) {
                         new_weapon_instance.affixes.push_back(pool[rand() % pool.size()]);
                     }
                }
            }

            // 新增:武器选择逻辑
            system("cls"); // 清屏以显示选择界面
            gotoxy(25, 2);
            set_color(light_yellow);
            cout << "--- 发现新武器! ---";

            int current_display_y = 5;
            gotoxy(4, current_display_y);
            set_color(light_cyan);
            cout << "你当前装备的武器:";
            current_display_y = print_weapon_details(all_weapons[have_sword], current_display_y + 1); // Get next Y

            current_display_y++; // Add a small gap
            gotoxy(4, current_display_y);
            set_color(light_cyan);
            cout << "你发现的新武器:";
            current_display_y = print_weapon_details(new_weapon_instance, current_display_y + 1); // Get next Y

            current_display_y++; // Add a small gap
            set_color(white);
            gotoxy(4, current_display_y++);
            cout << "请选择: [1] 装备新武器 (旧武器回收 " << all_weapons[have_sword].cost / 2 << " G)";
            gotoxy(4, current_display_y++);
            cout << "         [2] 回收新武器 (新武器回收 " << new_weapon_instance.cost / 2 << " G)";
            gotoxy(4, current_display_y++);
            cout << "你的选择: ";

            bool choice_made = false;
            while (!choice_made) {
                if (zxb('1')) { 
                    gold += all_weapons[have_sword].cost / 2; // 回收旧武器
                    all_weapons[have_sword] = new_weapon_instance; // 替换当前武器
                    add_message("你装备了 " + new_weapon_instance.name + "!旧武器已回收。");
                    choice_made=true;
                    while(zxb('1')); // Debounce
                } else if (zxb('2')) { 
                    gold += new_weapon_instance.cost / 2; // 回收新武器
                    add_message("你回收了 " + new_weapon_instance.name + ",获得 " + to_string(new_weapon_instance.cost / 2) + " 金币。");
                    choice_made=true;
                    while(zxb('2')); // Debounce
                }
                this_thread::sleep_for(chrono::milliseconds(50));
            }

            system("cls"); // 清屏以显示主界面
            refresh_ui();  // 刷新UI以显示新武器和更新的属性
            gotoxy(y_pos << 1, x_pos); // 重新绘制玩家角色在地图上
            set_color(bright_white);
            cout << "入";

        } else { // 获得护甲
            int armor_template_idx = rand() % (max_armor_template_idx + 1);
            Armor new_armor_instance = global_armor_templates[armor_template_idx];
            new_armor_instance.level = rand() % 2; // 宝箱护甲可能是Lv0或Lv1

            // 对于固定词条的护甲,不重新生成词条
            if (!(new_armor_instance.name == "神圣之盾" || new_armor_instance.name == "混沌胸甲")) {
                new_armor_instance.affixes.clear();
                for (int i = 0; i < new_armor_instance.get_current_affix_slots(); ++i) {
                     vector<Affix> pool;
                     for (const auto& affix_template : all_affixes) {
                         // 护甲词条:只选择护甲词条,且级别不超过护甲等级+1
                         if (affix_template.tier <= new_armor_instance.level + 1 &&
                             is_armor_affix_type(affix_template)) { 
                             pool.push_back(affix_template);
                         }
                     }
                     if (!pool.empty()) {
                         new_armor_instance.affixes.push_back(pool[rand() % pool.size()]);
                     }
                }
            }

            system("cls");
            gotoxy(25, 2); set_color(light_yellow); cout << "--- 发现新护甲! ---";
            int current_display_y = 5;
            gotoxy(4, current_display_y); set_color(light_cyan); cout << "你当前装备的护甲:";
            current_display_y = print_armor_details(all_armors[have_armor], current_display_y + 1);
            current_display_y++;
            gotoxy(4, current_display_y); set_color(light_cyan); cout << "你发现的新护甲:";
            current_display_y = print_armor_details(new_armor_instance, current_display_y + 1);
            current_display_y++;
            set_color(white);
            gotoxy(4, current_display_y++);
            cout << "请选择: [1] 装备新护甲 (旧护甲回收 " << all_armors[have_armor].cost / 2 << " G)";
            gotoxy(4, current_display_y++);
            cout << "         [2] 回收新护甲 (新护甲回收 " << new_armor_instance.cost / 2 << " G)";
            gotoxy(4, current_display_y++);
            cout << "你的选择: ";

            bool choice_made = false;
            while (!choice_made) {
                if (zxb('1')) { 
                    gold += all_armors[have_armor].cost / 2; // 回收旧护甲
                    all_armors[have_armor] = new_armor_instance; // 替换当前护甲
                    // 重要:装备新护甲后,更新当前生命值,确保不超过新的最大生命值上限
                    current_hp = min(current_hp, get_total_max_hp());
                    add_message("你装备了 " + new_armor_instance.name + "!旧护甲已回收。");
                    choice_made=true; while(zxb('1'));
                } else if (zxb('2')) { 
                    gold += new_armor_instance.cost / 2; // 回收新护甲
                    add_message("你回收了 " + new_armor_instance.name + ",获得 " + to_string(new_armor_instance.cost / 2) + " 金币。");
                    choice_made=true; while(zxb('2'));
                }
                this_thread::sleep_for(chrono::milliseconds(50));
            }
            system("cls"); refresh_ui(); gotoxy(y_pos << 1, x_pos); set_color(bright_white); cout << "入";
        }
    } else { // 35% 几率获得一次性物品
        // --- 修改:随机获得一种一次性物品 ---
        int item_type = rand() % 10; // 0-9
        if (item_type < 4) { // 40% 概率
            inventory["生命药水"]++;
            add_message("你从宝箱里找到了一瓶生命药水!");
        } else if (item_type < 6) { // 20% 概率
            inventory["力量药水"]++;
            add_message("你找到一瓶蕴含力量的药剂!");
        } else if (item_type < 8) { // 20% 概率
            inventory["坚韧药水"]++;
            add_message("你找到一瓶能强化体魄的药剂!");
        } else if (item_type == 8) { // 10% 概率
            inventory["火焰炸弹"]++;
            add_message("你发现了一个不稳定的火焰炸弹!");
        } else { // 10% 概率,原本是麻痹卷轴
            // --- 修改:检查麻痹卷轴的持有量 ---
            if (inventory["麻痹卷轴"] >= 1) {
                // 如果已经有了,给一个替代奖励,比如金币
                int amount = rand() % 50 + 20; // 给一笔不错的金币
                gold += amount;
                add_message("你本该找到一张卷轴,但它化作了 " + to_string(amount) + " 金币!");
            } else {
                // 如果没有,正常获得
                inventory["麻痹卷轴"]++;
                add_message("你发现了一张古老的麻痹卷轴!");
            }
        }
    }
}

// 检查是否升级
void check_level_up() {
    while (experience >= XP_REQUIRED[level] && level < MAX_LEVEL) { // 使用 MAX_LEVEL
        experience -= XP_REQUIRED[level];
        level++;
        add_message(">>>>> 等级提升!你现在是 " + to_string(level) + " 级!<<<<<");
        add_message("生命、攻击和防御都提升了!");
        current_hp = get_total_max_hp(); // 升级时生命值回满,并考虑护甲生命词条
        if (skill_cooldown > 0) skill_cooldown = max(0, skill_cooldown - 1); // 升级可以减少技能冷却
    }
}

// 绘制战斗界面
// --- 妙具系统: 更新战斗界面函数签名 ---
void draw_battle_screen(const Monster& monster, int monster_current_hp, const vector<string>& battle_log, 
                        bool player_poisoned, int player_poison_duration, bool monster_stunned,
                        bool monster_poisoned_status, int monster_poison_duration_status,
                        bool monster_crippled_status, int monster_cripple_duration_status,
                        const string& player_buff_name, int player_buff_duration,
                        const string& monster_debuff_name, int monster_debuff_duration,
                        int player_shield_hp)
{
    system("cls");
    set_color(light_yellow);
    gotoxy(30, 1);
    cout << "--- 战 斗 中 ---";
    set_color(white);
    gotoxy(5, 4);
    cout << "你 (等级 " << level << ")";

    // --- 新增:显示药水Buff状态 ---
    if (power_potion_active) {
        set_color(light_red);
        cout << " [力量!]";
    }
    if (defense_potion_active) {
        set_color(light_cyan);
        cout << " [坚韧!]";
    }
    // --- 妙具系统: 显示玩家Buff和护盾 ---
    if (player_buff_name != "" && player_buff_duration > 0) {
        set_color(light_yellow);
        cout << " [" << player_buff_name << ":" << player_buff_duration << "]";
    }
    if (player_shield_hp > 0) {
        set_color(cyan);
        cout << " [护盾:" << player_shield_hp << "]";
    }

    gotoxy(5, 5);
    set_color(light_green);
    cout << "生命: " << current_hp << " / " << get_total_max_hp(); // 使用get_total_max_hp
    if (player_poisoned && player_poison_duration > 0) {
        set_color(light_magenta);
        cout << " (中毒: " << player_poison_duration << " 回合)";
    }
    gotoxy(5, 6);
    set_color(light_red);
    cout << "攻击: " << get_total_attack();
    gotoxy(5, 7);
    set_color(cyan);
    cout << "防御: " << get_total_defense();

    set_color(white);
    gotoxy(60, 4);
    cout << monster.name;
    if (monster_stunned) {
        set_color(light_yellow);
        cout << " (眩晕)";
    }
    if (monster_poisoned_status && monster_poison_duration_status > 0) { // NEW
        set_color(light_magenta);
        cout << " (中毒: " << monster_poison_duration_status << " 回合)";
    }
    if (monster_crippled_status && monster_cripple_duration_status > 0) { // NEW
        set_color(light_blue);
        cout << " (攻击降低: " << monster_cripple_duration_status << " 回合)";
    }
    // --- 妙具系统: 显示怪物Debuff ---
    if (monster_debuff_name != "" && monster_debuff_duration > 0) {
        set_color(gray);
        cout << " (" << monster_debuff_name << ":" << monster_debuff_duration << ")";
    }

    set_color(white); // Reset color
    gotoxy(60, 5);
    set_color(light_green);
    cout << "生命: " << monster_current_hp << " / " << monster.max_hp;
    gotoxy(60, 6);
    set_color(light_red);
    cout << "攻击: " << monster.attack;
    gotoxy(60, 7);
    set_color(cyan);
    cout << "防御: " << monster.defense;

    set_color(gray);
    gotoxy(0, 10);
    for (int i = 0; i < 80; ++i) cout << "-";

    set_color(white);
    gotoxy(5, 12);
    cout << "你的回合, 请选择行动:";

    // --- 修改:增加新物品的使用选项 ---
    gotoxy(5, 14);
    cout << "[1] 普通攻击";
    gotoxy(5, 15);
    cout << "[2] " << class_definitions[player_class].skill_name;
    if (skill_cooldown == 0) {
        set_color(light_green);
        cout << " [准备就绪]";
    } else {
        set_color(gray);
        cout << " [冷却中: " << skill_cooldown << "]";
    }
    set_color(white);
    gotoxy(5, 16);
    cout << "[3] 使用生命药水 (" << inventory["生命药水"] << " 瓶)";
    gotoxy(5, 17);
    cout << "[4] 使用力量药水 (" << inventory["力量药水"] << " 瓶)";
    gotoxy(5, 18);
    cout << "[5] 使用坚韧药水 (" << inventory["坚韧药水"] << " 瓶)";
    gotoxy(5, 19);
    cout << "[6] 使用火焰炸弹 (" << inventory["火焰炸弹"] << " 个)";
    gotoxy(5, 20);
    cout << "[7] 使用麻痹卷轴 (" << inventory["麻痹卷轴"] << " 张)";
    gotoxy(5, 21);
    cout << "[8] 使用烟雾弹   (" << inventory["烟雾弹"] << " 个)";

    // --- 妙具系统: 添加妙具使用选项 ---
    gotoxy(5, 22);
    if (current_gadget_id != -1 && gadget_current_uses > 0) {
        Gadget current_gadget;
        for(const auto& g : all_gadgets) { if (g.id == current_gadget_id) { current_gadget = g; break; } }
        set_color(white);
        cout << "[G] 使用妙具: " << current_gadget.name;
        set_color(light_green);
        cout << " [" << gadget_current_uses << "次可用]";
    } else {
        set_color(gray);
        cout << "[G] 使用妙具 [无可用]";
    }
    set_color(white);

    set_color(light_yellow);
    gotoxy(40, 12);
    cout << "--- 战斗日志 ---";
    set_color(white);
    for (int i = 0; i < battle_log.size(); ++i) {
        gotoxy(40, 14 + i);
        cout << battle_log[i];
    }
}

// --- 新增:执行一次普通攻击的辅助函数 ---
// --- 妙具系统: 更新函数签名 ---
void perform_basic_attack(int& monster_current_hp, const Monster& monster_template, vector<string>& battle_log, bool& monster_stunned_ref,
                          bool& monster_poisoned_status_ref, int& monster_poison_duration_status_ref, int& monster_poison_damage_per_turn_status_ref,
                          bool& monster_crippled_status_ref, int& monster_cripple_duration_status_ref, int& monster_cripple_attack_reduction_ref,
                          float player_attack_multiplier, float monster_stat_multiplier) 
{
    int base_damage = get_total_attack();
    // --- 妙具系统: 应用玩家攻击增益 ---
    base_damage = static_cast<int>(base_damage * player_attack_multiplier);

    // 应用力量药水效果
    if (power_potion_active) {
        base_damage = static_cast<int>(base_damage * 1.5);
    }

    // --- 妙具系统: 应用怪物防御减益 ---
    int monster_effective_defense = static_cast<int>(monster_template.defense * monster_stat_multiplier);

    int crit_affix_count = 0;
    int lifesteal_affix_count = 0;
    int armor_pierce_affix_count = 0;
    int stun_affix_count = 0;
    int poison_blade_affix_count = 0; 
    int cripple_strike_affix_count = 0; 

    for (const auto& affix : all_weapons[have_sword].affixes) {
        if (affix.name == "暴击+") crit_affix_count++;
        else if (affix.name == "吸血") lifesteal_affix_count++;
        else if (affix.name == "穿甲") armor_pierce_affix_count++;
        else if (affix.name == "破碎一击") stun_affix_count++;
        else if (affix.name == "剧毒之刃") poison_blade_affix_count++;
        else if (affix.name == "致残打击") cripple_strike_affix_count++;
    }

    // 应用穿甲
    if (armor_pierce_affix_count > 0) {
        monster_effective_defense = max(0, monster_effective_defense - (armor_pierce_affix_count * 5));
        battle_log.push_back("你的武器穿透了敌人的防御 (" + to_string(armor_pierce_affix_count * 5) + ")!");
        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
    }

    int player_damage = max(1, base_damage - monster_effective_defense);

    // 应用暴击
    double crit_multiplier = 2.0;
    // 应用致命专注(ID:6)效果
    if(current_star_power_id == 6) crit_multiplier = 2.5;
    if (crit_affix_count > 0 && (rand() % 100 < crit_affix_count * 10)) {
        player_damage = static_cast<int>(player_damage * crit_multiplier);
        battle_log.push_back("你的武器触发了致命一击!");
        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
    }

    monster_current_hp -= player_damage;
    battle_log.push_back("你对 " + monster_template.name + " 造成 " + to_string(player_damage) + " 点伤害!");
    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());

    // 应用吸血
    if (lifesteal_affix_count > 0) {
        int heal_amount = max(1, static_cast<int>(player_damage * (lifesteal_affix_count * 0.10f)));
        current_hp = min(get_total_max_hp(), current_hp + heal_amount);
        battle_log.push_back("你通过吸血恢复了 " + to_string(heal_amount) + " 点生命!");
        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
    }

    // 应用破碎一击(眩晕)效果
    if (stun_affix_count > 0) {
        int total_stun_chance = min(85, stun_affix_count * 15);
        if (rand() % 100 < total_stun_chance) {
            monster_stunned_ref = true;
            battle_log.push_back(monster_template.name + " 被破碎一击击晕了!");
            if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
        }
    }

    // 应用剧毒之刃效果 (MODIFIED)
    if (poison_blade_affix_count > 0) {
        int total_poison_chance = min(100, poison_blade_affix_count * 25);
        if (rand() % 100 < total_poison_chance) {
            // 判定成功
            if (!monster_poisoned_status_ref) {
                // 首次施加
                monster_poisoned_status_ref = true;
                // 伤害仅在首次施加时计算
                monster_poison_damage_per_turn_status_ref = max(1, (int)(base_damage * 0.20));
                battle_log.push_back(monster_template.name + " 中毒了!");
            } else {
                // 刷新效果
                battle_log.push_back(monster_template.name + " 的中毒效果被刷新了!");
            }

            // 无论首次还是刷新,都更新持续时间为最大值
            monster_poison_duration_status_ref = max(monster_poison_duration_status_ref, 3); 

            if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
        }
    }

    // 应用致残打击效果 (MODIFIED)
    if (cripple_strike_affix_count > 0) {
        int total_cripple_chance = min(100, cripple_strike_affix_count * 20);
        if (rand() % 100 < total_cripple_chance) {
            // 判定成功
            if (!monster_crippled_status_ref) {
                // 首次施加
                monster_crippled_status_ref = true;
                // 攻击力削减值仅在首次施加时计算
                monster_cripple_attack_reduction_ref = max(1, (int)(monster_template.attack * 0.20));
                battle_log.push_back(monster_template.name + " 被致残,攻击力降低了!");
            } else {
                // 刷新效果
                battle_log.push_back(monster_template.name + " 的致残效果被刷新了!");
            }

            // 无论首次还是刷新,都更新持续时间为最大值
            monster_cripple_duration_status_ref = max(monster_cripple_duration_status_ref, 2);

            if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
        }
    }
}

// --- 新增:执行一次技能攻击的辅助函数 ---
// --- 妙具系统: 更新函数签名 ---
void perform_skill_attack(int& monster_current_hp, const Monster& monster_template, vector<string>& battle_log, bool& monster_stunned_ref,
                          float player_attack_multiplier, float monster_stat_multiplier) 
{
    float multiplier = 1.0f;
    int effective_attack = get_total_attack();
    // --- 妙具系统: 应用玩家攻击增益 ---
    effective_attack = static_cast<int>(effective_attack * player_attack_multiplier);

    // 应用力量药水效果
    if (power_potion_active) {
        effective_attack = static_cast<int>(effective_attack * 1.5);
    }

    // --- 妙具系统: 应用怪物防御减益 ---
    int monster_effective_defense = static_cast<int>(monster_template.defense * monster_stat_multiplier);

    int player_damage = 0;
    if (player_class == 1) { // 战士:强力一击
        multiplier = 1.8f;
        player_damage = max(1, static_cast<int>(effective_attack * multiplier) - monster_effective_defense);
        monster_current_hp -= player_damage;
        battle_log.push_back("你使用了强力一击,造成 " + to_string(player_damage) + " 点暴击伤害!");
        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
    } else if (player_class == 2) { // 游侠:精准射击
        multiplier = 1.2f;
        player_damage = max(1, static_cast<int>(effective_attack * multiplier) - monster_effective_defense);
        monster_current_hp -= player_damage;
        battle_log.push_back("你施展了精准射击,造成 " + to_string(player_damage) + " 点伤害!");
        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
        if (rand() % 100 < 50) { // 50% 几率眩晕
            monster_stunned_ref = true;
            battle_log.push_back(monster_template.name + " 被你精准的箭矢震慑住了,无法行动!");
            if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
        }
    } else if (player_class == 3) { // 法师:火球术
        multiplier = 6.5f;
        player_damage = max(1, static_cast<int>(effective_attack * multiplier) - monster_effective_defense);
        monster_current_hp -= player_damage;
        battle_log.push_back("你施放了火球术,对 " + monster_template.name + " 造成 " + to_string(player_damage) + " 点魔法伤害!");
        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
    }
}

// 战斗系统
void start_battle(Monster monster_template) {
    int monster_current_hp = monster_template.max_hp;
    vector<string> battle_log;
    bool player_poisoned = false;
    int poison_duration = 0;
    int poison_damage_per_turn = 0;
    bool monster_stunned = false; 

    bool monster_poisoned_status = false;
    int monster_poison_duration_status = 0;
    int monster_poison_damage_per_turn_status = 0;
    bool monster_crippled_status = false;
    int monster_cripple_duration_status = 0;
    int monster_cripple_attack_reduction = 0;

    string player_buff_name = "";
    int player_buff_duration = 0;
    float player_attack_multiplier = 1.0f;

    string monster_debuff_name = "";
    int monster_debuff_duration = 0;
    float monster_stat_multiplier = 1.0f;

    int player_shield_hp = 0;

    // --- 新增:为 mwh 技能服务的战斗内状态 ---
    bool player_gets_extra_turn = false; // 用于处理 mwh 的额外回合
    int mwh_battle_bonus_atk = 0;        // mwh 在本场战斗中窃取到的攻击力
    int mwh_battle_bonus_def = 0;        // mwh 在本场战斗中窃取到的防御力

    battle_log.push_back("你遭遇了 " + monster_template.name + "!");

    while (current_hp > 0 && monster_current_hp > 0) {
        // --- 回合开始时的状态处理 ---
        player_gets_extra_turn = false; // 每回合开始时重置额外回合标记

        if (player_buff_duration > 0) {
            player_buff_duration--;
            if (player_buff_duration == 0) {
                battle_log.push_back("你的 [" + player_buff_name + "] 效果结束了!");
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                player_buff_name = "";
                player_attack_multiplier = 1.0f; 
            }
        }
        if (monster_debuff_duration > 0) {
            monster_debuff_duration--;
            if (monster_debuff_duration == 0) {
                battle_log.push_back(monster_template.name + " 的 [" + monster_debuff_name + "] 效果结束了!");
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                monster_debuff_name = "";
                monster_stat_multiplier = 1.0f; 
            }
        }

        if (current_star_power_id == 2) {
            int heal_amount = max(1, static_cast<int>(get_total_max_hp() * 0.15));
            current_hp = min(get_total_max_hp(), current_hp + heal_amount);
            battle_log.push_back("生命源泉为你回复了 " + to_string(heal_amount) + " 点生命!");
            if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
        }

        int player_regeneration_affix_count = 0;
        for (const auto& affix : all_armors[have_armor].affixes) {
            if (affix.name == "再生") player_regeneration_affix_count++;
        }
        if (player_regeneration_affix_count > 0) {
            int heal_amount = player_regeneration_affix_count * 5;
            current_hp = min(get_total_max_hp(), current_hp + heal_amount);
            battle_log.push_back("你的再生护甲为你回复了 " + to_string(heal_amount) + " 点生命!");
            if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
        }

        if (player_poisoned && poison_duration > 0) {
            int effective_poison_damage = poison_damage_per_turn;
            int player_poison_resist_affix_count = 0;
            for (const auto& affix : all_armors[have_armor].affixes) {
                if (affix.name == "毒抗") player_poison_resist_affix_count++;
            }
            if (player_poison_resist_affix_count > 0) {
                int reduction_percentage = player_poison_resist_affix_count * 25;
                effective_poison_damage = max(0, effective_poison_damage * (100 - reduction_percentage) / 100);
            }

            if (effective_poison_damage > 0) {
                current_hp = max(0, current_hp - effective_poison_damage);
                battle_log.push_back("你因中毒受到 " + to_string(effective_poison_damage) + " 点伤害! (" + to_string(poison_duration) + " 回合剩余)");
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
            } else {
                battle_log.push_back("你的毒抗使你免受中毒伤害!");
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
            }
            poison_duration--;
            if (current_hp <= 0) break;
        }
        if (player_poisoned && poison_duration == 0) {
            player_poisoned = false;
            battle_log.push_back("你解除了中毒状态!");
            if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
        }

        if (monster_poisoned_status && monster_poison_duration_status > 0) {
            monster_current_hp = max(0, monster_current_hp - monster_poison_damage_per_turn_status);
            battle_log.push_back(monster_template.name + " 因中毒受到 " + to_string(monster_poison_damage_per_turn_status) + " 点伤害!");
            if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
            monster_poison_duration_status--;
            if (monster_poison_duration_status == 0) {
                monster_poisoned_status = false;
                battle_log.push_back(monster_template.name + " 解除了中毒状态!");
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
            }
            if (monster_current_hp <= 0) break;
        }

        if (monster_crippled_status && monster_cripple_duration_status > 0) {
            monster_cripple_duration_status--;
            if (monster_cripple_duration_status == 0) {
                monster_crippled_status = false;
                battle_log.push_back(monster_template.name + " 解除了攻击降低状态!");
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
            }
        }

        draw_battle_screen(monster_template, monster_current_hp, battle_log, player_poisoned, poison_duration, monster_stunned,
                           monster_poisoned_status, monster_poison_duration_status, monster_crippled_status, monster_cripple_duration_status,
                           player_buff_name, player_buff_duration, monster_debuff_name, monster_debuff_duration, player_shield_hp);

        bool turn_ended = false;

        while (true) {
            if (zxb('1')) { 
                auto perform_mwh_basic_attack = [&]() {
                    int base_damage = get_total_attack(mwh_battle_bonus_atk);
                    base_damage = static_cast<int>(base_damage * player_attack_multiplier);
                    if (power_potion_active) base_damage = static_cast<int>(base_damage * 1.5);
                    int monster_effective_defense = static_cast<int>(monster_template.defense * monster_stat_multiplier);
                    int player_damage = max(1, base_damage - monster_effective_defense);
                    monster_current_hp -= player_damage;
                    battle_log.push_back("你对 " + monster_template.name + " 造成 " + to_string(player_damage) + " 点伤害!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                };

                if (player_class == 4) {
                    perform_mwh_basic_attack();
                } else {
                    perform_basic_attack(monster_current_hp, monster_template, battle_log, monster_stunned, 
                                     monster_poisoned_status, monster_poison_duration_status, monster_poison_damage_per_turn_status, 
                                     monster_crippled_status, monster_cripple_duration_status, monster_cripple_attack_reduction,
                                     player_attack_multiplier, monster_stat_multiplier);
                }

                if (current_star_power_id == 4 && monster_current_hp > 0 && (rand() % 100 < 20)) {
                    battle_log.push_back("怒意连击触发,你再次发动攻击!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                    draw_battle_screen(monster_template, monster_current_hp, battle_log, player_poisoned, poison_duration, monster_stunned,
                                       monster_poisoned_status, monster_poison_duration_status, monster_crippled_status, monster_cripple_duration_status,
                                       player_buff_name, player_buff_duration, monster_debuff_name, monster_debuff_duration, player_shield_hp);
                    this_thread::sleep_for(chrono::milliseconds(800));
                    if (player_class == 4) perform_mwh_basic_attack();
                    else perform_basic_attack(monster_current_hp, monster_template, battle_log, monster_stunned, 
                                         monster_poisoned_status, monster_poison_duration_status, monster_poison_damage_per_turn_status, 
                                         monster_crippled_status, monster_cripple_duration_status, monster_cripple_attack_reduction,
                                         player_attack_multiplier, monster_stat_multiplier);
                }

                turn_ended = true;
                while(zxb('1'));
                break;
            }
            if (zxb('2')) {
                if (skill_cooldown > 0) {
                    battle_log.push_back("技能还在冷却中!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                    while(zxb('2'));
                } else {
                    if (player_class == 4) {
                        battle_log.push_back("你使用了 [次元断裂]!时空开始扭曲!");
                        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());

                        bool is_boss = monster_template.type >= BOSS_GOBLIN_KING;
                        int hits = 3; 

                        for (int i=0; i < hits && monster_current_hp > 0; ++i) {
                            if (!is_boss && (rand() % 100 < 50)) {
                                monster_current_hp = 0;
                                battle_log.push_back("次元裂缝直接吞噬了 " + monster_template.name + "!");
                                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                                break;
                            } else {
                                int damage = max(1, get_total_attack(mwh_battle_bonus_atk) - monster_template.defense);
                                monster_current_hp -= damage;
                                battle_log.push_back("第 "+to_string(i+1)+"击 造成 " + to_string(damage) + " 点伤害!");
                                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());

                                if (is_boss) {
                                    int atk_steal = max(1, static_cast<int>(monster_template.attack * 0.1));
                                    int def_steal = max(1, static_cast<int>(monster_template.defense * 0.1));
                                    mwh_battle_bonus_atk += atk_steal;
                                    mwh_battle_bonus_def += def_steal;
                                    battle_log.push_back("你窃取了Boss " + to_string(atk_steal) + "攻击和" + to_string(def_steal) + "防御!");
                                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                                }
                            }
                            draw_battle_screen(monster_template, monster_current_hp, battle_log, player_poisoned, poison_duration, monster_stunned, monster_poisoned_status, monster_poison_duration_status, monster_crippled_status, monster_cripple_duration_status, player_buff_name, player_buff_duration, monster_debuff_name, monster_debuff_duration, player_shield_hp);
                            this_thread::sleep_for(chrono::milliseconds(300));
                        }

                        battle_log.push_back("时空扭曲,你获得了额外一次行动机会!");
                        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                        player_gets_extra_turn = true; 

                    } else { 
                        perform_skill_attack(monster_current_hp, monster_template, battle_log, monster_stunned, player_attack_multiplier, monster_stat_multiplier);
                        if (current_star_power_id == 5 && monster_current_hp > 0 && (rand() % 100 < 15)) {
                            battle_log.push_back("奥术回响触发,你再次施放技能!");
                            if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                            // ---- THIS IS THE CORRECTED LINE ----
                            draw_battle_screen(monster_template, monster_current_hp, battle_log, player_poisoned, poison_duration, monster_stunned,
                                       monster_poisoned_status, monster_poison_duration_status, monster_crippled_status, monster_cripple_duration_status,
                                       player_buff_name, player_buff_duration, monster_debuff_name, monster_debuff_duration, player_shield_hp);
                            // ---- END OF CORRECTION ----
                            this_thread::sleep_for(chrono::milliseconds(800));
                            perform_skill_attack(monster_current_hp, monster_template, battle_log, monster_stunned, player_attack_multiplier, monster_stat_multiplier);
                        }
                    }

                    skill_cooldown = class_definitions[player_class].skill_cooldown_base;
                    turn_ended = true;
                    while(zxb('2'));
                }
                if (turn_ended) break;
            }
            if (zxb('3')) { 
                if (inventory["生命药水"] > 0) {
                    if (current_hp == get_total_max_hp()) {
                        battle_log.push_back("你的生命值已满!");
                        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                    } else {
                        int heal_amount = get_total_max_hp() / 2;
                        current_hp = min(get_total_max_hp(), current_hp + heal_amount);
                        inventory["生命药水"]--;
                        battle_log.push_back("你使用了药水,恢复了 " + to_string(heal_amount) + " 点生命!");
                        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                        turn_ended = true;
                    }
                } else {
                    battle_log.push_back("你没有生命药水了!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }
                while(zxb('3'));
                if (turn_ended) break;
            }
            if (zxb('4')) {
                if (power_potion_active) {
                    battle_log.push_back("力量药水的效果已经激活了!");
                } else if (inventory["力量药水"] > 0) {
                    inventory["力量药水"]--;
                    power_potion_active = true;
                    battle_log.push_back("你喝下了力量药水,感觉浑身充满力量!");
                } else {
                    battle_log.push_back("你没有力量药水了!");
                }
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                while(zxb('4'));
                draw_battle_screen(monster_template, monster_current_hp, battle_log, player_poisoned, poison_duration, monster_stunned,
                                   monster_poisoned_status, monster_poison_duration_status, monster_crippled_status, monster_cripple_duration_status,
                                   player_buff_name, player_buff_duration, monster_debuff_name, monster_debuff_duration, player_shield_hp);
            }
            if (zxb('5')) {
                if (defense_potion_active) {
                    battle_log.push_back("坚韧药水的效果已经激活了!");
                } else if (inventory["坚韧药水"] > 0) {
                    inventory["坚韧药水"]--;
                    defense_potion_active = true;
                    battle_log.push_back("你喝下了坚韧药水,感觉皮肤像岩石一样坚硬!");
                } else {
                    battle_log.push_back("你没有坚韧药水了!");
                }
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                while(zxb('5'));
                draw_battle_screen(monster_template, monster_current_hp, battle_log, player_poisoned, poison_duration, monster_stunned,
                                   monster_poisoned_status, monster_poison_duration_status, monster_crippled_status, monster_cripple_duration_status,
                                   player_buff_name, player_buff_duration, monster_debuff_name, monster_debuff_duration, player_shield_hp);
            }
            if (zxb('6')) {
                if (inventory["火焰炸弹"] > 0) {
                    inventory["火焰炸弹"]--;
                    float percentage = 0.15f; 
                    if (monster_template.type >= BOSS_GOBLIN_KING || monster_template.name.find("精英") != string::npos) {
                        percentage = 0.05f; 
                    }
                    int bomb_damage = max(1, static_cast<int>(monster_template.max_hp * percentage));
                    monster_current_hp -= bomb_damage;
                    battle_log.push_back("你扔出火焰炸弹,造成 " + to_string(bomb_damage) + " 点火焰伤害!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                    turn_ended = true;
                } else {
                    battle_log.push_back("你没有火焰炸弹了!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }
                while(zxb('6'));
                if(turn_ended) break;
            }
            if (zxb('7')) {
                if (inventory["麻痹卷轴"] > 0) {
                    inventory["麻痹卷轴"]--;
                    monster_stunned = true;
                    battle_log.push_back("卷轴爆发出强光," + monster_template.name + " 被麻痹了!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                    turn_ended = true;
                } else {
                    battle_log.push_back("你没有麻痹卷轴了!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }
                while(zxb('7'));
                if(turn_ended) break;
            }
            if (zxb('8')) {
                if (monster_template.type >= BOSS_GOBLIN_KING) { 
                    battle_log.push_back("在强大的领主面前,你无处可逃!");
                } else if (inventory["烟雾弹"] > 0) {
                    inventory["烟雾弹"]--;
                    add_message("你扔下烟雾弹,成功逃离了战斗!");
                    power_potion_active = false;
                    defense_potion_active = false;
                    system("cls");
                    refresh_ui();
                    gotoxy(y_pos << 1, x_pos);
                    set_color(bright_white);
                    cout << "入";
                    return; 
                } else {
                    battle_log.push_back("你没有烟雾弹了!");
                }
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                while(zxb('8'));
                draw_battle_screen(monster_template, monster_current_hp, battle_log, player_poisoned, poison_duration, monster_stunned,
                                   monster_poisoned_status, monster_poison_duration_status, monster_crippled_status, monster_cripple_duration_status,
                                   player_buff_name, player_buff_duration, monster_debuff_name, monster_debuff_duration, player_shield_hp);
            }
            if (zxb('G')) {
                if (current_gadget_id != -1 && gadget_current_uses > 0) {
                    Gadget current_gadget;
                    for(const auto& g : all_gadgets) { if (g.id == current_gadget_id) { current_gadget = g; break; } }

                    battle_log.push_back("你使用了妙具 [" + current_gadget.name + "]!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());

                    gadget_current_uses--;

                    switch(current_gadget_id) {
                        case 101: { 
                            int heal_amount = static_cast<int>(get_total_max_hp() * 0.35);
                            current_hp = min(get_total_max_hp(), current_hp + heal_amount);
                            battle_log.push_back("图腾发出光芒,你恢复了 " + to_string(heal_amount) + " 点生命!");
                            break;
                        }
                        case 102: {
                            int damage = static_cast<int>(get_total_max_hp() * 0.40);
                            monster_current_hp -= damage;
                            battle_log.push_back("能量脉冲对敌人造成 " + to_string(damage) + " 点真实伤害!");
                            break;
                        }
                        case 103: {
                            monster_debuff_name = "弱化";
                            monster_debuff_duration = 3;
                            monster_stat_multiplier = 0.7f;
                            battle_log.push_back("敌人的攻防被射线大幅削弱了!");
                            break;
                        }
                        case 104: {
                            player_buff_name = "兴奋";
                            player_buff_duration = 3;
                            player_attack_multiplier = 1.5f; 
                            battle_log.push_back("你注射了兴奋剂,攻击力大幅提升!");
                            break;
                        }
                        case 105: {
                            if (rand() % 100 < 75) { 
                                add_message("你使用妙具成功逃离了战斗!");
                                power_potion_active = false; 
                                defense_potion_active = false;
                                system("cls");
                                refresh_ui();
                                gotoxy(y_pos << 1, x_pos);
                                set_color(bright_white);
                                cout << "入";
                                return;
                            } else {
                                battle_log.push_back("传送被干扰,失败了!");
                            }
                            break;
                        }
                        case 106: {
                            int shield_amount = static_cast<int>(get_total_max_hp() * 0.25);
                            player_shield_hp += shield_amount;
                            battle_log.push_back("你获得了 " + to_string(shield_amount) + " 点护盾!");
                            break;
                        }
                    }
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                    turn_ended = true;

                } else {
                    battle_log.push_back("你没有可用的妙具!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }
                while(zxb('G'));
                if(turn_ended) break;
            }

            this_thread::sleep_for(chrono::milliseconds(10));
        }

        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
        if (!turn_ended) continue;

        draw_battle_screen(monster_template, monster_current_hp, battle_log, player_poisoned, poison_duration, monster_stunned,
                           monster_poisoned_status, monster_poison_duration_status, monster_crippled_status, monster_cripple_duration_status,
                           player_buff_name, player_buff_duration, monster_debuff_name, monster_debuff_duration, player_shield_hp);
        this_thread::sleep_for(chrono::milliseconds(1000));

        // --- 怪物回合 ---
        if (monster_current_hp > 0) {
            if (player_gets_extra_turn) {
                battle_log.push_back("由于时空扭曲," + monster_template.name + " 无法行动!");
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
            }
            else if (monster_stunned) {
                battle_log.push_back(monster_template.name + " 处于眩晕状态,无法行动!");
                if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                monster_stunned = false;
            } else {
                int player_effective_defense = get_total_defense(mwh_battle_bonus_def);

                int monster_actual_attack = static_cast<int>(monster_template.attack * monster_stat_multiplier);
                if (monster_crippled_status && monster_cripple_duration_status > 0) {
                    monster_actual_attack = max(1, monster_actual_attack - monster_cripple_attack_reduction);
                }

                int damage_taken = max(1, monster_actual_attack - player_effective_defense);

                if (current_star_power_id == 1) {
                    damage_taken = max(1, static_cast<int>(damage_taken * 0.85));
                    battle_log.push_back("神盾庇护为你抵挡了部分伤害!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }

                if (defense_potion_active) {
                    damage_taken = max(1, damage_taken / 2);
                    battle_log.push_back("坚韧药水的效果为你抵挡了大量伤害!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }

                int resilience_affix_count = 0;
                int reflection_affix_count = 0;
                for (const auto& affix : all_armors[have_armor].affixes) {
                    if (affix.name == "韧性") resilience_affix_count++;
                    else if (affix.name == "反伤") reflection_affix_count++;
                }

                if (resilience_affix_count > 0) {
                    int total_resilience_chance = min(85, resilience_affix_count * 15);
                    if (rand() % 100 < total_resilience_chance) {
                        damage_taken /= 2;
                        battle_log.push_back("你的护甲触发了韧性,伤害减少了!");
                        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                    }
                }

                if (player_shield_hp > 0) {
                    if (damage_taken >= player_shield_hp) {
                        damage_taken -= player_shield_hp;
                        battle_log.push_back("你的护盾吸收了 " + to_string(player_shield_hp) + " 点伤害并破碎了!");
                        player_shield_hp = 0;
                    } else {
                        player_shield_hp -= damage_taken;
                        battle_log.push_back("你的护盾吸收了 " + to_string(damage_taken) + " 点伤害!");
                        damage_taken = 0;
                    }
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }

                if(damage_taken > 0) {
                    current_hp -= damage_taken;
                    battle_log.push_back(monster_template.name + " 对你造成了 " + to_string(damage_taken) + " 点伤害!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }

                if (reflection_affix_count > 0 && damage_taken > 0) {
                    float total_reflection_rate = reflection_affix_count * 0.20f;
                    int reflected_damage = max(1, static_cast<int>(damage_taken * total_reflection_rate));
                    monster_current_hp -= reflected_damage;
                    battle_log.push_back("你的护甲反弹了 " + to_string(reflected_damage) + " 点伤害给 " + monster_template.name + "!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }

                if ((monster_template.type == SPIDER || monster_template.type >= BOSS_GOBLIN_KING) && rand() % 3 == 0) {
                    if (!player_poisoned) {
                        player_poisoned = true;
                        poison_duration = rand() % 3 + 2; 
                        poison_damage_per_turn = max(1, monster_template.attack / 5); 
                        battle_log.push_back(monster_template.name + " 的攻击附加了剧毒!");
                        if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                    }
                }

                if (monster_template.type == ZOMBIE && rand() % 4 == 0) {
                    battle_log.push_back(monster_template.name + " 腐蚀了你的盔甲,防御降低!(暂无效果)");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }
                if (monster_template.type == WIZARD_APPRENTICE && rand() % 3 == 0) {
                    int spell_damage = max(1, static_cast<int>(monster_template.attack * 1.5) - player_effective_defense);
                    current_hp -= spell_damage;
                    battle_log.push_back(monster_template.name + " 施放了法术暴击,造成 " + to_string(spell_damage) + " 点伤害!");
                    if (battle_log.size() >= 5) battle_log.erase(battle_log.begin());
                }
            }
            draw_battle_screen(monster_template, monster_current_hp, battle_log, player_poisoned, poison_duration, monster_stunned,
                               monster_poisoned_status, monster_poison_duration_status, monster_crippled_status, monster_cripple_duration_status,
                               player_buff_name, player_buff_duration, monster_debuff_name, monster_debuff_duration, player_shield_hp);
            this_thread::sleep_for(chrono::milliseconds(1000));
        }

        if (skill_cooldown > 0) {
            skill_cooldown--;
        }
    }

    power_potion_active = false;
    defense_potion_active = false;

    system("cls");
    if (current_hp > 0) {
        set_color(light_green);
        gotoxy(30, 8);
        cout << "你胜利了!";
        add_message("你战胜了 " + monster_template.name + "!");

        int xp_bonus_affix_count = 0;
        int gold_bonus_affix_count = 0;
        for (const auto& affix : all_weapons[have_sword].affixes) { 
            if (affix.name == "经验加成") xp_bonus_affix_count++;
            else if (affix.name == "财富掠夺") gold_bonus_affix_count++;
        }

        int final_xp_reward = monster_template.xp_reward;
        int final_gold_reward = monster_template.gold_reward;

        if (xp_bonus_affix_count > 0) {
            final_xp_reward = (int)(final_xp_reward * (1 + xp_bonus_affix_count * 0.15));
        }
        if (gold_bonus_affix_count > 0) {
            final_gold_reward = (int)(final_gold_reward * (1 + gold_bonus_affix_count * 0.15));
        }

        experience += final_xp_reward;
        gold += final_gold_reward;
        add_message("==========");
        add_message("获得 " + to_string(final_xp_reward) + " 经验和 " + to_string(final_gold_reward) + " 金币。");
        add_message("==========");
        check_level_up();

        if (monster_template.type >= BOSS_GOBLIN_KING) {
            if (is_in_endless_mode) {
                endless_boss_defeated_this_floor = true;
                add_message("守护者已被击败!通往下一层的道路开启了!");
            } else {
                boss_defeated[current_floor] = true;
                add_message(monster_template.name + " 已被击败!");

                if (current_floor == NUM_FLOORS && monster_template.type == BOSS_LORD_OF_CHAOS) {
                    on_final_boss_defeated();
                } else if (current_floor == max_unlocked_floor && max_unlocked_floor < NUM_FLOORS) {
                    max_unlocked_floor++;
                    add_message("恭喜!新的地牢区域已解锁:第 " + to_string(max_unlocked_floor) + " 层!");
                }
            }
        }

        if (!is_in_endless_mode) {
            current_maps[current_floor - 1][x_pos][y_pos] = '.'; 
        }

    } else {
        game_over();
        return;
    }

    set_color(gray);
    gotoxy(28, 12);
    cout << "按任意键返回地图..."; 
    while(!_kbhit()) { 
        this_thread::sleep_for(chrono::milliseconds(50)); 
    }
    _getch(); 

    system("cls");
    refresh_ui(); 
    gotoxy(y_pos << 1, x_pos); 
    set_color(bright_white);
    cout << "入";
}

// 重置游戏状态 (用于游戏结束重新开始)
void reset_game_state() {
    game_phase = 1; // 游戏轮次重置为1
    endless_max_floor = 1; // 重置无尽模式进度
    is_in_endless_mode = false;
    initialize_monster_templates(); // 根据新的 game_phase (1) 重新初始化怪物数据
    reset_player_progression(); // 重置玩家所有进度和强化
    reset_map_and_boss_status(); // 重置地图和Boss(用于新轮次或重开)
}
// 游戏结束
void game_over() {
    set_color(light_red);
    gotoxy(30, 8);
    cout << "你被击败了...";
    gotoxy(30, 10);
    cout << "--- GAME OVER ---";
    gotoxy(0, 20);
    set_color(white);
    cout << "你最终到达了第 " << game_phase << " 轮挑战。最高纪录:" << best_phase << " 轮。" << endl;
    cout << "无尽模式最高层数: " << endless_max_floor << " 层。" << endl;
    cout << "按 'R' 重新开始,按 'Esc' 退出游戏。";
    while (true) {
        if (zxb('R')) { // Using VK_R
            best_phase = max(best_phase, game_phase); // 记录最高(如果当前轮次是新的最高)

            reset_game_state();     // 重新开始游戏状态
            choose_class();         // 重新选择职业 (这将重置 class_definitions 和相关属性)
            current_hp = get_total_max_hp(); // 重新设置生命值

            system("cls");
            refresh_ui(); // 调用新的刷新函数
            x_pos = floor_entrance_coords[current_floor].first;
            y_pos = floor_entrance_coords[current_floor].second;
            gotoxy(y_pos << 1, x_pos);
            set_color(bright_white);
            cout << "入";
            while(zxb('R')); // Debounce
            return;
        }
        if (zxb(VK_ESCAPE)) {
            exit(0);
        }
        this_thread::sleep_for(chrono::milliseconds(50));
    }
}

// 更新游戏状态 (移动后触发的事件)
void update_game_state() {
    if (is_in_endless_mode) {
        char current_tile = endless_map[x_pos][y_pos];

        if (current_tile == 'R') { // 回归门
            add_message("你离开了无尽模式。");
            is_in_endless_mode = false;
            // 恢复位置
            current_floor = stored_normal_floor;
            x_pos = stored_normal_x;
            y_pos = stored_normal_y;
            system("cls");
            refresh_ui();
            gotoxy(y_pos << 1, x_pos);
            set_color(bright_white);
            cout << "入";
        } else if (current_tile == 'U') { // 下一层
            if (endless_boss_defeated_this_floor) {
                add_message("你前往了更深的一层!");
                endless_current_floor++;
                if (endless_current_floor > endless_max_floor) {
                    endless_max_floor = endless_current_floor;
                }
                // --- 妙具系统: 进入下一层时重置次数 ---
                if (current_gadget_id != -1) {
                    for (const auto& g : all_gadgets) {
                        if (g.id == current_gadget_id) {
                            gadget_current_uses = g.max_uses;
                            add_message("你的妙具 [" + g.name + "] 使用次数已重置!");
                            break;
                        }
                    }
                }
                generate_endless_map(endless_current_floor);
                system("cls");
                refresh_ui();
                gotoxy(y_pos << 1, x_pos);
                set_color(bright_white);
                cout << "入";
            } else {
                add_message("必须击败本层守护者才能前进!");
                // 将玩家弹回一格,防止卡住
                x_pos = x_pos_last;
                y_pos = y_pos_last;
            }
        } else if (current_tile == 'm' || current_tile == 'G' || current_tile == 'E' || current_tile == 'B') {
            Monster m = get_endless_monster(endless_current_floor, current_tile);
            start_battle(m);
            if (current_hp > 0) { // 如果战斗胜利
                endless_map[x_pos][y_pos] = '.';
            }
        } else if (current_tile == 'T') {
            open_treasure_chest();
            endless_map[x_pos][y_pos] = '.';
        } else if (current_tile == 'H') {
            add_message("你捡起一瓶生命药水!");
            inventory["生命药水"]++;
            endless_map[x_pos][y_pos] = '.';
        }
    } else {
        // --- 原有的 update_game_state 逻辑 ---
        char current_tile = current_maps[current_floor - 1][x_pos][y_pos];

        if (current_tile == 'H') {
            add_message("你捡起一瓶生命药水!");
            inventory["生命药水"]++;
            current_maps[current_floor - 1][x_pos][y_pos] = '.';
        } else if (current_tile == 'T') {
            open_treasure_chest();
            current_maps[current_floor - 1][x_pos][y_pos] = '.';
        } else if (current_tile == 'D') {
            enter_portal();
        } else if (current_tile == 'S') {
            enter_shop();
            system("cls");
            refresh_ui();
            gotoxy(y_pos << 1, x_pos);
            set_color(bright_white);
            cout << "入";
        } else if (current_tile == 'F') {
            enter_forging_hut();
            system("cls");
            refresh_ui();
            gotoxy(y_pos << 1, x_pos);
            set_color(bright_white);
            cout << "入";
        }
        else if (current_tile == 'm') {
            Monster m = get_random_monster_for_floor(current_floor, false);
            start_battle(m);
        } else if (current_tile == 'G') {
            Monster m = get_random_monster_for_floor(current_floor, true);
            start_battle(m);
        } else if (current_tile == 'B') {
            Monster m;
            if (current_floor == 1) m = get_monster_template(BOSS_GOBLIN_KING);
            else if (current_floor == 2) m = get_monster_template(BOSS_MINOTAUR);
            else if (current_floor == 3) m = get_monster_template(BOSS_NECROMANCER);
            else if (current_floor == 4) m = get_monster_template(BOSS_DRAGON_SPAWN);
            else if (current_floor == 5) m = get_monster_template(BOSS_FINAL);
            else if (current_floor == 6) m = get_monster_template(BOSS_LORD_OF_CHAOS);
            else m = get_monster_template(BOSS_GOBLIN_KING); // Fallback

            if (boss_defeated[current_floor]) {
                add_message("这片区域的领主已被你击败,没有敌人了。");
                current_maps[current_floor - 1][x_pos][y_pos] = '.';
            } else {
                start_battle(m);
            }
        }
    }
}

// 商店界面
void enter_shop() {
    system("cls");
    gotoxy(30, 1);
    set_color(bright_white);
    cout << "-----[商店]-----";

    int weapon_display_limit = min((int)global_weapon_templates.size(), current_floor + game_phase + 2);
    weapon_display_limit = max(1, weapon_display_limit);

    int armor_display_limit = min((int)global_armor_templates.size(), current_floor + game_phase + 2);
    armor_display_limit = max(1, armor_display_limit);

    auto display_shop_items = [&]() {
        // Clear a fixed large area for the shop items to prevent redraw issues
        clear_area(0, 2, 79, MAP_ROWS + 20);

        set_color(white);
        gotoxy(4, 2);
        cout << "武器 (拥有: " << all_weapons[have_sword].name << " Lv." << all_weapons[have_sword].level << ")";

        for (int i = 0; i < weapon_display_limit; ++i) {
            gotoxy(4, 3 + i);
            Weapon shop_weapon_template = global_weapon_templates[i];
            cout << (char)('0' + i) << " " << shop_weapon_template.name << "  伤害:" << shop_weapon_template.get_current_damage() << "  金币:" << shop_weapon_template.cost;

            if (all_weapons[have_sword].name == shop_weapon_template.name) {
                set_color(gray);
                cout << " (已装备)";
                set_color(white);
            }
        }

        int weapon_list_end_y = 3 + weapon_display_limit;
        gotoxy(4, weapon_list_end_y + 2);
        cout << "护甲 (拥有: " << all_armors[have_armor].name << " Lv." << all_armors[have_armor].level << ")";
        for (int i = 0; i < armor_display_limit; ++i) {
            gotoxy(4, weapon_list_end_y + 3 + i);
            Armor shop_armor_template = global_armor_templates[i];
            cout << static_cast<char>('A' + i) << " " << shop_armor_template.name << "  防御:" << shop_armor_template.get_current_defense() << "  金币:" << shop_armor_template.cost;
            if (all_armors[have_armor].name == shop_armor_template.name) {
                set_color(gray);
                cout << " (已装备)";
                set_color(white);
            }
        }

        int armor_list_end_y = weapon_list_end_y + 3 + armor_display_limit;

        // --- 修改:增加更多物品的显示 ---
        clear_area(4, armor_list_end_y + 2, 79, armor_list_end_y + 10); // 清理更大的区域
        gotoxy(4, armor_list_end_y + 2);
        cout << "[P] 生命药水      金币:15  (拥有: " << inventory["生命药水"] << " 瓶)";
        gotoxy(4, armor_list_end_y + 3);
        cout << "[O] 力量药水      金币:50  (拥有: " << inventory["力量药水"] << " 瓶)";
        gotoxy(4, armor_list_end_y + 4);
        cout << "[M] 坚韧药水      金币:50  (拥有: " << inventory["坚韧药水"] << " 瓶)";
        gotoxy(4, armor_list_end_y + 5);
        // --- 修改:更新火焰炸弹描述 ---
        cout << "[R] 火焰炸弹      金币:30  (拥有: " << inventory["火焰炸弹"] << " 个) - 造成敌人最大生命值百分比伤害";
        gotoxy(4, armor_list_end_y + 6);
        cout << "[K] 麻痹卷轴      金币:70  (拥有: " << inventory["麻痹卷轴"] << " 张) - 使敌人眩晕";
        gotoxy(4, armor_list_end_y + 7);
        cout << "[L] 烟雾弹        金币:40  (拥有: " << inventory["烟雾弹"] << " 个) - 逃离战斗";

        gotoxy(4, armor_list_end_y + 9);
        set_color(light_yellow);
        cout << "你现在有 " << gold << " 金币。";
        gotoxy(4, armor_list_end_y + 11);
        set_color(white);
        cout << "按[Q]退出";
    };

    display_shop_items();
    add_message("欢迎来到商店!");

    while (true) {
        char selected_char = 0;

        for (int i = 0; i < 10; ++i) {
            if (zxb('0' + i)) {
                selected_char = '0' + i;
                while(zxb(selected_char));
                break;
            }
        }

        if (selected_char == 0) {
            for (char c = 'A'; c <= 'Z'; ++c) {
                if (zxb(c)) {
                    selected_char = c;
                    while(zxb(selected_char));
                    break;
                }
            }
        }

        if (selected_char != 0) { 
            string item_name_to_confirm = "";
            int item_cost_to_confirm = 0;
            bool is_valid_selection = false;
            bool is_weapon_purchase = false;
            bool is_armor_purchase = false;

            if (selected_char >= '0' && selected_char <= '9') {
                int idx = selected_char - '0';
                if (idx >= 0 && idx < weapon_display_limit) { 
                    item_name_to_confirm = global_weapon_templates[idx].name;
                    item_cost_to_confirm = global_weapon_templates[idx].cost;
                    is_valid_selection = true;
                    is_weapon_purchase = true;
                }
            } else if (selected_char >= 'A' && selected_char <= 'Z') {
                int idx = selected_char - 'A';
                if (idx >= 0 && idx < armor_display_limit) {
                    item_name_to_confirm = global_armor_templates[idx].name;
                    item_cost_to_confirm = global_armor_templates[idx].cost;
                    is_valid_selection = true;
                    is_armor_purchase = true;
                }
            } 

            if (selected_char == 'P') { item_name_to_confirm = "生命药水"; item_cost_to_confirm = 15; is_valid_selection = true; }
            else if (selected_char == 'O') { item_name_to_confirm = "力量药水"; item_cost_to_confirm = 50; is_valid_selection = true; }
            else if (selected_char == 'M') { item_name_to_confirm = "坚韧药水"; item_cost_to_confirm = 50; is_valid_selection = true; }
            else if (selected_char == 'R') { item_name_to_confirm = "火焰炸弹"; item_cost_to_confirm = 30; is_valid_selection = true; }
            else if (selected_char == 'K') { item_name_to_confirm = "麻痹卷轴"; item_cost_to_confirm = 70; is_valid_selection = true; }
            else if (selected_char == 'L') { item_name_to_confirm = "烟雾弹"; item_cost_to_confirm = 40; is_valid_selection = true; }

            if (selected_char == 'Q') {
                add_message("你离开了商店。");
                refresh_ui(); 
                while(zxb('Q'));
                return;
            }
            if (is_valid_selection) {
                bool confirmed = true; // 默认确认,对一次性物品生效

                // 如果购买的是武器或护甲,则弹出确认窗口
                if (is_weapon_purchase || is_armor_purchase) {
                    clear_area(30, MAP_ROWS + 10, 79, MAP_ROWS + 12);
                    set_color(light_yellow);
                    gotoxy(30, MAP_ROWS + 10);
                    cout << "确认购买 " << item_name_to_confirm << " (花费 " << item_cost_to_confirm << " G) 吗? [Y/N]";

                    confirmed = false; // 重置为需要手动确认
                    bool decision_made = false;
                    while (!decision_made) {
                        if (zxb('Y')) { confirmed = true; decision_made = true; while(zxb('Y')); }
                        else if (zxb('N')) { confirmed = false; decision_made = true; while(zxb('N')); }
                        this_thread::sleep_for(chrono::milliseconds(50));
                    }
                    clear_area(30, MAP_ROWS + 10, 79, MAP_ROWS + 12);
                    set_color(white);
                }

                if (!confirmed) {
                    add_message("取消购买。");
                } else {
                    if (is_weapon_purchase) {
                        int i = selected_char - '0';
                        Weapon selected_template_weapon = global_weapon_templates[i]; 

                        if (gold < selected_template_weapon.cost) {
                            add_message("你的钱不够呦!");
                        } else {
                            system("cls");
                            gotoxy(25, 2); set_color(light_yellow); cout << "--- 购买新武器! ---";

                            int current_display_y = 5;
                            gotoxy(4, current_display_y); set_color(light_cyan); cout << "你当前装备的武器:";
                            current_display_y = print_weapon_details(all_weapons[have_sword], current_display_y + 1);

                            Weapon new_weapon_instance = selected_template_weapon;
                            new_weapon_instance.level = 0;

                            if (!(new_weapon_instance.name == "神圣之剑" || new_weapon_instance.name == "混沌战斧")) {
                                new_weapon_instance.affixes.clear();
                                for (int k = 0; k < new_weapon_instance.get_current_affix_slots(); ++k) {
                                     vector<Affix> pool;
                                     for (const auto& affix_template : all_affixes) {
                                         if (affix_template.tier <= 1 && is_weapon_affix_type(affix_template)) { 
                                             pool.push_back(affix_template);
                                         }
                                     }
                                     if (!pool.empty()) {
                                         new_weapon_instance.affixes.push_back(pool[rand() % pool.size()]);
                                     }
                                }
                            }

                            current_display_y++;
                            gotoxy(4, current_display_y); set_color(light_cyan); cout << "你购买的新武器:";
                            current_display_y = print_weapon_details(new_weapon_instance, current_display_y + 1);

                            current_display_y++;
                            set_color(white);
                            gotoxy(4, current_display_y++);
                            cout << "请选择: [1] 装备新武器 (旧武器回收 " << all_weapons[have_sword].cost / 2 << " G)";
                            gotoxy(4, current_display_y++);
                            cout << "         [2] 回收新武器 (新武器回收 " << new_weapon_instance.cost / 2 << " G)";
                            gotoxy(4, current_display_y++);
                            cout << "你的选择: ";

                            bool choice_made = false;
                            while (!choice_made) {
                                if (zxb('1')) {
                                    gold -= new_weapon_instance.cost;
                                    gold += all_weapons[have_sword].cost / 2;
                                    all_weapons[have_sword] = new_weapon_instance;
                                    add_message("你装备了 " + new_weapon_instance.name + "!旧武器已回收。");
                                    choice_made = true; while(zxb('1'));
                                } else if (zxb('2')) {
                                    gold -= new_weapon_instance.cost;
                                    gold += new_weapon_instance.cost / 2;
                                    add_message("你回收了 " + new_weapon_instance.name + ",获得 " + to_string(new_weapon_instance.cost / 2) + " 金币。");
                                    choice_made = true; while(zxb('2'));
                                }
                                this_thread::sleep_for(chrono::milliseconds(50));
                            }
                            system("cls"); refresh_ui(); gotoxy(y_pos << 1, x_pos); set_color(bright_white); cout << "入";
                        }
                    } else if (is_armor_purchase) { 
                        int i = selected_char - 'A';
                        Armor selected_template_armor = global_armor_templates[i];

                        if (gold < selected_template_armor.cost) {
                            add_message("你的钱不够呦!");
                        } else {
                            system("cls");
                            gotoxy(25, 2); set_color(light_yellow); cout << "--- 购买新护甲! ---";

                            int current_display_y = 5;
                            gotoxy(4, current_display_y); set_color(light_cyan); cout << "你当前装备的护甲:";
                            current_display_y = print_armor_details(all_armors[have_armor], current_display_y + 1);

                            Armor new_armor_instance = selected_template_armor;
                            new_armor_instance.level = 0;

                            if (!(new_armor_instance.name == "神圣之盾" || new_armor_instance.name == "混沌胸甲")) {
                                new_armor_instance.affixes.clear();
                                for (int k = 0; k < new_armor_instance.get_current_affix_slots(); ++k) {
                                    vector<Affix> pool;
                                    for (const auto& affix_template : all_affixes) {
                                        if (affix_template.tier <= 1 && is_armor_affix_type(affix_template)) { 
                                            pool.push_back(affix_template);
                                        }
                                    }
                                    if (!pool.empty()) { new_armor_instance.affixes.push_back(pool[rand()%pool.size()]); }
                                }
                            }

                            current_display_y++;
                            gotoxy(4, current_display_y); set_color(light_cyan); cout << "你购买的新护甲:";
                            current_display_y = print_armor_details(new_armor_instance, current_display_y + 1);

                            current_display_y++;
                            set_color(white);
                            gotoxy(4, current_display_y++);
                            cout << "请选择: [1] 装备新护甲 (旧护甲回收 " << all_armors[have_armor].cost / 2 << " G)";
                            gotoxy(4, current_display_y++);
                            cout << "         [2] 回收新护甲 (新护甲回收 " << new_armor_instance.cost / 2 << " G)";
                            gotoxy(4, current_display_y++);
                            cout << "你的选择: ";

                            bool choice_made = false;
                            while (!choice_made) {
                                if (zxb('1')) {
                                    gold -= new_armor_instance.cost;
                                    gold += all_armors[have_armor].cost / 2;
                                    all_armors[have_armor] = new_armor_instance;
                                    current_hp = min(current_hp, get_total_max_hp());
                                    add_message("你装备了 " + new_armor_instance.name + "!旧护甲已回收。");
                                    choice_made = true; while(zxb('1'));
                                } else if (zxb('2')) {
                                    gold -= new_armor_instance.cost;
                                    gold += new_armor_instance.cost / 2;
                                    add_message("你回收了 " + new_armor_instance.name + ",获得 " + to_string(new_armor_instance.cost / 2) + " 金币。");
                                    choice_made = true; while(zxb('2'));
                                }
                                this_thread::sleep_for(chrono::milliseconds(50));
                            }
                            system("cls"); refresh_ui(); gotoxy(y_pos << 1, x_pos); set_color(bright_white); cout << "入";
                        }
                    } else { // 处理所有药水和物品购买
                        // --- 修改:特殊处理麻痹卷轴 ---
                        if (item_name_to_confirm == "麻痹卷轴" && inventory["麻痹卷轴"] >= 1) {
                            add_message("你已经持有一个麻痹卷轴了,无法购买更多!");
                        } else if (gold < item_cost_to_confirm) {
                            add_message("你的钱不够呦!");
                        } else {
                            inventory[item_name_to_confirm]++;
                            gold -= item_cost_to_confirm;
                            add_message("恭喜获得 " + item_name_to_confirm + "×1!");
                        }
                    }
                }
                display_shop_items();
            }
        }

        this_thread::sleep_for(chrono::milliseconds(50));
    }
}

// 传送门界面
void enter_portal() {
    system("cls");
    gotoxy(30, 1);
    set_color(bright_white);
    cout << "-----[传送门]-----";

    auto display_portal_menu = [&]() { 
        clear_area(0, 4, 79, MAP_ROWS + 10); // Clear enough lines for the menu

        set_color(white);
        gotoxy(5, 4);
        cout << "选择你要前往的楼层:";

        int current_y = 6;
        for (int i = 1; i <= max_unlocked_floor; ++i) {
            gotoxy(5, current_y++);
            cout << "[" << i << "] 地牢第 " << i << " 层";
            if (i == current_floor) {
                set_color(light_green);
                cout << " (当前)";
                set_color(white);
            }
        }

        if (current_floor < NUM_FLOORS && boss_defeated[current_floor] && current_floor + 1 > max_unlocked_floor) {
            gotoxy(5, current_y++);
            set_color(light_yellow);
            cout << "[" << current_floor + 1 << "] 地牢第 " << current_floor + 1 << " 层 (新区域)";
            set_color(white);
        }

        current_y++; // Add a gap
        gotoxy(5, current_y++);
        set_color(light_magenta);
        cout << "[V] 进入无尽模式 (已达最高: " << endless_max_floor << " 层)";
        set_color(white);

        gotoxy(5, current_y + 2);
        set_color(white);
        cout << "按[Q]退出"; 
    };

    display_portal_menu();
    add_message("你来到了传送门。");
    while (true) {
        int target_floor = 0;
        bool input_received = false;

        for(int i = 1; i <= 9; ++i) { // Support up to floor 9 with number keys
            if (zxb('0' + i)) { 
                target_floor = i;
                while(zxb('0' + i)); // Debounce
                input_received = true;
                break;
            }
        }

        if (input_received) {
            if (target_floor <= 0 || target_floor > NUM_FLOORS) { // Invalid floor number
                add_message("无效的楼层选择!");
                display_portal_menu(); 
                this_thread::sleep_for(chrono::milliseconds(50));
                continue;
            }
            if (target_floor > max_unlocked_floor) {
                 if (!(target_floor == max_unlocked_floor + 1 && boss_defeated[max_unlocked_floor])) {
                    add_message("该楼层尚未解锁!请先击败当前楼层Boss。");
                    display_portal_menu(); 
                    this_thread::sleep_for(chrono::milliseconds(50));
                    continue;
                 }
            }

            if (target_floor == current_floor) {
                add_message("你已经在这一层了。");
                display_portal_menu(); 
                this_thread::sleep_for(chrono::milliseconds(50));
                continue;
            }

            if (target_floor == current_floor + 1 && current_floor < NUM_FLOORS && !boss_defeated[current_floor]) {
                add_message("你必须先击败当前楼层的Boss才能前往下一层!");
                display_portal_menu(); 
                this_thread::sleep_for(chrono::milliseconds(50));
                continue;
            }

            add_message("你前往了地牢第 " + to_string(target_floor) + " 层。");
            current_floor = target_floor;
            for(int r=0; r<MAP_ROWS; ++r) {
                current_maps[current_floor - 1][r] = initial_maps[current_floor - 1][r];
            }
            x_pos = floor_entrance_coords[current_floor].first;
            y_pos = floor_entrance_coords[current_floor].second;

            // --- 妙具系统: 传送后重置次数 ---
            if (current_gadget_id != -1) {
                for (const auto& g : all_gadgets) {
                    if (g.id == current_gadget_id) {
                        gadget_current_uses = g.max_uses;
                        add_message("你的妙具 [" + g.name + "] 使用次数已重置!");
                        break;
                    }
                }
            }

            system("cls");
            refresh_ui(); 
            gotoxy(y_pos << 1, x_pos);
            set_color(bright_white);
            cout << "入";
            return;
        }

        if (zxb('V')) { // 'V' for Void/Endless
            while(zxb('V'));
            add_message("你踏入了无尽虚空...");
            is_in_endless_mode = true;

            // 储存当前位置
            stored_normal_floor = current_floor;
            stored_normal_x = x_pos;
            stored_normal_y = y_pos;

            // 从最高记录层开始
            endless_current_floor = endless_max_floor;

            // --- 妙具系统: 进入无尽模式时重置次数 ---
            if (current_gadget_id != -1) {
                for (const auto& g : all_gadgets) {
                    if (g.id == current_gadget_id) {
                        gadget_current_uses = g.max_uses;
                        add_message("你的妙具 [" + g.name + "] 使用次数已重置!");
                        break;
                    }
                }
            }

            generate_endless_map(endless_current_floor); // 生成地图

            system("cls");
            refresh_ui();
            gotoxy(y_pos << 1, x_pos);
            set_color(bright_white);
            cout << "入";
            return;
        }

        if (zxb('Q')) { 
            add_message("你离开了传送门。");
            refresh_ui(); 
            while(zxb('Q'));
            return;
        }
        this_thread::sleep_for(chrono::milliseconds(50));
    }
}

// 移动函数
void move_player(int dx, int dy) {
    int next_x = x_pos + dx;
    int next_y = y_pos + dy;

    vector<string>& active_map = is_in_endless_mode ? endless_map : current_maps[current_floor - 1];

    if (next_x < 0 || next_x >= MAP_ROWS || next_y < 0 || next_y >= MAP_COLS || 
        active_map[next_x][next_y] == '#') {
        add_message("你撞到了墙。");
        return;
    }

    gotoxy(y_pos << 1, x_pos);
    print_tile(active_map[x_pos][y_pos]);

    x_pos_last = x_pos;
    y_pos_last = y_pos;
    x_pos = next_x;
    y_pos = next_y;

    update_game_state();

    gotoxy(y_pos << 1, x_pos);
    set_color(bright_white);
    cout << "入";
}

// 游戏初始化和职业选择
void choose_class() {
    system("cls");
    set_color(light_yellow);
    cout << "=== 选择你的职业 ===\n\n";
    set_color(white);
    cout << "1. ";
    set_color(light_red);
    cout << class_definitions[1].name;
    set_color(white);
    cout << " - 攻守兼备,技能[" << class_definitions[1].skill_name << "] (对敌人造成额外伤害)。\n";
    cout << "2. ";
    set_color(light_blue);
    cout << class_definitions[2].name;
    set_color(white);
    cout << " - 敏捷且箭术精湛,技能[" << class_definitions[2].skill_name << "] (对敌人造成伤害并有几率使敌人眩晕)。\n";
    cout << "3. ";
    set_color(light_green);
    cout << class_definitions[3].name;
    set_color(white);
    cout << " - 脆弱但法术伤害惊人,技能[" << class_definitions[3].skill_name << "] (对敌人造成高额魔法伤害)。\n";

    // 新增 mwh 选项
    cout << "4. ";
    set_color(light_magenta);
    cout << class_definitions[4].name;
    set_color(white);
    cout << " - ???技能[" << class_definitions[4].skill_name << "] (撕裂次元,造成毁灭性打击并扭曲时空)。\n\n";

    cout << "请输入你的选择 (1, 2, 3 或 4): ";

    while (true) {
        if (zxb('1')) {
            player_class = 1;
            while(zxb('1'));
            break;
        }
        if (zxb('2')) {
            player_class = 2;
            while(zxb('2'));
            break;
        }
        if (zxb('3')) {
            player_class = 3;
            while(zxb('3'));
            break;
        }
        // 新增对 '4' 的判断
        if (zxb('4')) {
            player_class = 4;
            while(zxb('4'));
            break;
        }
        this_thread::sleep_for(chrono::milliseconds(10));
    }
    system("cls");
}

// 初始化职业数据 (模板) - 已修改以支持 MAX_LEVEL
void initialize_class_data() {
    class_definitions.clear();

    class_definitions[1].name = "战士";
    class_definitions[1].skill_name = "强力一击";
    class_definitions[1].skill_cooldown_base = 3;
    int warrior_base_hp = 50; int warrior_hp_growth = 15;
    int warrior_base_atk = 8; int warrior_atk_growth = 2;
    int warrior_base_def = 4; int warrior_def_growth = 1;
    for (int i = 1; i <= MAX_LEVEL; ++i) {
        class_definitions[1].max_hp_per_level[i] = warrior_base_hp + (i - 1) * warrior_hp_growth;
        class_definitions[1].base_attack_per_level[i] = warrior_base_atk + (i - 1) * warrior_atk_growth;
        class_definitions[1].base_defense_per_level[i] = warrior_base_def + (i - 1) * warrior_def_growth;
    }

    class_definitions[2].name = "游侠";
    class_definitions[2].skill_name = "精准射击";
    class_definitions[2].skill_cooldown_base = 4;
    int ranger_base_hp = 45; int ranger_hp_growth = 13;
    int ranger_base_atk = 10; int ranger_atk_growth = 3;
    int ranger_base_def = 3; int ranger_def_growth = 1;
    for (int i = 1; i <= MAX_LEVEL; ++i) {
        class_definitions[2].max_hp_per_level[i] = ranger_base_hp + (i - 1) * ranger_hp_growth;
        class_definitions[2].base_attack_per_level[i] = ranger_base_atk + (i - 1) * ranger_atk_growth;
        class_definitions[2].base_defense_per_level[i] = ranger_base_def + (i - 1) * ranger_def_growth;
    }

    class_definitions[3].name = "法师";
    class_definitions[3].skill_name = "火球术";
    class_definitions[3].skill_cooldown_base = 4;
    int mage_base_hp = 40; int mage_hp_growth = 10;
    int mage_base_atk = 6; int mage_atk_growth = 2;
    int mage_base_def = 2; int mage_def_growth = 1;
    for (int i = 1; i <= MAX_LEVEL; ++i) {
        class_definitions[3].max_hp_per_level[i] = mage_base_hp + (i - 1) * mage_hp_growth;
        class_definitions[3].base_attack_per_level[i] = mage_base_atk + (i - 1) * mage_atk_growth;
        class_definitions[3].base_defense_per_level[i] = mage_base_def + (i - 1) * mage_def_growth;
    }

    // 新增:超模角色 "mwh" - 次元主宰
    class_definitions[4].name = "mwh";
    class_definitions[4].skill_name = "次元断裂";
    class_definitions[4].skill_cooldown_base = 2; // 极短的冷却时间
    int mwh_base_hp = 100; int mwh_hp_growth = 30;  // 极高的生命值和成长
    int mwh_base_atk = 20; int mwh_atk_growth = 5;  // 极高的攻击力和成长
    int mwh_base_def = 10; int mwh_def_growth = 3;  // 极高的防御力和成长
    for (int i = 1; i <= MAX_LEVEL; ++i) {
        class_definitions[4].max_hp_per_level[i] = mwh_base_hp + (i - 1) * mwh_hp_growth;
        class_definitions[4].base_attack_per_level[i] = mwh_base_atk + (i - 1) * mwh_atk_growth;
        class_definitions[4].base_defense_per_level[i] = mwh_base_def + (i - 1) * mwh_def_growth;
    }
}

// 初始化所有怪物模板并根据 game_phase 缩放
void initialize_monster_templates() {
    all_monster_templates_base.clear();

    all_monster_templates_base.push_back({"哥布林", 30, 10, 2, 15, 3, GOBLIN, 1});
    all_monster_templates_base.push_back({"剧毒蜘蛛", 25, 8, 1, 12, 5, SPIDER, 1});
    all_monster_templates_base.push_back({"哥布林国王", 75, 20, 8, 70, 20, BOSS_GOBLIN_KING, 1}); 

    all_monster_templates_base.push_back({"狂暴野兽", 70, 20, 6, 40, 8, BEAST, 2});
    all_monster_templates_base.push_back({"骷髅兵", 40, 15, 10, 20, 7, SKELETON, 2});
    all_monster_templates_base.push_back({"牛头怪", 180, 40, 15, 180, 40, BOSS_MINOTAUR, 2}); 

    all_monster_templates_base.push_back({"魔王守卫", 150, 35, 12, 100, 15, DEMON_GUARD, 3});
    all_monster_templates_base.push_back({"腐烂僵尸", 100, 30, 10, 80, 12, ZOMBIE, 3});
    all_monster_templates_base.push_back({"亡灵法师", 350, 60, 25, 300, 70, BOSS_NECROMANCER, 3});

    all_monster_templates_base.push_back({"暗影兽", 200, 45, 18, 150, 25, SHADOW_BEAST, 4});
    all_monster_templates_base.push_back({"学徒法师", 120, 40, 10, 120, 20, WIZARD_APPRENTICE, 4});
    all_monster_templates_base.push_back({"幼龙", 500, 80, 35, 500, 120, BOSS_DRAGON_SPAWN, 4});

    all_monster_templates_base.push_back({"精英守卫", 280, 55, 25, 200, 35, ELITE_GUARD, 5});
    all_monster_templates_base.push_back({"烈焰恶魔", 220, 50, 20, 180, 30, FIRE_DEMON, 5});
    all_monster_templates_base.push_back({"深渊领主", 800, 100, 50, 1000, 200, BOSS_FINAL, 5});

    all_monster_templates_base.push_back({"虚空掠夺者", 350, 65, 30, 250, 40, VOID_RAVAGER, 6});
    all_monster_templates_base.push_back({"远古守卫", 300, 60, 35, 220, 38, ANCIENT_GUARDIAN, 6});
    all_monster_templates_base.push_back({"混沌之主", 1500, 180, 80, 5000, 1000, BOSS_LORD_OF_CHAOS, 6});

    current_monster_templates.clear();
    for (auto& m : all_monster_templates_base) {
        Monster scaled_m = m;
        scaled_m.max_hp     = max(1, (int)(m.max_hp     * (1 + 0.25 * (game_phase - 1))));
        scaled_m.attack     = max(1, (int)(m.attack     * (1 + 0.2 * (game_phase - 1))));
        scaled_m.defense    = max(0, (int)(m.defense    * (1 + 0.2 * (game_phase - 1))));
        scaled_m.xp_reward  = max(1, (int)(m.xp_reward  * (1 + 0.15 * (game_phase - 1))));
        scaled_m.gold_reward= max(1, (int)(m.gold_reward* (1 + 0.15 * (game_phase - 1))));
        current_monster_templates.push_back(scaled_m);
    }
}

// 初始化武器/护甲模板和词条 (填充 global_weapon_templates, global_armor_templates, all_affixes)
void initialize_item_templates_and_affixes() {
    all_affixes.clear();
    all_affixes.push_back({"暴击+", 1, "增加10%的暴击几率 (暴击造成双倍伤害)。"});
    all_affixes.push_back({"吸血", 1, "每次攻击造成伤害的10%转化为生命。"});
    all_affixes.push_back({"穿甲", 2, "攻击时无视敌人5点防御。"});
    all_affixes.push_back({"破碎一击", 3, "攻击时有15%几率击晕敌人一回合。"});
    all_affixes.push_back({"经验加成", 1, "击败怪物时额外获得15%经验。"});
    all_affixes.push_back({"财富掠夺", 1, "击败怪物时额外获得15%金币。"});
    all_affixes.push_back({"剧毒之刃", 2, "攻击时有25%几率使敌人中毒,持续3回合,每回合造成攻击力20%的伤害。"});
    all_affixes.push_back({"致残打击", 3, "攻击时有20%几率使敌人攻击力降低20%,持续2回合。"});

    all_affixes.push_back({"生命+", 1, "增加生命上限10点。"});
    all_affixes.push_back({"韧性", 2, "受到伤害时有15%几率减少50%伤害。"});
    all_affixes.push_back({"反伤", 3, "受到伤害时反弹20%伤害给攻击者。"});
    all_affixes.push_back({"再生", 2, "每回合开始时回复5点生命值。"});
    all_affixes.push_back({"毒抗", 1, "减少受到的中毒伤害25%2。"});

    global_weapon_templates.clear();

    global_weapon_templates.emplace_back("破旧的匕首", 2, 1, 0);
    global_weapon_templates.emplace_back("崭新的匕首", 4, 5, 1);
    global_weapon_templates.emplace_back("精钢长剑", 10, 30, 1);
    global_weapon_templates.emplace_back("符文大剑", 20, 100, 2);
    global_weapon_templates.emplace_back("黑曜石之刃", 35, 300, 2);
    global_weapon_templates.emplace_back("龙骨巨剑", 55, 1000, 3);
    global_weapon_templates.emplace_back("毁灭之刃", 80, 3000, 3);

    global_weapon_templates.emplace_back("神圣之剑", 70, 4500, 3, vector<Affix>{
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "吸血"; })),
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "暴击+"; })),
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "穿甲"; }))
    }); 
    global_weapon_templates.emplace_back("混沌战斧", 90, 6000, 3, vector<Affix>{
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "破碎一击"; })),
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "暴击+"; })),
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "穿甲"; }))
    });

    global_armor_templates.clear();

    global_armor_templates.emplace_back("布衣", 1, 1, 0);
    global_armor_templates.emplace_back("皮甲", 3, 5, 1);
    global_armor_templates.emplace_back("锁子甲", 6, 25, 1);
    global_armor_templates.emplace_back("钢板甲", 10, 80, 2);
    global_armor_templates.emplace_back("秘银胸甲", 16, 300, 2);
    global_armor_templates.emplace_back("符文板甲", 25, 1200, 3);
    global_armor_templates.emplace_back("巨龙鳞甲", 40, 3500, 3);
    global_armor_templates.emplace_back("不朽战甲", 60, 6000, 4);

    global_armor_templates.emplace_back("神圣之盾", 50, 4800, 3, vector<Affix>{
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "生命+"; })),
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "韧性"; })),
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "反伤"; }))
    }); 
    global_armor_templates.emplace_back("混沌胸甲", 70, 6500, 4, vector<Affix>{
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "生命+"; })),
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "韧性"; })),
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "反伤"; })),
        *(find_if(all_affixes.begin(), all_affixes.end(), [](const Affix& a){ return a.name == "反伤"; }))
    });
}

// --- 新增:初始化星徽之力模板 ---
void initialize_star_powers() {
    all_star_powers.clear();
    // ID 1: 防御型
    all_star_powers.push_back({1, "神盾庇护", "受到的所有伤害降低15%。"});
    // ID 2: 恢复型
    all_star_powers.push_back({2, "生命源泉", "每回合开始时,恢复你15%的最大生命值。"});
    // ID 3: 属性型
    all_star_powers.push_back({3, "泰坦之力", "你的总攻击力、防御力和最大生命值提升10%。"});
    // ID 4: 进攻型 (普攻)
    all_star_powers.push_back({4, "怒意连击", "你的普通攻击有20%几率立即再次攻击一次。"});
    // ID 5: 技能型
    all_star_powers.push_back({5, "奥术回响", "使用技能后,有15%几率立即再次施放一次该技能。"});
    // ID 6: 进攻型 (暴击)
    all_star_powers.push_back({6, "致命专注", "你的暴击伤害从200%提升至250%。"});
}

// --- 妙具系统: 初始化妙具模板 ---
void initialize_gadgets() {
    all_gadgets.clear();
    // ID 101: 治疗型
    all_gadgets.push_back({101, "治疗图腾", "立即恢复你35%的最大生命值。", 2});
    // ID 102: 伤害型 - 已根据请求修改
    all_gadgets.push_back({102, "能量脉冲", "对敌人造成等同于你最大生命值40%的真实伤害(无视防御)。", 2});
    // ID 103: 减益型
    all_gadgets.push_back({103, "弱化射线", "使敌人的攻击力和防御力降低30%,持续3回合。", 1});
    // ID 104: 增益型
    all_gadgets.push_back({104, "战斗兴奋剂", "你的攻击力提升50%,持续3回合。", 2});
    // ID 105: 逃脱型 - 已根据请求修改
    all_gadgets.push_back({105, "紧急传送", "有75%的几率立即逃离战斗。", 1});
    // ID 106: 护盾型
    all_gadgets.push_back({106, "能量护盾", "获得一个能吸收等同于你25%最大生命值伤害的护盾。", 2});
}

// 初始化升级系统 (模板)
void initialize_upgrades() {
    upgrades.clear();

    upgrades.push_back({"生命上限提升", 0,  50, [&](){
        for(int i=1;i<=MAX_LEVEL;i++)
            class_definitions[player_class].max_hp_per_level[i] += 10;
    }});
    upgrades.push_back({"基础攻击提升", 0,  75, [&](){
        for(int i=1;i<=MAX_LEVEL;i++)
            class_definitions[player_class].base_attack_per_level[i] += 2;
    }});
    upgrades.push_back({"基础防御提升", 0,  75, [&](){
        for(int i=1;i<=MAX_LEVEL;i++)
            class_definitions[player_class].base_defense_per_level[i] += 2;
    }});
    upgrades.push_back({"技能冷却缩短", 0, 100, [&](){
        class_definitions[player_class].skill_cooldown_base =
            max(1, class_definitions[player_class].skill_cooldown_base - 1);
    }});
}

// 刷新武器词条
void reroll_affixes(Weapon& w) {
    bool is_fixed_affix_weapon = (w.name == "神圣之剑" || w.name == "混沌战斧");

    if (is_fixed_affix_weapon) {
        add_message("这把武器的词条是固定的,无法刷新。");
        return;
    }

    int cost = w.level * 20 + 50;
    if (gold < cost) {
        add_message("金币不足,无法刷新词条 (需要 " + to_string(cost) + " G)。");
        return;
    }
    gold -= cost;
    w.affixes.clear();
    vector<Affix> pool;
    for(auto &a: all_affixes) {
        if (a.tier <= w.level + 1 && is_weapon_affix_type(a)) { 
            pool.push_back(a);
        }
    }

    if (pool.empty()) {
        add_message("没有可用武器词条进行刷新。");
    } else {
        for(int i=0;i<w.get_current_affix_slots();i++){
            w.affixes.push_back(pool[rand()%pool.size()]);
        }
        add_message("武器词条已刷新!");
    }
}

// 刷新护甲词条 (新增)
void reroll_armor_affixes(Armor& a) {
    bool is_fixed_affix_armor = (a.name == "神圣之盾" || a.name == "混沌胸甲");

    if (is_fixed_affix_armor) {
        add_message("这件护甲的词条是固定的,无法刷新。");
        return;
    }

    int cost = a.level * 20 + 50;
    if (gold < cost) {
        add_message("金币不足,无法刷新词条 (需要 " + to_string(cost) + " G)。");
        return;
    }
    gold -= cost;
    a.affixes.clear();
    vector<Affix> pool;
    for(auto &affix_template: all_affixes) {
        if (affix_template.tier <= a.level + 1 && is_armor_affix_type(affix_template)) {
            pool.push_back(affix_template);
        }
    }

    if (pool.empty()) {
        add_message("没有可用护甲词条进行刷新。");
    } else {
        for(int i=0;i<a.get_current_affix_slots();i++){
            a.affixes.push_back(pool[rand()%pool.size()]);
        }
        add_message("护甲词条已刷新!");
    }
}

// 升级武器函数
void upgrade_weapon(int weapon_idx) {
    if (weapon_idx < 0 || weapon_idx >= all_weapons.size()) return;

    Weapon& w = all_weapons[weapon_idx];

    if (w.name == "神圣之剑" || w.name == "混沌战斧") {
        add_message(w.name + " 是特殊武器,无法进行升级。");
        return;
    }

    if (w.level >= level) {
        add_message(w.name + " 已达到最大升级等级 (与你的角色等级相同)。");
        return;
    }

    int upgrade_cost = (w.level + 1) * 100;
    if (gold < upgrade_cost) {
        add_message("金币不足,无法升级 " + w.name + " (需要 " + to_string(upgrade_cost) + " G)。");
        return;
    }

    gold -= upgrade_cost;
    w.level++;
    add_message(w.name + " 升到了 Lv." + to_string(w.level) + "!");

    int new_affix_slots = w.get_current_affix_slots();
    if (w.affixes.size() < new_affix_slots) {
        add_message("新的词条槽位已解锁!");
        for (size_t i = w.affixes.size(); i < new_affix_slots; ++i) {
            vector<Affix> pool;
            for (const auto& affix_template : all_affixes) {
                if (affix_template.tier <= w.level + 1 &&
                    is_weapon_affix_type(affix_template)) { 
                    pool.push_back(affix_template);
                }
            }
            if (!pool.empty()) {
                w.affixes.push_back(pool[rand() % pool.size()]);
            } else {
                add_message("未能找到合适的词条填充新槽位。");
            }
        }
    }
}
// 升级护甲函数 (新增)
void upgrade_armor(int armor_idx) {
    if (armor_idx < 0 || armor_idx >= all_armors.size()) return;

    Armor& a = all_armors[armor_idx];

    if (a.name == "神圣之盾" || a.name == "混沌胸甲") {
        add_message(a.name + " 是特殊护甲,无法进行升级。");
        return;
    }

    if (a.level >= level) {
        add_message(a.name + " 已达到最大升级等级 (与你的角色等级相同)。");
        return;
    }

    int upgrade_cost = (a.level + 1) * 100;
    if (gold < upgrade_cost) {
        add_message("金币不足,无法升级 " + a.name + " (需要 " + to_string(upgrade_cost) + " G)。");
        return;
    }

    gold -= upgrade_cost;
    a.level++;
    add_message(a.name + " 升到了 Lv." + to_string(a.level) + "!");

    int new_affix_slots = a.get_current_affix_slots();
    if (a.affixes.size() < new_affix_slots) {
        add_message("新的词条槽位已解锁!");
        for (size_t i = a.affixes.size(); i < new_affix_slots; ++i) { 
            vector<Affix> pool;
            for (const auto& affix_template : all_affixes) {
                if (affix_template.tier <= a.level + 1 && is_armor_affix_type(affix_template)) { 
                    pool.push_back(affix_template);
                }
            }
            if (!pool.empty()) {
                a.affixes.push_back(pool[rand() % pool.size()]);
            } else {
                add_message("未能找到合适的词条填充新槽位。");
            }
        }
    }
    current_hp = min(current_hp, get_total_max_hp());
}

// 锻造小屋函数
void enter_forging_hut() {
    system("cls");
    gotoxy(2,2); set_color(light_yellow);
    cout<<"----- 锻造小屋 -----";
    set_color(white);

    auto display_forging_hut_menu = [&]() {
        clear_area(0, 4, 79, MAP_ROWS + 25); 

        set_color(white);

        int current_display_y = 4;

        gotoxy(2,current_display_y++); cout << "你当前职业: " << class_definitions[player_class].name;
        gotoxy(2,current_display_y++); cout << "基础生命 (Lv1): " << class_definitions[player_class].max_hp_per_level[1];
        gotoxy(2,current_display_y++); cout << "基础攻击 (Lv1): " << class_definitions[player_class].base_attack_per_level[1];
        gotoxy(2,current_display_y++); cout << "基础防御 (Lv1): " << class_definitions[player_class].base_defense_per_level[1];
        gotoxy(2,current_display_y++); cout << "技能冷却: " << class_definitions[player_class].skill_cooldown_base << " 回合";

        current_display_y++;

        gotoxy(2, current_display_y++); set_color(light_yellow);
        cout << "--- 角色强化 ---";
        set_color(white);
        for(size_t i=0; i<upgrades.size(); i++){
            auto &u = upgrades[i];
            gotoxy(2, current_display_y++);
            // START OF CHANGE
            if (u.name == "技能冷却缩短" && player_class == 4) {
                set_color(gray);
                cout << "[" << i + 1 << "] " << u.name << " (mwh职业不可用)";
                set_color(white);
            } else {
                cout << "[" << i + 1 << "] " << u.name << " Lv." << u.level
                     << " 费用:" << (u.level + 1) * u.base_cost << " G";
            }
            // END OF CHANGE
        }

        current_display_y++;

        gotoxy(2, current_display_y++); set_color(light_yellow);
        cout << "--- 武器锻造 ---";
        set_color(white);

        Weapon& equipped_weapon = all_weapons[have_sword];

        gotoxy(2, current_display_y++);
        cout << "当前武器: " << equipped_weapon.name << " (Lv." << equipped_weapon.level << ")";
        gotoxy(2, current_display_y++);
        cout << "  伤害: " << equipped_weapon.get_current_damage();
        gotoxy(2, current_display_y++);
        cout << "  词条槽位: " << equipped_weapon.affixes.size() << "/" << equipped_weapon.get_current_affix_slots();

        map<string, int> weapon_affix_counts_forge;
        for (const auto& affix : equipped_weapon.affixes) {
            weapon_affix_counts_forge[affix.name]++;
        }
        string current_weapon_affix_name_line_forge = "  当前词条: ";
        if (!weapon_affix_counts_forge.empty()) {
             for (const auto& pair : weapon_affix_counts_forge) {
                 string affix_text = "[" + pair.first + "]";
                 if (pair.second > 1) {
                     affix_text += " (x" + to_string(pair.second) + ")";
                 }
                 if (current_weapon_affix_name_line_forge.length() + affix_text.length() + 1 > SIDEBAR_WIDTH) { 
                     gotoxy(2, current_display_y++);
                     cout << current_weapon_affix_name_line_forge;
                     current_weapon_affix_name_line_forge = "    " + affix_text;
                 } else {
                     current_weapon_affix_name_line_forge += " " + affix_text;
                 }
             }
             gotoxy(2, current_display_y++);
             cout << current_weapon_affix_name_line_forge;
        } else {
             gotoxy(2, current_display_y++);
             cout << current_weapon_affix_name_line_forge << "[无]";
        }

        vector<string> combined_weapon_affix_descs_forge = get_combined_affix_descriptions(equipped_weapon.affixes);
        if (!combined_weapon_affix_descs_forge.empty()) {
            for (const string& desc : combined_weapon_affix_descs_forge) {
                gotoxy(2, current_display_y++);
                cout << "    - " << desc;
            }
        }

        current_display_y++;

        gotoxy(2, current_display_y++); 
        if (equipped_weapon.name != "神圣之剑" && equipped_weapon.name != "混沌战斧") { 
            if (equipped_weapon.level < level) { 
                cout << "[W] 升级武器 (下一级Lv." << equipped_weapon.level + 1 << " 费用: " << (equipped_weapon.level + 1) * 100 << " G)";
            } else { 
                cout << "[W] 升级武器 (已达最大等级 Lv." << equipped_weapon.level << ")";
            }
        } else {
            cout << "[W] 升级武器 (特殊武器,不可升级)";
        }

        gotoxy(2, current_display_y++);
        if (equipped_weapon.name != "神圣之剑" && equipped_weapon.name != "混沌战斧") { 
            cout << "[X] 刷新武器词条 (费用: " << equipped_weapon.level * 20 + 50 << " G)";
        } else {
            cout << "[X] 刷新武器词条 (特殊武器,不可重铸)";
        }

        current_display_y++;

        gotoxy(2, current_display_y++); set_color(light_yellow);
        cout << "--- 护甲锻造 ---";
        set_color(white);

        Armor& equipped_armor = all_armors[have_armor];

        gotoxy(2, current_display_y++);
        cout << "当前护甲: " << equipped_armor.name << " (Lv." << equipped_armor.level << ")";
        gotoxy(2, current_display_y++);
        cout << "  防御: " << equipped_armor.get_current_defense();
        gotoxy(2, current_display_y++);
        cout << "  词条槽位: " << equipped_armor.affixes.size() << "/" << equipped_armor.get_current_affix_slots();

        map<string, int> armor_affix_counts_forge;
        for (const auto& affix : equipped_armor.affixes) {
            armor_affix_counts_forge[affix.name]++;
        }
        string current_armor_affix_name_line_forge = "  当前词条: ";
        if (!armor_affix_counts_forge.empty()) {
             for (const auto& pair : armor_affix_counts_forge) {
                 string affix_text = "[" + pair.first + "]";
                 if (pair.second > 1) {
                     affix_text += " (x" + to_string(pair.second) + ")";
                 }
                 if (current_armor_affix_name_line_forge.length() + affix_text.length() + 1 > SIDEBAR_WIDTH) { 
                     gotoxy(2, current_display_y++);
                     cout << current_armor_affix_name_line_forge;
                     current_armor_affix_name_line_forge = "    " + affix_text;
                 } else {
                     current_armor_affix_name_line_forge += " " + affix_text;
                 }
             }
             gotoxy(2, current_display_y++);
             cout << current_armor_affix_name_line_forge;
        } else {
             gotoxy(2, current_display_y++);
             cout << current_armor_affix_name_line_forge << "[无]";
        }

        vector<string> combined_armor_affix_descs_forge = get_combined_affix_descriptions(equipped_armor.affixes);
        if (!combined_armor_affix_descs_forge.empty()) {
            for (const string& desc : combined_armor_affix_descs_forge) {
                gotoxy(2, current_display_y++);
                cout << "    - " << desc;
            }
        }

        current_display_y++;

        gotoxy(2, current_display_y++);
        if (equipped_armor.name != "神圣之盾" && equipped_armor.name != "混沌胸甲") { 
            if (equipped_armor.level < level) { 
                cout << "[A] 升级护甲 (下一级Lv." << equipped_armor.level + 1 << " 费用: " << (equipped_armor.level + 1) * 100 << " G)";
            } else { 
                cout << "[A] 升级护甲 (已达最大等级 Lv." << equipped_armor.level << ")";
            }
        } else {
            cout << "[A] 升级护甲 (特殊护甲,不可升级)";
        }

        gotoxy(2, current_display_y++);
        if (equipped_armor.name != "神圣之盾" && equipped_armor.name != "混沌胸甲") { 
            cout << "[Z] 刷新护甲词条 (费用: " << equipped_armor.level * 20 + 50 << " G)";
        } else {
            cout << "[Z] 刷新护甲词条 (特殊护甲,不可重铸)";
        }

        current_display_y++;

        gotoxy(2, current_display_y++);
        set_color(light_yellow);
        cout << "你现在有 " << gold << " 金币。";
        gotoxy(2, current_display_y++);
        set_color(white);
        cout<<"按数字购买强化,按[W]升级武器,按[X]刷新武器词条,按[A]升级护甲,按[Z]刷新护甲词条,按[Q]退出";
    };

    display_forging_hut_menu();
    add_message("欢迎来到锻造小屋!");

    while(true){
        if (zxb('Q')) { 
            while(zxb('Q'));
            break;
        }

        bool input_handled_in_loop = false;

        for(size_t i=0; i<upgrades.size(); i++){ 
            if (zxb('1' + i)) { 
                // START OF CHANGE
                if (upgrades[i].name == "技能冷却缩短" && player_class == 4) {
                    add_message("mwh的技能冷却时间是固定的,无法强化。");
                    while(zxb('1' + i));
                    display_forging_hut_menu();
                    input_handled_in_loop = true;
                    break;
                }
                // END OF CHANGE

                int cost = (upgrades[i].level + 1) * upgrades[i].base_cost;
                if (gold < cost){
                    add_message("金币不足,无法升级。");
                } else {
                    gold -= cost;
                    upgrades[i].level++;

                    initialize_class_data();
                    for (size_t k = 0; k < upgrades.size(); ++k) {
                        for (int l = 0; l < upgrades[k].level; ++l) {
                            upgrades[k].apply_effect();
                        }
                    }

                    current_hp = min(current_hp, get_total_max_hp()); 
                    add_message(upgrades[i].name + " 提升到 Lv." + to_string(upgrades[i].level));
                }
                while(zxb('1' + i));
                display_forging_hut_menu();
                input_handled_in_loop = true;
                break;
            }
        }
        if (input_handled_in_loop) { 
            this_thread::sleep_for(chrono::milliseconds(50));
            continue;
        }

        if (zxb('W')) {
            upgrade_weapon(have_sword);
            while(zxb('W'));
            display_forging_hut_menu();
        }
        else if (zxb('X')) {
            reroll_affixes(all_weapons[have_sword]);
            while(zxb('X'));
            display_forging_hut_menu();
        }
        else if (zxb('A')) {
            upgrade_armor(have_armor);
            while(zxb('A'));
            display_forging_hut_menu();
        }
        else if (zxb('Z')) {
            reroll_armor_affixes(all_armors[have_armor]);
            while(zxb('Z'));
            display_forging_hut_menu();
        }

        this_thread::sleep_for(chrono::milliseconds(50));
    }
    system("cls");
    refresh_ui();
}

// 载入初始地图
void load_initial_maps() {
    const vector<string> default_map_floor1 = {
        "########################################",
        "#S...m.....m.......T.........#....m....#",
        "#...###...###...###...###....#.........#",
        "#...#...#...#...#...#...#....#....T....#",
        "#...#...#...#...#...#...#....#.........#",
        "#...###...###...###...###....#....m....#",
        "#.......m.....H..............#.........#",
        "#####...###########...#########....#####",
        "#.............................#........#",
        "#...G...................T.....#....H...#",
        "#.............................#........#",
        "#################...###########.########",
        "#.........F.........#..................#",
        "#...m...............#.......G..........#",
        "#...................#..................#",
        "#####...#############....###############",
        "#.......H.............B................#",
        "#......................................#",
        "#T.................................#D..#",
        "########################################",
    };
    const vector<string> default_map_floor2 = {
        "########################################",
        "#D.....................................#",
        "#..##################################..#",
        "#..#...........m..........H.........#..#",
        "#..#................................#..#",
        "#..#...G.......T....................#..#",
        "#..#..#######.......#######.........#..#",
        "#..#..#.....#.......#.....#.........#..#",
        "#..#..#.....#...m...#.....#.........#..#",
        "#..#..#.....#########.....#............#",
        "#..#  #...................#............#",
        "#..#  #...................#............#",
        "#..#  #...H...............#.......G....#",
        "#..#################################...#",
        "#....................................B.#",
        "#...T.......m...........F..............#",
        "#......................................#",
        "#...G.............................S....#",
        "#......................................#",
        "########################################",
    };
    const vector<string> default_map_floor3 = {
        "########################################",
        "#D....................................S#",
        "#....#####...#####...#####...#####.....#",
        "#....#TTT#...#TTT#G..#...#...#.G.#.....#",
        "#....#T.Tm...#T.TmmG.#...H...#GGGG.....#",
        "#....#TTT#...#TTT#G..#...#...#.G.#.....#",
        "#....#####...#####...#####...#####.....#",
        "#...........F..........................#",
        "##################...###################",
        "#......................................#",
        "#...m.............................G....#",
        "#......................................#",
        "#...H.......T..........................#",
        "##################...###################",
        "#......................................#",
        "#...G................-------...m..........#",
        "#...................-----............#",
        "#...m.......B................----------#",
        "#......................................#",
        "########################################",
    };
    const vector<string> default_map_floor4 = {
        "########################################",
        "#D....T...................G............#",
        "#...#####...############################",
        "#...#.T.#...#..........................#",
        "#...#...#...#...H...........m..........#",
        "#...#...#...#..........................#",
        "#...#...#...#############...############",
        "#...#...#..............................#",
        "#...#...#............G.................#",
        "#...#...#...###########################....#",
        "#...#............................#.....#",
        "#...m......................G.....#...S.#",
        "#.................m..............#.....#",
        "###########################......#######",
        "#.........F..............#.............#",
        "#...H...........G........#...T.........#",
        "#................--------#.............#",
        "#...............B........#-------------#",
        "#......................................#",
        "########################################",
    };
    const vector<string> default_map_floor5 = {
        "########################################",
        "#D....m.......H.......T.......G........#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...#...#...#...#......#",
        "#...#...#...#...#...F...#...#...#......#",
        "#...#...#...#...#.......#...#...#......#",
        "#...#...#...#...#.......#...#...#......#",
        "#...#...#...#...#.......#...#...#......#",
        "#...#...#...#...#...B...#...#...#......#",
        "########################################",
    };
    const vector<string> default_map_floor6 = {
        "########################################",
        "#D.....................................#",
        "#......................................#",
        "#......................................#",
        "#......................................#",
        "#......................................#",
        "#......................................#",
        "#...............mmTTTTTmm..............#",
        "#...............m.GGGGG.m..............#",
        "#...............T.G...G.T..............#",
        "#...............T.G.B.G.T..............#",
        "#...............T.G...G.T..............#",
        "#...............m.GGGGG.m..............#",
        "#...............mmTTTTTmm..............#",
        "#......................................#",
        "#......................................#",
        "#......................................#",
        "#......................................#",
        "#......................................#",
        "########################################",
    };

    initial_maps[0] = default_map_floor1;
    initial_maps[1] = default_map_floor2;
    initial_maps[2] = default_map_floor3;
    initial_maps[3] = default_map_floor4;
    initial_maps[4] = default_map_floor5;
    initial_maps[5] = default_map_floor6;
}

// 初始化所有游戏模板数据 (只调用一次,在程序启动时)
void initialize_base_templates() {
    initialize_class_data();
    initialize_item_templates_and_affixes();
    initialize_upgrades();
    load_initial_maps();
    initialize_star_powers();
    initialize_gadgets(); // --- 妙具系统: 调用初始化 ---
}

// 重置玩家进度相关数据 (用于游戏结束重新开始时,重置所有角色成长)
void reset_player_progression() {
    level = 1;
    experience = 0;
    gold = 10;
    skill_cooldown = 0;
    max_unlocked_floor = 1;
    inventory.clear();
    inventory["生命药水"] = 1;
    message_log.clear();
    current_star_power_id = -1;
    // --- 妙具系统: 重置妙具状态 ---
    current_gadget_id = -1;
    gadget_current_uses = 0;

    initialize_class_data(); 

    for(auto& upg : upgrades) {
        upg.level = 0;
    }
    for (size_t k = 0; k < upgrades.size(); ++k) {
        for (int l = 0; l < upgrades[k].level; ++l) { 
            upgrades[k].apply_effect();
        }
    }

    all_weapons.clear();

    if (!global_weapon_templates.empty()) {
        Weapon initial_weapon = global_weapon_templates[0];
        initial_weapon.level = 0; 
        initial_weapon.affixes.clear();
        for (int i = 0; i < initial_weapon.get_current_affix_slots(); ++i) {
            vector<Affix> pool;
            for (const auto& affix_template : all_affixes) {
                if (affix_template.tier <= 1 && is_weapon_affix_type(affix_template)) { 
                    pool.push_back(affix_template);
                }
            }
            if (!pool.empty()) {
                initial_weapon.affixes.push_back(pool[rand() % pool.size()]);
            }
        }
        all_weapons.push_back(initial_weapon);
        have_sword = 0;
    } else {
        all_weapons.emplace_back("默认武器", 1, 0, 0);
        have_sword = 0;
    }

    all_armors.clear();
    if (!global_armor_templates.empty()) {
        Armor initial_armor = global_armor_templates[0];
        initial_armor.level = 0;
        initial_armor.affixes.clear();
        for (int i = 0; i < initial_armor.get_current_affix_slots(); ++i) {
            vector<Affix> pool;
            for (const auto& affix_template : all_affixes) {
                if (affix_template.tier <= 1 && is_armor_affix_type(affix_template)) {
                    pool.push_back(affix_template);
                }
            }
            if (!pool.empty()) {
                initial_armor.affixes.push_back(pool[rand() % pool.size()]);
            }
        }
        all_armors.push_back(initial_armor);
        have_armor = 0;
    } else {
        all_armors.emplace_back("默认护甲", 0, 0, 0);
        have_armor = 0;
    }
}

// 重置地图和Boss状态 (用于新轮次或游戏重开时,重置地图布局)
void reset_map_and_boss_status() {
    for(int i=0; i<NUM_FLOORS; ++i) {
        current_maps[i] = initial_maps[i];
    }
    current_floor = 1;
    x_pos = floor_entrance_coords[current_floor].first;
    y_pos = floor_entrance_coords[current_floor].second;
    for (int i = 1; i <= NUM_FLOORS; ++i) {
        boss_defeated[i] = false;
    }
}

// 击败最终Boss后的处理
void on_final_boss_defeated() {
    add_message("恭喜你!你击败了混沌之主,征服了所有地牢!");
    game_phase++;
    best_phase = max(best_phase, game_phase);
    add_message("你进入了更深层的地牢,现在是第 " + to_string(game_phase) + " 轮挑战!");
    add_message("所有敌人变得更加强大了...");

    initialize_monster_templates();
    reset_map_and_boss_status();

    system("cls");
    refresh_ui(); 
    gotoxy(y_pos << 1, x_pos);
    set_color(bright_white);
    cout << "入";
    this_thread::sleep_for(chrono::seconds(2));
}

// --- Save/Load Game Functions ---
void save_game(const string& filename) {
    ofstream outFile(filename);
    if (!outFile.is_open()) {
        add_message("错误:无法保存游戏到文件 " + filename);
        return;
    }

    outFile << player_class << endl;
    outFile << level << endl;
    outFile << experience << endl;
    outFile << current_hp << endl;
    outFile << gold << endl;
    outFile << skill_cooldown << endl;

    outFile << have_sword << endl;
    outFile << have_armor << endl;

    outFile << current_floor << endl;
    outFile << max_unlocked_floor << endl;
    outFile << game_phase << endl;
    outFile << best_phase << endl;
    outFile << endless_max_floor << endl;
    outFile << current_star_power_id << endl;
    // --- 妙具系统: 保存妙具状态 ---
    outFile << current_gadget_id << endl;
    outFile << gadget_current_uses << endl;

    for (int i = 1; i <= NUM_FLOORS; ++i) {
        outFile << boss_defeated[i] << " ";
    }
    outFile << endl;

    outFile << inventory.size() << endl;
    for (const auto& pair : inventory) {
        outFile << pair.first << " " << pair.second << endl;
    }

    outFile << upgrades.size() << endl;
    for (const auto& upg : upgrades) {
        outFile << upg.level << " ";
    }
    outFile << endl;

    outFile << all_weapons.size() << endl;
    for (const auto& w : all_weapons) {
        outFile << w.name << endl;
        outFile << w.initial_damage << " " << w.cost << " " << w.initial_affix_slots << endl;
        outFile << w.level << endl;
        outFile << w.affixes.size() << endl;
        for (const auto& affix : w.affixes) {
            outFile << affix.name << endl;
        }
    }

    outFile << all_armors.size() << endl;
    for (const auto& a : all_armors) {
        outFile << a.name << endl;
        outFile << a.initial_defense_bonus << " " << a.cost << " " << a.initial_affix_slots << endl;
        outFile << a.level << endl;
        outFile << a.affixes.size() << endl;
        for (const auto& affix : a.affixes) {
            outFile << affix.name << endl;
        }
    }

    for (int f = 0; f < NUM_FLOORS; ++f) {
        for (int r = 0; r < MAP_ROWS; ++r) {
            outFile << current_maps[f][r] << endl;
        }
    }

    outFile.close();
    add_message("游戏已成功保存到 " + filename);
}
void load_game(const string& filename) {
    ifstream inFile(filename);
    if (!inFile.is_open()) {
        add_message("错误:无法读取存档文件 " + filename);
        return;
    }

    // 在开始加载前,重置所有模板数据和状态,确保一个干净的环境
    initialize_base_templates();
    for(int f=0; f<NUM_FLOORS; ++f) {
        current_maps[f].clear();
        current_maps[f].resize(MAP_ROWS);
    }

    // --- 开始读取核心玩家数据 ---
    inFile >> player_class;
    inFile >> level;
    inFile >> experience;
    inFile >> current_hp;
    inFile >> gold;
    inFile >> skill_cooldown;
    inFile >> have_sword;
    inFile >> have_armor;
    inFile >> current_floor;
    inFile >> max_unlocked_floor;
    inFile >> game_phase;
    inFile >> best_phase;
    inFile >> endless_max_floor;
    inFile >> current_star_power_id;
    inFile >> current_gadget_id;
    inFile >> gadget_current_uses;

    // 【防御性编程】检查流状态,如果前面读取失败,则停止
    if (!inFile) {
        add_message("错误:读取核心数据时存档文件格式损坏!");
        inFile.close();
        return;
    }

    is_in_endless_mode = false; // 总是从普通模式加载
    initialize_monster_templates(); // 根据加载的 game_phase 初始化怪物

    for (int i = 1; i <= NUM_FLOORS; ++i) {
        inFile >> boss_defeated[i];
    }
    // 【关键修复 1】: 在读取完一系列 `>>` 之后,准备读取下一个逻辑块前,清除换行符。
    inFile.ignore(numeric_limits<streamsize>::max(), '\n');

    // --- 读取物品栏 ---
    size_t inv_size;
    inFile >> inv_size;
    inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 清除 inv_size 后面的换行符
    inventory.clear();
    for (size_t i = 0; i < inv_size; ++i) {
        string item_name;
        int count;
        inFile >> item_name >> count;
        inventory[item_name] = count;
        inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 清除每行物品后的换行符
    }

    // --- 读取角色强化 ---
    size_t upg_size;
    inFile >> upg_size;
    initialize_upgrades(); // 确保 upgrades 向量是初始化的
    for (size_t i = 0; i < upg_size; ++i) {
        int loaded_level;
        inFile >> loaded_level;
        if (i < upgrades.size()) {
            upgrades[i].level = loaded_level;
        }
    }
    inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 清除强化等级行后的换行符
    // 重新应用强化效果
    initialize_class_data();
    for (size_t k = 0; k < upgrades.size(); ++k) {
        for (int l = 0; l < upgrades[k].level; ++l) {
            upgrades[k].apply_effect();
        }
    }
    current_hp = min(current_hp, get_total_max_hp());

    // --- 读取武器列表 (最容易出错的部分) ---
    size_t weapon_count;
    inFile >> weapon_count;
    inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 【关键修复 2】清除 weapon_count 后的换行符,为下面的 getline 做准备
    all_weapons.clear();
    for (size_t i = 0; i < weapon_count; ++i) {
        Weapon loaded_w_instance; // 创建一个空的武器实例来填充数据

        getline(inFile, loaded_w_instance.name); // 读取武器名称,这现在是安全的

        inFile >> loaded_w_instance.initial_damage >> loaded_w_instance.cost >> loaded_w_instance.initial_affix_slots;
        inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 【关键修复 3】清除这一行数字后的换行符

        inFile >> loaded_w_instance.level;
        inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 【关键修复 4】清除等级后的换行符

        size_t affix_size;
        inFile >> affix_size;
        inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 【关键修复 5】清除词条数量后的换行符

        loaded_w_instance.affixes.clear();
        for (size_t j = 0; j < affix_size; ++j) {
            string affix_name;
            getline(inFile, affix_name); // 读取词条名称,现在是安全的
            auto it = find_if(all_affixes.begin(), all_affixes.end(),
                              [&](const Affix& a){ return a.name == affix_name; });
            if (it != all_affixes.end()) {
                loaded_w_instance.affixes.push_back(*it);
            } else {
                add_message("警告: 武器词条 '" + affix_name + "' 未找到。");
            }
        }
        all_weapons.push_back(loaded_w_instance);
    }

    // 安全检查,防止索引越界
    if (all_weapons.empty()) {
        all_weapons.push_back(global_weapon_templates[0]);
        have_sword = 0;
    } else if (have_sword >= all_weapons.size()) {
        have_sword = 0; 
    }

    // --- 读取护甲列表 (应用相同的修复逻辑) ---
    size_t armor_count;
    inFile >> armor_count;
    inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 【关键修复 6】
    all_armors.clear();
    for (size_t i = 0; i < armor_count; ++i) {
        Armor loaded_a_instance;

        getline(inFile, loaded_a_instance.name);

        inFile >> loaded_a_instance.initial_defense_bonus >> loaded_a_instance.cost >> loaded_a_instance.initial_affix_slots;
        inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 【关键修复 7】

        inFile >> loaded_a_instance.level;
        inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 【关键修复 8】

        size_t affix_size;
        inFile >> affix_size;
        inFile.ignore(numeric_limits<streamsize>::max(), '\n'); // 【关键修复 9】

        loaded_a_instance.affixes.clear();
        for (size_t j = 0; j < affix_size; ++j) {
            string affix_name;
            getline(inFile, affix_name);
            auto it = find_if(all_affixes.begin(), all_affixes.end(),
                              [&](const Affix& a){ return a.name == affix_name; });
            if (it != all_affixes.end()) {
                loaded_a_instance.affixes.push_back(*it);
            } else {
                 add_message("警告: 护甲词条 '" + affix_name + "' 未找到。");
            }
        }
        all_armors.push_back(loaded_a_instance);
    }

    // 安全检查
    if (all_armors.empty()) {
        all_armors.push_back(global_armor_templates[0]);
        have_armor = 0;
    } else if (have_armor >= all_armors.size()) {
        have_armor = 0;
    }

    // 【防御性编程】在读取地图前再次检查流状态
    if (!inFile) {
        add_message("错误:读取装备数据时存档文件格式损坏!");
        inFile.close();
        // 此时游戏状态可能已损坏,可以考虑触发一个安全重置
        reset_game_state(); 
        choose_class();
        current_hp = get_total_max_hp();
        return;
    }

    // --- 读取地图状态 ---
    for (int f = 0; f < NUM_FLOORS; ++f) {
        for (int r = 0; r < MAP_ROWS; ++r) {
            // 这里之前的逻辑是正确的,因为是连续的 getline
            if (!getline(inFile, current_maps[f][r])) {
                // 如果在读取地图时出错,说明存档文件不完整
                add_message("错误:地图数据不完整或损坏!");
                inFile.close();
                // 同样可以触发安全重置
                reset_game_state();
                choose_class();
                current_hp = get_total_max_hp();
                return;
            }
        }
    }

    inFile.close();
    add_message("游戏存档已加载成功!");
    system("cls");
    refresh_ui();
    // 找到玩家在当前楼层的坐标,因为存档里没有存
    bool player_pos_found = false;
    for(int i = 0; i < MAP_ROWS; ++i) {
        for (int j = 0; j < MAP_COLS; ++j) {
            // 注意:玩家的位置不会被保存在地图字符中,所以我们需要一个逻辑来恢复它。
            // 最简单的假设是玩家总是在传送门处。
            // 一个更稳健的方法是保存玩家坐标。但既然没存,我们先用一个回退方案。
        }
    }

    gotoxy(y_pos << 1, x_pos);
    set_color(bright_white);
    cout << "入";
}

// --- 新增:用于地图生成的辅助结构体和函数 ---

// 代表一个房间的结构体
struct Room {
    int x, y, w, h;
    // 获取房间中心点
    pair<int, int> center() const {
        return {x + h / 2, y + w / 2};
    }
    // 检查此房间是否与另一个房间相交(重叠)
    bool intersects(const Room& other) const {
        return (x <= other.x + other.h && x + h >= other.x &&
                y <= other.y + other.w && y + w >= other.y);
    }
};

// 在两个点之间挖掘一条水平走廊
void carve_h_corridor(vector<string>& map, int y1, int y2, int x) {
    for (int y = min(y1, y2); y <= max(y1, y2); ++y) {
        map[x][y] = '.';
    }
}

// 在两个点之间挖掘一条垂直走廊
void carve_v_corridor(vector<string>& map, int x1, int x2, int y) {
    for (int x = min(x1, x2); x <= max(x1, x2); ++x) {
        map[x][y] = '.';
    }
}

// --- 结束新增 ---

// --- 新增:无尽模式函数 (已改进) ---
void generate_endless_map(int floor_level) {
    endless_map.assign(MAP_ROWS, string(MAP_COLS, '#')); // 用墙填充
    vector<Room> rooms;

    // --- 1. 随机生成不重叠的房间 ---
    int max_rooms = 12; // 增加房间数量上限
    int min_rooms = 7;  // 增加房间数量下限
    int num_rooms_to_generate = rand() % (max_rooms - min_rooms + 1) + min_rooms;

    for (int i = 0; i < num_rooms_to_generate; ++i) {
        int room_w = rand() % 6 + 5; // 宽 5-10
        int room_h = rand() % 5 + 4; // 高 4-8
        int room_x = rand() % (MAP_ROWS - room_h - 2) + 1;
        int room_y = rand() % (MAP_COLS - room_w - 2) + 1;

        Room new_room = {room_x, room_y, room_w, room_h};

        // 检查新房间是否与已存在的房间重叠
        bool failed = false;
        for (const auto& other_room : rooms) {
            if (new_room.intersects(other_room)) {
                failed = true;
                break;
            }
        }

        if (!failed) {
            // 在地图上挖掘房间
            for (int rx = new_room.x; rx < new_room.x + new_room.h; ++rx) {
                for (int ry = new_room.y; ry < new_room.y + new_room.w; ++ry) {
                    endless_map[rx][ry] = '.';
                }
            }
            rooms.push_back(new_room);
        }
    }

    // 如果没有成功生成任何房间,则重新生成
    if (rooms.empty()) {
        generate_endless_map(floor_level);
        return;
    }

    // --- 2. 用走廊连接所有房间 ---
    for (size_t i = 1; i < rooms.size(); ++i) {
        auto [prev_x, prev_y] = rooms[i - 1].center();
        auto [new_x, new_y] = rooms[i].center();

        // 随机决定是先挖横向还是纵向走廊,使地图更多样化
        if (rand() % 2 == 1) {
            carve_h_corridor(endless_map, prev_y, new_y, prev_x);
            carve_v_corridor(endless_map, prev_x, new_x, new_y);
        } else {
            carve_v_corridor(endless_map, prev_x, new_x, prev_y);
            carve_h_corridor(endless_map, prev_y, new_y, new_x);
        }
    }

    // --- 3. 放置特殊物件 (入口、出口、守护者) ---
    // 找到距离最远的两个房间,作为入口和出口
    int start_room_idx = 0;
    int end_room_idx = 0;
    float max_dist = 0.0f;

    for(size_t i = 0; i < rooms.size(); ++i) {
        for(size_t j = i + 1; j < rooms.size(); ++j) {
            auto [x1, y1] = rooms[i].center();
            auto [x2, y2] = rooms[j].center();
            float dist = sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));
            if (dist > max_dist) {
                max_dist = dist;
                start_room_idx = i;
                end_room_idx = j;
            }
        }
    }

    // 放置入口 (回归门) 和玩家
    auto [start_x, start_y] = rooms[start_room_idx].center();
    endless_map[start_x][start_y] = 'R';
    x_pos = start_x;
    y_pos = start_y;

    // 放置出口 (下一层) 和守护者
    auto [end_x, end_y] = rooms[end_room_idx].center();
    endless_map[end_x][end_y] = 'U';
    // 将Boss放在出口附近,但不要覆盖出口
    if (endless_map[end_x - 1][end_y] == '.') endless_map[end_x - 1][end_y] = 'B';
    else if (endless_map[end_x + 1][end_y] == '.') endless_map[end_x + 1][end_y] = 'B';
    else if (endless_map[end_x][end_y - 1] == '.') endless_map[end_x][end_y - 1] = 'B';
    else endless_map[end_x][end_y + 1] = 'B'; // Fallback

    // --- 4. 在房间内散布怪物和宝藏 ---
    int monster_count = 5 + floor_level / 2;
    int elite_count = 1 + floor_level / 4; // 精英怪少一些
    int treasure_count = 2 + floor_level / 5;
    int potion_count = 1 + floor_level / 6;

    // 收集所有房间内的可用地块
    vector<pair<int, int>> spawn_points;
    for (const auto& room : rooms) {
        // 在房间内部随机选择点,避开墙壁1格
        for (int rx = room.x + 1; rx < room.x + room.h - 1; ++rx) {
            for (int ry = room.y + 1; ry < room.y + room.w - 1; ++ry) {
                if (endless_map[rx][ry] == '.') {
                    spawn_points.push_back({rx, ry});
                }
            }
        }
    }

    // 打乱可用点,防止物品扎堆
    random_shuffle(spawn_points.begin(), spawn_points.end());

    auto place_object = [&](int count, char tile) {
        for (int i = 0; i < count && !spawn_points.empty(); ++i) {
            auto pos = spawn_points.back();
            spawn_points.pop_back();
            endless_map[pos.first][pos.second] = tile;
        }
    };

    place_object(monster_count, (rand() % 3 == 0) ? 'G' : 'm'); // 强弱小怪
    place_object(elite_count, 'E');
    place_object(treasure_count, 'T');
    place_object(potion_count, 'H');

    endless_boss_defeated_this_floor = false; // 重置Boss击败状态
}

Monster get_endless_monster(int floor_level, char tile_type) {
    Monster base_monster_template;

    // 从 all_monster_templates_base 获取原始数据,避免受游戏轮次缩放影响
    auto find_base_template = [&](MonsterType type_to_find) {
        for (const auto& m : all_monster_templates_base) {
            if (m.type == type_to_find) return m;
        }
        return all_monster_templates_base[0]; // Fallback
    };

    if (tile_type == 'B') {
        // 随机选一个主线Boss作为模板
        int boss_type_idx = rand() % 6; // 假设有6个主线Boss
        MonsterType type = static_cast<MonsterType>(BOSS_GOBLIN_KING + boss_type_idx);
        base_monster_template = find_base_template(type);
    } else if (tile_type == 'E') {
        // 从强力小怪中选一个做精英
        vector<MonsterType> elite_pool = {BEAST, SKELETON, DEMON_GUARD, SHADOW_BEAST, ELITE_GUARD, VOID_RAVAGER};
        base_monster_template = find_base_template(elite_pool[rand() % elite_pool.size()]);
        base_monster_template.name = "精英 " + base_monster_template.name;
    } else { // 'm' or 'G'
        // 从所有小怪中选
        vector<MonsterType> regular_pool;
        for (const auto& m_template : all_monster_templates_base) {
            if (m_template.type < BOSS_GOBLIN_KING) {
                regular_pool.push_back(m_template.type);
            }
        }
        base_monster_template = find_base_template(regular_pool[rand() % regular_pool.size()]);
    }

    Monster scaled_monster = base_monster_template;

    // 根据无尽层数进行属性缩放
    float scale_factor = 1.0f + 0.3f * (floor_level - 1);
    float reward_scale = 1.0f + 0.2f * (floor_level - 1);

    scaled_monster.max_hp = static_cast<int>(base_monster_template.max_hp * scale_factor);
    scaled_monster.attack = static_cast<int>(base_monster_template.attack * scale_factor);
    scaled_monster.defense = static_cast<int>(base_monster_template.defense * scale_factor);
    scaled_monster.xp_reward = static_cast<int>(base_monster_template.xp_reward * reward_scale);
    scaled_monster.gold_reward = static_cast<int>(base_monster_template.gold_reward * reward_scale);

    // 精英怪和Boss有额外加成
    if (tile_type == 'E') {
        scaled_monster.max_hp = static_cast<int>(scaled_monster.max_hp * 1.5);
        scaled_monster.attack = static_cast<int>(scaled_monster.attack * 1.2);
        scaled_monster.xp_reward *= 2;
        scaled_monster.gold_reward *= 2;
    }
    if (tile_type == 'B') {
        scaled_monster.max_hp = static_cast<int>(scaled_monster.max_hp * 2.5);
        scaled_monster.attack = static_cast<int>(scaled_monster.attack * 1.8);
        scaled_monster.xp_reward *= 5;
        scaled_monster.gold_reward *= 5;
    }

    return scaled_monster;
}
// --- 主函数 ---
int main() {
    srand(time(0));

    // --- 【关键修改点 1】---
    // 按照这个顺序执行,确保控制台状态稳定

    // 1. 设置控制台尺寸
    COORD bufferSize = {MAP_COLS * 2 + SIDEBAR_WIDTH + 5, MAP_ROWS + 10 + 25};
    SMALL_RECT windowSize = {0, 0, bufferSize.X - 1, bufferSize.Y - 1};
    SetConsoleScreenBufferSize(hConsole, bufferSize);
    SetConsoleWindowInfo(hConsole, TRUE, &windowSize);

    // 2. 立即清屏以“固化”控制台状态,防止任何后续输出引起滚动
    system("cls");
    // 3. 隐藏光标
    hide();

    // 现在可以安全地开始显示游戏内容
    display_game_intro();

    initialize_base_templates();
    reset_game_state();
    choose_class();

    current_hp = get_total_max_hp();

    refresh_ui();
    add_message("欢迎来到文字地牢!");
    add_message("W,A,S,D移动,H使用药水,F使用技能。");
    add_message("P保存游戏,L读取存档,Esc退出。");
    add_message("探索地图,击败怪物,寻找宝藏!");
    gotoxy(y_pos << 1, x_pos);
    set_color(bright_white);
    cout << "入";
    bool game_running = true;
    while (game_running) {
        if (zxb(VK_ESCAPE)) { 
            game_running = false;
            while(zxb(VK_ESCAPE));
        }
        if (zxb('W')) { 
            move_player(-1, 0);
            this_thread::sleep_for(chrono::milliseconds(20));
        }
        if (zxb('A') ){ 
            move_player(0, -1);
            this_thread::sleep_for(chrono::milliseconds(20));
        }
        if (zxb('S')) { 
            move_player(1, 0);
            this_thread::sleep_for(chrono::milliseconds(20));
        }
        if (zxb('D')) { 
            move_player(0, 1);
            this_thread::sleep_for(chrono::milliseconds(20));
        }
        if (zxb('H')) { 
            if (inventory["生命药水"] <= 0) {
                add_message("你没有生命药水了。");
            } else if (current_hp == get_total_max_hp()) {
                add_message("你的生命值已满。");
            } else {
                int heal_amount = get_total_max_hp() / 2;
                current_hp = min(get_total_max_hp(), current_hp + heal_amount);
                inventory["生命药水"]--;
                add_message("你使用了药水,恢复生命!");
                refresh_ui();
            }
            while(zxb('H')); 
        }
        if (zxb('P')) { 
            save_game("save.txt");
            while(zxb('P')); 
        }
        if (zxb('L')) { 
            load_game("save.txt");
            while(zxb('L')); 
        }
        this_thread::sleep_for(chrono::milliseconds(20));
    }
    gotoxy(0, MAP_ROWS + 15);
    set_color(white);
    cout << "游戏结束。再见!" << endl;
    return 0;
}