#include <iostream>
#include <vector>
#include <map>
#include <cstdlib>
#include <ctime>
#include <algorithm>
#include<bits/stdc++.h>
#include<windows.h>
#define ll long long
using namespace std;
namespace dj {
	inline void cd(int x) {
	Sleep(x);
	system("cls");
    }
	bool axj(long long key) {
		return (GetKeyState(key) < 0) ? (true) : (false);
	}
	struct hl {
		long long h,l;
	};
	void de(int x) {
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),x);
	}
	bool ax(long long key) {
		return (GetKeyState(key) < 0) ? (true) : (false);
	}
	hl wz(bool x = 1, bool n = 1) {
		HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
		HWND h = GetForegroundWindow();
		CONSOLE_FONT_INFO consoleCurrentFont;
		hl hl;
		POINT p;
		if (x) {
			GetCursorPos(&p);
			ScreenToClient(h, &p);
		} else {
			GetCursorPos(&p);
		}
		if (n) {
			GetCurrentConsoleFont(hOutput, FALSE, &consoleCurrentFont);
			p.x /= consoleCurrentFont.dwFontSize.X;
			p.y /= consoleCurrentFont.dwFontSize.Y;
		}
		hl.h = p.y + 1;
		hl.l = p.x + 1;
		return hl;
	}
	void ycbj() {
		HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
		DWORD mode;
		GetConsoleMode(hStdin, &mode);
		mode &= ~ENABLE_QUICK_EDIT_MODE;
		SetConsoleMode(hStdin, mode);
		return;
	}
	void ycgb() {
		CONSOLE_CURSOR_INFO cursor;
		cursor.bVisible = FALSE;
		cursor.dwSize = sizeof(cursor);
		HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleCursorInfo(handle, &cursor);
		return;
	}
	inline void ydgb(long long h, long long l) {
		COORD pos = { l - 1,h - 1 };
		HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleCursorPosition(hOut, pos);
		return;
	}
	bool pdbj(int y,int x,int x1,int x2,int ys,string zt) {
		ycgb();
		ycbj(); 
		hl z=wz(1,1);
		bool a=0;
		if(z.h==y&&z.l>=x1&&z.l<=x2) {
			ydgb(y,x);
			de(ys*16);
			cout<<zt;
			de(ys);
			if(axj(VK_LBUTTON)) {
				a=1;
			}
		} else {
			ydgb(y,x);
			de(ys);
			cout<<zt;
		}
		de(15);
		return a;
	}
};
using namespace dj;//一定要有
enum Realm { LIANQI, ZHUJI, JIEDAN, YUANYING, HUASHEN, LIANXU };
const string REALM_NAMES[] = {"凡人","淬体期","段体期","后天境","先天境","引气期","练气期","筑基期","结丹期","元婴期","化神期","炼虚期","渡劫期","半帝期","大帝期","半圣期","圣王期","圣君期","圣帝期","地仙期","天仙期","仙君期","仙帝期","半神期","神王期","神君期","神帝期"};
int zsdj=10,jjyan=5;
class Item {
	public:
		string name;
		string type; // "weapon", "armor", "potion", "pill"
		int value;
		int count;

		Item(string n, string t, int v) : name(n), type(t), value(v), count(1) {}
};

class Pill {
	public:
		string name;
		int hpRecover;
		int mpRecover;
		int expGain;

		Pill(string n, int h, int m, int e) : name(n), hpRecover(h), mpRecover(m), expGain(e) {}
};

class Cultivator {
	public:
		string name;
		Realm realm;
		int level;
		long long exp;
		int hp;
		int maxHp;
		int mp;
		int maxMp;
		int attack;
		int defense;
		string sect;
		vector<Item> items;
		vector<Pill> pills;

		Cultivator() : realm(LIANQI), level(1), exp(0), hp(100), maxHp(100),
			mp(50), maxMp(50), attack(15), defense(10) {}

		void levelUp() {
			cd(100);
			if(exp >= requiredExp()) {
				exp -= requiredExp();
				level++;

				if(level % 10 == 0 && realm < LIANXU+21) {//7
					realm = Realm(realm + 1);
					cout << "\n※※ 突破至" << REALM_NAMES[realm] << " ※※\n";
				}
                cout << "\n※※ 突破至" << REALM_NAMES[realm]<<" "<< level-realm*10<< "层 ※※\n";
                Sleep(1000);
				maxHp += 30 + realm * 10;
				maxMp += 20 + realm * 5;
				hp = maxHp;
				mp = maxMp;
				attack += 5 + realm * 2;
				defense += 3 + realm;
			}
		}

		long long requiredExp() const {
			return level * 100 * (realm + 1);
		}

