#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include <windows.h>

using namespace std;

enum CardType {
    ATTACK,
    DEFENSE,
    HEAL,
    STUN,
    DRAW,
    TAUNT,
    POISON,
    BUFF
};

struct Card {
    string name;
    CardType type;
    int value;
    string desc;
    string job;

    Card(string n, CardType t, int v, string d, string j = "all")
        : name(n), type(t), value(v), desc(d), job(j) {}
};

class Player {
private:
    string name;
    string job;
    int hp;
    int maxHp;
    int shield;
    int attackBuff;
    bool isStunned;
    bool isPoisoned;
    int poisonTurn;

    vector<Card> deck;
    vector<Card> hand;

public:
    Player(string n, string j, int mhp)
        : name(n), job(j), maxHp(mhp), hp(mhp), shield(0),
          attackBuff(0), isStunned(false), isPoisoned(false), poisonTurn(0) {}

    int getHp() const { return hp; }
    int getShield() const { return shield; }
    bool getStun() const { return isStunned; }
    bool getPoison() const { return isPoisoned; }
    string getName() const { return name; }
    string getJob() const { return job; }

    void setJob(string j) { job = j; }
    void setHp(int h) { hp = max(0, h); }
    void setShield(int s) { shield = max(0, s); }
    void setStun(bool s) { isStunned = s; }
    void setPoison(bool p, int turn = 2) {
        isPoisoned = p;
        poisonTurn = turn;
    }
    void addBuff(int a) { attackBuff += a; }

    void takeDamage(int dmg) {
        dmg += attackBuff;
        if (shield >= dmg) {
            shield -= dmg;
        } else {
            dmg -= shield;
            shield = 0;
            hp = max(0, hp - dmg);
        }
    }

    void poisonDamage() {
        if (isPoisoned && poisonTurn > 0) {
            hp = max(0, hp - 2);
            cout << getName() << " 中毒损失2点HP!\n";
            poisonTurn--;
            if (poisonTurn <= 0) isPoisoned = false;
        }
    }

    void initAllCards(vector<Card>& all) {
        all.clear();
        all.emplace_back("挥砍", ATTACK, 2, "造成2点伤害", "all");
        all.emplace_back("护盾", DEFENSE, 3, "获得3点护盾", "all");
        all.emplace_back("疗伤", HEAL, 3, "恢复3点生命", "all");
        all.emplace_back("眩晕击", STUN, 1, "眩晕敌人1回合", "all");
        all.emplace_back("抽卡", DRAW, 1, "抽1张牌", "all");

        all.emplace_back("猛击", ATTACK, 6, "造成6点伤害", "warrior");
        all.emplace_back("嘲讽", TAUNT, 0, "强制敌人攻击", "warrior");
        all.emplace_back("战争怒吼", BUFF, 2, "本回合攻击+2", "warrior");

        all.emplace_back("火球", ATTACK, 8, "造成8点伤害", "mage");
        all.emplace_back("冰冻", STUN, 1, "眩晕敌人", "mage");
        all.emplace_back("奥术抽卡", DRAW, 2, "抽2张牌", "mage");

        all.emplace_back("连射", ATTACK, 4, "造成4点伤害", "ranger");
        all.emplace_back("搜索", DRAW, 3, "抽3张牌", "ranger");
        all.emplace_back("毒箭", POISON, 2, "使敌人中毒2回合", "ranger");

        all.emplace_back("神圣打击", ATTACK, 5, "造成5点伤害", "priest");
        all.emplace_back("治愈", HEAL, 6, "恢复6点生命", "priest");
        all.emplace_back("群体治疗", HEAL, 4, "恢复4点生命", "priest");

        all.emplace_back("背刺", ATTACK, 7, "造成7点伤害", "assassin");
        all.emplace_back("剧毒", POISON, 3, "敌人中毒3回合", "assassin");
        all.emplace_back("突袭", DRAW, 2, "抽2张牌", "assassin");

        all.emplace_back("爪击", ATTACK, 5, "造成5点伤害", "druid");
        all.emplace_back("自然护盾", DEFENSE, 5, "获得5点护盾", "druid");
        all.emplace_back("自然愈合", HEAL, 5, "恢复5点生命", "druid");
    }

