Lot more tests!
- Tests for converting legacy terrain types - Tests for initialization to sane values Fixes: - cCreature no longer initializes spec1 and spec2 to 0. This probably didn't cause bugs, but who knows... - In fact, cCreature no longer explicitly initializes anything in its cTownperson superclass. That's what the superclass constructor is for after all. - Relatedly, cTownperson now defaults to a facial graphic of -1. Also a docile attitude. - iLiving defaults to ap 0, direction here. - Fix Change When Step terrains to properly support not having a sound while still allowing an arbitrary number of custom sounds. - Add support for a lack of sound to Change When Used terrains, including at conversion time (original game supported it but OBoE was forcing the sound to a door sound). - Fix conversion of crumbling terrain types (old conversion was allowing quickfire to destroy them) Other: - New addAttack method in cMonster. - Change snd_num_t to signed, because it's been getting annoying that I can't easily use -1 to mean "no sound".
This commit is contained in:
223
test/init.cpp
Normal file
223
test/init.cpp
Normal file
@@ -0,0 +1,223 @@
|
||||
//
|
||||
// init.cpp
|
||||
// BoE
|
||||
//
|
||||
// Created by Celtic Minstrel on 15-10-04.
|
||||
//
|
||||
//
|
||||
|
||||
#include <catch.hpp>
|
||||
#include "scenario.hpp"
|
||||
#include "creature.hpp"
|
||||
#include "creatlist.hpp"
|
||||
|
||||
TEST_CASE("Initialization sanity test for terrain") {
|
||||
cTerrain ter;
|
||||
CHECK(ter.name.empty());
|
||||
CHECK(ter.picture == 0);
|
||||
CHECK(ter.blockage == eTerObstruct::CLEAR);
|
||||
CHECK(ter.flag1 == -1);
|
||||
CHECK(ter.flag2 == 0);
|
||||
CHECK(ter.flag3 == 0);
|
||||
CHECK(ter.special == eTerSpec::NONE);
|
||||
CHECK(ter.trans_to_what == 0);
|
||||
CHECK_FALSE(ter.fly_over);
|
||||
CHECK_FALSE(ter.boat_over);
|
||||
CHECK_FALSE(ter.block_horse);
|
||||
CHECK_FALSE(ter.is_archetype);
|
||||
CHECK(ter.light_radius == 0);
|
||||
CHECK(ter.step_sound == eStepSnd::STEP);
|
||||
CHECK(ter.shortcut_key == 0);
|
||||
CHECK(ter.obj_num == 0);
|
||||
CHECK(ter.ground_type == 0);
|
||||
CHECK(ter.trim_type == eTrimType::NONE);
|
||||
CHECK(ter.trim_ter == 0);
|
||||
CHECK(ter.frill_for == -1);
|
||||
CHECK(ter.frill_chance == 0);
|
||||
CHECK(ter.combat_arena == 0);
|
||||
CHECK(ter.obj_pos == loc(0,0));
|
||||
CHECK(ter.obj_size == loc(0,0));
|
||||
CHECK(ter.map_pic == -1);
|
||||
}
|
||||
|
||||
TEST_CASE("Initialization sanity test for monster") {
|
||||
cCreature who;
|
||||
SECTION("Monster base class") {
|
||||
cMonster& monst = who;
|
||||
CHECK(monst.level == 0);
|
||||
CHECK(monst.m_name.empty());
|
||||
CHECK(monst.m_health == 0);
|
||||
CHECK(monst.armor == 0);
|
||||
CHECK(monst.skill == 0);
|
||||
CHECK(monst.a[0].dice == 0);
|
||||
CHECK(monst.a[0].sides == 0);
|
||||
CHECK(monst.a[0].type == eMonstMelee::SWING);
|
||||
CHECK(monst.a[1].dice == 0);
|
||||
CHECK(monst.a[1].sides == 0);
|
||||
CHECK(monst.a[1].type == eMonstMelee::SWING);
|
||||
CHECK(monst.a[2].dice == 0);
|
||||
CHECK(monst.a[2].sides == 0);
|
||||
CHECK(monst.a[2].type == eMonstMelee::SWING);
|
||||
CHECK(monst.m_type == eRace::HUMAN);
|
||||
CHECK(monst.speed == 4);
|
||||
CHECK(monst.mu == 0);
|
||||
CHECK(monst.cl == 0);
|
||||
CHECK(monst.treasure == 0);
|
||||
CHECK(monst.abil.empty());
|
||||
CHECK(monst.corpse_item == 0);
|
||||
CHECK(monst.corpse_item_chance == 0);
|
||||
CHECK(monst.resist.size() == 10);
|
||||
CHECK(monst.resist[eDamageType::WEAPON] == 100);
|
||||
CHECK(monst.resist[eDamageType::FIRE] == 100);
|
||||
CHECK(monst.resist[eDamageType::POISON] == 100);
|
||||
CHECK(monst.resist[eDamageType::COLD] == 100);
|
||||
CHECK(monst.resist[eDamageType::MAGIC] == 100);
|
||||
CHECK(monst.resist[eDamageType::UNBLOCKABLE] == 100);
|
||||
CHECK(monst.resist[eDamageType::UNDEAD] == 100);
|
||||
CHECK(monst.resist[eDamageType::DEMON] == 100);
|
||||
CHECK(monst.resist[eDamageType::MARKED] == 100);
|
||||
CHECK_FALSE(monst.mindless);
|
||||
CHECK_FALSE(monst.invuln);
|
||||
CHECK_FALSE(monst.invisible);
|
||||
CHECK_FALSE(monst.guard);
|
||||
CHECK_FALSE(monst.amorphous);
|
||||
CHECK(monst.x_width == 1);
|
||||
CHECK(monst.y_width == 1);
|
||||
CHECK(monst.default_attitude == eAttitude::DOCILE);
|
||||
CHECK(monst.summon_type == 0);
|
||||
CHECK(monst.default_facial_pic == 0);
|
||||
CHECK(monst.picture_num == 149);
|
||||
CHECK(monst.ambient_sound == -1);
|
||||
CHECK(monst.see_spec == -1);
|
||||
}
|
||||
SECTION("Townsperson base class") {
|
||||
cTownperson& dude = who;
|
||||
CHECK(dude.number == 0);
|
||||
CHECK(dude.start_attitude == eAttitude::DOCILE);
|
||||
CHECK(dude.start_loc == loc(80,80));
|
||||
CHECK(dude.mobility == 1);
|
||||
CHECK(dude.time_flag == eMonstTime::ALWAYS);
|
||||
CHECK(dude.spec1 == -1);
|
||||
CHECK(dude.spec2 == -1);
|
||||
CHECK(dude.spec_enc_code == 0);
|
||||
CHECK(dude.time_code == 0);
|
||||
CHECK(dude.monster_time == 0);
|
||||
CHECK(dude.personality == -1);
|
||||
CHECK(dude.special_on_kill == -1);
|
||||
CHECK(dude.special_on_talk == -1);
|
||||
CHECK(dude.facial_pic == -1);
|
||||
}
|
||||
SECTION("Living base class") {
|
||||
iLiving& base = who;
|
||||
CHECK(base.status.empty());
|
||||
CHECK(base.ap == 0);
|
||||
CHECK(base.direction == DIR_HERE);
|
||||
CHECK(base.marked_damage == 0);
|
||||
}
|
||||
SECTION("Main creature class") {
|
||||
CHECK(who.active == 0);
|
||||
CHECK(who.attitude == eAttitude::DOCILE);
|
||||
CHECK(who.cur_loc == loc(80,80));
|
||||
CHECK(who.summon_time == 0);
|
||||
CHECK(who.target == 6);
|
||||
CHECK(who.targ_loc == loc(80,80));
|
||||
CHECK(who.health == 0);
|
||||
CHECK(who.mp == 0);
|
||||
CHECK(who.max_mp == 0);
|
||||
CHECK(who.morale == 0);
|
||||
CHECK(who.m_morale == 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Construction sanity test for monster") {
|
||||
// First, build a base monster.
|
||||
cMonster monst;
|
||||
monst.default_facial_pic = 12;
|
||||
monst.default_attitude = eAttitude::HOSTILE_A;
|
||||
|
||||
cTownperson dude({10,10}, 7, monst); // This is here because the population sections also need it
|
||||
SECTION("Into townsperson") {
|
||||
CHECK(dude.number == 7);
|
||||
CHECK(dude.start_loc == loc(10,10));
|
||||
CHECK(dude.facial_pic == 12);
|
||||
CHECK(dude.start_attitude == eAttitude::HOSTILE_A);
|
||||
return; // Don't need to bother adding the extra monster/townperson attributes for this test
|
||||
}
|
||||
|
||||
cPopulation pop;
|
||||
SECTION("Population init sanity test") {
|
||||
CHECK(pop.size() == 0);
|
||||
CHECK(pop.which_town == 200);
|
||||
CHECK_FALSE(pop.hostile);
|
||||
return; // Don't need to bother adding the extra monster/townperson attributes for this test
|
||||
}
|
||||
|
||||
monst.addAbil(eMonstAbilTemplate::TOUCH_STEAL_GOLD);
|
||||
monst.addAttack(2, 8, eMonstMelee::STAB);
|
||||
monst.resist[eDamageType::FIRE] = 25;
|
||||
monst.level = 5;
|
||||
monst.m_name = "The Grinch";
|
||||
monst.m_health = 32;
|
||||
monst.armor = 9;
|
||||
monst.skill = 1;
|
||||
monst.m_type = eRace::GOBLIN;
|
||||
monst.invisible = true;
|
||||
monst.mu = 1;
|
||||
|
||||
dude.time_flag = eMonstTime::APPEAR_AFTER_CHOP;
|
||||
dude.personality = 8;
|
||||
dude.start_attitude = eAttitude::HOSTILE_B;
|
||||
|
||||
SECTION("Into population (normal mode)") {
|
||||
pop.assign(0, dude, monst, false, 1);
|
||||
REQUIRE(pop.size() == 1);
|
||||
CHECK(pop[0].active == 1);
|
||||
CHECK(pop[0].picture_num == 0);
|
||||
CHECK(pop[0].m_health == 32);
|
||||
CHECK(pop[0].health == 32);
|
||||
CHECK(pop[0].max_mp == 60);
|
||||
CHECK(pop[0].mp == 60);
|
||||
CHECK(pop[0].m_morale == 50);
|
||||
CHECK(pop[0].morale == 50);
|
||||
CHECK(pop[0].ap == 0);
|
||||
CHECK(pop[0].direction == DIR_HERE);
|
||||
CHECK(pop[0].status.size() == 0);
|
||||
CHECK(pop[0].attitude == eAttitude::HOSTILE_B);
|
||||
CHECK(pop[0].cur_loc == loc(10,10));
|
||||
// Townsperson stuff
|
||||
CHECK(pop[0].time_flag == eMonstTime::APPEAR_AFTER_CHOP);
|
||||
CHECK(pop[0].personality == 8);
|
||||
// Monster stuff
|
||||
CHECK(pop[0].m_name == "The Grinch");
|
||||
CHECK(pop[0].level == 5);
|
||||
CHECK(pop[0].armor == 9);
|
||||
CHECK(pop[0].skill == 1);
|
||||
CHECK(pop[0].speed == 4);
|
||||
CHECK(pop[0].m_type == eRace::GOBLIN);
|
||||
CHECK(pop[0].resist[eDamageType::FIRE] == 25);
|
||||
CHECK(pop[0].invisible);
|
||||
CHECK(pop[0].mu == 1);
|
||||
REQUIRE(pop[0].abil.size() == 1);
|
||||
CHECK(pop[0].abil[eMonstAbil::STEAL_GOLD].active);
|
||||
// No need to bother checking the attributes of the ability, just make sure it's there
|
||||
}
|
||||
SECTION("Into population (easy mode)") {
|
||||
pop.assign(0, dude, monst, true, 1);
|
||||
REQUIRE(pop.size() == 1);
|
||||
CHECK(pop[0].m_health == 16);
|
||||
CHECK(pop[0].health == 16);
|
||||
}
|
||||
SECTION("Into population (with difficulty adjust") {
|
||||
pop.assign(0, dude, monst, false, 10);
|
||||
REQUIRE(pop.size() == 1);
|
||||
CHECK(pop[0].m_health == 320);
|
||||
CHECK(pop[0].health == 320);
|
||||
}
|
||||
SECTION("Into population (high-level monster)") {
|
||||
monst.level = 50;
|
||||
pop.assign(0, dude, monst, false, 1);
|
||||
REQUIRE(pop.size() == 1);
|
||||
CHECK(pop[0].m_morale == 800);
|
||||
CHECK(pop[0].morale == 800);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user