		void usePill(int index) {
			if(index >= 0 && index < (int)pills.size()) {
				Pill p = pills[index];
				hp = min(hp + p.hpRecover, maxHp);
				mp = min(mp + p.mpRecover, maxMp);
				exp += p.expGain;
				cout << "服用" << p.name << ",恢复气血" << p.hpRecover
				     << ",灵力" << p.mpRecover << ",获得经验" << p.expGain << "\n";
				pills.erase(pills.begin() + index);
				levelUp();
			}
		}

		void showStatus() const {
			cout << "\n===== 角色状态 =====\n"
			     << "道号:" << name << "\n"
			     << "境界:" << REALM_NAMES[realm] << " " << level-realm*10 << "层\n"
			     << "宗门:" << (sect.empty() ? "散修" : sect) << "\n"
			     << "经验:" << exp << "/" << requiredExp() << "\n"
			     << "气血:" << hp << "/" << maxHp << "\n"
			     << "灵力:" << mp << "/" << maxMp << "\n"
			     << "攻击:" << attack << " 防御:" << defense << "\n";

			if(!items.empty()) {
				cout << "物品:";
				for(size_t i = 0; i < items.size(); ++i)
					cout << items[i].name << "(" << items[i].count << ") ";
				cout << "\n";
			}

			if(!pills.empty()) {
				cout << "丹药:";
				for(size_t i = 0; i < pills.size(); ++i)
					cout << pills[i].name << " ";
				cout << "\n";
			}
			cout << "==================\n";
		}
};

class Monster {
	public:
		string name;
		int hp;
		int attack;
		int defense;
		int expReward;
		int dropRate;
		vector<Item> possibleDrops;
		vector<Pill> possiblePills;

		Monster(string n, int h, int a, int d, int e, int dr)
			: name(n), hp(h), attack(a), defense(d), expReward(e), dropRate(dr) {}
};

void battle(Cultivator& player, Monster& monster) {
	cd(100);
	cout << "\n遭遇 " << monster.name << "!\n";

	while(player.hp > 0 && monster.hp > 0) {
		// Player attack
		int damage = player.attack - monster.defense/2;
		if(damage < 1) damage = 1;
		monster.hp -= damage;
		cout << player.name << " 对 " << monster.name<< " 造成 " << damage << " 点伤害\n";
		if(monster.hp <= 0) break;
		// Monster attack
		damage = monster.attack - player.defense/3;
		if(damage < 1) damage = 1;
		player.hp -= damage;
		cout << monster.name << " 对 " << player.name
		     << " 造成 " << damage << " 点伤害\n";
	}

	if(player.hp > 0) {
		player.exp += monster.expReward;
		cout << "\n战斗胜利!获得 " << monster.expReward << " 点经验\n";

		// Drop items
		if((rand() % 100) < monster.dropRate && !monster.possibleDrops.empty()) {
			Item drop = monster.possibleDrops[rand() % monster.possibleDrops.size()];
			bool found = false;
			for(size_t i = 0; i < player.items.size(); ++i) {
				if(player.items[i].name == drop.name) {
					player.items[i].count++;
					found = true;
					break;
				}
			}
			if(!found) player.items.push_back(drop);
			cout << "获得物品:" << drop.name << "!\n";
		}

		// Drop pills
		if((rand() % 100) < (monster.dropRate/2) && !monster.possiblePills.empty()) {
			Pill pill = monster.possiblePills[rand() % monster.possiblePills.size()];
			player.pills.push_back(pill);
			cout << "获得丹药:" << pill.name << "!\n";
		}

	}
	Sleep(1000);
}

void joinSect(Cultivator& player) {
	const string SECTS[] = {"青云门","天音寺","鬼王宗","合欢派","万毒门","焚香谷"};

	if(!player.sect.empty()) {
		cout << "\n你已是" << player.sect << "弟子\n";
		return;
	}

	int choice = rand() % 6;
	player.sect = SECTS[choice];
	cout << "\n※※ 拜入" << player.sect << " ※※\n";

	switch(choice) {
		case 0:
			player.attack += 20;
			break;
		case 1:
			player.defense += 20;
			break;
		case 2:
			player.hp += 50;
			break;
		case 3:
			player.mp += 30;
			break;
		case 4:
			player.exp += 200;
			break;
		case 5:
			player.level += 1;
			break;
	}
}

