Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
165 changes: 165 additions & 0 deletions solutions/lab6/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#include "src/dragon.h"
#include "src/elf.h"
#include "src/knight_errant.h"
#include "src/npc.h"

class TextObserver : public IFightObserver {
private:
TextObserver(){};

public:
static std::shared_ptr<IFightObserver> get() {
static TextObserver instance;
return std::shared_ptr<IFightObserver>(&instance, [](IFightObserver *) {});
}

void on_fight(const std::shared_ptr<NPC> attacker,
const std::shared_ptr<NPC> defender, bool win) override {
if (win) {
std::cout << std::endl << "Murder --------" << std::endl;
attacker->print();
defender->print();
}
}
};

std::shared_ptr<NPC> factory(std::istream &is) {
std::shared_ptr<NPC> result;
int type{0};
if (is >> type) {
switch (type) {
case KnightErrantType:
result = std::make_shared<KnightErrant>(is);
break;
case ElfType:
result = std::make_shared<Elf>(is);
break;
case DragonType:
result = std::make_shared<Dragon>(is);
break;
}
} else
std::cerr << "unexpected NPC type:" << type << std::endl;

if (result)
result->subscribe(TextObserver::get());

return result;
}

std::shared_ptr<NPC> factory(NpcType type, int x, int y) {
std::shared_ptr<NPC> result;
switch (type) {
case KnightErrantType:
result = std::make_shared<KnightErrant>(x, y);
break;
case ElfType:
result = std::make_shared<Elf>(x, y);
break;
case DragonType:
result = std::make_shared<Dragon>(x, y);
break;
default:
break;
}
if (result)
result->subscribe(TextObserver::get());

return result;
}

void save(const set_t &array, const std::string &filename) {
std::ofstream fs(filename);
fs << array.size() << std::endl;
for (auto &n : array)
n->save(fs);
fs.flush();
fs.close();
}

set_t load(const std::string &filename) {
set_t result;
std::ifstream is(filename);
if (is.good() && is.is_open()) {
int count;
is >> count;
for (int i = 0; i < count; ++i)
result.insert(factory(is));
is.close();
} else
std::cerr << "Error: " << std::strerror(errno) << std::endl;
return result;
}

std::ostream &operator<<(std::ostream &os, const set_t &array) {
for (auto &n : array)
n->print();
return os;
}

class AttackerVisitor : public Visitor {
public:
AttackerVisitor(const std::shared_ptr<NPC> &attacker) : attacker_(attacker) {}

bool visit(KnightErrant &knight) override {
return attacker_->fight(std::make_shared<KnightErrant>(knight));
}
bool visit(Elf &elf) override {
return attacker_->fight(std::make_shared<Elf>(elf));
}
bool visit(Dragon &dragon) override {
return attacker_->fight(std::make_shared<Dragon>(dragon));
}

private:
std::shared_ptr<NPC> attacker_;
};

set_t fight(const set_t &array, size_t distance) {
set_t dead_list;

for (const auto &attacker : array) {
for (const auto &defender : array) {
if (attacker != defender && attacker->is_close(defender, distance)) {
AttackerVisitor visitor(attacker);
if (defender->accept(visitor)) {
dead_list.insert(defender);
}
}
}
}
return dead_list;
}

int main() {
set_t array;

std::cout << "Generating ..." << std::endl;
for (size_t i = 0; i < 10; ++i)
array.insert(factory(NpcType(std::rand() % 3 + 1), std::rand() % 100,
std::rand() % 100));
std::cout << "Saving ..." << std::endl;

save(array, "npc.txt");

std::cout << "Loading ..." << std::endl;
array = load("npc.txt");

std::cout << "Fighting ..." << std::endl << array;

for (size_t distance = 20; (distance <= 100) && !array.empty();
distance += 10) {
auto dead_list = fight(array, distance);
for (auto &d : dead_list)
array.erase(d);
std::cout << "Fight stats ----------" << std::endl
<< "distance: " << distance << std::endl
<< "killed: " << dead_list.size() << std::endl
<< std::endl
<< std::endl;
}

std::cout << "Survivors:" << array;

return 0;
}
35 changes: 35 additions & 0 deletions solutions/lab6/src/dragon.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "dragon.h"
#include "elf.h"
#include "knight_errant.h"

Dragon::Dragon(int x, int y) : NPC(DragonType, x, y) {}
Dragon::Dragon(std::istream &is) : NPC(DragonType, is) {}

void Dragon::print() { std::cout << *this; }

bool Dragon::accept(Visitor &visitor) { return visitor.visit(*this); }

bool Dragon::fight(std::shared_ptr<KnightErrant> other) {
fight_notify(other, true);
return true;
}

bool Dragon::fight(std::shared_ptr<Elf> other) {
fight_notify(other, true);
return true;
}

bool Dragon::fight(std::shared_ptr<Dragon> other) {
fight_notify(other, true);
return true;
}

void Dragon::save(std::ostream &os) {
os << DragonType << std::endl;
NPC::save(os);
}

