You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

378 lines
12 KiB

4 years ago
  1. #include <iostream>
  2. #include <thread>
  3. #include <chrono>
  4. #include <random>
  5. #include <fstream>
  6. #include "lib/Character.hpp"
  7. #include "lib/Spell.hpp"
  8. #define INTERVAL 1000
  9. #define FLAG_INTERVAL 250
  10. void sleep(int ms)
  11. {
  12. std::this_thread::sleep_for(std::chrono::milliseconds(ms));
  13. }
  14. int strlen(const char *msg)
  15. {
  16. int i = 0;
  17. while (msg[i] != '\x00')
  18. {
  19. i++;
  20. }
  21. return i;
  22. }
  23. int getLowest(int a, int b)
  24. {
  25. return (a < b) ? a : b;
  26. }
  27. int getHighest(int a, int b)
  28. {
  29. return (a > b) ? a : b;
  30. }
  31. void intervalPrint(const char *msg, int interval = 1000, int len = 0)
  32. {
  33. if (len <= 0)
  34. {
  35. len = strlen(msg);
  36. }
  37. for (int i = 0; i < len; i++)
  38. {
  39. std::cout << msg[i] << std::flush;
  40. std::this_thread::sleep_for(std::chrono::milliseconds(interval));
  41. }
  42. std::cout << std::endl;
  43. }
  44. void intervalPrint(std::string &msg, int interval = 1000, int len = 0)
  45. {
  46. if (len <= 0)
  47. {
  48. len = msg.length();
  49. }
  50. for (int i = 0; i < len; i++)
  51. {
  52. std::cout << msg.at(i) << std::flush;
  53. std::this_thread::sleep_for(std::chrono::milliseconds(interval));
  54. }
  55. std::cout << std::endl;
  56. }
  57. int getNumber(const char *prompt, int min, int max)
  58. {
  59. int tmp = 0;
  60. std::cout << prompt;
  61. while (!(std::cin >> tmp) && (tmp >= min && tmp <= max))
  62. {
  63. if (std::cin.eofbit)
  64. {
  65. exit(1);
  66. }
  67. std::cin.get();
  68. std::cin.clear();
  69. std::cin.ignore(4096, '\x00');
  70. // std::cin.ignore(4096, '\n');
  71. std::cout << prompt;
  72. }
  73. return tmp;
  74. }
  75. Character *chooseEnemy()
  76. {
  77. std::cout << "List of challenger:" << std::endl;
  78. for (int i = 0; i < Character::Enemies.size(); i++)
  79. {
  80. std::cout << "[" << i << "] " << Character::Enemies[i]->getName() << std::endl;
  81. }
  82. int choice = 0;
  83. do
  84. {
  85. choice = getNumber("Choose your enemy: ", 0, Character::Enemies.size());
  86. } while (!(choice >= 0 && choice < Character::Enemies.size()));
  87. return Character::Enemies[choice];
  88. }
  89. Character *generatePlayer()
  90. {
  91. Character *tmp = new Character(
  92. Character::playerNames[std::rand() % Character::playerNames.size()],
  93. 1,
  94. 1,
  95. 100,
  96. 50,
  97. 1,
  98. 1);
  99. return tmp;
  100. }
  101. std::string loadFlag()
  102. {
  103. std::string tmp;
  104. std::ifstream flagFile("flag.txt");
  105. if (flagFile.is_open())
  106. {
  107. flagFile >> tmp;
  108. }
  109. return tmp;
  110. }
  111. void printCharacterInfo(Character *c)
  112. {
  113. std::cout << "Name : " << c->getName() << std::endl
  114. << "HP : " << c->getCurHP() << "/" << c->getMaxHP() << std::endl
  115. << "MP : " << c->getCurMP() << "/" << c->getMaxMP() << std::endl;
  116. }
  117. void printCharacterFullInfo(Character *c)
  118. {
  119. std::cout << "Name : " << c->getName() << std::endl
  120. << "Level: " << c->getLevel() << std::endl
  121. << "Exp : " << c->getExperience() << " | next: " << c->toNextLevel() << std::endl
  122. << "HP : " << c->getCurHP() << "/" << c->getMaxHP() << std::endl
  123. << "MP : " << c->getCurMP() << "/" << c->getMaxMP() << std::endl;
  124. }
  125. Character *startBattle(Character *p1, Character *p2)
  126. {
  127. int maxTurn = 1000;
  128. int turn = 0;
  129. std::cout << "===== BATTLE START ======" << std::endl;
  130. while ((p1->isAlive() && p2->isAlive()) && (++turn <= maxTurn))
  131. {
  132. std::cout << "== Turn " << turn << " ==" << std::endl;
  133. std::cout << "Player =====" << std::endl;
  134. printCharacterInfo(p1);
  135. std::cout << "Enemy ======" << std::endl;
  136. printCharacterInfo(p2);
  137. std::cout << "===== Spell Books =====" << std::endl;
  138. for (int i = 1; i <= p1->getLevel() && i < Spell::Book.size(); i++)
  139. {
  140. std::cout << "[" << i << "] " << Spell::Book[i]->getName() << std::endl;
  141. }
  142. int p1Choice = getNumber("Choose your spell: ", 0, getLowest(p1->getLevel(), Spell::Book.size() - 1));
  143. int p2Choice = (std::rand() % getLowest(p2->getLevel(), Spell::Book.size() - 1)) + 1;
  144. Spell *p1Spell = Spell::Book[p1Choice];
  145. Spell *p2Spell = Spell::Book[p2Choice];
  146. if (p1->canCastSpell(p1Spell))
  147. {
  148. p1->castSpell(p1Spell, p2);
  149. std::cout << p1->getName() << " cast " << p1Spell->getName() << std::endl;
  150. sleep(INTERVAL);
  151. std::cout << p2->getName() << " took " << p1Spell->getAmount() << " damage" << std::endl;
  152. sleep(INTERVAL);
  153. }
  154. else
  155. {
  156. std::cout << p1->getName() << " failed to cast " << p1Spell->getName() << std::endl;
  157. sleep(INTERVAL);
  158. std::cout << p1->getName() << " does not have enough MP to cast it!" << std::endl;
  159. sleep(INTERVAL);
  160. }
  161. if (p2->canCastSpell(p2Spell))
  162. {
  163. p2->castSpell(p2Spell, p1);
  164. std::cout << p2->getName() << " cast " << p2Spell->getName() << std::endl;
  165. sleep(INTERVAL);
  166. std::cout << p1->getName() << " took " << p2Spell->getAmount() << " damage" << std::endl;
  167. sleep(INTERVAL);
  168. }
  169. else
  170. {
  171. std::cout << p2->getName() << " failed to cast " << p2Spell->getName() << std::endl;
  172. sleep(INTERVAL);
  173. std::cout << p2->getName() << " does not have enough MP to cast it!" << std::endl;
  174. sleep(INTERVAL);
  175. }
  176. }
  177. Character *winner;
  178. if (turn >= maxTurn)
  179. {
  180. std::cout << "The battle took too long, a winner has to be decided." << std::endl;
  181. winner = (p1->getCurHP() > p2->getCurHP()) ? p1 : p2;
  182. }
  183. else
  184. {
  185. winner = (p1->isAlive()) ? p1 : p2;
  186. }
  187. return winner;
  188. }
  189. int main()
  190. {
  191. std::srand(std::time(0));
  192. std::string flag = loadFlag();
  193. Character *player = generatePlayer();
  194. Character *archMage = new Character("Arch-Mage", 999, 999999, 999999, 999999, 1, 1);
  195. std::cout << "Welcome to SpellWarz!" << std::endl;
  196. sleep(INTERVAL);
  197. std::cout << "You are a young mage named '" << player->getName() << "'" << std::endl;
  198. sleep(INTERVAL);
  199. std::cout << "Here's your flag: ";
  200. intervalPrint(flag, FLAG_INTERVAL, 10);
  201. std::cout << "Oh no!" << std::endl;
  202. sleep(INTERVAL);
  203. std::cout << "The Arch-Mage took your flag!" << std::endl;
  204. sleep(INTERVAL);
  205. std::cout << "He said you are not worthy of it," << std::endl;
  206. sleep(INTERVAL);
  207. std::cout << "defeat him to get it back!" << std::endl;
  208. sleep(INTERVAL);
  209. while (player->isAlive())
  210. {
  211. std::cout << "========================================" << std::endl;
  212. printCharacterFullInfo(player);
  213. std::cout << "========================================" << std::endl
  214. << "[1] Sleep" << std::endl
  215. << "[2] Meditate" << std::endl
  216. << "[3] Spar with other mages" << std::endl
  217. << "[4] Search info about Arch-Mage" << std::endl
  218. << "[5] Challenge the Arch-Mage" << std::endl
  219. << "[0] Give up on life" << std::endl;
  220. int choice = getNumber("Choose your action: ", 0, 5);
  221. std::cout << "========================================" << std::endl;
  222. if (choice == 0)
  223. {
  224. std::cout << "Farewell young mage, see you in the afterlife..." << std::endl;
  225. player->reduceHP(player->getMaxHP());
  226. }
  227. if (choice == 1)
  228. {
  229. std::cout << "You take a rest in your dormitory..." << std::endl;
  230. sleep(INTERVAL);
  231. std::cout << "You recovered to full HP and MP" << std::endl;
  232. sleep(INTERVAL);
  233. player->restoreHP(player->getMaxHP());
  234. player->restoreMP(player->getMaxMP());
  235. }
  236. if (choice == 2)
  237. {
  238. int tmp;
  239. tmp = (rand() % 10) + 1;
  240. std::cout << "You meditate on your mana..." << std::endl;
  241. sleep(INTERVAL);
  242. std::cout << "And got " << tmp << " experience!" << std::endl;
  243. sleep(INTERVAL);
  244. player->increaseExperience(tmp);
  245. if (player->readytoLevelUp())
  246. {
  247. std::cout << "Congratulations, you leveled up!" << std::endl;
  248. while (player->readytoLevelUp())
  249. {
  250. player->levelUp();
  251. }
  252. sleep(200);
  253. }
  254. }
  255. if (choice == 3)
  256. {
  257. Character *enemy = new Character(*chooseEnemy());
  258. Character *winner = startBattle(player, enemy);
  259. if (winner == player)
  260. {
  261. std::cout << "You win! You got " << enemy->getExperience() << "exp" << std::endl;
  262. sleep(INTERVAL);
  263. player->increaseExperience(enemy->getExperience());
  264. if (player->readytoLevelUp())
  265. {
  266. std::cout << "Congratulations, you leveled up!" << std::endl;
  267. while (player->readytoLevelUp())
  268. {
  269. player->levelUp();
  270. }
  271. sleep(200);
  272. }
  273. }
  274. else
  275. {
  276. while (!player->isAlive())
  277. {
  278. player->restoreHP(1);
  279. }
  280. std::cout << "You lose the fight, it was a fair fight." << std::endl;
  281. sleep(INTERVAL);
  282. }
  283. }
  284. if (choice == 4)
  285. {
  286. std::cout << "You are searching info about the Arch-Mage..." << std::endl;
  287. sleep(INTERVAL);
  288. std::cout << "Here's some info about the Arch-Mage:" << std::endl;
  289. printCharacterFullInfo(archMage);
  290. }
  291. if (choice == 5)
  292. {
  293. if (archMage->isAlive())
  294. {
  295. std::cout << "You are challenging the Arch-Mage" << std::endl;
  296. sleep(INTERVAL);
  297. std::cout << "Arch-Mage: ";
  298. sleep(INTERVAL);
  299. intervalPrint("so you have come to challenge me. Prepare to die!", 200);
  300. Character *winner = startBattle(player, archMage);
  301. if (winner == player)
  302. {
  303. std::cout << "You win! You got " << archMage->getExperience() << "exp" << std::endl;
  304. player->increaseExperience(archMage->getExperience());
  305. sleep(INTERVAL);
  306. if (player->readytoLevelUp())
  307. {
  308. std::cout << "Congratulations, you leveled up!" << std::endl;
  309. while (player->readytoLevelUp())
  310. {
  311. player->levelUp();
  312. }
  313. sleep(200);
  314. }
  315. std::cout << "You did a good job! Now you are the Arch-Mage!" << std::endl;
  316. sleep(INTERVAL);
  317. std::cout << "Here's the flag the previous Arch-Mage took from you: " << std::endl;
  318. sleep(INTERVAL);
  319. intervalPrint(flag, FLAG_INTERVAL);
  320. }
  321. else
  322. {
  323. std::cout << "You lose the fight..." << std::endl;
  324. sleep(INTERVAL);
  325. std::cout << "Unfortunately, the Arch-Mage was serious about this fight..." << std::endl;
  326. sleep(INTERVAL);
  327. std::cout << "You were killed in battle..." << std::endl;
  328. intervalPrint("GAME OVER", 250);
  329. }
  330. }
  331. else
  332. {
  333. std::cout << "You are the Arch-Mage now." << std::endl;
  334. sleep(INTERVAL);
  335. std::cout << "Here's your flag:";
  336. sleep(INTERVAL);
  337. intervalPrint(flag, FLAG_INTERVAL);
  338. }
  339. }
  340. }
  341. }