    void buildDeck() {
        vector<Card> all;
        initAllCards(all);
        deck.clear();

        cout << "\n【卡组构筑:选择12张卡牌】\n";
        int i = 1;
        for (auto& c : all) {
            if (c.job == job || c.job == "all") {
                cout << i << ". " << c.name << " | " << c.desc << "\n";
                i++;
            }
        }

        for (int cnt = 0; cnt < 12; ) {
            int c;
            cout << "选择卡牌" << cnt+1 << ": ";
            cin >> c;
            int real = 0;
            bool ok = false;
            for (auto& card : all) {
                if (card.job == job || card.job == "all") {
                    real++;
                    if (real == c) {
                        deck.push_back(card);
                        cnt++;
                        ok = true;
                        break;
                    }
                }
            }
            if (!ok) cout << "无效选择!\n";
        }

        random_shuffle(deck.begin(), deck.end());
        cout << "卡组构筑完成!\n";
    }

    void draw(int n = 1) {
        for (int i = 0; i < n; ++i) {
            if (deck.empty()) return;
            hand.push_back(deck.front());
            deck.erase(deck.begin());
        }
    }

    void showHand() {
        cout << "\n【手牌】\n";
        for (int i = 0; i < hand.size(); i++)
            cout << i+1 << ". " << hand[i].name << " | " << hand[i].desc << "\n";
    }

    Card play(int idx) {
        if (idx < 0 || idx >= hand.size())
            return Card("空", ATTACK, 0, "无");

        Card c = hand[idx];
        hand.erase(hand.begin() + idx);
        deck.push_back(c);
        return c;
    }

    int getHandCount() { return hand.size(); }

    int aiChoose(Player& enemy) {
        if (hand.empty()) return -1;

        if (hp < 12) {
            for (int i = 0; i < hand.size(); i++)
                if (hand[i].type == HEAL) return i;
        }

        if (isPoisoned) {
            for (int i = 0; i < hand.size(); i++)
                if (hand[i].type == HEAL || hand[i].type == DEFENSE) return i;
        }

        if (enemy.getStun()) {
            for (int i = 0; i < hand.size(); i++)
                if (hand[i].type == ATTACK) return i;
        }

        int maxAtk = -1, id = 0;
        for (int i = 0; i < hand.size(); i++) {
            if (hand[i].type == ATTACK && hand[i].value > maxAtk) {
                maxAtk = hand[i].value;
                id = i;
            }
        }
        return id;
    }
};

class CardGame {
private:
    Player player;
    Player ai;
    bool gameOver;
    int level;

    void anim(int ms = 500) { Sleep(ms); }
    void sound() { Beep(550,120); Sleep(80); Beep(700,120); }
    void soundWin() { Beep(800,100); Beep(900,100); Beep(1000,200); }
    void soundLose() { Beep(300,200); Beep(200,200); Beep(100,300); }

    void printStatus() {
        cout << "\n====================================\n";
        cout << player.getName() << " HP:" << player.getHp()
             << " 护盾:" << player.getShield()
             << (player.getStun()?" 【眩晕】":"")
             << (player.getPoison()?" 【中毒】":"") << "\n";
        cout << ai.getName() << " HP:" << ai.getHp()
             << " 护盾:" << ai.getShield()
             << (ai.getStun()?" 【眩晕】":"")
             << (ai.getPoison()?" 【中毒】":"") << "\n";
        cout << "====================================\n";
    }

    void apply(Card c, Player& from, Player& to) {
        sound();
        cout << "\n? " << from.getName() << " 使用:" << c.name << "\n";
        anim();

        switch (c.type) {
            case ATTACK:
                cout << "造成" << c.value << "点伤害!\n";
                to.takeDamage(c.value);
                break;
            case DEFENSE:
                from.setShield(from.getShield() + c.value);
                cout << "获得" << c.value << "点护盾!\n";
                break;
            case HEAL:
                from.setHp(from.getHp() + c.value);
                cout << "恢复" << c.value << "点生命!\n";
                break;
            case STUN:
                to.setStun(true);
                cout << to.getName() << "被眩晕!\n";
                break;
            case DRAW:
                from.draw(c.value);
                cout << "抽" << c.value << "张牌!\n";
                break;
            case TAUNT:
                cout << "强制攻击!\n";
                break;
            case POISON:
                to.setPoison(true, c.value);
                cout << to.getName() << "中毒!\n";
                break;
            case BUFF:
                from.addBuff(c.value);
                cout << "攻击提升!\n";
                break;
        }
        printStatus();
    }

