#include <memory>
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <random>
#include <ctime>
#include <map>
#include <limits>
#include <unordered_map>
using namespace std;
class Card;
class Player;
class GameState;
enum class SkillType { ACTIVE, PASSIVE, TRIGGERED, LIMITED };
enum class Suit { SPADE, HEART, CLUB, DIAMOND, NONE };
enum class CardType { BASIC, TRICK, EQUIPMENT, DELAY_TRICK };
enum class Kingdom { WEI, SHU, WU, QUN };
enum class EquipSlot { WEAPON, ARMOR, OFF_MOUNT, DEF_MOUNT };
enum class CardColor { BLACK, RED, ANY };
enum class Identity { ZHU_GONG, ZHONG_CHEN, FAN_ZEI, NEI_JIAN };
class Card : public enable_shared_from_this<Card>
{
private:
Suit suit;
int number;
CardType type;
string name;
string description;
CardColor color;
public:
Card(Suit s, int n, CardType t, string name, string desc = "")
: suit(s), number(n), type(t), name(name), description(desc)
{
if (suit == Suit::SPADE || suit == Suit::CLUB)
color = CardColor::BLACK;
else if (suit == Suit::HEART || suit == Suit::DIAMOND)
color = CardColor::RED;
else
color = CardColor::ANY;
}
virtual ~Card() = default;
virtual bool use(Player* user, vector<Player*>& targets, GameState* state) { return false; }
Suit getSuit() const { return suit; }
int getNumber() const { return number; }
CardType getType() const { return type; }
string getName() const { return name; }
string getDescription() const { return description; }
CardColor getColor() const { return color; }
string suitToString() const
{
switch (suit)
{
case Suit::SPADE: return "黑桃";
case Suit::HEART: return "红桃";
case Suit::CLUB: return "梅花";
case Suit::DIAMOND: return "方片";
default: return "";
}
}
string numberToString() const
{
switch (number)
{
case 1: return "A";
case 11: return "J";
case 12: return "Q";
case 13: return "K";
default: return to_string(number);
}
}
string colorToString() const
{
switch (color)
{
case CardColor::RED: return "红色";
case CardColor::BLACK: return "黑色";
default: return "无色";
}
}
virtual string toString() const
{
return suitToString() + numberToString() + " " + name;
}
};
class TrickCard : public Card
{
public:
enum TrickType
{
DISMANTLE, SNATCH, HARVEST, DUEL, BARBARIANS, ARROWS,
PEACH_GARDEN, GRAIN_FULL, NULLIFY, FIRE, ICE,
LE_BU_SI_SHU, SHAN_DIAN, BING_LIANG_CUN_DUAN
};
TrickCard(Suit s, int num, TrickType tt)
: Card(s, num, CardType::TRICK, trickTypeToString(tt)), trickType(tt) {}
TrickType getTrickType() const { return trickType; }
virtual bool use(Player* user, vector<Player*>& targets, GameState* state) override = 0;
bool canBeNullified() const { return true; }
static string trickTypeToString(TrickType tt)
{
switch (tt)
{
case DISMANTLE: return "过河拆桥";
case SNATCH: return "顺手牵羊";
case HARVEST: return "无中生有";
case DUEL: return "决斗";
case BARBARIANS: return "南蛮入侵";
case ARROWS: return "万箭齐发";
case PEACH_GARDEN: return "桃园结义";
case GRAIN_FULL: return "五谷丰登";
case NULLIFY: return "无懈可击";
case FIRE: return "火攻";
case ICE: return "铁索连环";
case LE_BU_SI_SHU: return "乐不思蜀";
case SHAN_DIAN: return "闪电";
case BING_LIANG_CUN_DUAN: return "兵粮寸断";
default: return "";
}
}
private:
TrickType trickType;
};
class DismantleCard : public TrickCard
{
public:
DismantleCard(Suit s, int num) : TrickCard(s, num, TrickCard::DISMANTLE) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class SnatchCard : public TrickCard
{
public:
SnatchCard(Suit s, int num) : TrickCard(s, num, TrickCard::SNATCH) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class BountifulHarvestCard : public TrickCard
{
public:
BountifulHarvestCard(Suit s, int num) : TrickCard(s, num, TrickCard::HARVEST) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class DuelCard : public TrickCard
{
public:
DuelCard(Suit s, int num) : TrickCard(s, num, TrickCard::DUEL) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class NanManCard : public TrickCard
{
public:
NanManCard(Suit s, int num) : TrickCard(s, num, TrickCard::BARBARIANS) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class WanJianCard : public TrickCard
{
public:
WanJianCard(Suit s, int num) : TrickCard(s, num, TrickCard::ARROWS) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class TaoYuanCard : public TrickCard
{
public:
TaoYuanCard(Suit s, int num) : TrickCard(s, num, TrickCard::PEACH_GARDEN) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class LeBuSiShuCard : public TrickCard
{
public:
LeBuSiShuCard(Suit s, int num) : TrickCard(s, num, TrickCard::LE_BU_SI_SHU) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class ShanDianCard : public TrickCard
{
public:
ShanDianCard(Suit s, int num) : TrickCard(s, num, TrickCard::SHAN_DIAN) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class BingLiangCunDuanCard : public TrickCard
{
public:
BingLiangCunDuanCard(Suit s, int num) : TrickCard(s, num, TrickCard::BING_LIANG_CUN_DUAN) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class EquipmentCard : public Card
{
public:
enum EquipmentType { WEAPON, ARMOR, OFF_MOUNT, DEF_MOUNT };
EquipmentCard(Suit s, int num, EquipmentType type, string name, int atkRange = 1, int extraAtk = 0, int extraHp = 0)
: Card(s, num, CardType::EQUIPMENT, name), equipType(type), attackRange(atkRange), extraAttack(extraAtk), extraMaxHp(extraHp) {}
virtual bool use(Player* user, vector<Player*>& targets, GameState* state) override;
EquipmentType getEquipType() const { return equipType; }
int getAttackRange() const { return attackRange; }
private:
EquipmentType equipType;
int attackRange;
int extraAttack;
int extraMaxHp;
};
class QingGangSword : public EquipmentCard
{
public:
QingGangSword(Suit s, int num) : EquipmentCard(s, num, WEAPON, "青釭剑", 2) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class ZhangBaSpear : public EquipmentCard
{
public:
ZhangBaSpear(Suit s, int num) : EquipmentCard(s, num, WEAPON, "丈八蛇矛", 3) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class QilinBow : public EquipmentCard
{
public:
QilinBow(Suit s, int num) : EquipmentCard(s, num, WEAPON, "麒麟弓", 5) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class BaGuaArmor : public EquipmentCard
{
public:
BaGuaArmor(Suit s, int num) : EquipmentCard(s, num, ARMOR, "八卦阵") {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class TengJiaArmor : public EquipmentCard
{
public:
TengJiaArmor(Suit s, int num) : EquipmentCard(s, num, ARMOR, "藤甲") {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class DaYuanHorse : public EquipmentCard
{
public:
DaYuanHorse(Suit s, int num) : EquipmentCard(s, num, OFF_MOUNT, "大宛") {}
};
class ChiTuHorse : public EquipmentCard
{
public:
ChiTuHorse(Suit s, int num) : EquipmentCard(s, num, DEF_MOUNT, "赤兔") {}
};
class HanBingJian : public EquipmentCard
{
public:
HanBingJian(Suit s, int num) : EquipmentCard(s, num, WEAPON, "寒冰剑", 2) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class ZhuGeLianNu : public EquipmentCard
{
public:
ZhuGeLianNu(Suit s, int num) : EquipmentCard(s, num, WEAPON, "诸葛连弩", 1) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class QingLongYanYueDao : public EquipmentCard
{
public:
QingLongYanYueDao(Suit s, int num) : EquipmentCard(s, num, WEAPON, "青龙偃月刀", 3) {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class RenWangDun : public EquipmentCard
{
public:
RenWangDun(Suit s, int num) : EquipmentCard(s, num, ARMOR, "仁王盾") {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class BaiYinShiZi : public EquipmentCard
{
public:
BaiYinShiZi(Suit s, int num) : EquipmentCard(s, num, ARMOR, "白银狮子") {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class JueYing : public EquipmentCard
{
public:
JueYing(Suit s, int num) : EquipmentCard(s, num, OFF_MOUNT, "绝影") {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class ZhaoYeYuShi : public EquipmentCard
{
public:
ZhaoYeYuShi(Suit s, int num) : EquipmentCard(s, num, DEF_MOUNT, "爪黄飞电") {}
bool use(Player* user, vector<Player*>& targets, GameState* state) override;
};
class Skill
{
public:
enum TriggerTiming { ON_TURN_START, ON_DAMAGE, ON_PLAY, ON_KILL, ON_JUDGEMENT };
Skill(const string& name, SkillType type) : name_(name), type_(type) {}
virtual ~Skill() = default;
virtual bool canActivate(Player* owner, GameState* state, TriggerTiming timing) = 0;
virtual bool execute(Player* owner, GameState* state) = 0;
const string& getName() const { return name_; }
protected:
string name_;
SkillType type_;
};
class JianXiongSkill : public Skill
{
public:
JianXiongSkill() : Skill("奸雄", SkillType::PASSIVE) {}
bool canActivate(Player* owner, GameState* state, TriggerTiming timing) override;
bool execute(Player* owner, GameState* state) override;
};
class RenDeSkill : public Skill
{
public:
RenDeSkill() : Skill("仁德", SkillType::ACTIVE) {}
bool canActivate(Player* owner, GameState* state, TriggerTiming timing) override;
bool execute(Player* owner, GameState* state) override;
};
class ZhiHengSkill : public Skill
{
public:
ZhiHengSkill() : Skill("制衡", SkillType::ACTIVE) {}
bool canActivate(Player* owner, GameState* state, TriggerTiming timing) override;
bool execute(Player* owner, GameState* state) override;
};
class LeiJiSkill : public Skill
{
public:
LeiJiSkill() : Skill("雷击", SkillType::TRIGGERED) {}
bool canActivate(Player* owner, GameState* state, TriggerTiming timing) override;
bool execute(Player* owner, GameState* state) override;
};
class WuShengSkill : public Skill
{
public:
WuShengSkill() : Skill("武圣", SkillType::ACTIVE) {}
bool canActivate(Player* owner, GameState* state, TriggerTiming timing) override;
bool execute(Player* owner, GameState* state) override;
};
class YiJiSkill : public Skill
{
public:
YiJiSkill() : Skill("遗计", SkillType::TRIGGERED) {}
bool canActivate(Player* owner, GameState* state, TriggerTiming timing) override;
bool execute(Player* owner, GameState* state) override;
};
class LianYinSkill : public Skill
{
public:
LianYinSkill() : Skill("联姻", SkillType::ACTIVE) {}
bool canActivate(Player* owner, GameState* state, TriggerTiming timing) override;
bool execute(Player* owner, GameState* state) override;
};
class LuanJiSkill : public Skill
{
public:
LuanJiSkill() : Skill("乱击", SkillType::ACTIVE) {}
bool canActivate(Player* owner, GameState* state, TriggerTiming timing) override;
bool execute(Player* owner, GameState* state) override;
};
class General
{
public:
General(const string& name, int maxHp, Kingdom kingdom) : name_(name), maxHp_(maxHp), kingdom_(kingdom) {}
void addSkill(Skill* skill) { skills_.push_back(skill); }
const vector<Skill*>& getSkills() const { return skills_; }
string getName() const { return name_; }
virtual ~General()
{
for (auto s : skills_) delete s;
}
private:
string name_;
int maxHp_;
Kingdom kingdom_;
vector<Skill*> skills_;
};
class CaoCao : public General
{
public:
CaoCao() : General("曹操", 4, Kingdom::WEI)
{
addSkill(new JianXiongSkill());
}
};
class LiuBei : public General
{
public:
LiuBei() : General("刘备", 4, Kingdom::SHU)
{
addSkill(new RenDeSkill());
}
};
class SunQuan : public General
{
public:
SunQuan() : General("孙权", 4, Kingdom::WU)
{
addSkill(new ZhiHengSkill());
}
};
class ZhangJiao : public General
{
public:
ZhangJiao() : General("张角", 3, Kingdom::QUN)
{
addSkill(new LeiJiSkill());
}
};
class GuanYu : public General
{
public:
GuanYu() : General("关羽", 4, Kingdom::SHU)
{
addSkill(new WuShengSkill());
}
};
class GuoJia : public General
{
public:
GuoJia() : General("郭嘉", 3, Kingdom::WEI)
{
addSkill(new YiJiSkill());
}
};
class SunShangXiang : public General
{
public:
SunShangXiang() : General("孙尚香", 3, Kingdom::WU)
{
addSkill(new LianYinSkill());
}
};
class YuanShao : public General
{
public:
YuanShao() : General("袁绍", 4, Kingdom::QUN)
{
addSkill(new LuanJiSkill());
}
};
class Player
{
public:
string name;
int health;
int maxHealth;
Kingdom kingdom;
Identity identity;
vector<shared_ptr<Card>> handCards;
map<EquipSlot, shared_ptr<Card>> equipment;
vector<shared_ptr<Card>> judgeArea;
bool isHuman;
bool isAlive;
int playerId;
bool hasUsedKillThisTurn;
General* general;
bool hasTakenDamageThisTurn;
bool isGeneralAssigned = false;
bool isDying = false;
bool isLegalDodgeScenario = false;
Player(string n, int hp, Kingdom k, bool human, int id = 0)
: name(n), health(hp), maxHealth(hp), kingdom(k), isHuman(human), isAlive(true), playerId(id), hasUsedKillThisTurn(false), general(nullptr), hasTakenDamageThisTurn(false) {}
void drawCards(vector<shared_ptr<Card>>& deck, int count)
{
if (deck.empty()) {
cout << "全局牌堆已耗尽,不再摸新牌,保留当前剩余手牌继续对局!" << endl;
return;
}
for (int i = 0; i < count && !deck.empty(); i++)
{
handCards.push_back(deck.back());
deck.pop_back();
}
}
void showHand() const
{
cout << "\n" << name << " (ID:" << playerId << ") 体力:" << health << "/" << maxHealth;
cout << " 手牌:" << handCards.size() << "张" << endl;
for (size_t i = 0; i < handCards.size(); i++)
{
cout << " [" << i + 1 << "] " << handCards[i]->toString() << endl;
}
}
bool hasCard(const string& cardName) const
{
for (auto& card : handCards)
{
if (card->getName() == cardName) return true;
}
return false;
}
int findCardIndex(const string& cardName) const
{
for (size_t i = 0; i < handCards.size(); i++)
{
if (handCards[i]->getName() == cardName) return (int)i;
}
return -1;
}
void removeCard(int index)
{
if (index >= 0 && index < (int)handCards.size())
{
handCards.erase(handCards.begin() + index);
}
}
int getHandCount() const { return (int)handCards.size(); }
int getEquipCount() const { return (int)equipment.size(); }
int getDistanceTo(Player* target) const
{
int baseDistance = 1;
if (target->equipment.count(EquipSlot::OFF_MOUNT)) baseDistance += 1;
if (this->equipment.count(EquipSlot::DEF_MOUNT)) baseDistance -= 1;
return max(1, baseDistance);
}
shared_ptr<Card> stealRandomCard()
{
if (handCards.empty()) return nullptr;
auto res = handCards[0];
handCards.erase(handCards.begin());
return res;
}
Player* chooseTarget(vector<Player*> targets)
{
if (targets.empty())
{
cout << "没有可选目标!" << endl;
return nullptr;
}
cout << "自动选中目标:" << targets[0]->name << endl;
return targets[0];
}
string getIdentityName() const
{
switch (identity)
{
case Identity::ZHU_GONG: return "主公";
case Identity::ZHONG_CHEN: return "忠臣";
case Identity::FAN_ZEI: return "反贼";
case Identity::NEI_JIAN: return "内奸";
default: return "未知身份";
}
}
};
bool EquipmentCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
if (equipType == EquipmentType::ARMOR)
{
auto oldEquipIter = user->equipment.find(EquipSlot::ARMOR);
if (oldEquipIter != user->equipment.end())
{
if (oldEquipIter->second->getName() == "白银狮子")
{
if (user->health < user->maxHealth)
{
user->health += 1;
cout << user->name << "失去白银狮子,回复1点体力!" << endl;
}
}
}
}
if (equipType == EquipmentType::WEAPON)
{
user->equipment[EquipSlot::WEAPON] = shared_from_this();
cout << user->name << " 装备了武器【" << getName() << "】,攻击距离变为" << attackRange << endl;
}
else if (equipType == EquipmentType::ARMOR)
{
user->equipment[EquipSlot::ARMOR] = shared_from_this();
cout << user->name << " 装备了防具【" << getName() << "】" << endl;
}
else if (equipType == EquipmentType::OFF_MOUNT)
{
user->equipment[EquipSlot::OFF_MOUNT] = shared_from_this();
cout << user->name << " 装备了+1马【" << getName() << "】,别人计算和你的距离+1" << endl;
}
else if (equipType == EquipmentType::DEF_MOUNT)
{
user->equipment[EquipSlot::DEF_MOUNT] = shared_from_this();
cout << user->name << " 装备了-1马【" << getName() << "】,你计算和别人的距离-1" << endl;
}
return true;
}
void showPlayerPublicInfo(Player* p, Player* currentViewer)
{
cout << p->name << " 当前体力:" << p->health << "/" << p->maxHealth << endl;
if (p->identity == Identity::ZHU_GONG)
{
cout << "公开身份:【主公】" << endl;
}
else if (p == currentViewer)
{
cout << "你的身份:【" << p->getIdentityName() << "】" << endl;
}
else
{
cout << "身份:【隐藏】" << endl;
}
}
void showEquip(Player* p)
{
cout << "【装备区】";
bool hasEquip = false;
if (p->equipment.count(EquipSlot::WEAPON))
{
cout << "武器:" << p->equipment[EquipSlot::WEAPON]->getName() << " ";
hasEquip = true;
}
if (p->equipment.count(EquipSlot::ARMOR))
{
cout << "防具:" << p->equipment[EquipSlot::ARMOR]->getName() << " ";
hasEquip = true;
}
if (p->equipment.count(EquipSlot::OFF_MOUNT))
{
cout << "+1马:" << p->equipment[EquipSlot::OFF_MOUNT]->getName() << " ";
hasEquip = true;
}
if (p->equipment.count(EquipSlot::DEF_MOUNT))
{
cout << "-1马:" << p->equipment[EquipSlot::DEF_MOUNT]->getName() << " ";
hasEquip = true;
}
if (!hasEquip) cout << "无";
cout << endl;
}
class GameState
{
vector<Player*> players;
vector<shared_ptr<Card>> cardPool;
int currentPlayerIndex;
bool gameOver;
public:
GameState() : currentPlayerIndex(0), gameOver(false) {}
void addPlayer(Player* p) { players.push_back(p); }
vector<Player*>& getPlayers() { return players; }
vector<shared_ptr<Card>>& getCardPool() { return cardPool; }
bool isGameOver() { return gameOver; }
void setGameOver(bool v) { gameOver = v; }
vector<Player*> getAliveEnemies(Player* self)
{
vector<Player*> res;
for (auto p : players)
{
if (p != self && p->isAlive) res.push_back(p);
}
return res;
}
Player* getNextAlivePlayer(Player* current)
{
for (size_t i = 0; i < players.size(); i++)
{
if (players[i] == current)
{
for (size_t j = i + 1; j < i + players.size(); j++)
{
if (players[j % players.size()]->isAlive)
{
return players[j % players.size()];
}
}
}
}
return nullptr;
}
bool isSameCamp(Player* a, Player* b)
{
if ((a->identity == Identity::ZHU_GONG || a->identity == Identity::ZHONG_CHEN) &&
(b->identity == Identity::ZHU_GONG || b->identity == Identity::ZHONG_CHEN))
return true;
if (a->identity == Identity::FAN_ZEI && b->identity == Identity::FAN_ZEI)
return true;
if (a->identity == Identity::NEI_JIAN || b->identity == Identity::NEI_JIAN)
return false;
return false;
}
Player* getGlobalLord()
{
for (auto p : players)
{
if (p->identity == Identity::ZHU_GONG && p->isAlive)
{
return p;
}
}
return nullptr;
}
Player* getAIPrimaryTarget(Player* aiSelf)
{
auto allAliveEnemies = getAliveEnemies(aiSelf);
Player* zhuGong = getGlobalLord();
switch (aiSelf->identity)
{
case Identity::ZHONG_CHEN:
for (auto p : allAliveEnemies)
if (p->identity == Identity::FAN_ZEI) return p;
for (auto p : allAliveEnemies)
if (p->identity == Identity::NEI_JIAN) return p;
return nullptr;
case Identity::FAN_ZEI:
if (zhuGong != nullptr && zhuGong->isAlive)
{
if (aiSelf->getDistanceTo(zhuGong) <= 2) return zhuGong;
}
for (auto p : allAliveEnemies)
if (p->identity == Identity::ZHONG_CHEN) return p;
if (allAliveEnemies.empty()) return nullptr;
else return allAliveEnemies[0];
case Identity::NEI_JIAN:
for (auto p : allAliveEnemies)
if (p->identity == Identity::FAN_ZEI) return p;
for (auto p : allAliveEnemies)
if (p->identity == Identity::ZHONG_CHEN) return p;
return zhuGong;
case Identity::ZHU_GONG:
for (auto p : allAliveEnemies)
if (p->identity == Identity::FAN_ZEI) return p;
for (auto p : allAliveEnemies)
if (p->identity == Identity::NEI_JIAN) return p;
if (allAliveEnemies.empty()) return nullptr;
else return allAliveEnemies[0];
default:
if (allAliveEnemies.empty()) return nullptr;
else return allAliveEnemies[0];
}
}
void handleDying(Player* dyingPlayer, int damageValue)
{
int remainingHpAfterDamage = dyingPlayer->health - damageValue;
int needPeachCount = 1 - remainingHpAfterDamage;
dyingPlayer->isDying = true;
cout << dyingPlayer->name << " 受到" << damageValue << "点伤害,进入濒死状态!当前剩余血量为" << remainingHpAfterDamage
<< ",需要累计使用" << needPeachCount << "个桃才能复活到1点体力,等待求桃结算..." << endl;
int maxPeachRound = 10;
while (needPeachCount > 0 && maxPeachRound-- > 0)
{
cout << "还需要" << needPeachCount << "个桃才能将体力恢复至1点..." << endl;
if (dyingPlayer->hasCard("酒"))
{
if (dyingPlayer->isHuman)
{
int op;
while(true)
{
cout << dyingPlayer->name << " 你处于濒死状态,是否使用【酒】恢复1点体力?1.是 0.否:";
cin >> op;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(op == 0 || op == 1) break;
cout << "只能输入1或0,请重新输入!\n";
}
if (op == 1)
{
int wineIdx = dyingPlayer->findCardIndex("酒");
dyingPlayer->removeCard(wineIdx);
remainingHpAfterDamage += 1;
needPeachCount -= 1;
cout << dyingPlayer->name << " 使用【酒】自救成功,当前体力回升至" << remainingHpAfterDamage << "!" << endl;
continue;
}
}
else
{
int wineIdx = dyingPlayer->findCardIndex("酒");
if (wineIdx != -1)
{
dyingPlayer->removeCard(wineIdx);
remainingHpAfterDamage += 1;
needPeachCount -= 1;
cout << dyingPlayer->name << " 使用【酒】自救成功,当前体力回升至" << remainingHpAfterDamage << "!" << endl;
continue;
}
}
}
bool hasPlayerUsePeach = false;
for (auto p : players)
{
if (p == dyingPlayer || !p->isAlive) continue;
if (p->hasCard("桃"))
{
if (p->isHuman)
{
int op;
cout << p->name << " 是否使用【桃】救濒死的" << dyingPlayer->name << ",帮其恢复1点体力?1.是 0.否:";
cin >> op;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if (op == 1)
{
int peachIdx = p->findCardIndex("桃");
p->removeCard(peachIdx);
remainingHpAfterDamage += 1;
needPeachCount -= 1;
hasPlayerUsePeach = true;
cout << p->name << " 使用【桃】救了" << dyingPlayer->name << ",对方当前体力回升至" << remainingHpAfterDamage << endl;
break;
}
}
else
{
if (isSameCamp(p, dyingPlayer))
{
int peachIdx = p->findCardIndex("桃");
p->removeCard(peachIdx);
remainingHpAfterDamage += 1;
needPeachCount -= 1;
hasPlayerUsePeach = true;
cout << p->name << " 使用【桃】救了" << dyingPlayer->name << ",对方当前体力回升至" << remainingHpAfterDamage << endl;
break;
}
}
}
}
if (!hasPlayerUsePeach) break;
}
if (needPeachCount <= 0)
{
dyingPlayer->health = 1;
dyingPlayer->isDying = false;
cout << dyingPlayer->name << " 凑够了足够的桃,成功复活,当前体力为1!" << endl;
return;
}
dyingPlayer->isDying = false;
dyingPlayer->isAlive = false;
dyingPlayer->health = 0;
cout << dyingPlayer->name << " 凑不够足够的桃复活,正式阵亡!" << endl;
}
};
bool LeiJiSkill::canActivate(Player* owner, GameState* state, TriggerTiming timing)
{
return timing == Skill::ON_KILL && owner->hasCard("闪") && owner->isAlive;
}
bool DismantleCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
if (targets.empty()) return false;
Player* target = targets[0];
if (!target->isAlive) return false;
if (target->getHandCount() == 0 && target->getEquipCount() == 0 && target->judgeArea.empty())
{
cout << target->name << " 没有可弃置的牌!" << endl;
return false;
}
cout << user->name << " 对 " << target->name << " 使用【过河拆桥】!" << endl;
if (target->getHandCount() > 0)
{
target->removeCard(0);
cout << "弃置了" << target->name << "的一张手牌!" << endl;
}
else if (target->getEquipCount() > 0)
{
auto firstEquip = target->equipment.begin();
target->equipment.erase(firstEquip);
cout << "弃置了" << target->name << "的一张装备牌!" << endl;
}
else if (!target->judgeArea.empty())
{
target->judgeArea.erase(target->judgeArea.begin());
cout << "弃置了" << target->name << "判定区的延时锦囊!" << endl;
}
return true;
}
bool SnatchCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
if (targets.empty()) return false;
Player* target = targets[0];
if (!target->isAlive) return false;
if (user->getDistanceTo(target) > 1)
{
cout << "距离大于1,无法使用【顺手牵羊】!" << endl;
return false;
}
cout << user->name << " 对 " << target->name << " 使用【顺手牵羊】!" << endl;
if (target->handCards.empty())
{
cout << target->name << "没有剩余手牌可以牵走!" << endl;
return false;
}
auto stolenCardIter = target->handCards.begin();
auto stolenCard = std::move(*stolenCardIter);
target->handCards.erase(stolenCardIter);
user->handCards.push_back(stolenCard);
cout << "获得了" << target->name << "的一张卡牌【" << stolenCard->getName() << "】!" << endl;
return true;
}
bool BountifulHarvestCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
cout << user->name << " 使用【无中生有】,摸两张牌!" << endl;
user->drawCards(state->getCardPool(), 2);
return true;
}
bool DuelCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
if (targets.empty()) return false;
Player* target = targets[0];
if (!target->isAlive) return false;
cout << user->name << " 向 " << target->name << " 发起【决斗】!" << endl;
Player* current = target;
while (true)
{
if (!current->hasCard("杀"))
{
cout << current->name << " 在【决斗】中没有出【杀】,结算来自决斗的1点格斗伤害!" << endl;
current->health -= 1;
current->hasTakenDamageThisTurn = true;
if (current->health <= 0)
{
cout << current->name << " 受到【决斗】1点伤害后血量归零,进入濒死求桃结算环节!" << endl;
state->handleDying(current, 1);
}
cout << current->name << " 【决斗】伤害结算完成,当前剩余体力:" << current->health << endl;
break;
}
current->removeCard(current->findCardIndex("杀"));
cout << current->name << " 打出了一张【杀】!" << endl;
current = (current == target) ? user : target;
}
return true;
}
bool NanManCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
cout << user->name << " 使用【南蛮入侵】!所有其他角色需出【杀】!" << endl;
for (auto p : state->getPlayers())
{
if (p != user && p->isAlive)
{
cout << "开始结算【南蛮入侵】对" << p->name << "的伤害判定:" << endl;
if (!p->hasCard("杀"))
{
p->health--;
p->hasTakenDamageThisTurn = true;
cout << p->name << " 手牌中没有【杀】,结算来自【南蛮入侵】的1点基础伤害!" << endl;
if (p->health <= 0)
{
p->health = 0;
cout << p->name << " 受到【南蛮入侵】1点伤害后血量归零,进入濒死求桃结算环节!" << endl;
state->handleDying(p, 1);
}
cout << p->name << " 【南蛮入侵】伤害结算完成,当前剩余体力:" << p->health << endl;
}
else
{
p->removeCard(p->findCardIndex("杀"));
cout << p->name << " 打出了【杀】完全抵消南蛮入侵伤害!【南蛮入侵】伤害结算结束。" << endl;
}
}
}
return true;
}
bool WanJianCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
cout << user->name << " 使用【万箭齐发】!所有其他角色需出【闪】!" << endl;
for (auto p : state->getPlayers())
{
if (p != user && p->isAlive)
{
cout << "开始结算【万箭齐发】对" << p->name << "的伤害判定:" << endl;
if (!p->hasCard("闪"))
{
p->health--;
p->hasTakenDamageThisTurn = true;
cout << p->name << " 手牌中没有【闪】,结算来自【万箭齐发】的1点万箭属性伤害!" << endl;
if (p->health <= 0)
{
p->health = 0;
cout << p->name << " 受到【万箭齐发】1点伤害后血量归零,进入濒死求桃结算环节!" << endl;
state->handleDying(p, 1);
}
cout << p->name << " 【万箭齐发】伤害结算完成,当前剩余体力:" << p->health << endl;
}
else {
p->isLegalDodgeScenario = true;
p->removeCard(p->findCardIndex("闪"));
cout << p->name << " 打出了【闪】完全抵消万箭齐发伤害!【万箭齐发】伤害结算结束。" << endl;
if (p->general != nullptr && p->general->getName() == "张角") {
for (auto& skill : p->general->getSkills()) {
if (skill->getName() == "雷击" && skill->canActivate(p, state, Skill::ON_KILL)) {
cout << p->name << " 打出闪响应万箭齐发,触发雷击技能结算流程!" << endl;
skill->execute(p, state);
}
}
}
p->isLegalDodgeScenario = false;
}
}
}
return true;
}
bool TaoYuanCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
cout << user->name << " 使用【桃园结义】!所有角色恢复1点体力!" << endl;
for (auto p : state->getPlayers())
{
if (p->isAlive && p->health < p->maxHealth)
{
p->health++;
cout << p->name << " 回复1点体力,当前体力:" << p->health << endl;
}
}
return true;
}
bool LeBuSiShuCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
if (targets.empty()) return false;
Player* target = targets[0];
if (!target->isAlive) return false;
cout << user->name << " 对 " << target->name << " 使用【乐不思蜀】!" << endl;
target->judgeArea.push_back(shared_from_this());
cout << "【乐不思蜀】已置入" << target->name << "的判定区,下回合开始需先进行红桃判定:" << endl;
cout << " 若判定结果为红桃,则乐不思蜀生效失败,目标可正常出牌" << endl;
cout << " 若判定结果不为红桃,则目标直接跳过出牌阶段" << endl;
return true;
}
bool ShanDianCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
cout << user->name << " 使用【闪电】!" << endl;
user->judgeArea.push_back(shared_from_this());
cout << "【闪电】已置入" << user->name << "的判定区,回合开始时自动判定:" << endl;
cout << " 若判定结果为黑桃2-9,目标立即受到3点雷电伤害" << endl;
cout << " 若判定结果不为黑桃2-9,闪电自动传递到下家的判定区" << endl;
return true;
}
bool BingLiangCunDuanCard::use(Player* user, vector<Player*>& targets, GameState* state)
{
if (targets.empty()) return false;
Player* target = targets[0];
if (!target->isAlive) return false;
cout << user->name << " 对 " << target->name << " 使用【兵粮寸断】!" << endl;
target->judgeArea.push_back(shared_from_this());
cout << "【兵粮寸断】已置入" << target->name << "的判定区,下回合开始需先进行梅花判定:" << endl;
cout << " 若判定结果为梅花,则兵粮寸断生效失败,目标可正常摸牌" << endl;
cout << " 若判定结果不为梅花,则目标直接跳过摸牌阶段" << endl;
return true;
}
bool JianXiongSkill::canActivate(Player* owner, GameState* state, TriggerTiming timing)
{
return timing == Skill::ON_DAMAGE && owner->hasTakenDamageThisTurn;
}
bool JianXiongSkill::execute(Player* owner, GameState* state)
{
cout << owner->name << " 触发【奸雄】,获得造成本次伤害的卡牌!" << endl;
if (!state->getCardPool().empty())
{
owner->handCards.push_back(state->getCardPool().back());
state->getCardPool().pop_back();
}
return true;
}
bool RenDeSkill::canActivate(Player* owner, GameState* state, TriggerTiming timing)
{
return timing == Skill::ON_PLAY && owner->getHandCount() >= 2 && owner->health < owner->maxHealth;
}
bool RenDeSkill::execute(Player* owner, GameState* state)
{
cout << owner->name << " 发动【仁德】,交出2张手牌,回复1点体力!" << endl;
if(owner->getHandCount() >= 2)
{
owner->removeCard(0);
owner->removeCard(0);
owner->health++;
}
return true;
}
bool ZhiHengSkill::canActivate(Player* owner, GameState* state, TriggerTiming timing)
{
return timing == Skill::ON_PLAY && owner->getHandCount() >= 1;
}
bool ZhiHengSkill::execute(Player* owner, GameState* state)
{
if(owner->getHandCount() == 0)
{
cout << "当前无手牌,无法发动制衡!" << endl;
return false;
}
cout << owner->name << " 发动【制衡】,请选择你想要弃置的任意数量手牌,弃置几张就摸几张新牌!" << endl;
owner->showHand();
int discardTotalCount = 0;
while(true)
{
cout << "请输入你想要弃置的手牌总数量(1-" << owner->getHandCount() << "):";
cin >> discardTotalCount;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(discardTotalCount >= 1 && discardTotalCount <= owner->getHandCount()) break;
cout << "输入数量超出当前手牌范围,请重新输入合法值!\n";
}
vector<int> discardIndexList;
for(int selectRound = 1; selectRound <= discardTotalCount; selectRound++)
{
int selectIndex = -1;
while(true)
{
cout << "第" << selectRound << "张弃置,输入当前要弃置的手牌编号:";
cin >> selectIndex;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
int realIndex = selectIndex - 1;
if(realIndex >= 0 && realIndex < owner->getHandCount())
{
bool isDuplicate = false;
for(auto idx : discardIndexList)
{
if(idx == realIndex)
{
isDuplicate = true;
break;
}
}
if(!isDuplicate)
{
discardIndexList.push_back(realIndex);
break;
}
else
{
cout << "该手牌已经被选中弃置,请选择其他未选择的手牌!\n";
}
}
else
{
cout << "输入的手牌编号超出范围,请重新输入合法编号!\n";
}
}
}
sort(discardIndexList.begin(), discardIndexList.end(), [](int a, int b) { return a > b; });
for(auto idx : discardIndexList)
{
owner->removeCard(idx);
}
cout << "你已经成功弃置" << discardTotalCount << "张手牌,现在摸取等量的新牌!" << endl;
owner->drawCards(state->getCardPool(), discardTotalCount);
cout << "制衡结算完成,你当前手牌为:" << endl;
owner->showHand();
return true;
}
bool LeiJiSkill::execute(Player* owner, GameState* state)
{
cout << owner->name << " 触发【雷击】!指定一名其他角色进行判定" << endl;
auto enemies = state->getAliveEnemies(owner);
if (enemies.empty()) return false;
Player* target = enemies[rand() % enemies.size()];
cout << owner->name << " 对 " << target->name << " 发动雷击,目标开始进行判定..." << endl;
Suit judgeSuit = (Suit)(rand() % 4);
int judgePoint = rand() % 13 + 1;
switch (judgeSuit)
{
case Suit::SPADE: cout << "雷击判定结果:黑桃" << judgePoint << endl; break;
case Suit::HEART: cout << "雷击判定结果:红桃" << judgePoint << endl; break;
case Suit::CLUB: cout << "雷击判定结果:梅花" << judgePoint << endl; break;
case Suit::DIAMOND: cout << "雷击判定结果:方片" << judgePoint << endl; break;
}
if (judgeSuit == Suit::SPADE)
{
cout << target->name << " 判定命中黑桃,结算来自【雷击】的2点雷电属性伤害!" << endl;
target->health -= 2;
target->hasTakenDamageThisTurn = true;
if (target->health <= 0)
{
cout << target->name << " 受到【雷击】2点雷电伤害后血量归零,进入濒死求桃结算环节!" << endl;
state->handleDying(target, 2);
}
cout << target->name << " 【雷击】伤害结算完成,当前剩余体力:" << target->health << endl;
}
else
{
cout << target->name << " 判定不为黑桃,雷击未造成任何伤害,本次雷击结算结束。" << endl;
}
return true;
}
bool WuShengSkill::canActivate(Player* owner, GameState* state, TriggerTiming timing)
{
return timing == Skill::ON_PLAY && owner->getHandCount() >= 1;
}
bool WuShengSkill::execute(Player* owner, GameState* state)
{
cout << owner->name << " 发动【武圣】,将一张红色手牌转换为【杀】使用!" << endl;
bool hasUnconvertedRedCard = false;
for (int i = 0; i < owner->getHandCount(); i++)
{
if (owner->handCards[i]->getColor() == CardColor::RED && owner->handCards[i]->getName() != "杀")
{
hasUnconvertedRedCard = true;
owner->handCards[i] = make_shared<Card>(
owner->handCards[i]->getSuit(),
owner->handCards[i]->getNumber(),
CardType::BASIC,
"杀"
);
break;
}
}
if (!hasUnconvertedRedCard)
{
cout << owner->name << " 手牌中没有可转换的非杀红色牌,武圣自动终止不会重复触发!" << endl;
return false;
}
return true;
}
bool YiJiSkill::canActivate(Player* owner, GameState* state, TriggerTiming timing)
{
return timing == Skill::ON_DAMAGE && owner->hasTakenDamageThisTurn;
}
bool YiJiSkill::execute(Player* owner, GameState* state)
{
cout << owner->name << " 触发【遗计】,受到伤害后摸2张牌,可以分配给存活队友!" << endl;
owner->drawCards(state->getCardPool(), 2);
auto players = state->getPlayers();
int distributeCount = 0;
for (auto p : players)
{
if (p != owner && p->isAlive && p->getHandCount() < 10)
{
p->handCards.push_back(owner->handCards.back());
owner->handCards.pop_back();
cout << owner->name << " 分配了1张遗计牌给" << p->name << endl;
distributeCount++;
if(distributeCount >= 2) break;
}
}
return true;
}
bool LianYinSkill::canActivate(Player* owner, GameState* state, TriggerTiming timing)
{
return timing == Skill::ON_PLAY && owner->getEquipCount() >= 1 && owner->health < owner->maxHealth;
}
bool LianYinSkill::execute(Player* owner, GameState* state)
{
int equipCount = owner->getEquipCount();
cout << owner->name << " 发动【联姻】,弃置所有" << equipCount << "张装备牌,回复等量体力!" << endl;
owner->equipment.clear();
for (int i = 0; i < equipCount; i++)
{
if (owner->health < owner->maxHealth) owner->health++;
}
return true;
}
bool LuanJiSkill::canActivate(Player* owner, GameState* state, TriggerTiming timing)
{
return timing == Skill::ON_PLAY && owner->getHandCount() >= 2;
}
bool LuanJiSkill::execute(Player* owner, GameState* state)
{
if(!owner->isHuman)
{
cout << owner->name << " 自动发动【乱击】,将两张手牌当作【万箭齐发】打出!" << endl;
owner->removeCard(0);
owner->removeCard(0);
}
else
{
cout << owner->name << " 发动【乱击】,请选择两张手牌当作【万箭齐发】打出!" << endl;
owner->showHand();
int idx1, idx2;
while(true)
{
cout << "输入第一张手牌编号:";
cin >> idx1;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(idx1 >= 1 && idx1 <= owner->getHandCount()) break;
cout << "编号非法,重新输入第一张!\n";
}
while(true)
{
cout << "输入第二张手牌编号:";
cin >> idx2;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(idx2 >= 1 && idx2 <= owner->getHandCount()) break;
cout << "编号非法,重新输入第二张!\n";
}
int i1 = idx1 - 1;
int i2 = idx2 - 1;
while (i1 == i2 || i1 < 0 || i2 < 0 || i1 >= owner->getHandCount() || i2 >= owner->getHandCount())
{
cout << "两张手牌不能为同一张,请重新输入第二张手牌编号:";
cin >> idx2;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
i2 = idx2 - 1;
}
if (i2 > i1)
owner->removeCard(i2);
owner->removeCard(i1);
}
cout << "弃置两张手牌,发动乱击转换万箭齐发!" << endl;
for (auto p : state->getPlayers())
{
if (p != owner && p->isAlive)
{
p->isLegalDodgeScenario = true;
cout << "开始结算【乱击】转换万箭对" << p->name << "的伤害判定:" << endl;
if (!p->hasCard("闪"))
{
p->health--;
p->hasTakenDamageThisTurn = true;
cout << p->name << " 没有出【闪】,结算来自袁绍【乱击】转换万箭的1点万箭属性伤害!" << endl;
if (p->health <= 0)
{
p->health = 0;
cout << p->name << " 受到【乱击】1点伤害后血量归零,进入濒死求桃结算环节!" << endl;
state->handleDying(p, 1);
}
cout << p->name << " 【乱击】伤害结算完成,当前剩余体力:" << p->health << endl;
}
else
{
p->removeCard(p->findCardIndex("闪"));
cout << p->name << " 打出了【闪】完全抵消袁绍乱击的万箭伤害,乱击伤害结算结束。" << endl;
}
}
}
return true;
}
bool QingGangSword::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "青釭剑特效激活:你使用【杀】时无视目标的防具效果" << endl;
return true;
}
bool ZhangBaSpear::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "丈八蛇矛特效激活:你可以将任意两张手牌拼接当作【杀】使用" << endl;
return true;
}
bool QilinBow::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "麒麟弓特效激活:你使用【杀】造成伤害后,弃置目标所有坐骑牌" << endl;
return true;
}
bool BaGuaArmor::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "八卦阵特效激活:当你需要使用【闪】时进行判定,红牌则视为成功出闪" << endl;
return true;
}
bool TengJiaArmor::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "藤甲特效激活:无视普通杀和普通锦囊伤害,受到火焰伤害时伤害+1" << endl;
return true;
}
bool HanBingJian::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "【寒冰剑】生效:你使用【杀】造成伤害时,可弃置目标2张手牌代替伤害" << endl;
return true;
}
bool ZhuGeLianNu::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "【诸葛连弩】生效:你出【杀】无次数限制" << endl;
return true;
}
bool QingLongYanYueDao::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "【青龙偃月刀】生效:你使用的【杀】被【闪】抵消后,可继续对同一目标出【杀】" << endl;
return true;
}
bool RenWangDun::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "【仁王盾】生效:黑色的【杀】对你无效" << endl;
return true;
}
bool BaiYinShiZi::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "【白银狮子】生效:你受到的伤害最多为1点;失去该装备时回复1点体力" << endl;
return true;
}
bool JueYing::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "【绝影】生效:其他角色计算与你的距离+1" << endl;
return true;
}
bool ZhaoYeYuShi::use(Player* user, vector<Player*>& targets, GameState* state)
{
EquipmentCard::use(user, targets, state);
cout << "【爪黄飞电】生效:你计算与其他角色的距离-1" << endl;
return true;
}
int main()
{
srand(time(nullptr));
Player user("玩家", 4, Kingdom::SHU, true, 0);
Player ai1("AI", 4, Kingdom::WEI, false, 1);
Player ai2("AI", 4, Kingdom::WU, false, 2);
Player ai3("AI", 4, Kingdom::QUN, false, 3);
GameState globalGame;
globalGame.addPlayer(&user);
globalGame.addPlayer(&ai1);
globalGame.addPlayer(&ai2);
globalGame.addPlayer(&ai3);
int gameModeChoice;
cout << "\n========== 游戏模式选择 ==========" << endl;
cout << "1. 正常局模式:4名玩家自由对战,无身份限制,最先决出最后存活者即为胜利" << endl;
cout << "2. 身份局模式:分配主公/忠臣/反贼/内奸4种专属身份,按照三国杀官方身份规则判定胜负" << endl;
while(true)
{
cout << "请选择游戏模式编号:";
cin >> gameModeChoice;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(gameModeChoice == 1 || gameModeChoice == 2) break;
cout << "输入非法,仅能输入1或2,请重新输入!\n";
}
int currentGameMode = gameModeChoice;
auto& players = globalGame.getPlayers();
vector<pair<string, shared_ptr<General>>> allAvailableGenerals = {
{"刘备", make_shared<LiuBei>()},
{"曹操", make_shared<CaoCao>()},
{"孙权", make_shared<SunQuan>()},
{"张角", make_shared<ZhangJiao>()},
{"关羽", make_shared<GuanYu>()},
{"郭嘉", make_shared<GuoJia>()},
{"孙尚香", make_shared<SunShangXiang>()},
{"袁绍", make_shared<YuanShao>()}
};
if (currentGameMode == 2)
{
cout << "\n========== 身份分配完成 ==========" << endl;
vector<Identity> identityPool = {Identity::ZHU_GONG, Identity::ZHONG_CHEN, Identity::FAN_ZEI, Identity::NEI_JIAN};
shuffle(identityPool.begin(), identityPool.end(), mt19937(rand()));
auto iterIdentity = identityPool.begin();
for (auto& p : globalGame.getPlayers())
p->identity = *iterIdentity++;
for (auto& p : players)
{
if (p->identity == Identity::ZHU_GONG)
{
p->maxHealth = 5;
p->health = 5;
if (p->isHuman)
cout << "恭喜你抽中【主公】身份!体力上限提升至5点,全场身份明牌公开" << endl;
else
cout << "本局主公是【" << p->name << "】,主公身份全场公开,体力上限提升至5点" << endl;
}
if (p->isHuman && p->identity != Identity::ZHU_GONG)
cout << "\n你的身份是:【" << p->getIdentityName() << "】,该身份仅你自己可见,其他玩家无法获知" << endl;
}
}
Player* zhuGongPointer = nullptr;
for (auto& p : players)
{
if (p->identity == Identity::ZHU_GONG && p->isAlive)
{
zhuGongPointer = p;
break;
}
}
cout << "\n身份局主公选将环节开启,主公将优先挑选出战武将:" << endl;
shared_ptr<General> selectedGeneral;
if (zhuGongPointer->isHuman)
{
cout << "作为主公的你拥有优先选将权限!" << endl;
cout << "\n========== 武将选择 ==========" << endl;
for (size_t i = 0; i < allAvailableGenerals.size(); i++)
{
cout << i + 1 << ". " << allAvailableGenerals[i].first << endl;
auto& generals = allAvailableGenerals[i].second;
cout << " 武将技能:";
for (auto& skill : generals->getSkills())
cout << skill->getName() << " ";
cout << endl;
}
int selectGeneralId;
while (true)
{
cout << "输入武将编号:";
cin >> selectGeneralId;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if (selectGeneralId >= 1 && selectGeneralId <= (int)allAvailableGenerals.size()) break;
cout << "输入无效,请重新输入合法编号!\n";
}
selectedGeneral = allAvailableGenerals[selectGeneralId - 1].second;
user.general = selectedGeneral.get();
user.name = "玩家" + selectedGeneral->getName();
cout << "主公【你】已成功选择【" << selectedGeneral->getName() << "】作为你的出战武将!" << endl;
vector<int> remainingIndex;
for (size_t i = 0; i < allAvailableGenerals.size(); i++)
{
if (i != (size_t)(selectGeneralId - 1))
remainingIndex.push_back((int)i);
}
vector<int> filteredIndex;
for (auto idx : remainingIndex)
{
if (idx >= 0 && idx < (int)allAvailableGenerals.size())
filteredIndex.push_back(idx);
}
remainingIndex.swap(filteredIndex);
if (remainingIndex.size() < 3)
{
cout << "剩余武将数量不足,自动补全可用武将池" << endl;
for (size_t fillIdx = remainingIndex.size(); fillIdx < 3; fillIdx++)
remainingIndex.push_back(0);
}
for (auto& p : players)
{
if (p == zhuGongPointer || !p->isHuman) continue;
cout << "\n========== 非主公玩家自由选将 ==========" << endl;
cout << "当前你身份为【" << p->getIdentityName() << "】,可以从剩余可选武将里自由挑选出战武将" << endl;
vector<pair<string, shared_ptr<General>>> remainGeneralPool;
for (auto idx : remainingIndex)
remainGeneralPool.emplace_back(allAvailableGenerals[idx].first, allAvailableGenerals[idx].second);
for (size_t i = 0; i < remainGeneralPool.size(); i++)
{
cout << i + 1 << ". " << remainGeneralPool[i].first << endl;
auto& generals = remainGeneralPool[i].second;
cout << " 武将技能:";
for (auto& skill : generals->getSkills())
cout << skill->getName() << " ";
cout << endl;
}
int selectNonLordGeneralId;
while (true)
{
cout << "输入你想要使用的武将编号:";
cin >> selectNonLordGeneralId;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if (selectNonLordGeneralId >= 1 && selectNonLordGeneralId <= (int)remainGeneralPool.size()) break;
cout << "输入无效,请重新选择合法编号!\n";
}
auto selectedNonLordGeneral = remainGeneralPool[selectNonLordGeneralId - 1].second;
p->general = selectedNonLordGeneral.get();
p->name = "玩家" + selectedNonLordGeneral->getName();
cout << "你成功选择【" << selectedNonLordGeneral->getName() << "】作为出战武将!" << endl;
int removedIdx = remainingIndex[selectNonLordGeneralId - 1];
remainingIndex.erase(remove(remainingIndex.begin(), remainingIndex.end(), removedIdx), remainingIndex.end());
break;
}
shuffle(remainingIndex.begin(), remainingIndex.end(), mt19937(rand()));
if (remainingIndex.size() < 1) remainingIndex.push_back(0);
if (remainingIndex.size() < 2) remainingIndex.push_back(0);
if (remainingIndex.size() < 3) remainingIndex.push_back(0);
if (remainingIndex.size() >= 1)
{
int ai1Index = remainingIndex[0];
ai1.general = allAvailableGenerals[ai1Index].second.get();
ai1.name = "AI" + allAvailableGenerals[ai1Index].second->getName();
}
if (remainingIndex.size() >= 2)
{
int ai2Index = remainingIndex[1];
ai2.general = allAvailableGenerals[ai2Index].second.get();
ai2.name = "AI" + allAvailableGenerals[ai2Index].second->getName();
}
if (remainingIndex.size() >= 3)
{
int ai3Index = remainingIndex[2];
ai3.general = allAvailableGenerals[ai3Index].second.get();
ai3.name = "AI" + allAvailableGenerals[ai3Index].second->getName();
}
}
else
{
cout << "本局主公是AI玩家" << zhuGongPointer->name << ",由AI主公优先随机选择出战武将" << endl;
int aiLordSelect = rand() % allAvailableGenerals.size();
auto aiLordGeneral = allAvailableGenerals[aiLordSelect].second;
zhuGongPointer->general = aiLordGeneral.get();
zhuGongPointer->name = "AI主公" + aiLordGeneral->getName();
zhuGongPointer->isGeneralAssigned = true;
cout << "AI主公优先选择了【" << aiLordGeneral->getName() << "】作为自己的出战武将!" << endl;
vector<int> remainingIndex;
for (size_t i = 0; i < allAvailableGenerals.size(); i++)
{
if (i != aiLordSelect)
remainingIndex.push_back(i);
}
vector<int> filteredIndex;
for (auto idx : remainingIndex)
{
if (idx >= 0 && idx < (int)allAvailableGenerals.size())
filteredIndex.push_back(idx);
}
remainingIndex.swap(filteredIndex);
if (remainingIndex.size() < 3)
{
cout << "剩余武将数量不足,自动补全可用武将池" << endl;
for (size_t fillIdx = remainingIndex.size(); fillIdx < 3; fillIdx++)
remainingIndex.push_back(0);
}
shuffle(remainingIndex.begin(), remainingIndex.end(), mt19937(rand()));
int remainingGeneralIndex = 0;
for (auto& p : players)
{
if (p == zhuGongPointer || p->isGeneralAssigned || !p->isHuman) continue;
cout << "\n========== 非主公玩家自由选将 ==========" << endl;
cout << "当前你身份为【" << p->getIdentityName() << "】,可以从剩余可选武将里自由挑选出战武将" << endl;
vector<pair<string, shared_ptr<General>>> remainGeneralPool;
for (auto idx : remainingIndex)
remainGeneralPool.emplace_back(allAvailableGenerals[idx].first, allAvailableGenerals[idx].second);
for (size_t i = 0; i < remainGeneralPool.size(); i++)
{
cout << i + 1 << ". " << remainGeneralPool[i].first << endl;
auto& generals = remainGeneralPool[i].second;
cout << " 武将技能:";
for (auto& skill : generals->getSkills())
cout << skill->getName() << " ";
cout << endl;
}
int selectNonLordGeneralId;
while (true)
{
cout << "输入你想要使用的武将编号:";
cin >> selectNonLordGeneralId;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if (selectNonLordGeneralId >= 1 && selectNonLordGeneralId <= (int)remainGeneralPool.size()) break;
cout << "输入无效,请重新选择合法编号!" << endl;
}
auto selectedNonLordGeneral = remainGeneralPool[selectNonLordGeneralId - 1].second;
p->general = selectedNonLordGeneral.get();
p->name = "玩家" + selectedNonLordGeneral->getName();
cout << "你成功选择【" << selectedNonLordGeneral->getName() << "】作为出战武将!" << endl;
int removedIdx = remainingIndex[selectNonLordGeneralId - 1];
remainingIndex.erase(remove(remainingIndex.begin(), remainingIndex.end(), removedIdx), remainingIndex.end());
break;
}
int aiAssignCount = 0;
for (auto& p : players)
{
if (p == zhuGongPointer || p->isHuman || p->isGeneralAssigned) continue;
if (aiAssignCount >= 3) break;
int currentIdx = remainingIndex[aiAssignCount];
p->general = allAvailableGenerals[currentIdx].second.get();
p->name = "AI" + allAvailableGenerals[currentIdx].second->getName();
p->isGeneralAssigned = true;
aiAssignCount++;
cout << p->name << " 随机选择了【" << allAvailableGenerals[currentIdx].second->getName() << "】作为出战武将!" << endl;
}
}
cout << "\n========== 最终对战阵容 ==========" << endl;
cout << "玩家方武将:" << (user.general ? user.name : "未分配武将") << endl;
cout << "AI对战武将1:" << (ai1.general ? ai1.name : "未分配武将") << endl;
cout << "AI对战武将2:" << (ai2.general ? ai2.name : "未分配武将") << endl;
cout << "AI对战武将3:" << (ai3.general ? ai3.name : "未分配武将") << endl;
cout << "所有武将加载完成,即将进入游戏!" << endl;
for(auto& p : players)
{
p->isGeneralAssigned = false;
}
for(auto& p : players)
{
if(p->general == nullptr)
{
p->general = new LiuBei();
p->name = "默认武将" + p->name;
p->isGeneralAssigned = true;
}
}
auto& deck = globalGame.getCardPool();
for(int i = 0; i < 15; i++)
{
deck.push_back(make_shared<Card>(Suit::SPADE, (i % 13) + 1, CardType::BASIC, "杀"));
}
for(int i = 0; i < 12; i++)
{
deck.push_back(make_shared<Card>(Suit::HEART, (i % 13) + 1, CardType::BASIC, "闪"));
}
for(int i = 0; i < 8; i++)
{
deck.push_back(make_shared<Card>(Suit::DIAMOND, (i % 13) + 1, CardType::BASIC, "桃"));
}
for(int i = 0; i < 8; i++) deck.push_back(make_shared<DismantleCard>(Suit::SPADE, (i%13)+1));
for(int i = 0; i < 5; i++) deck.push_back(make_shared<SnatchCard>(Suit::SPADE, (i%13)+1));
for(int i = 0; i < 4; i++) deck.push_back(make_shared<BountifulHarvestCard>(Suit::HEART, (i%13)+1));
deck.push_back(make_shared<DuelCard>(Suit::SPADE, 1));
deck.push_back(make_shared<NanManCard>(Suit::SPADE, 7));
deck.push_back(make_shared<WanJianCard>(Suit::HEART, 1));
deck.push_back(make_shared<TaoYuanCard>(Suit::HEART, 1));
deck.push_back(make_shared<LeBuSiShuCard>(Suit::HEART, 6));
deck.push_back(make_shared<ShanDianCard>(Suit::SPADE, 12));
deck.push_back(make_shared<BingLiangCunDuanCard>(Suit::CLUB, 4));
deck.push_back(make_shared<QingGangSword>(Suit::SPADE, 6));
deck.push_back(make_shared<ZhangBaSpear>(Suit::SPADE, 12));
deck.push_back(make_shared<QilinBow>(Suit::HEART, 5));
deck.push_back(make_shared<BaGuaArmor>(Suit::SPADE, 2));
deck.push_back(make_shared<TengJiaArmor>(Suit::CLUB, 2));
deck.push_back(make_shared<DaYuanHorse>(Suit::HEART, 13));
deck.push_back(make_shared<ChiTuHorse>(Suit::DIAMOND, 5));
deck.push_back(make_shared<HanBingJian>(Suit::SPADE, 6));
deck.push_back(make_shared<ZhuGeLianNu>(Suit::DIAMOND, 1));
deck.push_back(make_shared<QingLongYanYueDao>(Suit::CLUB, 5));
deck.push_back(make_shared<RenWangDun>(Suit::CLUB, 2));
deck.push_back(make_shared<BaiYinShiZi>(Suit::DIAMOND, 10));
deck.push_back(make_shared<JueYing>(Suit::CLUB, 13));
deck.push_back(make_shared<ZhaoYeYuShi>(Suit::DIAMOND, 1));
shuffle(deck.begin(), deck.end(), mt19937(rand()));
for(auto& player : globalGame.getPlayers())
{
player->drawCards(deck, 4);
}
int roundCount = 0;
int currentPlayerIndex = 0;
while(!globalGame.isGameOver())
{
roundCount++;
cout << "\n========== 第" << roundCount << "回合 ==========" << endl;
Player* currentPlayer = players[currentPlayerIndex];
cout << "\n--- 当前场上所有存活玩家状态 ---" << endl;
for(auto& p : globalGame.getPlayers())
{
if(p->isAlive)
{
showPlayerPublicInfo(p, currentPlayer);
if(p->general)
{
cout << "当前出战武将:" << p->general->getName() << endl;
}
showEquip(p);
}
}
if(!currentPlayer->isAlive)
{
currentPlayerIndex = (currentPlayerIndex + 1) % players.size();
continue;
}
cout << "\n当前行动玩家:" << currentPlayer->name
<< " (体力:" << currentPlayer->health << "/" << currentPlayer->maxHealth << ")" << endl;
currentPlayer->hasUsedKillThisTurn = false;
bool hasZhuGeLianNu = false;
if(currentPlayer->equipment.count(EquipSlot::WEAPON))
{
if(currentPlayer->equipment[EquipSlot::WEAPON]->getName() == "诸葛连弩")
{
hasZhuGeLianNu = true;
cout << currentPlayer->name << "装备了诸葛连弩,本回合出杀无次数限制!" << endl;
}
}
if(currentPlayer->general != nullptr)
{
for(auto& skill : currentPlayer->general->getSkills())
{
if(skill->canActivate(currentPlayer, &globalGame, Skill::ON_TURN_START))
{
skill->execute(currentPlayer, &globalGame);
}
}
}
cout << "--- 判定阶段 ---" << endl;
vector<shared_ptr<Card>> newJudgeArea;
bool skipDrawPhase = false;
bool skipPlayPhase = false;
for(auto& judgeCard : currentPlayer->judgeArea)
{
if(judgeCard->getName() == "乐不思蜀")
{
int judgeRes = rand() % 3;
if(judgeRes == 0)
{
cout << currentPlayer->name << "的【乐不思蜀】判定为红桃,失效!可正常出牌" << endl;
}
else
{
cout << currentPlayer->name << "的【乐不思蜀】判定不为红桃,跳过出牌阶段!" << endl;
skipPlayPhase = true;
}
}
else if(judgeCard->getName() == "闪电")
{
int judgePoint = rand() % 13 + 1;
Suit judgeSuit = (Suit)(rand() % 4);
cout << currentPlayer->name << " 开始结算【闪电】延时锦囊判定!" << endl;
if(judgeSuit == Suit::SPADE && judgePoint >=2 && judgePoint <=9)
{
cout << "闪电判定命中黑桃" << judgePoint << "!结算来自【闪电】的3点雷电属性伤害!" << endl;
currentPlayer->health -= 3;
currentPlayer->hasTakenDamageThisTurn = true;
if(currentPlayer->health <= 0)
{
cout << currentPlayer->name << " 受到【闪电】3点雷电伤害后血量归零,进入濒死求桃结算环节!" << endl;
globalGame.handleDying(currentPlayer, 3);
}
cout << currentPlayer->name << " 【闪电】伤害结算完成,当前剩余体力:" << currentPlayer->health << endl;
}
else
{
Player* nextPlayer = globalGame.getNextAlivePlayer(currentPlayer);
if(nextPlayer)
{
cout << currentPlayer->name << "的闪电判定未命中雷电区域,闪电自动传递到下家" << nextPlayer->name << "的判定区。" << endl;
nextPlayer->judgeArea.push_back(judgeCard);
}
continue;
}
}
else if(judgeCard->getName() == "兵粮寸断")
{
int judgeRes = rand() % 3;
if(judgeRes == 0)
{
cout << currentPlayer->name << "的【兵粮寸断】判定为草花,失效!可正常摸牌" << endl;
}
else
{
cout << currentPlayer->name << "的【兵粮寸断】判定不为草花,跳过摸牌阶段!" << endl;
skipDrawPhase = true;
}
}
newJudgeArea.push_back(judgeCard);
}
currentPlayer->judgeArea = newJudgeArea;
if(skipDrawPhase)
{
cout << currentPlayer->name << "跳过摸牌阶段,直接进入出牌阶段" << endl;
}
else
{
cout << "--- 摸牌阶段 ---" << endl;
currentPlayer->drawCards(deck, 2);
currentPlayer->showHand();
}
cout << "你的装备:";
showEquip(currentPlayer);
if(skipPlayPhase)
{
cout << currentPlayer->name << "直接进入弃牌阶段,跳过出牌操作" << endl;
}
else
{
if(currentPlayer->isHuman)
{
cout << "\n--- 出牌阶段 ---" << endl;
bool continuePlay = true;
while(continuePlay && currentPlayer->getHandCount() > 0)
{
cout << "\n--- 当前你的所有手牌列表 ---" << endl;
for(size_t i = 0; i < currentPlayer->handCards.size(); i++)
{
cout << "[" << i + 1 << "] " << currentPlayer->handCards[i]->toString() << endl;
}
int cardSelect;
while(true)
{
cout << "\n请选择要使用的手牌编号,输入0直接结束出牌阶段:";
cin >> cardSelect;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(cardSelect == 0 || (cardSelect >=1 && cardSelect <= currentPlayer->getHandCount())) break;
cout << "输入的编号无效,请重新输入!\n";
}
if(cardSelect == 0)
{
continuePlay = false;
break;
}
int useCardIndex = cardSelect - 1;
auto selectCard = currentPlayer->handCards[useCardIndex];
string cardName = selectCard->getName();
if(selectCard->getType() == CardType::BASIC)
{
if(cardName == "杀")
{
auto killCard = currentPlayer->handCards[useCardIndex];
auto killColor = killCard->colorToString();
if(!hasZhuGeLianNu && currentPlayer->hasUsedKillThisTurn)
{
cout << "本回合你已经出过一张杀,未装备诸葛连弩无法继续出杀!" << endl;
continue;
}
auto enemies = globalGame.getAliveEnemies(currentPlayer);
if(!enemies.empty())
{
cout << "请选择【杀】的攻击目标:" << endl;
for(size_t i = 0; i < enemies.size(); i++)
{
cout << i + 1 << ". " << enemies[i]->name << " (体力:" << enemies[i]->health << ")" << endl;
}
int targetChoice;
cin >> targetChoice;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(targetChoice >= 1 && targetChoice <= (int)enemies.size())
{
Player* target = enemies[targetChoice - 1];
bool ignoreArmor = false;
if(currentPlayer->equipment.count(EquipSlot::WEAPON) &&
currentPlayer->equipment[EquipSlot::WEAPON]->getName() == "青釭剑")
{
cout << "【青釭剑】特效生效,本次【杀】无视目标防具!" << endl;
ignoreArmor = true;
}
if(!ignoreArmor && target->equipment.count(EquipSlot::ARMOR) &&
target->equipment[EquipSlot::ARMOR]->getName() == "仁王盾" && killColor == "黑色")
{
cout << "【仁王盾】特效触发,黑色杀对目标无效!本次杀没有造成伤害" << endl;
currentPlayer->removeCard(useCardIndex);
continue;
}
bool skipDamage = false;
if(currentPlayer->equipment.count(EquipSlot::WEAPON) &&
currentPlayer->equipment[EquipSlot::WEAPON]->getName() == "寒冰剑" &&
target->getHandCount() >= 2)
{
cout << "寒冰剑特效触发,是否弃置目标2张手牌代替伤害?1.是 0.否:";
int op;
cin >> op;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(op == 1)
{
target->removeCard(0);
target->removeCard(0);
cout << currentPlayer->name << "发动寒冰剑,弃置了" << target->name << "的2张手牌,本次杀不造成伤害!" << endl;
skipDamage = true;
currentPlayer->removeCard(useCardIndex);
currentPlayer->hasUsedKillThisTurn = true;
}
}
if(!skipDamage)
{
currentPlayer->removeCard(useCardIndex);
currentPlayer->hasUsedKillThisTurn = true;
cout << currentPlayer->name << " 对 " << target->name << " 使用了【杀】!" << endl;
}
if(target->hasCard("闪"))
{
bool autoDodge = false;
if(target->equipment.count(EquipSlot::ARMOR) &&
target->equipment[EquipSlot::ARMOR]->getName() == "八卦阵")
{
int judgeRes = rand() % 2;
if(judgeRes == 1)
{
cout << target->name << "的八卦阵判定为红牌,自动视为打出闪!" << endl;
autoDodge = true;
}
else
{
cout << target->name << "的八卦阵判定为黑牌,需要手动打出闪!" << endl;
}
}
if(autoDodge)
{
cout << "八卦阵自动抵消了本次杀的伤害!" << endl;
continue;
}
cout << target->name << " 是否要出【闪】抵消?1.是 0.否:";
int useDodge;
cin >> useDodge;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
target->isLegalDodgeScenario = true;
if(useDodge == 1 && target->isLegalDodgeScenario) {
int dodgeIndex = target->findCardIndex("闪");
target->removeCard(dodgeIndex);
cout << target->name << " 使用了【闪】抵消了伤害!" << endl;
target->isLegalDodgeScenario = false;
if(currentPlayer->equipment.count(EquipSlot::WEAPON) &&
currentPlayer->equipment[EquipSlot::WEAPON]->getName() == "青龙偃月刀") {
cout << currentPlayer->name << "的【杀】被抵消,是否继续使用青龙偃月刀特效出杀?1.是 0.否:";
int op;
cin >> op;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(op == 1 && currentPlayer->hasCard("杀")) {
int newKillIndex = currentPlayer->findCardIndex("杀");
currentPlayer->removeCard(newKillIndex);
currentPlayer->hasUsedKillThisTurn = false;
useCardIndex--;
cout << currentPlayer->name << " 继续对 " << target->name << " 使用了【杀】!" << endl;
continue;
}
}
if (target->general != nullptr && target->general->getName() == "张角")
{
for(auto& skill : target->general->getSkills())
{
if(skill->getName() == "雷击" && skill->canActivate(target, &globalGame, Skill::ON_KILL))
{
cout << target->name << " 打出闪响应杀,是否触发雷击技能?1.是 0.否:";
int op;
cin >> op;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(op == 1)
{
skill->execute(target, &globalGame);
}
}
}
}
continue;
}
}
int finalDamage = 1;
if(!ignoreArmor && target->equipment.count(EquipSlot::ARMOR) &&
target->equipment[EquipSlot::ARMOR]->getName() == "藤甲")
{
cout << "【藤甲】特效触发,本次普通杀伤害被完全无视!" << endl;
finalDamage = 0;
}
if(target->equipment.count(EquipSlot::ARMOR) &&
target->equipment[EquipSlot::ARMOR]->getName() == "白银狮子" && finalDamage > 1)
{
cout << "【白银狮子】特效触发,本次伤害限定为1点!" << endl;
finalDamage = 1;
}
if(finalDamage > 0)
{
target->health -= finalDamage;
cout << target->name << " 受到" << finalDamage << "点伤害!(剩余体力:" << target->health << ")" << endl;
if(currentPlayer->equipment.count(EquipSlot::WEAPON) &&
currentPlayer->equipment[EquipSlot::WEAPON]->getName() == "麒麟弓")
{
if(target->equipment.count(EquipSlot::OFF_MOUNT))
{
target->equipment.erase(EquipSlot::OFF_MOUNT);
cout << "麒麟弓特效触发,弃置了" << target->name << "+1坐骑!" << endl;
}
if(target->equipment.count(EquipSlot::DEF_MOUNT))
{
target->equipment.erase(EquipSlot::DEF_MOUNT);
cout << "麒麟弓特效触发,弃置了" << target->name << "-1坐骑!" << endl;
}
}
}
if(target->health <= 0)
{
target->health = 0;
globalGame.handleDying(target, 1);
}
if(target->general != nullptr)
{
target->hasTakenDamageThisTurn = true;
for(auto& skill : target->general->getSkills())
{
if(skill->canActivate(target, &globalGame, Skill::ON_DAMAGE))
{
skill->execute(target, &globalGame);
}
}
}
}
}
}
else if(cardName == "桃")
{
if(currentPlayer->health < currentPlayer->maxHealth)
{
currentPlayer->removeCard(useCardIndex);
currentPlayer->health++;
cout << currentPlayer->name << " 使用了【桃】,回复1点体力!(当前体力:" << currentPlayer->health << ")" << endl;
}
else
{
cout << "体力已满,无需使用【桃】!" << endl;
}
}
}
else if(selectCard->getType() == CardType::TRICK)
{
auto trickCard = dynamic_pointer_cast<TrickCard>(selectCard);
vector<Player*> targetVec;
auto enemies = globalGame.getAliveEnemies(currentPlayer);
if(trickCard->getTrickType() == TrickCard::DISMANTLE ||
trickCard->getTrickType() == TrickCard::SNATCH ||
trickCard->getTrickType() == TrickCard::DUEL)
{
cout << "请选择锦囊的使用目标:" << endl;
for(size_t i = 0; i < enemies.size(); i++)
{
cout << i + 1 << ". " << enemies[i]->name << endl;
}
int targetChoice;
cin >> targetChoice;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(targetChoice >= 1 && targetChoice <= (int)enemies.size())
{
targetVec.push_back(enemies[targetChoice - 1]);
}
else
{
cout << "选择目标非法,锦囊牌自动弃置,手牌已扣除" << endl;
currentPlayer->removeCard(useCardIndex);
continue;
}
}
bool trickResult = trickCard->use(currentPlayer, targetVec, &globalGame);
currentPlayer->removeCard(useCardIndex);
if(!trickResult)
{
cout << "锦囊结算执行完毕,手牌已正常扣除" << endl;
}
if(trickCard->getTrickType() == TrickCard::BARBARIANS || trickCard->getTrickType() == TrickCard::ARROWS)
{
for(auto p : players)
{
if(p->general != nullptr && p->hasTakenDamageThisTurn)
{
for(auto& skill : p->general->getSkills())
{
if(skill->canActivate(p, &globalGame, Skill::ON_DAMAGE))
{
skill->execute(p, &globalGame);
}
}
}
}
}
}
else if(selectCard->getType() == CardType::DELAY_TRICK)
{
auto delayTrickCard = dynamic_pointer_cast<TrickCard>(selectCard);
vector<Player*> targetVec;
auto enemies = globalGame.getAliveEnemies(currentPlayer);
cout << "请选择延时锦囊的置入目标:" << endl;
for(size_t i = 0; i < enemies.size(); i++)
{
cout << i + 1 << ". " << enemies[i]->name << endl;
}
int targetChoice;
while(true)
{
cout << "请选择延时锦囊的置入目标编号:";
cin >> targetChoice;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(targetChoice >= 1 && targetChoice <= (int)enemies.size()) break;
cout << "目标编号非法,请重新输入!\n";
}
targetVec.push_back(enemies[targetChoice - 1]);
delayTrickCard->use(currentPlayer, targetVec, &globalGame);
currentPlayer->removeCard(useCardIndex);
cout << "延时锦囊已成功置入目标判定区,手牌已正常扣除" << endl;
}
else if(selectCard->getType() == CardType::EQUIPMENT)
{
auto equipCard = dynamic_pointer_cast<EquipmentCard>(selectCard);
vector<Player*> emptyTarget;
equipCard->use(currentPlayer, emptyTarget, &globalGame);
currentPlayer->removeCard(useCardIndex);
if(equipCard->getName() == "诸葛连弩")
{
hasZhuGeLianNu = true;
cout << "诸葛连弩已装备激活,你本回合剩余时间出杀无次数限制!" << endl;
}
}
currentPlayer->showHand();
if(currentPlayer->general != nullptr)
{
for(auto& skill : currentPlayer->general->getSkills())
{
if(skill->canActivate(currentPlayer, &globalGame, Skill::ON_PLAY))
{
cout << "\n检测到可发动主动技能:" << skill->getName() << ",是否发动?1.是 0.否:";
int op;
cin >> op;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(op == 1)
{
skill->execute(currentPlayer, &globalGame);
currentPlayer->showHand();
}
}
}
}
}
}
else
{
unordered_map<string, bool> hasUsedSkillThisRound;
int maxAiPlayLoopCount = 15;
while (maxAiPlayLoopCount-- > 0)
{
int roundCount = 0;
int MAX_ALLOWED_TOTAL_ROUNDS = 200; int currentPlayerIndex = 0;
while(!globalGame.isGameOver() && roundCount <= MAX_ALLOWED_TOTAL_ROUNDS)
{
roundCount++;
}
if(roundCount > MAX_ALLOWED_TOTAL_ROUNDS && !globalGame.isGameOver())
{
cout << "达到最大回合上限,自动触发胜负判定避免无限循环!" << endl;
if(currentGameMode == 2)
{
int remainAliveFanzei = 0;
int remainAliveLordCamp = 0;
for(auto p : players)
{
if(!p->isAlive) continue;
if(p->identity == Identity::ZHU_GONG || p->identity == Identity::ZHONG_CHEN) remainAliveLordCamp++;
if(p->identity == Identity::FAN_ZEI) remainAliveFanzei++;
}
if(remainAliveFanzei == 0)
{
cout << "超过最大回合上限,所有反贼阵亡,主公忠臣阵营超时获胜!" << endl;
}
else if(remainAliveLordCamp == 0)
{
cout << "超过最大回合上限,主公忠臣全灭,反贼阵营超时获胜!" << endl;
}
else
{
cout << "超过最大回合上限,双方剩余存活角色太多,自动判定当前回合行动玩家所属阵营获胜终止对局!" << endl;
}
}
globalGame.setGameOver(true);
}
bool aiDoSomething = false;
if (currentPlayer->general != nullptr)
{
for (auto& skill : currentPlayer->general->getSkills())
{
if (!hasUsedSkillThisRound[skill->getName()] && skill->canActivate(currentPlayer, &globalGame, Skill::ON_PLAY))
{
cout << currentPlayer->name << " 自动发动主动技能【" << skill->getName() << "】\n";
if (!skill->execute(currentPlayer, &globalGame))
{
continue;
}
hasUsedSkillThisRound[skill->getName()] = true;
aiDoSomething = true;
break;
}
}
}
if (aiDoSomething) continue;
if(currentPlayer->hasCard("桃") && currentPlayer->health < currentPlayer->maxHealth)
{
int cardIndex = currentPlayer->findCardIndex("桃");
currentPlayer->removeCard(cardIndex);
currentPlayer->health++;
cout << currentPlayer->name << " 使用了【桃】,回复1点体力!" << endl;
aiDoSomething = true;
}
if (aiDoSomething) continue;
if(currentPlayer->hasCard("无中生有"))
{
shared_ptr<Card> trick = make_shared<BountifulHarvestCard>(Suit::HEART,7);
vector<Player*> emptyTarget;
trick->use(currentPlayer, emptyTarget, &globalGame);
int cardIndex = currentPlayer->findCardIndex("无中生有");
currentPlayer->removeCard(cardIndex);
aiDoSomething = true;
}
if (aiDoSomething) continue;
if(currentPlayer->hasCard("杀"))
{
if(!hasZhuGeLianNu && currentPlayer->hasUsedKillThisTurn)
{
cout << currentPlayer->name << "本回合已出过杀,停止出杀操作" << endl;
break;
}
auto enemies = globalGame.getAliveEnemies(currentPlayer);
if(enemies.empty()) break;
Player* target = globalGame.getAIPrimaryTarget(currentPlayer);
if(target == nullptr)
{
cout << currentPlayer->name << "当前身份优先级无合法攻击目标,跳过本次出杀" << endl;
int discardIndex = currentPlayer->findCardIndex("杀");
currentPlayer->removeCard(discardIndex);
aiDoSomething = true;
continue;
}
if(currentPlayer->getDistanceTo(target) > 1 && currentPlayer->equipment.count(EquipSlot::DEF_MOUNT) == 0)
{
cout << currentPlayer->name << "距离目标过远,无法攻击" << target->name << endl;
break;
}
int cardIndex = currentPlayer->findCardIndex("杀");
currentPlayer->removeCard(cardIndex);
currentPlayer->hasUsedKillThisTurn = true;
cout << currentPlayer->name << " 对 " << target->name << " 使用了【杀】!" << endl;
if(target->hasCard("闪"))
{
target->isLegalDodgeScenario = true;
target->removeCard(target->findCardIndex("闪"));
cout << target->name << " 使用了【闪】抵消了伤害!" << endl;
target->isLegalDodgeScenario = false;
if (target->general != nullptr && target->general->getName() == "张角")
{
for(auto& skill : target->general->getSkills())
{
if(!hasUsedSkillThisRound[skill->getName()] && skill->getName() == "雷击" && skill->canActivate(target, &globalGame, Skill::ON_KILL))
{
skill->execute(target, &globalGame);
hasUsedSkillThisRound[skill->getName()] = true;
}
}
}
}
else
{
target->health--;
cout << target->name << " 受到1点伤害!(剩余体力:" << target->health << ")" << endl;
if(target->health <= 0)
{
target->health = 0;
globalGame.handleDying(target, 1);
}
if(target->general != nullptr)
{
target->hasTakenDamageThisTurn = true;
for(auto& skill : target->general->getSkills())
{
if(!hasUsedSkillThisRound[skill->getName()] && skill->canActivate(target, &globalGame, Skill::ON_DAMAGE))
{
skill->execute(target, &globalGame);
hasUsedSkillThisRound[skill->getName()] = true;
}
}
}
}
aiDoSomething = true;
continue;
}
break;
}
cout << "\nAI出牌阶段结束,请输入y继续:";
char tmp;
while (cin >> tmp)
{
if (tmp == 'y')
break;
cout << "输入无效,请仅输入y:";
}
}
}
cout << "\n--- 弃牌阶段 ---" << endl;
while(currentPlayer->getHandCount() > currentPlayer->health)
{
if(currentPlayer->isHuman)
{
int discardChoice;
while(true)
{
cout << "手牌数超过体力值,请选择要弃置的牌(1-" << currentPlayer->getHandCount() << "): ";
cin >> discardChoice;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
if(discardChoice >= 1 && discardChoice <= currentPlayer->getHandCount()) break;
cout << "弃置编号非法,请重新输入!\n";
}
currentPlayer->removeCard(discardChoice - 1);
cout << "弃置了一张牌!" << endl;
}
else
{
currentPlayer->removeCard(0);
cout << currentPlayer->name << " 弃置了一张牌!" << endl;
}
}
for(auto p : players)
{
p->hasTakenDamageThisTurn = false;
}
int aliveCount = 0;
Player* lastAlive = nullptr;
int aliveFanzeiCount = 0;
int aliveZhongChenCount = 0;
int aliveNeiJianCount = 0;
bool zhuGongAlive = false;
for(auto& p : players)
{
if(p->isAlive)
{
aliveCount++;
lastAlive = p;
if(currentGameMode == 2)
{
if(p->identity == Identity::ZHU_GONG) zhuGongAlive = true;
if(p->identity == Identity::FAN_ZEI) aliveFanzeiCount++;
if(p->identity == Identity::ZHONG_CHEN) aliveZhongChenCount++;
if(p->identity == Identity::NEI_JIAN) aliveNeiJianCount++;
}
}
}
if(currentGameMode == 1)
{
if(aliveCount <= 1)
{
globalGame.setGameOver(true);
if(lastAlive)
{
cout << "\n========== 游戏结束 正常局 ==========" << endl;
cout << lastAlive->name << " 成为全场最后存活的玩家,获得自由对战胜利!" << endl;
}
break;
}
}
else if(currentGameMode == 2)
{
if(!zhuGongAlive)
{
globalGame.setGameOver(true);
cout << "\n========== 游戏结束 身份局 ==========" << endl;
if(aliveCount == 1 && lastAlive->identity == Identity::NEI_JIAN)
{
cout << lastAlive->name << " 是唯一存活的内奸,完成最后对决任务,内奸阵营获得最终胜利!" << endl;
}
else
{
cout << "主公提前阵亡,反贼阵营获得胜利!" << endl;
}
break;
}
else if(aliveFanzeiCount == 0 && aliveNeiJianCount == 0)
{
globalGame.setGameOver(true);
cout << "\n========== 游戏结束 身份局 ==========" << endl;
cout << "所有反贼和内奸全部阵亡,主公与忠臣阵营获得胜利!" << endl;
break;
}
}
currentPlayerIndex = (currentPlayerIndex + 1) % players.size();
}
cout << "\n感谢游玩三国杀完整版!" << endl;
return 0;
}