|
|
#include <iostream>
|
|
#include <thread>
|
|
#include <chrono>
|
|
#include <random>
|
|
#include <fstream>
|
|
|
|
#include "lib/Character.hpp"
|
|
#include "lib/Spell.hpp"
|
|
|
|
#define INTERVAL 1000
|
|
#define FLAG_INTERVAL 250
|
|
|
|
Spell spellBook[] = {
|
|
Spell("Spanish Inquisition", 1, 111111, 0),
|
|
Spell("Mana Bolt", 1, 5, 1),
|
|
Spell("Flame Bolt", 1, 8, 2),
|
|
Spell("Mana Flare", 1, 10, 3),
|
|
Spell("Ice Spear", 1, 13, 4),
|
|
Spell("Mana Misile", 1, 15, 5),
|
|
Spell("Thunder Strike", 1, 18, 6),
|
|
Spell("Mana Blast", 1, 20, 7),
|
|
};
|
|
|
|
void sleep(int ms)
|
|
{
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
|
|
}
|
|
|
|
int strlen(const char *msg)
|
|
{
|
|
int i = 0;
|
|
while (msg[i] != '\x00')
|
|
{
|
|
i++;
|
|
}
|
|
return i;
|
|
}
|
|
|
|
int getLowest(int a, int b)
|
|
{
|
|
return (a < b) ? a : b;
|
|
}
|
|
|
|
int getHighest(int a, int b)
|
|
{
|
|
return (a > b) ? a : b;
|
|
}
|
|
|
|
void intervalPrint(const char *msg, int interval = 1000, int len = 0)
|
|
{
|
|
if (len <= 0)
|
|
{
|
|
len = strlen(msg);
|
|
}
|
|
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
std::cout << msg[i] << std::flush;
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
void intervalPrint(std::string &msg, int interval = 1000, int len = 0)
|
|
{
|
|
if (len <= 0)
|
|
{
|
|
len = msg.length();
|
|
}
|
|
|
|
for (int i = 0; i < len; i++)
|
|
{
|
|
std::cout << msg.at(i) << std::flush;
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
|
|
}
|
|
std::cout << std::endl;
|
|
}
|
|
|
|
int getNumber(const char *prompt, int min, int max)
|
|
{
|
|
int tmp = 0;
|
|
std::cout << prompt;
|
|
while (!(std::cin >> tmp) && (tmp >= min && tmp <= max))
|
|
{
|
|
if (std::cin.eofbit)
|
|
{
|
|
exit(1);
|
|
}
|
|
std::cin.get();
|
|
std::cin.clear();
|
|
std::cin.ignore(4096, '\x00');
|
|
// std::cin.ignore(4096, '\n');
|
|
std::cout << prompt;
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
Character *chooseEnemy()
|
|
{
|
|
Character Enemies[] = {
|
|
Character("Red Mage", 1, 1, 10, 5, 1, 1),
|
|
Character("Green Mage", 2, 3, 20, 10, 1, 1),
|
|
Character("Blue Mage", 3, 7, 40, 25, 1, 1),
|
|
Character("White Mage", 4, 11, 80, 40, 1, 1),
|
|
Character("Black Mage", 5, 16, 160, 80, 1, 1),
|
|
};
|
|
std::cout << "List of challenger:" << std::endl;
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
std::cout << "[" << i << "] " << Enemies[i].getName() << std::endl;
|
|
}
|
|
|
|
int choice = 0;
|
|
choice = getNumber("Choose your enemy: ", 0, 4);
|
|
return new Character(Enemies[choice]);
|
|
}
|
|
|
|
Character *generatePlayer()
|
|
{
|
|
const char *playerNames[] = {
|
|
"Abby",
|
|
"John",
|
|
"Adam",
|
|
"Johny",
|
|
"Christo",
|
|
"Greg",
|
|
};
|
|
Character *tmp = new Character(
|
|
playerNames[std::rand() % 6],
|
|
1,
|
|
1,
|
|
100,
|
|
50,
|
|
1,
|
|
1);
|
|
|
|
return tmp;
|
|
}
|
|
|
|
std::string loadFlag()
|
|
{
|
|
std::string tmp;
|
|
std::ifstream flagFile("flag.txt");
|
|
if (flagFile.is_open())
|
|
{
|
|
flagFile >> tmp;
|
|
}
|
|
return tmp;
|
|
}
|
|
|
|
void printCharacterInfo(Character *c)
|
|
{
|
|
std::cout << "Name : " << c->getName() << std::endl
|
|
<< "HP : " << c->getCurHP() << "/" << c->getMaxHP() << std::endl
|
|
<< "MP : " << c->getCurMP() << "/" << c->getMaxMP() << std::endl;
|
|
}
|
|
|
|
void printCharacterFullInfo(Character *c)
|
|
{
|
|
std::cout << "Name : " << c->getName() << std::endl
|
|
<< "Level: " << c->getLevel() << std::endl
|
|
<< "Exp : " << c->getExperience() << " | next: " << c->toNextLevel() << std::endl
|
|
<< "HP : " << c->getCurHP() << "/" << c->getMaxHP() << std::endl
|
|
<< "MP : " << c->getCurMP() << "/" << c->getMaxMP() << std::endl;
|
|
}
|
|
|
|
Character *startBattle(Character *p1, Character *p2)
|
|
{
|
|
int maxTurn = 1000;
|
|
int turn = 0;
|
|
std::cout << "===== BATTLE START ======" << std::endl;
|
|
while ((p1->isAlive() && p2->isAlive()) && (++turn <= maxTurn))
|
|
{
|
|
std::cout << "== Turn " << turn << " ==" << std::endl;
|
|
std::cout << "Player =====" << std::endl;
|
|
printCharacterInfo(p1);
|
|
|
|
std::cout << "Enemy ======" << std::endl;
|
|
printCharacterInfo(p2);
|
|
|
|
std::cout << "===== Spell Books =====" << std::endl;
|
|
for (int i = 1; i <= p1->getLevel() && i < 8; i++)
|
|
{
|
|
std::cout << "[" << i << "] " << spellBook[i].getName() << std::endl;
|
|
}
|
|
|
|
int p1Choice = getNumber("Choose your spell: ", 0, getLowest(p1->getLevel(), 8 - 1));
|
|
int p2Choice = (std::rand() % getLowest(p2->getLevel(), 8 - 1)) + 1;
|
|
|
|
Spell *p1Spell = &spellBook[p1Choice];
|
|
Spell *p2Spell = &spellBook[p2Choice];
|
|
|
|
if (p1->canCastSpell(p1Spell))
|
|
{
|
|
p1->castSpell(p1Spell, p2);
|
|
std::cout << p1->getName() << " cast " << p1Spell->getName() << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << p2->getName() << " took " << p1Spell->getAmount() << " damage" << std::endl;
|
|
sleep(INTERVAL);
|
|
}
|
|
else
|
|
{
|
|
std::cout << p1->getName() << " failed to cast " << p1Spell->getName() << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << p1->getName() << " does not have enough MP to cast it!" << std::endl;
|
|
sleep(INTERVAL);
|
|
}
|
|
|
|
if (p2->canCastSpell(p2Spell))
|
|
{
|
|
p2->castSpell(p2Spell, p1);
|
|
std::cout << p2->getName() << " cast " << p2Spell->getName() << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << p1->getName() << " took " << p2Spell->getAmount() << " damage" << std::endl;
|
|
sleep(INTERVAL);
|
|
}
|
|
else
|
|
{
|
|
std::cout << p2->getName() << " failed to cast " << p2Spell->getName() << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << p2->getName() << " does not have enough MP to cast it!" << std::endl;
|
|
sleep(INTERVAL);
|
|
}
|
|
}
|
|
|
|
Character *winner;
|
|
|
|
if (turn >= maxTurn)
|
|
{
|
|
std::cout << "The battle took too long, a winner has to be decided." << std::endl;
|
|
winner = (p1->getCurHP() > p2->getCurHP()) ? p1 : p2;
|
|
}
|
|
else
|
|
{
|
|
winner = (p1->isAlive()) ? p1 : p2;
|
|
}
|
|
|
|
return winner;
|
|
}
|
|
|
|
int main()
|
|
{
|
|
std::srand(std::time(0));
|
|
std::string flag = loadFlag();
|
|
Character *player = generatePlayer();
|
|
Character *archMage = new Character("Arch-Mage", 999, 999999, 999999, 999999, 1, 1);
|
|
|
|
std::cout << "Welcome to SpellWarz!" << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "You are a young mage named '" << player->getName() << "'" << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "Here's your flag: ";
|
|
|
|
intervalPrint(flag, FLAG_INTERVAL, 13);
|
|
|
|
std::cout << "Oh no!" << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "The Arch-Mage took your flag!" << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "He said you are not worthy of it," << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "defeat him to get it back!" << std::endl;
|
|
sleep(INTERVAL);
|
|
|
|
while (player->isAlive())
|
|
{
|
|
std::cout << "========================================" << std::endl;
|
|
printCharacterFullInfo(player);
|
|
|
|
std::cout << "========================================" << std::endl
|
|
<< "[1] Sleep" << std::endl
|
|
<< "[2] Meditate" << std::endl
|
|
<< "[3] Spar with other mages" << std::endl
|
|
<< "[4] Search info about Arch-Mage" << std::endl
|
|
<< "[5] Challenge the Arch-Mage" << std::endl
|
|
<< "[0] Give up on life" << std::endl;
|
|
|
|
int choice = getNumber("Choose your action: ", 0, 5);
|
|
std::cout << "========================================" << std::endl;
|
|
|
|
if (choice == 0)
|
|
{
|
|
std::cout << "Farewell young mage, see you in the afterlife..." << std::endl;
|
|
player->reduceHP(player->getMaxHP());
|
|
}
|
|
if (choice == 1)
|
|
{
|
|
std::cout << "You take a rest in your dormitory..." << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "You recovered to full HP and MP" << std::endl;
|
|
sleep(INTERVAL);
|
|
player->restoreHP(player->getMaxHP());
|
|
player->restoreMP(player->getMaxMP());
|
|
}
|
|
if (choice == 2)
|
|
{
|
|
int tmp;
|
|
tmp = (rand() % 10) + 1;
|
|
std::cout << "You meditate on your mana..." << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "And got " << tmp << " experience!" << std::endl;
|
|
sleep(INTERVAL);
|
|
player->increaseExperience(tmp);
|
|
if (player->readytoLevelUp())
|
|
{
|
|
std::cout << "Congratulations, you leveled up!" << std::endl;
|
|
while (player->readytoLevelUp())
|
|
{
|
|
player->levelUp();
|
|
}
|
|
sleep(200);
|
|
}
|
|
}
|
|
if (choice == 3)
|
|
{
|
|
Character *enemy = new Character(*chooseEnemy());
|
|
Character *winner = startBattle(player, enemy);
|
|
if (winner == player)
|
|
{
|
|
std::cout << "You win! You got " << enemy->getExperience() << "exp" << std::endl;
|
|
sleep(INTERVAL);
|
|
player->increaseExperience(enemy->getExperience());
|
|
if (player->readytoLevelUp())
|
|
{
|
|
std::cout << "Congratulations, you leveled up!" << std::endl;
|
|
while (player->readytoLevelUp())
|
|
{
|
|
player->levelUp();
|
|
}
|
|
sleep(200);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (!player->isAlive())
|
|
{
|
|
player->restoreHP(1);
|
|
}
|
|
std::cout << "You lose the fight, it was a fair fight." << std::endl;
|
|
sleep(INTERVAL);
|
|
}
|
|
}
|
|
if (choice == 4)
|
|
{
|
|
std::cout << "You are searching info about the Arch-Mage..." << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "Here's some info about the Arch-Mage:" << std::endl;
|
|
printCharacterFullInfo(archMage);
|
|
}
|
|
if (choice == 5)
|
|
{
|
|
if (archMage->isAlive())
|
|
{
|
|
std::cout << "You are challenging the Arch-Mage" << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "Arch-Mage: ";
|
|
sleep(INTERVAL);
|
|
intervalPrint("so you have come to challenge me. Prepare to die!", 200);
|
|
|
|
Character *winner = startBattle(player, archMage);
|
|
if (winner == player)
|
|
{
|
|
std::cout << "You win! You got " << archMage->getExperience() << "exp" << std::endl;
|
|
player->increaseExperience(archMage->getExperience());
|
|
sleep(INTERVAL);
|
|
if (player->readytoLevelUp())
|
|
{
|
|
std::cout << "Congratulations, you leveled up!" << std::endl;
|
|
while (player->readytoLevelUp())
|
|
{
|
|
player->levelUp();
|
|
}
|
|
sleep(200);
|
|
}
|
|
std::cout << "You did a good job! Now you are the Arch-Mage!" << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "Here's the flag the previous Arch-Mage took from you: " << std::endl;
|
|
sleep(INTERVAL);
|
|
intervalPrint(flag, FLAG_INTERVAL);
|
|
}
|
|
else
|
|
{
|
|
std::cout << "You lose the fight..." << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "Unfortunately, the Arch-Mage was serious about this fight..." << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "You were killed in battle..." << std::endl;
|
|
intervalPrint("GAME OVER", 250);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::cout << "You are the Arch-Mage now." << std::endl;
|
|
sleep(INTERVAL);
|
|
std::cout << "Here's your flag:";
|
|
sleep(INTERVAL);
|
|
intervalPrint(flag, FLAG_INTERVAL);
|
|
}
|
|
}
|
|
}
|
|
}
|