    bool check() {
        if (player.getHp() <= 0) {
            soundLose();
            cout << "\n?? 你倒下了... 黑暗吞噬了一切\n";
            gameOver = true;
            return true;
        }
        if (ai.getHp() <= 0) {
            soundWin();
            cout << "\n?? 胜利!你击败了敌人!\n";
            if (level == 3) {
                cout << "\n? 最终胜利!你拯救了王国,成为传说卡牌大师!\n";
            }
            gameOver = true;
            return true;
        }
        return false;
    }

public:
    CardGame() : player("冒险者","",35), ai("敌人","all",30), gameOver(false), level(1) {
        srand(time(0));
    }

    void storyIntro() {
        cout << "===== 战略卡牌传说 · 终极版 =====\n\n";
        cout << "故事开始:\n";
        anim();
        cout << "黑暗军团入侵王国,唯有卡牌之力能阻挡邪恶...\n";
        anim();
        cout << "你,一位年轻的冒险者,踏上拯救世界的征途!\n";
        anim();
        cout << "选择你的职业,构筑卡组,战胜所有敌人!\n\n";
    }

    void selectJob() {
        cout << "===== 选择你的职业 =====\n";
        cout << "1. 战士  2. 法师  3. 游侠\n";
        cout << "4. 牧师  5. 刺客  6. 德鲁伊\n";
        int c; cin >> c;
        string j;
        if (c==1) j="warrior";
        else if (c==2) j="mage";
        else if (c==3) j="ranger";
        else if (c==4) j="priest";
        else if (c==5) j="assassin";
        else j="druid";

        player.setJob(j);

        cout << "你选择了:" << (c==1?"战士":c==2?"法师":c==3?"游侠":c==4?"牧师":c==5?"刺客":"德鲁伊") << "\n";
    }

    void start() {
        storyIntro();
        selectJob();
        player.buildDeck();

        while (level <= 3) {
            gameOver = false;
            if (level == 1) {
                cout << "\n==== 第一关:守卫士兵 ====\n";
                ai = Player("士兵","warrior",30);
            } else if (level == 2) {
                cout << "\n==== 第二关:黑暗法师 ====\n";
                ai = Player("法师","mage",35);
            } else {
                cout << "\n==== 最终关:魔王 ====\n";
                ai = Player("魔王","all",45);
            }

            player.draw(5);
            ai.draw(5);
            printStatus();

            while (!gameOver) {
                playerTurn();
                if (gameOver) break;
                aiTurn();
                check();
            }

            if (player.getHp() <= 0) break;
            level++;
        }
    }

    void playerTurn() {
        cout << "\n===== 你的回合 ====\n";
        anim();
        player.poisonDamage();
        if (check()) return;

        if (player.getStun()) {
            cout << "你被眩晕,无法行动!\n";
            player.setStun(false);
            return;
        }

        player.draw(1);
        player.showHand();
        int c; cout << "出牌:"; cin >> c;
        Card card = player.play(c-1);
        apply(card, player, ai);
    }

    void aiTurn() {
        cout << "\n===== 敌方回合 ====\n";
        anim();
        ai.poisonDamage();
        if (check()) return;

        if (ai.getStun()) {
            cout << "敌人被眩晕!\n";
            ai.setStun(false);
            return;
        }

        ai.draw(1);
        int idx = ai.aiChoose(player);
        if (idx < 0 || idx >= ai.getHandCount()) return;
        Card c = ai.play(idx);
        apply(c, ai, player);
    }
};

int main() {
    CardGame game;
    game.start();
    return 0;
}