std::ostream &operator<<(std::ostream &os, Dragon &dragon) {
os << "Dragon: " << *static_cast<NPC *>(&dragon) << std::endl;
return os;
}
19 changes: 19 additions & 0 deletions solutions/lab6/src/dragon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once
#include "npc.h"

struct Dragon : public NPC {
Dragon(int x, int y);
Dragon(std::istream &is);

void print() override;

bool accept(Visitor &visitor) override;

bool fight(std::shared_ptr<KnightErrant> other) override;
bool fight(std::shared_ptr<Elf> other) override;
bool fight(std::shared_ptr<Dragon> other) override;

void save(std::ostream &os) override;

friend std::ostream &operator<<(std::ostream &os, Dragon &dragon);
};
35 changes: 35 additions & 0 deletions solutions/lab6/src/elf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "elf.h"
#include "dragon.h"
#include "knight_errant.h"

Elf::Elf(int x, int y) : NPC(ElfType, x, y) {}
Elf::Elf(std::istream &is) : NPC(ElfType, is) {}

void Elf::print() { std::cout << *this; }

bool Elf::accept(Visitor &visitor) { return visitor.visit(*this); }

bool Elf::fight(std::shared_ptr<KnightErrant> other) {
fight_notify(other, true);
return true;
}

bool Elf::fight(std::shared_ptr<Elf> other) {
fight_notify(other, false);
return false;
}

bool Elf::fight(std::shared_ptr<Dragon> other) {
fight_notify(other, false);
return false;
}

void Elf::save(std::ostream &os) {
os << ElfType << std::endl;
NPC::save(os);
}

std::ostream &operator<<(std::ostream &os, Elf &elf) {
os << "Elf: " << *static_cast<NPC *>(&elf) << std::endl;
return os;
}
19 changes: 19 additions & 0 deletions solutions/lab6/src/elf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once
#include "npc.h"

struct Elf : public NPC {
Elf(int x, int y);
Elf(std::istream &is);

void print() override;

bool accept(Visitor &visitor) override;

bool fight(std::shared_ptr<KnightErrant> other) override;
bool fight(std::shared_ptr<Elf> other) override;
bool fight(std::shared_ptr<Dragon> other) override;

void save(std::ostream &os) override;

friend std::ostream &operator<<(std::ostream &os, Elf &elf);
};
35 changes: 35 additions & 0 deletions solutions/lab6/src/knight_errant.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include "knight_errant.h"
#include "dragon.h"
#include "elf.h"

KnightErrant::KnightErrant(int x, int y) : NPC(KnightErrantType, x, y) {}
KnightErrant::KnightErrant(std::istream &is) : NPC(KnightErrantType, is) {}

void KnightErrant::print() { std::cout << *this; }

bool KnightErrant::accept(Visitor &visitor) { return visitor.visit(*this); }

bool KnightErrant::fight(std::shared_ptr<KnightErrant> other) {
fight_notify(other, false);
return false;
}

bool KnightErrant::fight(std::shared_ptr<Elf> other) {
fight_notify(other, false);
return false;
}

bool KnightErrant::fight(std::shared_ptr<Dragon> other) {
fight_notify(other, true);
return true;
}

void KnightErrant::save(std::ostream &os) {
os << KnightErrantType << std::endl;
NPC::save(os);
}

std::ostream &operator<<(std::ostream &os, KnightErrant &knight_errant) {
os << "Knight Errant: " << *static_cast<NPC *>(&knight_errant) << std::endl;
return os;
}
20 changes: 20 additions & 0 deletions solutions/lab6/src/knight_errant.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once
#include "npc.h"

struct KnightErrant : public NPC {
KnightErrant(int x, int y);
KnightErrant(std::istream &is);

void print() override;

bool accept(Visitor& visitor) override;

bool fight(std::shared_ptr<KnightErrant> other) override;
bool fight(std::shared_ptr<Elf> other) override;
bool fight(std::shared_ptr<Dragon> other) override;

void save(std::ostream &os) override;

friend std::ostream &operator<<(std::ostream &os,
KnightErrant &knight_errant);
};
37 changes: 37 additions & 0 deletions solutions/lab6/src/npc.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include "npc.h"

NPC::NPC(NpcType t, int _x, int _y) : type(t), x(_x), y(_y) {}

NPC::NPC(NpcType t, std::istream &is) : type(t) {
is >> x;
is >> y;
}

void NPC::subscribe(std::shared_ptr<IFightObserver> observer) {
observers.push_back(observer);
}

void NPC::fight_notify(const std::shared_ptr<NPC> defender, bool win) {
for (auto &o : observers) {
o->on_fight(shared_from_this(), defender, win);
}
}

bool NPC::is_close(const std::shared_ptr<NPC> &other, size_t distance) const {
if (std::pow(x - other->x, 2) + std::pow(y - other->y, 2) <=
std::pow(distance, 2)) {
return true;
} else {
return false;
}
}

void NPC::save(std::ostream &os) {
os << x << std::endl;
os << y << std::endl;
}

std::ostream &operator<<(std::ostream &os, NPC &npc) {
os << "{ x:" << npc.x << ", y:" << npc.y << " }";
return os;
}
Loading