Files
oboe/test/monst_read.cpp

472 lines
22 KiB
C++

//
// monst_read.cpp
// BoE
//
// Created by Celtic Minstrel on 15-07-29.
//
//
#include <fstream>
#include "ticpp.h"
#include "catch.hpp"
#include "dialogxml/dialogs/dialog.hpp"
#include "scenario/scenario.hpp"
using namespace std;
using namespace ticpp;
extern Document xmlDocFromStream(istream& stream, string name);
extern void readMonstersFromXml(Document&& data, cScenario& scenario);
TEST_CASE("Loading a monster type definition") {
ifstream fin;
cScenario scen;
Document doc;
fin.exceptions(ios::badbit);
SECTION("When the root tag is wrong") {
fin.open("files/bad_root.xml");
doc = xmlDocFromStream(fin, "bad_root.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("When the version attribute is missing") {
fin.open("files/monsters/no_version.xml");
doc = xmlDocFromStream(fin, "no_version.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingAttr);
}
SECTION("When the root tag has a bad attribute") {
fin.open("files/monsters/bad_root_attr.xml");
doc = xmlDocFromStream(fin, "bad_root_attr.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadAttr);
}
SECTION("When an unknown toplevel tag appears") {
fin.open("files/monsters/bad_toplevel.xml");
doc = xmlDocFromStream(fin, "bad_toplevel.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("When the ID attribute is missing") {
fin.open("files/monsters/missing_id.xml");
doc = xmlDocFromStream(fin, "missing_id.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), Exception);
}
SECTION("When the ID attribute is zero") {
fin.open("files/monsters/bad_id.xml");
doc = xmlDocFromStream(fin, "missing_id.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
}
SECTION("When a required subtag is missing") {
fin.open("files/monsters/missing_req.xml");
doc = xmlDocFromStream(fin, "missing_req.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
}
SECTION("When a bad subtag is found") {
fin.open("files/monsters/bad_tag.xml");
doc = xmlDocFromStream(fin, "bad_tag.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("When an attack has a bad subtag") {
fin.open("files/monsters/bad_attack_tag.xml");
doc = xmlDocFromStream(fin, "bad_attack_tag.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("When an attack has a bad attribute") {
fin.open("files/monsters/bad_attack_attr.xml");
doc = xmlDocFromStream(fin, "bad_attack_attr.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadAttr);
}
SECTION("When an attack has a bad type") {
fin.open("files/monsters/bad_attack_type.xml");
doc = xmlDocFromStream(fin, "bad_attack_type.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), Exception);
}
SECTION("When an attack damage is invalid") {
fin.open("files/monsters/bad_attack.xml");
doc = xmlDocFromStream(fin, "bad_attack.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
}
SECTION("When an attack damage is missing 'd'") {
fin.open("files/monsters/bad_attack2.xml");
doc = xmlDocFromStream(fin, "bad_attack2.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
}
SECTION("When an attack is missing the type") {
fin.open("files/monsters/missing_attack_type.xml");
doc = xmlDocFromStream(fin, "missing_attack_type.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingAttr);
}
SECTION("When the picture is missing the size attributes") {
fin.open("files/monsters/bad_pic.xml");
doc = xmlDocFromStream(fin, "bad_pic.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingAttr);
}
SECTION("When the picture has a bad attribute") {
fin.open("files/monsters/bad_pic2.xml");
doc = xmlDocFromStream(fin, "bad_pic2.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadAttr);
}
SECTION("When there is a bad immunity") {
fin.open("files/monsters/bad_immune.xml");
doc = xmlDocFromStream(fin, "bad_immune.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("When the loot has a bad subtag") {
fin.open("files/monsters/bad_loot.xml");
doc = xmlDocFromStream(fin, "bad_loot.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("When the loot has a missing subtag") {
fin.open("files/monsters/bad_loot2.xml");
doc = xmlDocFromStream(fin, "bad_loot2.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
}
SECTION("With the minimal required data") {
fin.open("files/monsters/minimal.xml");
doc = xmlDocFromStream(fin, "minimal.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].m_name == "Test Monster");
CHECK(scen.scen_monsters[1].level == 1);
CHECK(scen.scen_monsters[1].armor == 0);
CHECK(scen.scen_monsters[1].skill == 2);
CHECK(scen.scen_monsters[1].m_health == 10);
CHECK(scen.scen_monsters[1].speed == 4);
CHECK(scen.scen_monsters[1].m_type == eRace::HUMANOID);
CHECK(scen.scen_monsters[1].picture_num == 5);
CHECK(scen.scen_monsters[1].x_width == 1);
CHECK(scen.scen_monsters[1].y_width == 1);
CHECK(scen.scen_monsters[1].default_attitude == eAttitude::HOSTILE_A);
}
SECTION("With some attacks") {
fin.open("files/monsters/attacks.xml");
doc = xmlDocFromStream(fin, "attacks.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].a[0].type == eMonstMelee::SWING);
CHECK(scen.scen_monsters[1].a[0].dice == 1);
CHECK(scen.scen_monsters[1].a[0].sides == 10);
CHECK(scen.scen_monsters[1].a[1].type == eMonstMelee::PUNCH);
CHECK(scen.scen_monsters[1].a[1].dice == 2);
CHECK(scen.scen_monsters[1].a[1].sides == 4);
CHECK(scen.scen_monsters[1].a[2].type == eMonstMelee::BURN);
CHECK(scen.scen_monsters[1].a[2].dice == 1);
CHECK(scen.scen_monsters[1].a[2].sides == 8);
}
SECTION("With some immunities") {
fin.open("files/monsters/immunity.xml");
doc = xmlDocFromStream(fin, "immunity.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].amorphous);
CHECK(scen.scen_monsters[1].mindless);
CHECK(scen.scen_monsters[1].invuln);
CHECK(scen.scen_monsters[1].resist[eDamageType::FIRE] == 10);
CHECK(scen.scen_monsters[1].resist[eDamageType::COLD] == 20);
CHECK(scen.scen_monsters[1].resist[eDamageType::MAGIC] == 30);
CHECK(scen.scen_monsters[1].resist[eDamageType::POISON] == 40);
CHECK(scen.scen_monsters[1].resist[eDamageType::UNDEAD] == 50);
CHECK(scen.scen_monsters[1].resist[eDamageType::DEMON] == 60);
CHECK(scen.scen_monsters[1].resist[eDamageType::UNBLOCKABLE] == 70);
CHECK(scen.scen_monsters[1].resist[eDamageType::WEAPON] == 80);
CHECK(scen.scen_monsters[1].resist[eDamageType::SPECIAL] == 90);
// TODO: Setting special damage resistance shouldn't be allowed though
}
SECTION("With some misc optional data") {
fin.open("files/monsters/optional.xml");
doc = xmlDocFromStream(fin, "optional.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].speed == 3);
CHECK(scen.scen_monsters[1].mu == 1);
CHECK(scen.scen_monsters[1].cl == 2);
CHECK(scen.scen_monsters[1].treasure == 4);
CHECK(scen.scen_monsters[1].corpse_item == 128);
CHECK(scen.scen_monsters[1].corpse_item_chance == 35);
CHECK(scen.scen_monsters[1].summon_type == 3);
CHECK(scen.scen_monsters[1].default_facial_pic == 12);
CHECK(scen.scen_monsters[1].ambient_sound == 42);
CHECK(scen.scen_monsters[1].see_spec == 91);
}
}
TEST_CASE("Loading monster abilities") {
ifstream fin;
cScenario scen;
Document doc;
fin.exceptions(ios::badbit);
SECTION("With an invalid category") {
fin.open("files/monsters/bad_abil_type_tag.xml");
doc = xmlDocFromStream(fin, "bad_abil_type_tag.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("With missing type attribute") {
fin.open("files/monsters/bad_abil_no_type.xml");
doc = xmlDocFromStream(fin, "bad_abil_no_type.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingAttr);
}
SECTION("With an invalid attribute") {
fin.open("files/monsters/bad_abil_bad_attr.xml");
doc = xmlDocFromStream(fin, "bad_abil_bad_attr.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadAttr);
}
SECTION("With an invalid type") {
fin.open("files/monsters/bad_abil_type_attr.xml");
doc = xmlDocFromStream(fin, "bad_abil_type_attr.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), Exception);
}
SECTION("With a type of none") {
fin.open("files/monsters/bad_abil_type_none.xml");
doc = xmlDocFromStream(fin, "bad_abil_type_none.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
}
SECTION("General Abilities") {
SECTION("With a bad ability type") {
fin.open("files/monsters/abil_gen/bad_type.xml");
doc = xmlDocFromStream(fin, "bad_type.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
}
SECTION("With an invalid subtag") {
fin.open("files/monsters/abil_gen/bad_node.xml");
doc = xmlDocFromStream(fin, "bad_node.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("Missing a required subtag") {
fin.open("files/monsters/abil_gen/missing_elem.xml");
doc = xmlDocFromStream(fin, "missing_elem.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
}
SECTION("Minimal touch ability") {
fin.open("files/monsters/abil_gen/minimal_touch.xml");
doc = xmlDocFromStream(fin, "minimal_touch.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.type == eMonstGen::TOUCH);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.strength == 8);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.odds == 600);
}
SECTION("Minimal ranged ability") {
fin.open("files/monsters/abil_gen/minimal_range.xml");
doc = xmlDocFromStream(fin, "minimal_range.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.type == eMonstGen::RAY);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.strength == 8);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.odds == 600);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.pic == 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DRAIN_SP].gen.range == 10);
}
SECTION("With an extra value when not needed") {
fin.open("files/monsters/abil_gen/bad_extra.xml");
doc = xmlDocFromStream(fin, "bad_extra.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("Damage ability without type") {
fin.open("files/monsters/abil_gen/bad_damage.xml");
doc = xmlDocFromStream(fin, "bad_damage.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
}
SECTION("Field ability without type") {
fin.open("files/monsters/abil_gen/bad_field.xml");
doc = xmlDocFromStream(fin, "bad_field.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
}
SECTION("Status ability without type") {
fin.open("files/monsters/abil_gen/bad_status.xml");
doc = xmlDocFromStream(fin, "bad_status.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
}
SECTION("Ranged damage ability") {
fin.open("files/monsters/abil_gen/minimal_damage.xml");
doc = xmlDocFromStream(fin, "minimal_damage.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.type == eMonstGen::RAY);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.strength == 8);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.odds == 600);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.pic == 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.range == 10);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::DAMAGE].gen.dmg == eDamageType::FIRE);
}
SECTION("Ranged field ability") {
fin.open("files/monsters/abil_gen/minimal_field.xml");
doc = xmlDocFromStream(fin, "minimal_field.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.type == eMonstGen::RAY);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.strength == 8);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.odds == 600);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.pic == 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.range == 10);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::FIELD].gen.fld == CLOUD_SLEEP);
}
SECTION("Ranged status ability") {
fin.open("files/monsters/abil_gen/minimal_status.xml");
doc = xmlDocFromStream(fin, "minimal_status.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.type == eMonstGen::RAY);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.strength == 8);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.odds == 600);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.pic == 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.range == 10);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::STATUS].gen.stat == eStatus::POISON);
}
}
SECTION("Missile Abilities") {
SECTION("With a bad ability type") {
fin.open("files/monsters/abil_missile/bad_type.xml");
doc = xmlDocFromStream(fin, "bad_type.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
}
SECTION("With an invalid subtag") {
fin.open("files/monsters/abil_missile/bad_node.xml");
doc = xmlDocFromStream(fin, "bad_node.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("Missing a required subtag") {
fin.open("files/monsters/abil_missile/missing_elem.xml");
doc = xmlDocFromStream(fin, "missing_elem.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
}
SECTION("Minimal ability") {
fin.open("files/monsters/abil_missile/minimal.xml");
doc = xmlDocFromStream(fin, "minimal.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.type == eMonstMissile::ARROW);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.pic == 3);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.dice == 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.sides == 6);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.skill == 8);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.range == 10);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::MISSILE].missile.odds == 800);
}
}
SECTION("Radiate Abilities") {
SECTION("With a bad ability type") {
fin.open("files/monsters/abil_radiate/bad_type.xml");
doc = xmlDocFromStream(fin, "bad_type.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
}
SECTION("With an invalid subtag") {
fin.open("files/monsters/abil_radiate/bad_node.xml");
doc = xmlDocFromStream(fin, "bad_node.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("Missing a required subtag") {
fin.open("files/monsters/abil_radiate/missing_elem.xml");
doc = xmlDocFromStream(fin, "missing_elem.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
}
SECTION("Minimal ability") {
fin.open("files/monsters/abil_radiate/minimal.xml");
doc = xmlDocFromStream(fin, "minimal.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.type == CLOUD_SLEEP);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.pat == PAT_SQ);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.chance == 75);
}
SECTION("With non-default spell pattern") {
fin.open("files/monsters/abil_radiate/pattern.xml");
doc = xmlDocFromStream(fin, "pattern.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.type == CLOUD_SLEEP);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.pat == PAT_PLUS);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RADIATE].radiate.chance == 75);
}
}
SECTION("Summon Abilities") {
SECTION("With a bad ability type") {
fin.open("files/monsters/abil_summon/bad_type.xml");
doc = xmlDocFromStream(fin, "bad_type.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
}
SECTION("With an invalid subtag") {
fin.open("files/monsters/abil_summon/bad_node.xml");
doc = xmlDocFromStream(fin, "bad_node.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("Missing a required subtag") {
fin.open("files/monsters/abil_summon/missing_elem.xml");
doc = xmlDocFromStream(fin, "missing_elem.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xMissingElem);
}
SECTION("Minimal type ability") {
fin.open("files/monsters/abil_summon/minimal_type.xml");
doc = xmlDocFromStream(fin, "minimal_type.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.type == eMonstSummon::TYPE);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.what == 32);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.min == 1);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.max == 5);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.len == 15);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.chance == 500);
}
SECTION("Minimal level ability") {
fin.open("files/monsters/abil_summon/minimal_lvl.xml");
doc = xmlDocFromStream(fin, "minimal_lvl.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.type == eMonstSummon::LEVEL);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.what == 3);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.min == 1);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.max == 5);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.len == 15);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.chance == 500);
}
SECTION("Minimal race ability") {
fin.open("files/monsters/abil_summon/minimal_race.xml");
doc = xmlDocFromStream(fin, "minimal_race.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.type == eMonstSummon::SPECIES);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.what == int(eRace::REPTILE));
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.min == 1);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.max == 5);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.len == 15);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::SUMMON].summon.chance == 500);
}
}
SECTION("Special Abilities") {
SECTION("With a bad ability type") {
fin.open("files/monsters/abil_spec/bad_type.xml");
doc = xmlDocFromStream(fin, "bad_type.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadVal);
}
SECTION("With an invalid subtag") {
fin.open("files/monsters/abil_spec/bad_node.xml");
doc = xmlDocFromStream(fin, "bad_node.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("With too many parameters") {
fin.open("files/monsters/abil_spec/too_many_params.xml");
doc = xmlDocFromStream(fin, "too_many_params.xml");
REQUIRE_THROWS_AS(readMonstersFromXml(move(doc), scen), xBadNode);
}
SECTION("With all parameters") {
fin.open("files/monsters/abil_spec/minimal.xml");
doc = xmlDocFromStream(fin, "minimal.xml");
REQUIRE_NOTHROW(readMonstersFromXml(move(doc), scen));
REQUIRE(scen.scen_monsters.size() >= 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RAY_HEAT].active);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RAY_HEAT].special.extra1 == 1);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RAY_HEAT].special.extra2 == 2);
CHECK(scen.scen_monsters[1].abil[eMonstAbil::RAY_HEAT].special.extra3 == 3);
}
}
}