Advertisement
Guest User

Untitled

a guest
Jun 25th, 2017
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 18.67 KB | None | 0 0
  1. //*************************
  2. //****** Console RPG ******
  3. //****** Version 1.0 ******
  4. //*************************
  5.  
  6. #include <windows.h>
  7. #include "monster.h"
  8.  
  9. int Randomize(int, int);
  10. void doTurn(Player *, Player *, short *);
  11. void createStock(short, const Item *, const short, short);
  12. void getDrop(short, const Item *, const short, Monster *, Player *);
  13. void useItem(Player *, const Item *);
  14.  
  15. const short HP_GAIN = 5;
  16. const short STR_GAIN = 2;
  17. const short ARM_GAIN = 1;
  18. const short AR_GAIN = 2;
  19. const short LVL_BASE_XP = 100;
  20. const short MAX_LVL = 20;
  21. const short ITEMS_STOCK = 3;
  22. const short POTIONS_STOCK = 1;
  23. const short ELIXERS_STOCK = 1;
  24. const string names[] = {"Andariel", "Duriel", "Mephisto", "Diablo", "Baal", "Lilith", "Uber Duriel", "Uber Mephisto", "Uber Diablo", "Uber Baal"};
  25. const Item items[] =
  26. {
  27. Item("Sword", weapon, 1, 0, 5, 0, 10, 750, false),
  28. Item("Armor", armor, 1, 0, 5, 0, 10, 750, false),
  29. Item("Shield", shield, 1, 0, 5, 0, 10, 750, false),
  30. Item("Helm", helm, 1, 0, 5, 0, 10, 750, false),
  31. Item("Belt", belt, 1, 0, 5, 0, 10, 750, false),
  32. Item("Gloves", gloves, 1, 0, 5, 0, 10, 750, false),
  33. Item("Boots", boots, 1, 0, 5, 0, 10, 750, false),
  34. Item("Ring of lesser Health", ring, 1, 5, 0, 0, 10, 750, false),
  35. Item("Amulet of lesser Clarity", amulet, 1, 0, 5, 0, 10, 750, false),
  36. Item("Sturdy Sword", weapon, 5, 0, 5, 0, 10, 750, false),
  37. Item("Sturdy Helm", armor, 5, 0, 5, 0, 10, 750, false),
  38. Item("Sturdy Shield", shield, 5, 0, 5, 0, 10, 750, false),
  39. Item("Sturdy Helm", helm, 5, 0, 5, 0, 10, 750, false),
  40. Item("Sturdy Belt", belt, 5, 0, 5, 0, 10, 750, false),
  41. Item("Sturdy Gloves", gloves, 5, 0, 5, 0, 10, 750, false),
  42. Item("Sturdy Boots", boots, 5, 0, 5, 0, 10, 750, false),
  43. Item("Ring of Health", ring, 5, 10, 0, 0, 15, 750, false),
  44. Item("Amulet of Clarity", amulet, 5, 2, 5, 0, 10, 750, false),
  45. Item("Knight's Sword", weapon, 10, 0, 5, 0, 10, 750, false),
  46. Item("Knight's Armor", armor, 10, 0, 5, 0, 10, 750, false),
  47. Item("Knight's Shield", shield, 10, 0, 5, 0, 10, 750, false),
  48. Item("Knight's Helm", helm, 10, 0, 5, 0, 10, 750, false),
  49. Item("Knight's Belt", belt, 10, 0, 5, 0, 10, 750, false),
  50. Item("Knight's Gloves", gloves, 10, 0, 5, 0, 10, 750, false),
  51. Item("Knight's Boots", boots, 10, 0, 5, 0, 10, 750, false),
  52. Item("Ring of Power", ring, 10, 20, 5, 5, 10, 750, false),
  53. Item("Amulet of Agility", amulet, 10, 20, 0, 5, 30, 750, false),
  54. Item("Sword of the Colossus", weapon, 15, 0, 5, 0, 10, 750, false),
  55. Item("Armor of the Colossus", armor, 15, 0, 5, 0, 10, 750, false),
  56. Item("Shield of the Colossus", shield, 15, 0, 5, 0, 10, 750, false),
  57. Item("Helm of the Colossus", helm, 15, 0, 5, 0, 10, 750, false),
  58. Item("Belt of the Colossus", belt, 15, 0, 5, 0, 10, 750, false),
  59. Item("Gloves of the Colossus", gloves, 15, 0, 5, 0, 10, 750, false),
  60. Item("Boots of the Colossus", boots, 15, 0, 5, 0, 10, 750, false),
  61. Item("Ring of greater Health", ring, 15, 0, 5, 0, 10, 750, false),
  62. Item("Amulet of greater Clarity", amulet, 15, 0, 5, 0, 10, 750, false),
  63. Item("Sword of the Giant", weapon, 20, 0, 5, 0, 10, 750, false),
  64. Item("Armor of the Giant", armor, 20, 0, 5, 0, 10, 750, false),
  65. Item("Shield of the Giant", shield, 20, 0, 5, 0, 10, 750, false),
  66. Item("Helm of the Giant", helm, 20, 0, 5, 0, 10, 750, false),
  67. Item("Belt of the Giant", belt, 20, 0, 5, 0, 10, 750, false),
  68. Item("Gloves of the Giant", gloves, 20, 0, 5, 0, 10, 750, false),
  69. Item("Boots of the Giant", boots, 20, 0, 5, 0, 10, 750, false),
  70. Item("Ring of greatest Health", ring, 20, 40, 10, 0, 10, 750, false),
  71. Item("Amulet of greatest Clarity", amulet, 20, 40, 5, 5, 20, 750, false)
  72. };
  73. const Item potions[] =
  74. {
  75. Item("Minor Potion of Healing", potion, 1, 50, 0, 0, 0, 75),
  76. Item("Lesser Potion of Healing", potion, 5, 75, 0, 0, 0, 100),
  77. Item("Potion of Healing", potion, 10, 100, 0, 0, 0, 150),
  78. Item("Greater Potion of Healing", potion, 15, 125, 0, 0, 0, 200),
  79. Item("Super Potion of Healing", potion, 20, 150, 0, 0, 0, 250)
  80. };
  81. const Item elixers[] =
  82. {
  83. Item("Light Elixer", elixer, 1, 2, 1, 0, 0, 150),
  84. Item("Potent Elixer", elixer, 5, 4, 2, 0, 0, 250),
  85. Item("Strong Elixer", elixer, 10, 8, 3, 0, 0, 350),
  86. Item("Stronger Elixer", elixer, 15, 16, 5, 0, 0, 450),
  87. Item("Super Elixer", elixer, 20, 32, 10, 0, 0, 550)
  88. };
  89. const short items_size = sizeof(items) / sizeof(Item);
  90. const short ITEMS_INDEX = 8 - ITEMS_STOCK;
  91. const short potions_size = sizeof(potions) / sizeof(Item);
  92. const short elixers_size = sizeof(elixers) / sizeof(Item);
  93. Shop shop;
  94.  
  95. int main(int argc, char *args[])
  96. {
  97. system("TITLE RPG Game");
  98. char keypress;
  99. short area_lvl = 1;
  100. boolean start = true;
  101. cout << "Welcome to my little console RPG." << endl;
  102. cout << "A character will be created for you to start with." << endl;
  103. cout << "Your character starts at level 1 with 0 experience." << endl;
  104. cout << "Your character starts with a purse of 50 gold." << endl << endl;
  105. cout << "Enter your new character's name: ";
  106. string name;
  107. cin >> name;
  108. // Create a player with
  109. // 100 hitpoints
  110. // 15 strength
  111. // 1 armor
  112. // 33 attack rating
  113. Player p = Player(name, 100, 15, 1, 33);
  114. do
  115. {
  116. system("cls");
  117. if (!start)
  118. cout << "Welcome back " << p.getName() << endl;
  119. else
  120. {
  121. system("cls");
  122. cout << "Welcome to the console realm " << name << "! " << endl;
  123. cout << "From here you will start your adventure. " << endl;
  124. cout << "Buy items to increase your character's stats. " << endl;
  125. cout << "When you want to buy items, be sure to check. " << endl;
  126. cout << "your character's stats. This will give you a " << endl;
  127. cout << "better view of your character's needs. " << endl << endl;
  128. cout << "In the combat zone you can fight against random " << endl;
  129. cout << "monsters. Each time you kill a monster, your " << endl;
  130. cout << "character will gain experience. When enough " << endl;
  131. cout << "experience points are earned, your character " << endl;
  132. cout << "will gain a level. Monsters will have a random " << endl;
  133. cout << "chance to drop gold or items. Monsters will get " << endl;
  134. cout << "stronger and harder to kill when you gain levels." << endl << endl << endl;
  135. start = false;
  136. }
  137. cout << "Choose your path." << endl << endl;
  138. cout << "(B)uy items" << endl;
  139. cout << "(V)iew character stats" << endl;
  140. cout << "(C)ombat zone" << endl;
  141. cout << "(H)ealer" << endl;
  142. cout << "(Q)uit" << endl;
  143. do keypress = _getch(); while (keypress != 'B' && keypress != 'b' && keypress != 'V' && keypress != 'v' && keypress != 'C' && keypress != 'c' && keypress != 'H' && keypress != 'h' && keypress != 'Q' && keypress != 'q');
  144. system("cls");
  145. if (keypress == 'B' || keypress == 'b')
  146. {
  147. shop.inv.clear();
  148. shop.resetStock();
  149. createStock(area_lvl, items, items_size, ITEMS_STOCK);
  150. createStock(area_lvl, potions, potions_size, POTIONS_STOCK);
  151. createStock(area_lvl, elixers, elixers_size, ELIXERS_STOCK);
  152. short inventory = shop.inv.getSize();
  153. if (inventory > 0)
  154. {
  155. Item *new_item;
  156. Item *old_item;
  157. short gold;
  158. short size;
  159. short slot;
  160. do
  161. {
  162. cout << "ITEMS SHOP" << endl << endl;
  163. for (short i = 0; i < inventory; ++i)
  164. {
  165. cout << i + 1 << ". " << (shop.inv.getItem(i))->getName() << " " << shop.inv.getItem(i)->getGoldCost() << " gold (" << shop.getStock(i) << " in stock)" << endl;
  166. }
  167. cout << "6. Sell unused items" << endl;
  168. cout << "7. Leave Shop" << endl;
  169. cout << endl << "Which item do you want to buy? ";
  170. do keypress = _getch(); while (keypress < '1' || keypress > '7'); //This works because chars are in fact 8 bits integers
  171. cout << endl << endl;
  172. if (keypress == '6')
  173. {
  174. gold = p.getGold();
  175. size = p.inv.getSize();
  176. for (short i = 0; i < size; ++i)
  177. {
  178. old_item = p.inv.getItem(i);
  179. if (!old_item->equipped())
  180. shop.sellItem(&p, *old_item);
  181. }
  182. if (gold == p.getGold())
  183. cout << endl << endl << "You have no unused items to sell." << endl;
  184. }
  185. else if (keypress == '7')
  186. break;
  187. else
  188. {
  189. slot = keypress - 49; //ASCII char 1 starts at 49 and char 5 ends at 53
  190. if (shop.getStock(slot) > 0)
  191. {
  192. new_item = shop.inv.getItem(slot);
  193. if (shop.buyItem(&p, *new_item))
  194. {
  195. shop.lowerStock(slot);
  196. useItem(&p, new_item);
  197. }
  198. }
  199. else
  200. cout << "Sorry, that item is currently out of stock." << endl;
  201. }
  202. cout << "Press any key...";
  203. _getch();
  204. system("cls");
  205. } while (1);
  206. }
  207. else
  208. cout << "I'm currently out of stock, please come back later." << endl;
  209. }
  210. else if (keypress == 'V' || keypress == 'v')
  211. {
  212. Item *item;
  213. cout << "CHARACTER STATS" << endl << endl;
  214. cout << "Hitpoints : " << p.getHp() << "/" << p.getHpMax() << endl;
  215. cout << "Strength : " << p.getStr() << endl;
  216. cout << "Armor : " << p.getArm() << endl;
  217. cout << "Attack rating: " << p.getAr() << endl;
  218. cout << "Total experience: " << p.getXp() << endl;
  219. cout << "Experience needed for level up: " << (p.getLvl() * LVL_BASE_XP) + ((p.getLvl() - 1) * LVL_BASE_XP) - p.getXp() << endl;
  220. cout << "Level: " << p.getLvl() << endl;
  221. cout << "Gold: " << p.getGold() << endl << endl;
  222. cout << "INVENTORY" << endl << endl;
  223. for (short i = 0; i < p.inv.getSize(); ++i)
  224. {
  225. item = p.inv.getItem(i);
  226. string equipped;
  227. if (item->getType() != potion && item->getType() != elixer)
  228. {
  229. if (item->equipped())
  230. equipped = " (equipped)";
  231. else
  232. equipped = " (not equipped)";
  233. cout << item->getName() << equipped << endl;
  234. }
  235. else
  236. cout << item->getName() << endl;
  237. }
  238. cout << "Press any key...";
  239. _getch();
  240. }
  241. else if (keypress == 'C' || keypress == 'c')
  242. {
  243. string name = names[Randomize(0, 9)];
  244. short monster_hp = 1;//(area_lvl * 100 / 5);
  245. short str = p.getStr() - 4 + Randomize(0, 8);
  246. short arm = p.getArm() - 2 + Randomize(0, 4);
  247. short ar = p.getAr() - 8 + Randomize(0, 16);
  248. Monster m = Monster(name, monster_hp, str, arm, ar, area_lvl);
  249. short player_hp = p.getHp();
  250. Item *item;
  251. short size;
  252. short healed_hp;
  253. cout << "COMBAT ZONE" << endl << endl;
  254. do
  255. {
  256. keypress = 'n'; //Just making sure that the loop isn't exited unexpected
  257. doTurn(&p, &m, &monster_hp); //Player's turn
  258. if (monster_hp <= 0) //No need to do another turn when the monster is killed
  259. break;
  260. doTurn(&m, &p, &player_hp); //Monster's turn
  261. if (player_hp <= p.getHpMax() / 2)
  262. {
  263. size = p.inv.getSize();
  264. for (short i = 0; i < size; ++i)
  265. {
  266. item = p.inv.getItem(i);
  267. if (item->getType() == potion)
  268. {
  269. if (player_hp + item->getHpBonus() < p.getHpMax())
  270. healed_hp = item->getHpBonus();
  271. else
  272. healed_hp = item->getHpBonus() - (player_hp - p.getHpMax());
  273. p.inv.removeItem(*item);
  274. player_hp += healed_hp;
  275. cout << p.getName() << " drinks a potion and heals " << healed_hp << " hitpoints." << endl;
  276. break;
  277. }
  278. }
  279. }
  280. if (player_hp > 0 && player_hp <= 20 && monster_hp > 0)
  281. {
  282. cout << endl << "You are badly hurt! Do you want to flee? (y/n) ";
  283. do keypress = _getch(); while (keypress != 'Y' && keypress != 'y' && keypress != 'N' && keypress != 'n');
  284. }
  285. cout << endl << endl;
  286. } while ((player_hp > 0 && monster_hp > 0) && (keypress == 'N' || keypress == 'n'));
  287. p.setHp(player_hp);
  288. if (monster_hp <= 0 && player_hp > 0)
  289. {
  290. int chance = Randomize(1, 100);
  291. m.setXp(LVL_BASE_XP / m.getLvl() + Randomize(0, LVL_BASE_XP));
  292. p.setXp(p.getXp() + m.getXp());
  293. if (((p.getLvl() * LVL_BASE_XP) + ((p.getLvl() - 1) * LVL_BASE_XP) - p.getXp()) <= 0)
  294. {
  295. cout << "Congratulations, you just gained a level!" << endl;
  296. p.setLvl(p.getLvl() + 1);
  297. area_lvl += Randomize(0, 2);
  298. p.setHpMax(p.getHpMax() + HP_GAIN);
  299. p.setStr(p.getStr() + STR_GAIN);
  300. p.setArm(p.getArm() + ARM_GAIN);
  301. p.setAr(p.getAr() + AR_GAIN);
  302. }
  303. if (chance <= m.elixer_chance)
  304. {
  305. cout << "ELIXER DROP" << endl;
  306. getDrop(m.getLvl(), elixers, elixers_size, &m, &p);
  307. }
  308. else if (chance <= m.item_chance)
  309. {
  310. cout << "ITEM DROP" << endl;
  311. getDrop(m.getLvl(), items, items_size, &m, &p);
  312. }
  313. else if (chance <= m.potion_chance)
  314. {
  315. cout << "POTION DROP" << endl;
  316. getDrop(m.getLvl(), potions, potions_size, &m, &p);
  317. }
  318. m.setGold(Randomize(m.getLvl() * 25, m.getLvl() * 50));
  319. cout << "You loot " << m.getName() << "'s corpse and got " << m.getGold() << " gold!" << endl;
  320. p.setGold(p.getGold() + m.getGold());
  321. }
  322. else if (player_hp <= 0)
  323. {
  324. cout << p.getName() << " was slain by " << m.getName() << endl;
  325. p.inv.clear();
  326. p.setHp(100);
  327. p.setHpMax(100);
  328. p.setStr(15);
  329. p.setArm(1);
  330. p.setAr(50);
  331. p.setXp(0);
  332. p.setLvl(1);
  333. p.setGold(50);
  334. start = true;
  335. }
  336. else
  337. cout << p.getName() << " has escaped a certain death." << endl;
  338. // Create a new stock for the shop
  339. shop.inv.clear();
  340. shop.resetStock();
  341. createStock(area_lvl, items, items_size, ITEMS_STOCK);
  342. createStock(area_lvl, potions, potions_size, POTIONS_STOCK);
  343. createStock(area_lvl, elixers, elixers_size, ELIXERS_STOCK);
  344. cout << "Press any key...";
  345. _getch();
  346. }
  347. else if (keypress == 'H' || keypress == 'h')
  348. {
  349. cout << "HEALER" << endl << endl;
  350. if (p.getHp() < p.getHpMax())
  351. {
  352. cout << "I only ask a minor 10 gold for my healing services." << endl;
  353. cout << "Do you want me to heal you? (y/n) ";
  354. do keypress = _getch(); while (keypress != 'Y' && keypress != 'y' && keypress != 'N' && keypress != 'n');
  355. cout << endl << endl << endl;
  356. if (keypress == 'Y' || keypress == 'y')
  357. {
  358. if (p.getGold() >= 10)
  359. {
  360. cout << "The healer looks at your injuries and tends to them." << endl;
  361. cout << "You feel refreshed and ready for another round of combat." << endl;
  362. p.setGold(p.getGold() - 10);
  363. p.setHp(p.getHpMax());
  364. }
  365. else
  366. cout << "Sorry, but you don't have enough gold to pay for my services." << endl;
  367. }
  368. else
  369. cout << "Step by whenever you think you need my services, goodbye!" << endl;
  370. }
  371. else
  372. cout << "The healer inspects you and says that you don't need his services." << endl;
  373. cout << "Press any key...";
  374. _getch();
  375. }
  376. else if (keypress == 'Q' || keypress == 'q')
  377. {
  378. cout << "Thank you for playing, goodbye!" << endl;
  379. }
  380. } while (keypress != 'Q' && keypress != 'q');
  381. return 0;
  382. }
  383.  
  384. int Randomize(int low, int high)
  385. {
  386. // 32767 / 32767 + 1 will cause the high value to never be returned
  387. // I added 1 to the high to make sure the chance exists that high is returned
  388. // Why not just remove the 1.0? That would make the chance for high very low
  389. // By adding 1 to high you don't have to hope for rand to return RAND_MAX
  390. srand(GetTickCount());
  391. return (int)(rand() / (RAND_MAX + 1.0) * (high + 1 - low) + low);
  392. }
  393.  
  394. void doTurn(Player *attacker, Player *target, short *hp)
  395. {
  396. short damage;
  397.  
  398. damage = ((attacker->getStr() + attacker->getLvl()) * 2 / 3) - target->getArm() - Randomize(0, 10);
  399. if (damage <= 0)
  400. damage = 1;
  401. if (attacker->getAr() <= Randomize(1, 100))
  402. {
  403. if (damage < *hp)
  404. cout << attacker->getName() << " attacks and deals " << damage << " damage to " << target->getName() << endl;
  405. else
  406. cout << attacker->getName() << " attacks and kills " << target->getName() << endl;
  407. *hp -= damage;
  408. }
  409. else
  410. cout << attacker->getName() << " tries to hit " << target->getName() << " but misses!" << endl;
  411. Sleep(1000);
  412. }
  413.  
  414. void createStock(short area_lvl, const Item *goods, const short size, short qty)
  415. {
  416. short ilvl;
  417. short itype;
  418. short random;
  419. for (short i = 0; i < size && qty > 0; ++i)
  420. {
  421. ilvl = goods[i].getLvlReq();
  422. if (ilvl >= area_lvl || ilvl == MAX_LVL)
  423. {
  424. itype = goods[i].getType(); // Only need to check once, there are 3 different item categories
  425. random = Randomize(0, ITEMS_INDEX + 1); //Add items in a random way above and below the current area level
  426. if (itype != potion && itype != elixer)
  427. {
  428. for (; qty > 0; --qty)
  429. {
  430. if (Randomize(0, 2) == 0 || i < 2)
  431. shop.inv.addItem(goods[i + qty + random]);
  432. else
  433. shop.inv.addItem(goods[i - qty - random]);
  434. shop.setStock(Randomize(1, 2));
  435. }
  436. }
  437. else
  438. {
  439. shop.inv.addItem(goods[i]);
  440. shop.setStock(Randomize(1, 4));
  441. --qty;
  442. }
  443. }
  444. }
  445. }
  446.  
  447. void getDrop(short mlvl, const Item *goods, const short size, Monster *m, Player *p)
  448. {
  449. const Item *new_item;
  450. short ilvl;
  451. short itype;
  452. short random;
  453. bool added = false;
  454. for (short i = 0; i < size; ++i)
  455. {
  456. ilvl = goods[i].getLvlReq();
  457. if (ilvl >= mlvl || ilvl == MAX_LVL)
  458. {
  459. itype = goods[i].getType();
  460. random = Randomize(0, ITEMS_INDEX + ITEMS_STOCK); //Add items in a random way above and below the current area level
  461. if (itype != potion && itype != elixer) // Only need to check once, there are 3 different item categories
  462. {
  463. if (Randomize(0, 2) == 0 || i < random)
  464. {
  465. new_item = goods + i + random;
  466. if (p->inv.addItem(goods[i + random]))
  467. {
  468. added = true;
  469. break;
  470. }
  471. }
  472. else
  473. {
  474. new_item = goods + i - random;
  475. if (p->inv.addItem(goods[i - random]))
  476. {
  477. added = true;
  478. break;
  479. }
  480. }
  481. }
  482. else
  483. new_item = goods + i;
  484. if (p->inv.addItem(goods[i]))
  485. {
  486. added = true;
  487. break;
  488. }
  489. }
  490. }
  491. if (added)
  492. {
  493. cout << m->getName() << " dropped a " << new_item->getName() << endl;
  494. useItem(p, new_item);
  495. }
  496. }
  497.  
  498. void useItem(Player *p, const Item *new_item)
  499. {
  500. Item *old_item;
  501. short itype = new_item->getType();
  502. bool add_bonus = false;
  503. if (itype != potion && itype != elixer)
  504. {
  505. short size = p->inv.getSize();
  506. for (short i = 0; i < size; ++i)
  507. {
  508. old_item = p->inv.getItem(i);
  509. if (itype == old_item->getType())
  510. {
  511. if ((new_item->getLvlReq() > old_item->getLvlReq()) && old_item->equipped())
  512. {
  513. old_item->unequip();
  514. p->setHpMax(p->getHpMax() - old_item->getHpBonus());
  515. p->setStr(p->getStr() - old_item->getStrBonus());
  516. p->setArm(p->getArm() - old_item->getArmBonus());
  517. p->setAr(p->getAr() - old_item->getArBonus());
  518. break;
  519. }
  520. }
  521. }
  522. if (!old_item->equipped())
  523. {
  524. add_bonus = true;
  525. p->inv.getItem(size - 1)->equip();
  526. }
  527. }
  528. else if (itype == elixer)
  529. {
  530. add_bonus = true;
  531. p->inv.removeItem(*new_item);
  532. }
  533. if (add_bonus)
  534. {
  535. p->setHpMax(p->getHpMax() + new_item->getHpBonus());
  536. p->setStr(p->getStr() + new_item->getStrBonus());
  537. p->setArm(p->getArm() + new_item->getArmBonus());
  538. p->setAr(p->getAr() + new_item->getArBonus());
  539. }
  540. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement