Skip to content

Commit

Permalink
More read/write tests for town and outdoors, including maps/dialogue
Browse files Browse the repository at this point in the history
Fixes:
- For towns, the "has tavern" flag was not saved or loaded
- Outdoor roads were not saved or loaded
- For outdoor encounters, the "can't flee" and "forced" flags were not loaded, and "forced" was not saved
--> These two flags have also been separated in the code
  • Loading branch information
CelticMinstrel committed Sep 30, 2015
1 parent 16a0998 commit 43e8228
Show file tree
Hide file tree
Showing 26 changed files with 576 additions and 20 deletions.
1 change: 1 addition & 0 deletions rsrc/schemas/outdoor.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
</xs:element>
</xs:sequence>
<xs:attribute name="can-flee" type="bool" default="true"/>
<xs:attribute name="force" type="bool" default="false"/>
</xs:complexType>
<xs:element name="sector">
<xs:complexType>
Expand Down
1 change: 1 addition & 0 deletions rsrc/schemas/town.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@
<xs:element name="strong-barriers" minOccurs="0" type="bool"/>
<xs:element name="defy-mapping" minOccurs="0" type="bool"/>
<xs:element name="defy-scrying" minOccurs="0" type="bool"/>
<xs:element name="tavern" minOccurs="0" type="bool"/>
</xs:all>
</xs:complexType>
</xs:element>
Expand Down
4 changes: 2 additions & 2 deletions src/boe.actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1498,7 +1498,7 @@ void handle_monster_actions(bool& need_redraw, bool& need_reprint) {
create_wand_monst();
for(int i = 0; i < 10; i++)
if(univ.party.out_c[i].exists)
if((adjacent(univ.party.p_loc,univ.party.out_c[i].m_loc) || univ.party.out_c[i].what_monst.cant_flee >= 10)
if((adjacent(univ.party.p_loc,univ.party.out_c[i].m_loc) || univ.party.out_c[i].what_monst.forced)
&& univ.party.in_boat < 0 && !flying()) {
store_wandering_special = univ.party.out_c[i].what_monst;
if(handle_wandering_specials(0,0))
Expand Down Expand Up @@ -1584,7 +1584,7 @@ void initiate_outdoor_combat(short i) {

// Is combat too easy?
if((univ.party.get_level() > ((out_enc_lev_tot(i) * 5) / 3) ) && (out_enc_lev_tot(i) < 200)
&& (univ.party.out_c[i].what_monst.cant_flee % 10 != 1)) {
&& !univ.party.out_c[i].what_monst.cant_flee) {
add_string_to_buf("Combat: Monsters fled!");
univ.party.out_c[i].exists = false;
return;
Expand Down
8 changes: 5 additions & 3 deletions src/classes/outdoors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ cOutdoors::cOutdoors(cScenario& scenario) : scenario(&scenario) {
for(j = 0; j < 48; j++) {
terrain[i][j] = scenario.default_ground;
special_spot[i][j] = false;
roads[i][j] = false;
}

for(i = 0; i < 4; i++) {
Expand All @@ -134,7 +135,8 @@ void cOutdoors::cWandering::append(legacy::out_wandering_type old){
spec_on_meet = old.spec_on_meet;
spec_on_win = old.spec_on_win;
spec_on_flee = old.spec_on_flee;
cant_flee = old.cant_flee;
cant_flee = old.cant_flee % 10 == 1;
forced = old.cant_flee >= 10;
end_spec1 = old.end_spec1;
end_spec2 = old.end_spec2;
}
Expand All @@ -157,7 +159,7 @@ void cOutdoors::cWandering::writeTo(std::ostream& file, std::string prefix) cons
file << prefix << "MEET " << spec_on_meet << '\n';
file << prefix << "WIN " << spec_on_win << '\n';
file << prefix << "FLEE " << spec_on_flee << '\n';
file << prefix << "FLAGS " << cant_flee << '\n';
file << prefix << "FLAGS " << cant_flee << ' ' << forced << '\n';
file << prefix << "SDF " << end_spec1 << ' ' << end_spec2 << '\n';
}

Expand All @@ -182,7 +184,7 @@ void cOutdoors::cWandering::readFrom(std::istream& file){
else if(cur == "FLEE")
sin >> spec_on_flee;
else if(cur == "FLAGS")
sin >> cant_flee;
sin >> cant_flee >> forced;
else if(cur == "SDF")
sin >> end_spec1 >> end_spec2;
}
Expand Down
3 changes: 2 additions & 1 deletion src/classes/outdoors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ class cOutdoors {
public:
std::array<mon_num_t,7> monst;
std::array<mon_num_t,3> friendly;
short spec_on_meet,spec_on_win,spec_on_flee,cant_flee;
short spec_on_meet,spec_on_win,spec_on_flee;
short end_spec1,end_spec2;
bool cant_flee, forced;

bool isNull();
void append(legacy::out_wandering_type old);
Expand Down
2 changes: 1 addition & 1 deletion src/classes/town.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class cTown { // formerly town_record_type
public:
class cWandering { // formerly wandering_type
public:
mon_num_t monst[4];
std::array<mon_num_t,4> monst;

bool isNull();
void append(legacy::wandering_type old);
Expand Down
5 changes: 5 additions & 0 deletions src/scenedit/scen.fileio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ template<> void ticpp::Printer::PushElement(std::string tagName, cMonster::cAtta
template<> void ticpp::Printer::PushElement(std::string tagName, cOutdoors::cWandering enc, bool) {
OpenElement(tagName);
PushAttribute("can-flee", !enc.cant_flee);
PushAttribute("force", enc.forced);
for(size_t i = 0; i < enc.monst.size(); i++) {
PushElement("monster", enc.monst[i]);
}
Expand Down Expand Up @@ -719,6 +720,8 @@ void writeTownToXml(ticpp::Printer&& data, cTown& town) {
data.PushElement("defy-scrying", true);
if(town.is_hidden)
data.PushElement("hidden", true);
if(town.has_tavern)
data.PushElement("tavern", true);
data.CloseElement("flags");
for(int i = 0; i < town.wandering.size(); i++) {
if(town.wandering[i].isNull()) continue;
Expand Down Expand Up @@ -849,6 +852,8 @@ map_data buildOutMapData(location which, cScenario& scenario) {
terrain.set(x, y, sector.terrain[x][y]);
if(sector.special_spot[x][y])
terrain.addFeature(x, y, eMapFeature::FIELD, SPECIAL_SPOT);
if(sector.roads[x][y])
terrain.addFeature(x, y, eMapFeature::FIELD, SPECIAL_ROAD);
}
}
for(size_t i = 0; i < sector.special_locs.size(); i++) {
Expand Down
11 changes: 4 additions & 7 deletions src/scenedit/scen.townout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -520,8 +520,8 @@ static void put_out_wand_in_dlog(cDialog& me, short which, const cOutdoors::cWan
// TODO: Wait a second, if 0 is no monster, does that mean it's impossible to use monster 0? Should 1 be subtracted here?
else me[id].setText(scenario.scen_monsters[wand.friendly[i]].m_name);
}
dynamic_cast<cLed&>(me["no-flee"]).setState(wand.cant_flee % 10 == 1 ? led_red : led_off);
dynamic_cast<cLed&>(me["forced"]).setState(wand.cant_flee >= 10 ? led_red : led_off);
dynamic_cast<cLed&>(me["no-flee"]).setState(wand.cant_flee ? led_red : led_off);
dynamic_cast<cLed&>(me["forced"]).setState(wand.forced ? led_red : led_off);
me["onmeet"].setTextToNum(wand.spec_on_meet);
me["onwin"].setTextToNum(wand.spec_on_win);
me["onflee"].setTextToNum(wand.spec_on_flee);
Expand All @@ -536,11 +536,8 @@ static void save_out_wand(cDialog& me, short which, cOutdoors::cWandering& wand,
wand.end_spec1 = me["endx"].getTextAsNum();
wand.end_spec2 = me["endy"].getTextAsNum();

wand.cant_flee = 0;
if(dynamic_cast<cLed&>(me["forced"]).getState() != led_off)
wand.cant_flee += 10;
if(dynamic_cast<cLed&>(me["no-flee"]).getState() != led_off)
wand.cant_flee += 1;
wand.forced = dynamic_cast<cLed&>(me["forced"]).getState() != led_off;
wand.cant_flee = dynamic_cast<cLed&>(me["no-flee"]).getState() != led_off;

switch(mode) {
case 0:
Expand Down
17 changes: 17 additions & 0 deletions src/tools/fileio_scen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1501,6 +1501,17 @@ void readOutdoorsFromXml(ticpp::Document&& data, cOutdoors& out) {
auto& enc_list = type == "encounter" ? out.special_enc : out.wandering;
int num_hostile = 0, num_friendly = 0;
Iterator<Attribute> attr;
for(attr = attr.begin(elem.Get()); attr != attr.end(); attr++) {
std::string name, strval;
attr->GetName(&name);
attr->GetValue(&strval);
bool val = strval == "true";
if(name == "can-flee")
enc_list[count].cant_flee = !val;
else if(name == "force")
enc_list[count].forced = val;
else throw xBadAttr(type, name, attr->Row(), attr->Column(), fname);
}
Iterator<Element> enc;
for(enc = enc.begin(elem.Get()); enc != enc.end(); enc++) {
std::string type;
Expand Down Expand Up @@ -1656,6 +1667,10 @@ void readTownFromXml(ticpp::Document&& data, cTown*& town, cScenario& scen) {
flag->GetText(&val);
if(val == "true")
town->defy_scrying = true;
} else if(type == "tavern") {
flag->GetText(&val);
if(val == "true")
town->has_tavern = true;
} else throw xBadNode(type, flag->Row(), flag->Column(), fname);
}
} else if(type == "wandering") {
Expand Down Expand Up @@ -1891,6 +1906,8 @@ void loadOutMapData(map_data&& data, location which, cScenario& scen) {
case eMapFeature::FIELD:
if(feat.second == SPECIAL_SPOT)
out.special_spot[x][y] = true;
else if(feat.second == SPECIAL_ROAD)
out.roads[x][y] = true;
else throw xMapParseError(map_out_bad_field, feat.second, y, x, data.file);
break;
case eMapFeature::SIGN:
Expand Down
3 changes: 2 additions & 1 deletion test/files/maps/fields.map
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
0&9,0&10,0&11,0&12
0&13,0&14,0&15,0&16
0&17,0&18,0&19,0&20
0&21,0&22,0&23,0&24
0&21,0&22,0&23,0&24
0&25
5 changes: 5 additions & 0 deletions test/files/maps/fields_out.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
1,2,3,4,5
6,7,8,9,10
11,12,13&9,14,15
16,17,18&25,19,20
21,22,23&25,24,25
4 changes: 1 addition & 3 deletions test/files/outdoor/encounter_bad_attr.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
<sector boes="2.0.0">
<encounter>
<monster human='false'/>
</encounter>
<encounter bad='no'/>
</sector>
5 changes: 5 additions & 0 deletions test/files/outdoor/encounter_bad_monst_attr.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<sector boes="2.0.0">
<encounter>
<monster human='false'/>
</encounter>
</sector>
26 changes: 26 additions & 0 deletions test/files/outdoor/full.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<sector boes="2.0.0">
<name>Test Sector</name>
<comment>Hello World!</comment>
<sound>birds</sound>
<encounter can-flee='false' force='true'>
<monster>12</monster>
<monster friendly='true'>15</monster>
<onmeet>90</onmeet>
<onwin>92</onwin>
<onflee>84</onflee>
<sdf x='202' y='19'/>
</encounter>
<wandering can-flee='false' force='true'>
<monster>12</monster>
<monster friendly='true'>15</monster>
<onmeet>90</onmeet>
<onwin>92</onwin>
<onflee>84</onflee>
<sdf x='202' y='19'/>
</wandering>
<sign id='7'>The best sign ever!</sign>
<area top='4' left='8' bottom='9' right='12'>
<![CDATA[Some random area Amazing!]]>
</area>
<string id='9'>A random special string</string>
</sector>
4 changes: 4 additions & 0 deletions test/files/outdoor/sound.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<sector boes="2.0.0">
<name>Test Sector</name>
<sound>42</sound>
</sector>
37 changes: 37 additions & 0 deletions test/files/talk/full.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<dialogue boes="2.0.0">
<personality id='0'>
<title>Billy Kumquat</title>
<look>You see a small boy juggling fruit.</look>
<name>"I'm Billy Kumquat!"</name>
<job>"I juggle!"</job>
<unknown>"No clue!"</unknown>
</personality>
<node for='0'>
<keyword>jugg</keyword>
<type>reg</type>
<text>"It's fun!"</text>
</node>
<node for='0'>
<keyword>info</keyword>
<type>buy-sdf</type>
<param>1</param>
<param>2</param>
<param>3</param>
<text>"There's a treasure hidden in the old tree!"</text>
<text>"For a gold piece I'll tell you something interesting!"</text>
</node>
<node for='0'>
<keyword>purc</keyword>
<type>shop</type>
<param>0</param>
<param>4</param>
<text>Billy Kumquat's Oddest Fruit</text>
</node>
<node for='0'>
<keyword>kumq</keyword>
<type>quest</type>
<param>5</param>
<text>"I'll reward you if you find me some bigger kumquats!"</text>
<text>"Thanks for finding the bigger kumquats!"</text>
</node>
</dialogue>
6 changes: 6 additions & 0 deletions test/files/town/dup_onenter_condition.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<town boes="2.0.0">
<size>32</size>
<name>Hello World</name>
<onenter condition='alive'>1</onenter>
<onenter condition='alive'>2</onenter>
</town>
56 changes: 56 additions & 0 deletions test/files/town/full.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<town boes="2.0.0">
<size>32</size>
<name>Test Town</name>
<comment>This is a silly little comment.</comment>
<bounds top='4' left='4' right='28' bottom='28'/>
<difficulty>1</difficulty>
<lighting>lit</lighting>
<onenter condition='alive'>12</onenter>
<onenter condition='dead'>13</onenter>
<exit dir='n' x='4' y='16'/>
<onexit dir='n'>52</onexit>
<onoffend>42</onoffend>
<timer freq='100'>15</timer>
<flags>
<chop day='18' event='4' kills='50000'/>
<hidden>true</hidden>
<strong-barriers>true</strong-barriers>
<defy-mapping>true</defy-mapping>
<defy-scrying>true</defy-scrying>
<tavern>true</tavern>
</flags>
<wandering>
<monster>40</monster>
<monster>41</monster>
<monster>42</monster>
<monster>43</monster>
</wandering>
<sign id='1'>This is a sample sign.</sign>
<string id='7'>Here is a town string.</string>
<item id='2'>
<type>120</type>
<mod>2</mod>
<charges>17</charges>
<always>true</always>
<property>true</property>
<contained>true</contained>
</item>
<creature id='12'>
<type>140</type>
<attitude>hostile-b</attitude>
<mobility>1</mobility>
<sdf x='12' y='13'/>
<encounter>50</encounter>
<time type='after-event'>
<day>17</day>
<event>14</event>
</time>
<face>142</face>
<personality>1</personality>
<onkill>80</onkill>
<ontalk>81</ontalk>
</creature>
<area top='14' left='16' bottom='20' right='22'>
<![CDATA[This is a sample area description.]]>
</area>
</town>
23 changes: 22 additions & 1 deletion test/map_read.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,17 @@ TEST_CASE("Loading map data from file") {
CHECK(map.getFeatures(2, 5) == test);
test[0].second = BARRIER_CAGE;
CHECK(map.getFeatures(3, 5) == test);
test[0].second = SPECIAL_ROAD;
CHECK(map.getFeatures(0, 6) == test);
}
SECTION("With fields outdoors") {
fin.open("files/maps/fields_out.map");
map = load_map(fin, false, "fields_out.map");
test.emplace_back(make_pair(eMapFeature::FIELD, SPECIAL_SPOT));
CHECK(map.getFeatures(2, 2) == test);
test[0].second = SPECIAL_ROAD;
CHECK(map.getFeatures(2, 3) == test);
CHECK(map.getFeatures(2, 4) == test);
}
SECTION("With town entrance") {
fin.open("files/maps/towns_out.map");
Expand Down Expand Up @@ -215,15 +226,17 @@ TEST_CASE("Interpreting loaded map data") {
fin.open("files/maps/fields.map");
map = load_map(fin, true, "fields.map");
loadTownMapData(move(map), 0, scen);
REQUIRE(scen.towns[0]->preset_fields.size() == 24);
static const std::map<eFieldType, location> check = {
{WALL_FORCE, {0,0}}, {WALL_FIRE, {1,0}}, {FIELD_ANTIMAGIC, {2,0}}, {CLOUD_STINK, {3,0}},
{WALL_ICE, {0,1}}, {WALL_BLADES, {1,1}}, {CLOUD_SLEEP, {2,1}}, {OBJECT_BLOCK, {3,1}},
{SPECIAL_SPOT, {0,2}}, {FIELD_WEB, {1,2}}, {OBJECT_CRATE, {2,2}}, {OBJECT_BARREL, {3,2}},
{BARRIER_FIRE, {0,3}}, {BARRIER_FORCE, {1,3}}, {FIELD_QUICKFIRE, {2,3}}, {SFX_SMALL_BLOOD, {3,3}},
{SFX_MEDIUM_BLOOD, {0,4}}, {SFX_LARGE_BLOOD, {1,4}}, {SFX_SMALL_SLIME, {2,4}}, {SFX_LARGE_SLIME, {3,4}},
{SFX_ASH, {0,5}}, {SFX_BONES, {1,5}}, {SFX_RUBBLE, {2,5}}, {BARRIER_CAGE, {3,5}},
{SPECIAL_ROAD, {0,6}},
};
CAPTURE(check.size());
REQUIRE(scen.towns[0]->preset_fields.size() == check.size());
set<eFieldType> found;
for(const auto& fld : scen.towns[0]->preset_fields) {
if(found.count(fld.type))
Expand All @@ -237,6 +250,14 @@ TEST_CASE("Interpreting loaded map data") {
if(found.size() != check.size())
FAIL("Error: A field is missing!");
}
SECTION("With fields outdoors") {
fin.open("files/maps/fields_out.map");
map = load_map(fin, false, "fields_out.map");
loadOutMapData(move(map), loc(0,0), scen);
CHECK(scen.outdoors[0][0]->special_spot[2][2]);
CHECK(scen.outdoors[0][0]->roads[2][3]);
CHECK(scen.outdoors[0][0]->roads[2][4]);
}
SECTION("With town entrance") {
fin.open("files/maps/towns_out.map");
map = load_map(fin, false, "towns_out.map");
Expand Down
Loading

0 comments on commit 43e8228

Please sign in to comment.