diff options
Diffstat (limited to 'game/gst.cpp')
-rw-r--r-- | game/gst.cpp | 264 |
1 files changed, 263 insertions, 1 deletions
diff --git a/game/gst.cpp b/game/gst.cpp index 5c195c8..f6d5aa1 100644 --- a/game/gst.cpp +++ b/game/gst.cpp @@ -1 +1,263 @@ -#include "gst.h"
\ No newline at end of file +#include "gst.h" + +#include <iostream> + +EntityInfo* Gst::get_info (std::string name) { + for (EntityInfo &info : infos) { + if (name == info.name) return &info; + } +} + +EntityInfo* Gst::get_info (int id) { + for (EntityInfo &info : infos) { + if (id == info.id) return &info; + } +} + +bool Gst::info_has_ability (EntityInfo* info, std::string name) { + for (int ab : info->abilities) { + if (abilities[ab].name == name) return true; + } + return false; +} + +Entity& Gst::get_at (int x, int y) { + for (Entity &e : entities) { + if (e.x ==x && e.y == y) return e; + } +} + +float Gst::get_type_bonus (Entity &atk, Entity &def) { + float b = 1; + switch(atk.info->ent_class) { + case EntityInfo::Class::inf: + if (def.info->ent_class == EntityInfo::Class::bld) b += 1.0/3; + if (def.info->ent_class == EntityInfo::Class::sie) b += 1.0/3; + break; + + case EntityInfo::Class::cav: + if (def.info->ent_class == EntityInfo::Class::bld) b += -0.5; + if (def.info->ent_class == EntityInfo::Class::inf) b += 1.0/3; + if (def.info->ent_class == EntityInfo::Class::ran) b += 1.0/3; + break; + + case EntityInfo::Class::ran: + if (def.info->ent_class == EntityInfo::Class::bld) b += -0.5; + break; + + case EntityInfo::Class::sie: + if (def.info->ent_class == EntityInfo::Class::bld) b += +0.5; + break; + } + return b; +} + +std::vector<Bonus> Gst::get_bonuses (Entity &atk, Entity &def) { + std::vector<Bonus> bs; + bs.emplace_back( + tiles[ground.tiles[ground.at(atk.x, atk.y)]].attack_bonus, + Bonus::Id::ground, true); + bs.emplace_back( + tiles[ground.tiles[ground.at(def.x, def.y)]].defence_bonus, + Bonus::Id::ground, false); + + bs.emplace_back(get_type_bonus(atk, def), Bonus::Id::type, true); + bs.emplace_back(get_type_bonus(def, atk), Bonus::Id::type, false); + + if (info_has_ability(atk.info, "Causes Fear")) + bs.emplace_back(-1.0f/3, Bonus::Id::ability, false); + if (info_has_ability(def.info, "Causes Fear")) + bs.emplace_back(-1.0f/3, Bonus::Id::ability, true); + + if (info_has_ability(atk.info, "Anti-Cavalry")) + bs.emplace_back(4.0f/3, Bonus::Id::ability, true); + if (info_has_ability(def.info, "Anti-Cavalry")) + bs.emplace_back(4.0f/3, Bonus::Id::ability, false); + + if (info_has_ability(atk.info, "Desert Charge") + && !info_has_ability(def.info, "Desert Charge") + && tiles[ground.tiles[ground.at(def.x, def.y)]].name == "Desert") + bs.emplace_back(1.0f/3, Bonus::Id::ability, true); + + if (info_has_ability(atk.info, "Plains Charge") + && !info_has_ability(def.info, "Plains Charge") + && tiles[ground.tiles[ground.at(def.x, def.y)]].name == "Plains") + bs.emplace_back(1.0f/3, Bonus::Id::ability, true); + + if (info_has_ability(atk.info, "Woodsman") + && !info_has_ability(def.info, "Woodsman") + && tiles[ground.tiles[ground.at(def.x, def.y)]].name == "Forest") + bs.emplace_back(1.0f/3, Bonus::Id::ability, true); + + if (info_has_ability(atk.info, "Volley") && atk.hp >= 50) + bs.emplace_back(1.0f/3, Bonus::Id::ability, true); + + if (info_has_ability(atk.info, "Frenzy")) + bs.emplace_back(1/atk.hp, Bonus::Id::ability, true); + + + return bs; +} + +float Gst::get_damage (Entity &atk, Entity &def) { + float atkmul = 1; + float defmul = 1; + + auto bonuses = get_bonuses(atk, def); + for (auto bonus : bonuses) { + if (bonus.atk) { atkmul += bonus.amt; } + else { defmul += bonus.amt; } + } + + float dam = (atk.info->attack * atk.hp * atkmul) + / (2.0f*def.info->defence * defmul); + + return dam; +} + +bool Gst::get_first_strike (Entity &atk, Entity &def) { + bool fs { false }; + fs = info_has_ability(atk.info, "First Strike"); + return fs; +} + +float clamp (float hp) { if (hp > 100) hp = 100; return hp; } + +void Gst::battle (Entity &atk, Entity &def) { + std::cout << "! attack " << atk.info->name << "(hp:" << atk.hp << "), " + << def.info->name << "(hp:" << def.hp << ") \n"; + + bool first_strike_atk = info_has_ability(atk.info, "First Strike"); + bool first_strike_def = info_has_ability(def.info, "First Strike"); + bool skirmish_atk = info_has_ability(atk.info, "Skirmish"); + bool skirmish_def = info_has_ability(def.info, "Skirmish"); + bool anticav_atk = info_has_ability(atk.info, "Anti-Cavalry"); + bool anticav_def = info_has_ability(def.info, "Anti-Cavalry"); + first_strike_atk = first_strike_atk + || (skirmish_atk && def.info->range == 1); + first_strike_def = first_strike_def + || (skirmish_def && atk.info->range == 1); + first_strike_atk = first_strike_atk + || (anticav_atk && def.info->ent_class == EntityInfo::Class::cav); + first_strike_def = first_strike_def + || (anticav_def && atk.info->ent_class == EntityInfo::Class::cav); + + bool swap = false; + if (first_strike_def && !first_strike_atk) swap = true; + if (swap) { + atk.hp = clamp(atk.hp - get_damage(def, atk)); + if (!info_has_ability(atk.info, "No Counter")) + if (atk.hp > 0) def.hp -= get_damage(atk, def); + } else { + def.hp = clamp(def.hp - get_damage(atk, def)); + if (!info_has_ability(def.info, "No Counter")) + if (def.hp > 0) atk.hp -= get_damage(def, atk); + } + + if (info_has_ability(atk.info, "Rapid Fire")) + if (def.hp > 0) + def.hp = clamp(def.hp - get_damage(atk, def)); + + if (info_has_ability(def.info, "Rapid Fire")) + if (atk.hp > 0) + atk.hp = clamp(atk.hp - get_damage(def, atk)); + + if (atk.hp > 0 && info_has_ability(atk.info, "Zeal")) + atk.hp = clamp(atk.hp + 20); + if (def.hp > 0 && info_has_ability(def.info, "Zeal")) + def.hp = clamp(def.hp + 20); + + std::cout << "! result " << atk.info->name << "(hp:" << atk.hp << "), " + << def.info->name << "(hp:" << def.hp << ") \n"; + clear_dead(); +} + +void Gst::clear_dead() { + auto i = std::begin(entities); + while (i != std::end(entities)) { + if (i->hp <= 0) { + entities.erase(i); + } + else i++; + } +} + +std::vector<int> Gst::get_possible_builds (Entity &ent) { + std::vector<int> builds; + for (int id : ent.info->build) { + if (check_req_build(ent, get_info(id))) { + builds.push_back(id); + } + } + return builds; +} + +bool Gst::check_req_build(Entity &ent, EntityInfo *info) { + for (int id : info->adjacent) { + bool adj = false; + for (Entity &e : entities) { + if (e.info->id == id) { + int dist = abs(e.x-ent.x) + abs(e.y-ent.y); + if (dist == 1) { + adj = true; + } + } + } + if (!adj) return false; + } + if (info->id == 100) { + for (Resource &r : ground.resources) { + if (r.pos == ground.at(ent.x, ent.y)) { + return false; + } + } + int mindist = 9999; + for (Entity &e : entities) { + if (e.info->id == 100) { + int dist = abs(e.x-ent.x) + abs(ent.y-e.y); + if (dist < mindist) { + mindist = dist; + } + } + } + std::cout << " " << mindist; + if (mindist < 5) { + return false; + } + return true; + } + if (info->id == 101) { + for (Resource &r : ground.resources) { + if (r.kind == Resource::Type::food + && r.pos == ground.at(ent.x, ent.y)) { + return true; + } + } + return false; + } + if (info->id == 102) { + for (Resource &r : ground.resources) { + if (r.kind == Resource::Type::gold + && r.pos == ground.at(ent.x, ent.y)) { + return true; + } + } + return false; + } + return true; +} + +bool Gst::check_obstructed (Entity &ent) { + for (Entity &e : entities) { + if (&ent != &e && e.x == ent.x && ent.y == e.y) return true; + } + return false; +} + +void Gst::end_day () { + turn++; + if (turn >= players.size()) { + turn = 0; + day++; + } +}
\ No newline at end of file |