int main() {
	srand(time(0));
	Cultivator player;

	cout << "请输入道号:";
	cin >> player.name;
    cd(100);
	// Initialize items
	Item sword("青钢剑", "weapon", 10);
	Item armor("铁布衫", "armor", 8);
	Item herb("灵草", "potion", 5);

	// Initialize pills
	Pill smallPill("小还丹", 30, 20, 100);
	Pill bigPill("大还丹", 80, 50, 300);
	Pill expPill("经验丹", 0, 0, 1000);

	// Initialize monsters
	vector<Monster> monsters;
	Monster goblin("山野精怪", 300, 80, 50, 300, 10);
	goblin.possibleDrops.push_back(herb);
	goblin.possiblePills.push_back(smallPill);
	monsters.push_back(goblin);

	Monster treeDemon("百年树妖", 500, 102, 80, 500, 15);
	treeDemon.possibleDrops.push_back(Item("灵木", "material", 3));
	treeDemon.possiblePills.push_back(smallPill);
	monsters.push_back(treeDemon);

	Monster demonCultist("魔教弟子", 700, 180, 120, 800, 20);
	demonCultist.possibleDrops.push_back(sword);
	demonCultist.possiblePills.push_back(bigPill);
	monsters.push_back(demonCultist);

	Monster elder("元婴老怪", 1020, 205, 200, 1500, 30);
	elder.possibleDrops.push_back(armor);
	elder.possiblePills.push_back(bigPill);
	elder.possiblePills.push_back(expPill);
	monsters.push_back(elder);

	Monster beast("上古神兽", 2000, 305, 300, 3000, 50);
	beast.possibleDrops.push_back(Item("神兽内丹", "material", 50));
	beast.possiblePills.push_back(expPill);
	monsters.push_back(beast);
 
	while(player.hp > 0) {
		player.showStatus();
		cout << "\n选择行动:\n"
		     << "1. 修炼(随机获得经验)\n"
		     << "2. 挑战妖兽\n"
		     << "3. 加入宗门\n"
		     << "4. 使用丹药\n"
		     << "5. 突破境界\n"
             << "6. 重生\n"; 
		int choice=7;
		int szs=0;
		if(GetAsyncKeyState('1'))choice=1;
        if(GetAsyncKeyState('2'))choice=2;
        if(GetAsyncKeyState('3'))choice=3;
        if(GetAsyncKeyState('4'))choice=4;
        if(GetAsyncKeyState('5'))choice=5;
        if(GetAsyncKeyState('6'))choice=6;
		switch(choice) {
			case 1: {
				int expGain = 20 + rand() % 50;
				player.exp += expGain;
				cout << "\n修炼获得 " << expGain << " 点经验\n";
				Sleep(100);
				break;
			}
			case 2: {
				int monsterIndex = min(rand() % 10, (int)monsters.size()-1);
				battle(player, monsters[monsterIndex]);
				break;
			}
			case 3:
				if(player.level>15)joinSect(player);
				else cout<<"境界不足"<<endl;
				Sleep(100);
				break;
			case 4: {
				if(player.pills.empty()) {
					cout << "没有可用的丹药\n";
					Sleep(100);
					break;
				}
				cout << "选择丹药(0-" << player.pills.size()-1 << "): ";
				for(size_t i = 0; i < player.pills.size(); ++i)
					cout << i << "." << player.pills[i].name << " ";
				cout << "\n";
				int pillChoice;
				cin >> pillChoice;
				player.usePill(pillChoice);
				break;
			}
			case 5:
				if(player.exp>=player.requiredExp()){
					while(player.exp>=player.requiredExp())player.levelUp();
				}
				else cout<<"经验不足"<<endl;
				Sleep(1000);
				break;
				
			case 6:
			   cd(100);
			   cout<<"转世需要"<< REALM_NAMES[zsdj/10] << " " <<zsdj -(zsdj/10)*10 << "层\n";
			   cout<<"是否转世 1/2\n";
			   
			   while(!szs){
			   	if(GetAsyncKeyState('1'))szs=1;
                if(GetAsyncKeyState('2'))szs=2;
			   }
			   if(szs==1&& player.level>=zsdj){
			   	cout<<"转世成功"<<endl;
			   	player.level=1;
			   player.realm = Realm(player.realm - player.realm);;
			   zsdj+=2;
			   jjyan++;
			   Sleep(1000);
			   }else if(szs==1){
			   	cout<<"修为不足"<<endl;
			   	Sleep(1000);
			   }
			   break;
			   
			case 7:
				int expGain = rand() % jjyan;
				player.exp += expGain;
				cout << "\n修炼获得 " << expGain << " 点经验\n";
				Sleep(100);
				break;
		}
		if(pdbj(1,30,30,30,0,"")){
		}
		cd(50); 
	}
    if(player.hp <= 0) {
		cout << "\n你已陨落,游戏结束!\n";
	}
	return 0;
}