Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //*************************
- //****** Console RPG ******
- //****** Version 1.0 ******
- //*************************
- #include <windows.h>
- #include "monster.h"
- int Randomize(int, int);
- void doTurn(Player *, Player *, short *);
- void createStock(short, const Item *, const short, short);
- void getDrop(short, const Item *, const short, Monster *, Player *);
- void useItem(Player *, const Item *);
- const short HP_GAIN = 5;
- const short STR_GAIN = 2;
- const short ARM_GAIN = 1;
- const short AR_GAIN = 2;
- const short LVL_BASE_XP = 100;
- const short MAX_LVL = 20;
- const short ITEMS_STOCK = 3;
- const short POTIONS_STOCK = 1;
- const short ELIXERS_STOCK = 1;
- const string names[] = {"Andariel", "Duriel", "Mephisto", "Diablo", "Baal", "Lilith", "Uber Duriel", "Uber Mephisto", "Uber Diablo", "Uber Baal"};
- const Item items[] =
- {
- Item("Sword", weapon, 1, 0, 5, 0, 10, 750, false),
- Item("Armor", armor, 1, 0, 5, 0, 10, 750, false),
- Item("Shield", shield, 1, 0, 5, 0, 10, 750, false),
- Item("Helm", helm, 1, 0, 5, 0, 10, 750, false),
- Item("Belt", belt, 1, 0, 5, 0, 10, 750, false),
- Item("Gloves", gloves, 1, 0, 5, 0, 10, 750, false),
- Item("Boots", boots, 1, 0, 5, 0, 10, 750, false),
- Item("Ring of lesser Health", ring, 1, 5, 0, 0, 10, 750, false),
- Item("Amulet of lesser Clarity", amulet, 1, 0, 5, 0, 10, 750, false),
- Item("Sturdy Sword", weapon, 5, 0, 5, 0, 10, 750, false),
- Item("Sturdy Helm", armor, 5, 0, 5, 0, 10, 750, false),
- Item("Sturdy Shield", shield, 5, 0, 5, 0, 10, 750, false),
- Item("Sturdy Helm", helm, 5, 0, 5, 0, 10, 750, false),
- Item("Sturdy Belt", belt, 5, 0, 5, 0, 10, 750, false),
- Item("Sturdy Gloves", gloves, 5, 0, 5, 0, 10, 750, false),
- Item("Sturdy Boots", boots, 5, 0, 5, 0, 10, 750, false),
- Item("Ring of Health", ring, 5, 10, 0, 0, 15, 750, false),
- Item("Amulet of Clarity", amulet, 5, 2, 5, 0, 10, 750, false),
- Item("Knight's Sword", weapon, 10, 0, 5, 0, 10, 750, false),
- Item("Knight's Armor", armor, 10, 0, 5, 0, 10, 750, false),
- Item("Knight's Shield", shield, 10, 0, 5, 0, 10, 750, false),
- Item("Knight's Helm", helm, 10, 0, 5, 0, 10, 750, false),
- Item("Knight's Belt", belt, 10, 0, 5, 0, 10, 750, false),
- Item("Knight's Gloves", gloves, 10, 0, 5, 0, 10, 750, false),
- Item("Knight's Boots", boots, 10, 0, 5, 0, 10, 750, false),
- Item("Ring of Power", ring, 10, 20, 5, 5, 10, 750, false),
- Item("Amulet of Agility", amulet, 10, 20, 0, 5, 30, 750, false),
- Item("Sword of the Colossus", weapon, 15, 0, 5, 0, 10, 750, false),
- Item("Armor of the Colossus", armor, 15, 0, 5, 0, 10, 750, false),
- Item("Shield of the Colossus", shield, 15, 0, 5, 0, 10, 750, false),
- Item("Helm of the Colossus", helm, 15, 0, 5, 0, 10, 750, false),
- Item("Belt of the Colossus", belt, 15, 0, 5, 0, 10, 750, false),
- Item("Gloves of the Colossus", gloves, 15, 0, 5, 0, 10, 750, false),
- Item("Boots of the Colossus", boots, 15, 0, 5, 0, 10, 750, false),
- Item("Ring of greater Health", ring, 15, 0, 5, 0, 10, 750, false),
- Item("Amulet of greater Clarity", amulet, 15, 0, 5, 0, 10, 750, false),
- Item("Sword of the Giant", weapon, 20, 0, 5, 0, 10, 750, false),
- Item("Armor of the Giant", armor, 20, 0, 5, 0, 10, 750, false),
- Item("Shield of the Giant", shield, 20, 0, 5, 0, 10, 750, false),
- Item("Helm of the Giant", helm, 20, 0, 5, 0, 10, 750, false),
- Item("Belt of the Giant", belt, 20, 0, 5, 0, 10, 750, false),
- Item("Gloves of the Giant", gloves, 20, 0, 5, 0, 10, 750, false),
- Item("Boots of the Giant", boots, 20, 0, 5, 0, 10, 750, false),
- Item("Ring of greatest Health", ring, 20, 40, 10, 0, 10, 750, false),
- Item("Amulet of greatest Clarity", amulet, 20, 40, 5, 5, 20, 750, false)
- };
- const Item potions[] =
- {
- Item("Minor Potion of Healing", potion, 1, 50, 0, 0, 0, 75),
- Item("Lesser Potion of Healing", potion, 5, 75, 0, 0, 0, 100),
- Item("Potion of Healing", potion, 10, 100, 0, 0, 0, 150),
- Item("Greater Potion of Healing", potion, 15, 125, 0, 0, 0, 200),
- Item("Super Potion of Healing", potion, 20, 150, 0, 0, 0, 250)
- };
- const Item elixers[] =
- {
- Item("Light Elixer", elixer, 1, 2, 1, 0, 0, 150),
- Item("Potent Elixer", elixer, 5, 4, 2, 0, 0, 250),
- Item("Strong Elixer", elixer, 10, 8, 3, 0, 0, 350),
- Item("Stronger Elixer", elixer, 15, 16, 5, 0, 0, 450),
- Item("Super Elixer", elixer, 20, 32, 10, 0, 0, 550)
- };
- const short items_size = sizeof(items) / sizeof(Item);
- const short ITEMS_INDEX = 8 - ITEMS_STOCK;
- const short potions_size = sizeof(potions) / sizeof(Item);
- const short elixers_size = sizeof(elixers) / sizeof(Item);
- Shop shop;
- int main(int argc, char *args[])
- {
- system("TITLE RPG Game");
- char keypress;
- short area_lvl = 1;
- boolean start = true;
- cout << "Welcome to my little console RPG." << endl;
- cout << "A character will be created for you to start with." << endl;
- cout << "Your character starts at level 1 with 0 experience." << endl;
- cout << "Your character starts with a purse of 50 gold." << endl << endl;
- cout << "Enter your new character's name: ";
- string name;
- cin >> name;
- // Create a player with
- // 100 hitpoints
- // 15 strength
- // 1 armor
- // 33 attack rating
- Player p = Player(name, 100, 15, 1, 33);
- do
- {
- system("cls");
- if (!start)
- cout << "Welcome back " << p.getName() << endl;
- else
- {
- system("cls");
- cout << "Welcome to the console realm " << name << "! " << endl;
- cout << "From here you will start your adventure. " << endl;
- cout << "Buy items to increase your character's stats. " << endl;
- cout << "When you want to buy items, be sure to check. " << endl;
- cout << "your character's stats. This will give you a " << endl;
- cout << "better view of your character's needs. " << endl << endl;
- cout << "In the combat zone you can fight against random " << endl;
- cout << "monsters. Each time you kill a monster, your " << endl;
- cout << "character will gain experience. When enough " << endl;
- cout << "experience points are earned, your character " << endl;
- cout << "will gain a level. Monsters will have a random " << endl;
- cout << "chance to drop gold or items. Monsters will get " << endl;
- cout << "stronger and harder to kill when you gain levels." << endl << endl << endl;
- start = false;
- }
- cout << "Choose your path." << endl << endl;
- cout << "(B)uy items" << endl;
- cout << "(V)iew character stats" << endl;
- cout << "(C)ombat zone" << endl;
- cout << "(H)ealer" << endl;
- cout << "(Q)uit" << endl;
- do keypress = _getch(); while (keypress != 'B' && keypress != 'b' && keypress != 'V' && keypress != 'v' && keypress != 'C' && keypress != 'c' && keypress != 'H' && keypress != 'h' && keypress != 'Q' && keypress != 'q');
- system("cls");
- if (keypress == 'B' || keypress == 'b')
- {
- shop.inv.clear();
- shop.resetStock();
- createStock(area_lvl, items, items_size, ITEMS_STOCK);
- createStock(area_lvl, potions, potions_size, POTIONS_STOCK);
- createStock(area_lvl, elixers, elixers_size, ELIXERS_STOCK);
- short inventory = shop.inv.getSize();
- if (inventory > 0)
- {
- Item *new_item;
- Item *old_item;
- short gold;
- short size;
- short slot;
- do
- {
- cout << "ITEMS SHOP" << endl << endl;
- for (short i = 0; i < inventory; ++i)
- {
- cout << i + 1 << ". " << (shop.inv.getItem(i))->getName() << " " << shop.inv.getItem(i)->getGoldCost() << " gold (" << shop.getStock(i) << " in stock)" << endl;
- }
- cout << "6. Sell unused items" << endl;
- cout << "7. Leave Shop" << endl;
- cout << endl << "Which item do you want to buy? ";
- do keypress = _getch(); while (keypress < '1' || keypress > '7'); //This works because chars are in fact 8 bits integers
- cout << endl << endl;
- if (keypress == '6')
- {
- gold = p.getGold();
- size = p.inv.getSize();
- for (short i = 0; i < size; ++i)
- {
- old_item = p.inv.getItem(i);
- if (!old_item->equipped())
- shop.sellItem(&p, *old_item);
- }
- if (gold == p.getGold())
- cout << endl << endl << "You have no unused items to sell." << endl;
- }
- else if (keypress == '7')
- break;
- else
- {
- slot = keypress - 49; //ASCII char 1 starts at 49 and char 5 ends at 53
- if (shop.getStock(slot) > 0)
- {
- new_item = shop.inv.getItem(slot);
- if (shop.buyItem(&p, *new_item))
- {
- shop.lowerStock(slot);
- useItem(&p, new_item);
- }
- }
- else
- cout << "Sorry, that item is currently out of stock." << endl;
- }
- cout << "Press any key...";
- _getch();
- system("cls");
- } while (1);
- }
- else
- cout << "I'm currently out of stock, please come back later." << endl;
- }
- else if (keypress == 'V' || keypress == 'v')
- {
- Item *item;
- cout << "CHARACTER STATS" << endl << endl;
- cout << "Hitpoints : " << p.getHp() << "/" << p.getHpMax() << endl;
- cout << "Strength : " << p.getStr() << endl;
- cout << "Armor : " << p.getArm() << endl;
- cout << "Attack rating: " << p.getAr() << endl;
- cout << "Total experience: " << p.getXp() << endl;
- cout << "Experience needed for level up: " << (p.getLvl() * LVL_BASE_XP) + ((p.getLvl() - 1) * LVL_BASE_XP) - p.getXp() << endl;
- cout << "Level: " << p.getLvl() << endl;
- cout << "Gold: " << p.getGold() << endl << endl;
- cout << "INVENTORY" << endl << endl;
- for (short i = 0; i < p.inv.getSize(); ++i)
- {
- item = p.inv.getItem(i);
- string equipped;
- if (item->getType() != potion && item->getType() != elixer)
- {
- if (item->equipped())
- equipped = " (equipped)";
- else
- equipped = " (not equipped)";
- cout << item->getName() << equipped << endl;
- }
- else
- cout << item->getName() << endl;
- }
- cout << "Press any key...";
- _getch();
- }
- else if (keypress == 'C' || keypress == 'c')
- {
- string name = names[Randomize(0, 9)];
- short monster_hp = 1;//(area_lvl * 100 / 5);
- short str = p.getStr() - 4 + Randomize(0, 8);
- short arm = p.getArm() - 2 + Randomize(0, 4);
- short ar = p.getAr() - 8 + Randomize(0, 16);
- Monster m = Monster(name, monster_hp, str, arm, ar, area_lvl);
- short player_hp = p.getHp();
- Item *item;
- short size;
- short healed_hp;
- cout << "COMBAT ZONE" << endl << endl;
- do
- {
- keypress = 'n'; //Just making sure that the loop isn't exited unexpected
- doTurn(&p, &m, &monster_hp); //Player's turn
- if (monster_hp <= 0) //No need to do another turn when the monster is killed
- break;
- doTurn(&m, &p, &player_hp); //Monster's turn
- if (player_hp <= p.getHpMax() / 2)
- {
- size = p.inv.getSize();
- for (short i = 0; i < size; ++i)
- {
- item = p.inv.getItem(i);
- if (item->getType() == potion)
- {
- if (player_hp + item->getHpBonus() < p.getHpMax())
- healed_hp = item->getHpBonus();
- else
- healed_hp = item->getHpBonus() - (player_hp - p.getHpMax());
- p.inv.removeItem(*item);
- player_hp += healed_hp;
- cout << p.getName() << " drinks a potion and heals " << healed_hp << " hitpoints." << endl;
- break;
- }
- }
- }
- if (player_hp > 0 && player_hp <= 20 && monster_hp > 0)
- {
- cout << endl << "You are badly hurt! Do you want to flee? (y/n) ";
- do keypress = _getch(); while (keypress != 'Y' && keypress != 'y' && keypress != 'N' && keypress != 'n');
- }
- cout << endl << endl;
- } while ((player_hp > 0 && monster_hp > 0) && (keypress == 'N' || keypress == 'n'));
- p.setHp(player_hp);
- if (monster_hp <= 0 && player_hp > 0)
- {
- int chance = Randomize(1, 100);
- m.setXp(LVL_BASE_XP / m.getLvl() + Randomize(0, LVL_BASE_XP));
- p.setXp(p.getXp() + m.getXp());
- if (((p.getLvl() * LVL_BASE_XP) + ((p.getLvl() - 1) * LVL_BASE_XP) - p.getXp()) <= 0)
- {
- cout << "Congratulations, you just gained a level!" << endl;
- p.setLvl(p.getLvl() + 1);
- area_lvl += Randomize(0, 2);
- p.setHpMax(p.getHpMax() + HP_GAIN);
- p.setStr(p.getStr() + STR_GAIN);
- p.setArm(p.getArm() + ARM_GAIN);
- p.setAr(p.getAr() + AR_GAIN);
- }
- if (chance <= m.elixer_chance)
- {
- cout << "ELIXER DROP" << endl;
- getDrop(m.getLvl(), elixers, elixers_size, &m, &p);
- }
- else if (chance <= m.item_chance)
- {
- cout << "ITEM DROP" << endl;
- getDrop(m.getLvl(), items, items_size, &m, &p);
- }
- else if (chance <= m.potion_chance)
- {
- cout << "POTION DROP" << endl;
- getDrop(m.getLvl(), potions, potions_size, &m, &p);
- }
- m.setGold(Randomize(m.getLvl() * 25, m.getLvl() * 50));
- cout << "You loot " << m.getName() << "'s corpse and got " << m.getGold() << " gold!" << endl;
- p.setGold(p.getGold() + m.getGold());
- }
- else if (player_hp <= 0)
- {
- cout << p.getName() << " was slain by " << m.getName() << endl;
- p.inv.clear();
- p.setHp(100);
- p.setHpMax(100);
- p.setStr(15);
- p.setArm(1);
- p.setAr(50);
- p.setXp(0);
- p.setLvl(1);
- p.setGold(50);
- start = true;
- }
- else
- cout << p.getName() << " has escaped a certain death." << endl;
- // Create a new stock for the shop
- shop.inv.clear();
- shop.resetStock();
- createStock(area_lvl, items, items_size, ITEMS_STOCK);
- createStock(area_lvl, potions, potions_size, POTIONS_STOCK);
- createStock(area_lvl, elixers, elixers_size, ELIXERS_STOCK);
- cout << "Press any key...";
- _getch();
- }
- else if (keypress == 'H' || keypress == 'h')
- {
- cout << "HEALER" << endl << endl;
- if (p.getHp() < p.getHpMax())
- {
- cout << "I only ask a minor 10 gold for my healing services." << endl;
- cout << "Do you want me to heal you? (y/n) ";
- do keypress = _getch(); while (keypress != 'Y' && keypress != 'y' && keypress != 'N' && keypress != 'n');
- cout << endl << endl << endl;
- if (keypress == 'Y' || keypress == 'y')
- {
- if (p.getGold() >= 10)
- {
- cout << "The healer looks at your injuries and tends to them." << endl;
- cout << "You feel refreshed and ready for another round of combat." << endl;
- p.setGold(p.getGold() - 10);
- p.setHp(p.getHpMax());
- }
- else
- cout << "Sorry, but you don't have enough gold to pay for my services." << endl;
- }
- else
- cout << "Step by whenever you think you need my services, goodbye!" << endl;
- }
- else
- cout << "The healer inspects you and says that you don't need his services." << endl;
- cout << "Press any key...";
- _getch();
- }
- else if (keypress == 'Q' || keypress == 'q')
- {
- cout << "Thank you for playing, goodbye!" << endl;
- }
- } while (keypress != 'Q' && keypress != 'q');
- return 0;
- }
- int Randomize(int low, int high)
- {
- // 32767 / 32767 + 1 will cause the high value to never be returned
- // I added 1 to the high to make sure the chance exists that high is returned
- // Why not just remove the 1.0? That would make the chance for high very low
- // By adding 1 to high you don't have to hope for rand to return RAND_MAX
- srand(GetTickCount());
- return (int)(rand() / (RAND_MAX + 1.0) * (high + 1 - low) + low);
- }
- void doTurn(Player *attacker, Player *target, short *hp)
- {
- short damage;
- damage = ((attacker->getStr() + attacker->getLvl()) * 2 / 3) - target->getArm() - Randomize(0, 10);
- if (damage <= 0)
- damage = 1;
- if (attacker->getAr() <= Randomize(1, 100))
- {
- if (damage < *hp)
- cout << attacker->getName() << " attacks and deals " << damage << " damage to " << target->getName() << endl;
- else
- cout << attacker->getName() << " attacks and kills " << target->getName() << endl;
- *hp -= damage;
- }
- else
- cout << attacker->getName() << " tries to hit " << target->getName() << " but misses!" << endl;
- Sleep(1000);
- }
- void createStock(short area_lvl, const Item *goods, const short size, short qty)
- {
- short ilvl;
- short itype;
- short random;
- for (short i = 0; i < size && qty > 0; ++i)
- {
- ilvl = goods[i].getLvlReq();
- if (ilvl >= area_lvl || ilvl == MAX_LVL)
- {
- itype = goods[i].getType(); // Only need to check once, there are 3 different item categories
- random = Randomize(0, ITEMS_INDEX + 1); //Add items in a random way above and below the current area level
- if (itype != potion && itype != elixer)
- {
- for (; qty > 0; --qty)
- {
- if (Randomize(0, 2) == 0 || i < 2)
- shop.inv.addItem(goods[i + qty + random]);
- else
- shop.inv.addItem(goods[i - qty - random]);
- shop.setStock(Randomize(1, 2));
- }
- }
- else
- {
- shop.inv.addItem(goods[i]);
- shop.setStock(Randomize(1, 4));
- --qty;
- }
- }
- }
- }
- void getDrop(short mlvl, const Item *goods, const short size, Monster *m, Player *p)
- {
- const Item *new_item;
- short ilvl;
- short itype;
- short random;
- bool added = false;
- for (short i = 0; i < size; ++i)
- {
- ilvl = goods[i].getLvlReq();
- if (ilvl >= mlvl || ilvl == MAX_LVL)
- {
- itype = goods[i].getType();
- random = Randomize(0, ITEMS_INDEX + ITEMS_STOCK); //Add items in a random way above and below the current area level
- if (itype != potion && itype != elixer) // Only need to check once, there are 3 different item categories
- {
- if (Randomize(0, 2) == 0 || i < random)
- {
- new_item = goods + i + random;
- if (p->inv.addItem(goods[i + random]))
- {
- added = true;
- break;
- }
- }
- else
- {
- new_item = goods + i - random;
- if (p->inv.addItem(goods[i - random]))
- {
- added = true;
- break;
- }
- }
- }
- else
- new_item = goods + i;
- if (p->inv.addItem(goods[i]))
- {
- added = true;
- break;
- }
- }
- }
- if (added)
- {
- cout << m->getName() << " dropped a " << new_item->getName() << endl;
- useItem(p, new_item);
- }
- }
- void useItem(Player *p, const Item *new_item)
- {
- Item *old_item;
- short itype = new_item->getType();
- bool add_bonus = false;
- if (itype != potion && itype != elixer)
- {
- short size = p->inv.getSize();
- for (short i = 0; i < size; ++i)
- {
- old_item = p->inv.getItem(i);
- if (itype == old_item->getType())
- {
- if ((new_item->getLvlReq() > old_item->getLvlReq()) && old_item->equipped())
- {
- old_item->unequip();
- p->setHpMax(p->getHpMax() - old_item->getHpBonus());
- p->setStr(p->getStr() - old_item->getStrBonus());
- p->setArm(p->getArm() - old_item->getArmBonus());
- p->setAr(p->getAr() - old_item->getArBonus());
- break;
- }
- }
- }
- if (!old_item->equipped())
- {
- add_bonus = true;
- p->inv.getItem(size - 1)->equip();
- }
- }
- else if (itype == elixer)
- {
- add_bonus = true;
- p->inv.removeItem(*new_item);
- }
- if (add_bonus)
- {
- p->setHpMax(p->getHpMax() + new_item->getHpBonus());
- p->setStr(p->getStr() + new_item->getStrBonus());
- p->setArm(p->getArm() + new_item->getArmBonus());
- p->setAr(p->getAr() + new_item->getArBonus());
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement