diff --git a/osx/classes/item.cpp b/osx/classes/item.cpp index 9978915f..92f38bb1 100644 --- a/osx/classes/item.cpp +++ b/osx/classes/item.cpp @@ -334,70 +334,74 @@ cItemRec& cItemRec::operator = (legacy::item_record_type& old){ } void cItemRec::writeTo(std::ostream& file, std::string prefix){ - file << prefix << "VARIETY " << variety << std::endl; - file << prefix << "LEVEL " << item_level << std::endl; - file << prefix << "AWKWARD " << awkward << std::endl; - file << prefix << "BONUS " << bonus << std::endl; - file << prefix << "PROT " << protection << std::endl; - file << prefix << "CHARGES " << charges << std::endl; - file << prefix << "WEAPON " << type << std::endl; - file << prefix << "USE " << magic_use_type << std::endl; - file << prefix << "ICON " << graphic_num << std::endl; - file << prefix << "ABILITY " << ability << std::endl; - file << prefix << "ABILSTR " << ability_strength << std::endl; - file << prefix << "TYPE " << type_flag << std::endl; - file << prefix << "ISSPEC " << is_special << std::endl; - file << prefix << "VALUE " << value << std::endl; - file << prefix << "WEIGHT " << weight << std::endl; - file << prefix << "SPEC " << special_class << std::endl; - file << prefix << "AT " << item_loc.x << ' ' << item_loc.y << std::endl; - file << prefix << "FULLNAME " << full_name << std::endl; - file << prefix << "NAME " << name << std::endl; - file << prefix << "TREASURE " << treas_class << std::endl; - if(ident) file << prefix << "IDENTIFIED" << std::endl; - if(property) file << prefix << "PROPERTY" << std::endl; - if(magic) file << prefix << "MAGIC" << std::endl; - if(contained) file << prefix << "CONTAINED" << std::endl; - if(cursed) file << prefix << "CURSED" << std::endl; - if(concealed) file << prefix << "CONCEALED" << std::endl; - if(enchanted) file << prefix << "ENCHANTED" << std::endl; - if(unsellable) file << prefix << "UNSELLABLE" << std::endl; + file << prefix << "VARIETY " << variety << '\n'; + file << prefix << "LEVEL " << item_level << '\n'; + file << prefix << "AWKWARD " << awkward << '\n'; + file << prefix << "BONUS " << bonus << '\n'; + file << prefix << "PROT " << protection << '\n'; + file << prefix << "CHARGES " << charges << '\n'; + file << prefix << "WEAPON " << type << '\n'; + file << prefix << "USE " << magic_use_type << '\n'; + file << prefix << "ICON " << graphic_num << '\n'; + file << prefix << "ABILITY " << ability << '\n'; + file << prefix << "ABILSTR " << ability_strength << '\n'; + file << prefix << "TYPE " << type_flag << '\n'; + file << prefix << "ISSPEC " << is_special << '\n'; + file << prefix << "VALUE " << value << '\n'; + file << prefix << "WEIGHT " << weight << '\n'; + file << prefix << "SPEC " << special_class << '\n'; + file << prefix << "AT " << item_loc.x << ' ' << item_loc.y << '\n'; + file << prefix << "FULLNAME " << full_name << '\n'; + file << prefix << "NAME " << name << '\n'; + file << prefix << "TREASURE " << treas_class << '\n'; + if(ident) file << prefix << "IDENTIFIED\n"; + if(property) file << prefix << "PROPERTY\n"; + if(magic) file << prefix << "MAGIC\n"; + if(contained) file << prefix << "CONTAINED\n"; + if(cursed) file << prefix << "CURSED\n"; + if(concealed) file << prefix << "CONCEALED\n"; + if(enchanted) file << prefix << "ENCHANTED\n"; + if(unsellable) file << prefix << "UNSELLABLE\n"; } -void cItemRec::readAttrFrom(std::string cur, std::istream& sin){ - if(cur == "VARIETY") sin >> variety; - else if(cur == "LEVEL") sin >> item_level; - else if(cur == "AWKWARD") sin >> awkward; - else if(cur == "BONUS") sin >> bonus; - else if(cur == "PROT") sin >> protection; - else if(cur == "CHARGES") sin >> charges; - else if(cur == "WEAPON") sin >> type; - else if(cur == "USE") sin >> magic_use_type; - else if(cur == "ICON") sin >> graphic_num; - else if(cur == "ABILITY") sin >> ability; - else if(cur == "ABILSTR") sin >> ability_strength; - else if(cur == "TYPE") sin >> type_flag; - else if(cur == "ISSPEC") sin >> is_special; - else if(cur == "VALUE") sin >> value; - else if(cur == "WEIGHT") sin >> weight; - else if(cur == "SPEC") sin >> special_class; - else if(cur == "AT") sin >> item_loc.x >> item_loc.y; - else if(cur == "FULLNAME"){ - getline(sin,cur); - full_name = cur; - }else if(cur == "NAME"){ - getline(sin,cur); - name = cur; +void cItemRec::readFrom(std::istream& sin){ + while(sin) { + std::string cur; + getline(sin, cur); + if(cur == "VARIETY") sin >> variety; + else if(cur == "LEVEL") sin >> item_level; + else if(cur == "AWKWARD") sin >> awkward; + else if(cur == "BONUS") sin >> bonus; + else if(cur == "PROT") sin >> protection; + else if(cur == "CHARGES") sin >> charges; + else if(cur == "WEAPON") sin >> type; + else if(cur == "USE") sin >> magic_use_type; + else if(cur == "ICON") sin >> graphic_num; + else if(cur == "ABILITY") sin >> ability; + else if(cur == "ABILSTR") sin >> ability_strength; + else if(cur == "TYPE") sin >> type_flag; + else if(cur == "ISSPEC") sin >> is_special; + else if(cur == "VALUE") sin >> value; + else if(cur == "WEIGHT") sin >> weight; + else if(cur == "SPEC") sin >> special_class; + else if(cur == "AT") sin >> item_loc.x >> item_loc.y; + else if(cur == "FULLNAME"){ + getline(sin,cur); + full_name = cur; + }else if(cur == "NAME"){ + getline(sin,cur); + name = cur; + } + else if(cur == "TREASURE") sin >> treas_class; + else if(cur == "IDENTIFIED") ident = true; + else if(cur == "PROPERTY") property = true; + else if(cur == "MAGIC") magic = true; + else if(cur == "CONTAINED") contained = true; + else if(cur == "CURSED") cursed = true; + else if(cur == "CONCEALED") concealed = true; + else if(cur == "ENCHANTED") enchanted = true; + else if(cur == "UNSELLABLE") unsellable = true; } - else if(cur == "TREASURE") sin >> treas_class; - else if(cur == "IDENTIFIED") ident = true; - else if(cur == "PROPERTY") property = true; - else if(cur == "MAGIC") magic = true; - else if(cur == "CONTAINED") contained = true; - else if(cur == "CURSED") cursed = true; - else if(cur == "CONCEALED") concealed = true; - else if(cur == "ENCHANTED") enchanted = true; - else if(cur == "UNSELLABLE") unsellable = true; } std::ostream& operator << (std::ostream& out, eWeapType& e){ diff --git a/osx/classes/item.h b/osx/classes/item.h index 4c3f420c..57cfea7b 100644 --- a/osx/classes/item.h +++ b/osx/classes/item.h @@ -74,7 +74,7 @@ public: cItemRec(long preset); cItemRec& operator = (legacy::item_record_type& old); void writeTo(std::ostream& file, std::string prefix = ""); - void readAttrFrom(std::string cur, std::istream& sin); + void readFrom(std::istream& sin); }; std::ostream& operator << (std::ostream& out, eWeapType& e); diff --git a/osx/classes/monster.cpp b/osx/classes/monster.cpp index 03f71d16..380b4b8a 100644 --- a/osx/classes/monster.cpp +++ b/osx/classes/monster.cpp @@ -492,6 +492,10 @@ void cMonster::writeTo(std::ostream& file) { // TODO: Implement this (low priority since only used for exported summons) } +void cMonster::readFrom(std::istream& file) { + // TODO: Implement this (low priority since only used for exported summons) +} + void cCreature::writeTo(std::ostream& file) { file << "MONSTER " << number << '\n'; file << "ATTITUDE " << attitude << '\n'; @@ -520,3 +524,75 @@ void cCreature::writeTo(std::ostream& file) { file << "MORALE " << morale << '\n'; file << "DIRECTION " << direction << '\n'; } + +void cCreature::readFrom(std::istream& file) { + while(file) { + std::string cur; + getline(file, cur); + std::istringstream line(cur); + line >> cur; + if(cur == "MONSTER") + line >> number; + else if(cur == "ATTITUDE") + line >> attitude; + else if(cur == "STARTATT") { + unsigned int i; + line >> i; + start_attitude = i; + } else if(cur == "STARTLOC") + line >> start_loc.x >> start_loc.y; + else if(cur == "LOCATION") + line >> cur_loc.x >> cur_loc.y; + else if(cur == "MOBILITY") { + unsigned int i; + line >> i; + mobility = i; + } else if(cur == "TIMEFLAG") { + unsigned int i; + line >> i; + time_flag = i; + } else if(cur == "SUMMONED") + line >> summoned; + else if(cur == "EXTRA") { + unsigned int i,j; + line >> i >> j; + extra1 = i; + extra2 = j; + } else if(cur == "SPEC") + line >> spec1 >> spec2; + else if(cur == "SPECCODE") { + int i; + line >> i; + spec_enc_code = i; + } else if(cur == "TIMECODE") { + int i; + line >> i; + time_code = i; + } else if(cur == "TIME") + line >> monster_time; + else if(cur == "TALK") + line >> personality; + else if(cur == "DEATH") + line >> special_on_kill; + else if(cur == "FACE") + line >> facial_pic; + else if(cur == "TARGET") + line >> target; + else if(cur == "TARGLOC") + line >> targ_loc.x >> targ_loc.y; + else if(cur == "CURHP") + line >> health; + else if(cur == "CURSP") + line >> mp; + else if(cur == "MORALE") + line >> morale; + else if(cur == "DIRECTION") + line >> direction; + else if(cur == "STATUS") { + int i; + line >> i; + if(i >= 0 && i < 15) + line >> status[i]; + } + } +} diff --git a/osx/classes/monster.h b/osx/classes/monster.h index 2b19efa1..c400fffa 100644 --- a/osx/classes/monster.h +++ b/osx/classes/monster.h @@ -149,6 +149,7 @@ public: cMonster& operator = (legacy::monster_record_type& old); cMonster(); void writeTo(std::ostream& file); + void readFrom(std::istream& file); }; class cCreature : public cMonster { @@ -178,6 +179,7 @@ public: cCreature& operator = (const cCreature& other); //cCreature& operator = (const cMonster& other); void writeTo(std::ostream& file); + void readFrom(std::istream& file); }; std::ostream& operator << (std::ostream& out, eStatus& e); diff --git a/osx/classes/outdoors.cpp b/osx/classes/outdoors.cpp index de6d625f..4eba4d3e 100644 --- a/osx/classes/outdoors.cpp +++ b/osx/classes/outdoors.cpp @@ -169,47 +169,43 @@ cOutdoors::cCreature& cOutdoors::cCreature::operator = (legacy::outdoor_creature return *this; } -void cOutdoors::writeTo(std::ostream& file){ -// for(int i = 0; i < 48; i++){ -// file << expl[i][0]; -// for(int j = 1; j < 48; j++){ -// file << '\t' << expl[i][j]; -// } -// file << std::endl; -// } -} - void cOutdoors::cWandering::writeTo(std::ostream& file, std::string prefix){ for(int i = 0; i < 7; i++) - file << prefix << "HOSTILE " << i << ' ' << monst[i] << std::endl; + file << prefix << "HOSTILE " << i << ' ' << monst[i] << '\n'; for(int i = 0; i < 3; i++) - file << prefix << "FRIEND " << i << ' ' << friendly[i] << std::endl; - file << prefix << "MEET " << spec_on_meet << std::endl; - file << prefix << "WIN " << spec_on_win << std::endl; - file << prefix << "FLEE " << spec_on_flee << std::endl; - file << prefix << "FLAGS " << cant_flee << std::endl; - file << prefix << "SDF " << end_spec1 << ' ' << end_spec2 << std::endl; + file << prefix << "FRIEND " << i << ' ' << friendly[i] << '\n'; + 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 << "SDF " << end_spec1 << ' ' << end_spec2 << '\n'; } -void cOutdoors::cWandering::readAttrFrom(std::string cur, std::istream& sin){ - if(cur == "HOSTILE"){ - int i; - sin >> i; - sin >> monst[i]; - }else if(cur == "FRIEND"){ - int i; - sin >> i; - sin >> friendly[i]; - }else if(cur == "MEET") - sin >> spec_on_meet; - else if(cur == "WIN") - sin >> spec_on_win; - else if(cur == "FLEE") - sin >> spec_on_flee; - else if(cur == "FLAGS") - sin >> cant_flee; - else if(cur == "SDF") - sin >> end_spec1 >> end_spec2; +void cOutdoors::cWandering::readFrom(std::istream& file){ + while(file) { + std::string cur; + getline(file, cur); + std::istringstream sin(cur); + sin >> cur; + if(cur == "HOSTILE"){ + int i; + sin >> i; + sin >> monst[i]; + }else if(cur == "FRIEND"){ + int i; + sin >> i; + sin >> friendly[i]; + }else if(cur == "MEET") + sin >> spec_on_meet; + else if(cur == "WIN") + sin >> spec_on_win; + else if(cur == "FLEE") + sin >> spec_on_flee; + else if(cur == "FLAGS") + sin >> cant_flee; + else if(cur == "SDF") + sin >> end_spec1 >> end_spec2; + } } bool cOutdoors::cWandering::isNull(){ diff --git a/osx/classes/outdoors.h b/osx/classes/outdoors.h index 0dfbae9e..834b73eb 100644 --- a/osx/classes/outdoors.h +++ b/osx/classes/outdoors.h @@ -35,7 +35,7 @@ public: bool isNull(); cWandering& operator = (legacy::out_wandering_type old); void writeTo(std::ostream& file, std::string prefix = ""); - void readAttrFrom(std::string cur, std::istream& sin); + void readFrom(std::istream& sin); template type get(m_num_t who,bool hostile,type cMonster::* what); }; class cCreature { // formerly outdoor_creature_type @@ -69,7 +69,6 @@ public: char(& out_strs(short i))[256] __attribute__((deprecated)); cOutdoors(); cOutdoors& operator = (legacy::outdoor_record_type& old); - void writeTo(std::ostream& file); }; #endif \ No newline at end of file diff --git a/osx/classes/party.cpp b/osx/classes/party.cpp index 9e20591b..8b0c4499 100644 --- a/osx/classes/party.cpp +++ b/osx/classes/party.cpp @@ -14,6 +14,7 @@ #include "classes.h" #include "oldstructs.h" +#include "fileio.h" cParty& cParty::operator = (legacy::party_record_type& old){ int i,j; @@ -285,7 +286,7 @@ void cParty::writeTo(std::ostream& file){ } file << '\f'; for(int i = 0; i < 5; i++) - for(int j = 0; j < 50; j++) + for(int j = 0; j < 10; j++) if(magic_store_items[i][j].variety > ITEM_TYPE_NO_ITEM){ file << "MAGICSTORE " << i << ' ' << j << '\n'; magic_store_items[i][j].writeTo(file); @@ -298,6 +299,7 @@ void cParty::writeTo(std::ostream& file){ file << "SECTOR " << out_c[i].which_sector.x << ' ' << out_c[i].which_sector.y << '\n'; file << "LOCINSECTOR " << out_c[i].m_loc.x << ' ' << out_c[i].m_loc.y << '\n'; file << "HOME " << out_c[i].home_sector.x << ' ' << out_c[i].home_sector.y << '\n'; + file << "-\n"; out_c[i].what_monst.writeTo(file); } file << '\f'; @@ -311,16 +313,6 @@ void cParty::writeTo(std::ostream& file){ file << "TIMER " << ' ' << party_event_timers[i].time << ' ' << party_event_timers[i].global_or_town << ' ' << party_event_timers[i].node_to_call << '\n'; file << '\f'; - for(int i = 0; i < 4; i++){ - for(int j = 0; j < 64; j++){ - file << setup[i][j][0]; - for(int k = 1; k < 64; k++) - file << '\t' << setup[i][j][k]; - file << std::endl; - } - file << '\f'; - } - file << '\f'; for(int i = 0; i < 4; i++) for(int j = 0; j < 60; j++) { if(creature_save[i][j].active > 0) { @@ -337,13 +329,14 @@ void cParty::writeTo(std::ostream& file){ } if(summons.size() > 0) { file << '\f'; + file << "SUMMON" << '\n'; for(cMonster& monst : summons) monst.writeTo(file); } if(journal.size() > 0) { file << '\f'; for(cJournal& entry : journal) { - file << "JOURNAL " << entry.str_num << ' ' << entry.day << ' ' << entry.in_scen << '\n'; + file << "JOURNAL " << entry.str_num << ' ' << entry.day << ' ' << maybe_quote_string(entry.in_scen) << '\n'; // TODO: Save the actual string, if the player has asked us to } } @@ -360,6 +353,7 @@ void cParty::writeTo(std::ostream& file){ file << "TALKNOTE " << note.str_num1 << ' ' << note.str_num2 << '\n'; file << "WHO " << note.personality << '\n'; file << "WHERE " << note.town_num << ' ' << note.in_scen << '\n'; + file << "-\n"; // TODO: Save the actual strings and names, if the player has asked us to } } @@ -367,13 +361,14 @@ void cParty::writeTo(std::ostream& file){ void cParty::readFrom(std::istream& file){ // TODO: Error-check input - std::istringstream bin, sin; + // TODO: Don't call this sin, it's a trig function + std::istringstream bin; std::string cur; getline(file, cur, '\f'); bin.str(cur); while(bin) { // continue as long as no error, such as eof, occurs getline(bin, cur); - sin.str(cur); + std::istringstream sin(cur); sin >> cur; if(cur == "AGE") sin >> age; @@ -383,13 +378,21 @@ void cParty::readFrom(std::istream& file){ sin >> food; else if(cur == "SDF"){ int i,j; - sin >> i >> j; - sin >> stuff_done[i][j]; + unsigned int n; + sin >> i >> j >> n; + stuff_done[i][j] = n; + } else if(cur == "POINTER") { + int i,j,k; + sin >> i >> j >> k; + pointers[i] = std::make_pair(j,k); }else if(cur == "ITEMTAKEN"){ int i; sin >> i; - sin >> item_taken[i][0] >> item_taken[i][1] >> item_taken[i][2] >> item_taken[i][3] - >> item_taken[i][4] >> item_taken[i][5] >> item_taken[i][6] >> item_taken[i][7]; + for(int j = 0; j < 8; j++) { + unsigned int n; + sin >> n; + item_taken[i][j] = n; + } }else if(cur == "LIGHT") sin >> light_level; else if(cur == "OUTCORNER") @@ -400,24 +403,12 @@ void cParty::readFrom(std::istream& file){ sin >> p_loc.x >> p_loc.y; else if(cur == "LOCINSECTOR") sin >> loc_in_sec.x >> loc_in_sec.y; - else if(cur == "BOAT"){ - int i; - sin >> i; - sin >> boats[i].loc.x >> boats[i].loc.y >> boats[i].loc_in_sec.x >> boats[i].loc_in_sec.y - >> boats[i].sector.x >> boats[i].sector.y >> boats[i].which_town >> boats[i].property; - boats[i].exists = true; - }else if(cur == "HORSE"){ - int i; - sin >> i; - sin >> horses[i].loc.x >> horses[i].loc.y >> horses[i].loc_in_sec.x >> horses[i].loc_in_sec.y - >> horses[i].sector.x >> horses[i].sector.y >> horses[i].which_town >> horses[i].property; - horses[i].exists = true; - }else if(cur == "IN") + else if(cur == "IN") sin >> in_boat >> in_horse; else if(cur == "MAGICSTORE"){ int i,j; sin >> i >> j >> cur; - magic_store_items[i][j].readAttrFrom(cur,sin); + magic_store_items[i][j].readFrom(sin); }else if(cur == "ROSTER"){ int i; sin >> i; @@ -426,18 +417,6 @@ void cParty::readFrom(std::istream& file){ int i; sin >> i; m_seen[i] = true; - }else if(cur == "ENCOUNTER"){ - int i; - sin >> i >> cur; - if(cur == "DIRECTION") - sin >> out_c[i].direction; - else if(cur == "SECTOR") - sin >> out_c[i].which_sector.x >> out_c[i].which_sector.y; - else if(cur == "LOCINSECTOR") - sin >> out_c[i].m_loc.x >> out_c[i].m_loc.y; - else if(cur == "HOME") - sin >> out_c[i].home_sector.x >> out_c[i].home_sector.y; - else out_c[i].what_monst.readAttrFrom(cur,sin); }else if(cur == "SOULCRYSTAL"){ int i; sin >> i; @@ -450,7 +429,7 @@ void cParty::readFrom(std::istream& file){ int i; sin >> i; alchemy[i] = true; - }else if(cur == "TOWN"){ + } else if(cur == "TOWNVISIBLE") { int i; sin >> i; can_find_town[i] = true; @@ -484,32 +463,107 @@ void cParty::readFrom(std::istream& file){ sin >> scen_won; else if(cur == "PLAYED") sin >> scen_played; - else if(cur == "CAMPAIGN"){ - unsigned int i; - int j; - if(sin.peek() == '"'){ - sin.get(); - getline(sin, cur, '"'); - }else sin >> cur; - sin >> i >> j; - while(campaign_flags[cur].size() < i) campaign_flags[cur].push_back(0); - campaign_flags[cur][i] = j; - }else if(cur == "GRAPHIC"){ + else if(cur == "GRAPHIC") { int i; sin >> i; graphicUsed[i] = true; - }else if(cur == "TIMER"){ - int i; - sin >> i; - sin >> party_event_timers[i].time >> party_event_timers[i].global_or_town >> party_event_timers[i].node_to_call; } } - getline(file, cur, '\f'); - bin.str(cur); - for(int i = 0; i < 4; i++) - for(int j = 0; j < 64; j++) - for(int k = 0; k < 64; k++) - bin >> setup[i][j][k]; + while(file) { + getline(file, cur, '\f'); + bin.str(cur); + bin >> cur; + if(cur == "BOAT") { + int i; + bin >> i; + boats[i].exists = true; + boats[i].readFrom(bin); + } else if(cur == "HORSE") { + int i; + bin >> i; + horses[i].exists = true; + horses[i].readFrom(bin); + + } else if(cur == "MAGICSTORE") { + int i,j; + bin >> i >> j; + magic_store_items[i][j].readFrom(bin); + } else if(cur == "ENCOUNTER") { + int i; + bin >> i >> cur; + while(bin) { + getline(bin, cur); + std::istringstream sin(cur); + sin >> cur; + if(cur == "DIRECTION") + sin >> out_c[i].direction; + else if(cur == "SECTOR") + sin >> out_c[i].which_sector.x >> out_c[i].which_sector.y; + else if(cur == "LOCINSECTOR") + sin >> out_c[i].m_loc.x >> out_c[i].m_loc.y; + else if(cur == "HOME") + sin >> out_c[i].home_sector.x >> out_c[i].home_sector.y; + else if(cur == "-") break; + } + out_c[i].what_monst.readFrom(bin); + }else if(cur == "CAMPAIGN") { + unsigned int i; + int j; + cur = read_maybe_quoted_string(bin); + bin >> i >> j; + // TODO: value_type of campaign_flags is a vector, but maybe a map would be better? + while(campaign_flags[cur].size() < i) campaign_flags[cur].push_back(0); + campaign_flags[cur][i] = j; + } else if(cur == "TIMER") { + int i; + bin >> i; + bin >> party_event_timers[i].time >> party_event_timers[i].global_or_town >> party_event_timers[i].node_to_call; + } else if(cur == "CREATURE") { + int i, j; + bin >> i >> j; + creature_save[i][j].active = true; + creature_save[i][j].readFrom(bin); + } else if(cur == "STORED") { + int i, j; + bin >> i >> j; + stored_items[i][j].readFrom(bin); + } else if(cur == "SUMMON") { + int i; + bin >> i; + cMonster monst; + monst.readFrom(bin); + summons.push_back(monst); + } else if(cur == "JOURNAL") { + cJournal entry; + bin >> entry.str_num >> entry.day; + entry.in_scen = read_maybe_quoted_string(bin); + getline(bin, entry.the_str); + } else if(cur == "ENCNOTE") { + cEncNote note; + bin >> note.type >> note.str_num >> note.where; + getline(bin, note.the_str1); + getline(bin, note.the_str2); + } else if(cur == "TALKNOTE") { + cConvers note; + bin >> note.str_num1 >> note.str_num2; + while(bin) { + getline(bin, cur); + std::istringstream sin(cur); + sin >> cur; + if(cur == "WHO") + sin >> note.personality; + else if(cur == "WHERE") { + sin >> note.town_num; + note.in_scen = read_maybe_quoted_string(sin); + } else if(cur == "NAMES") { + note.in_town = read_maybe_quoted_string(sin); + note.who_said = read_maybe_quoted_string(sin); + } else if(cur == "-") break; + } + getline(bin, note.the_str1); + getline(bin, note.the_str2); + } + } } cPlayer& cParty::operator[](unsigned short n){ @@ -631,3 +685,33 @@ bool operator==(const cParty::cEncNote& one, const cParty::cEncNote& two) { return true; } +std::istream& operator>>(std::istream& in, eEncNoteType& type) { + std::string name; + in >> name; + if(name == "SCEN") type = NOTE_SCEN; + else if(name == "OUT") type = NOTE_OUT; + else if(name == "TOWN") type = NOTE_TOWN; + else if(name == "MONST") type = NOTE_MONST; + else in.setstate(std::ios_base::failbit); + return in; +} + +std::ostream& operator<<(std::ostream& out, eEncNoteType type) { + switch(type) { + case NOTE_SCEN: + out << "SCEN"; + break; + case NOTE_OUT: + out << "OUT"; + break; + case NOTE_TOWN: + out << "TOWN"; + break; + case NOTE_MONST: + out << "MONST"; + break; + } + return out; +} + + diff --git a/osx/classes/party.h b/osx/classes/party.h index ba9875c8..e15931f3 100644 --- a/osx/classes/party.h +++ b/osx/classes/party.h @@ -150,4 +150,7 @@ bool operator==(const cParty::cConvers& one, const cParty::cConvers& two); bool operator==(const cParty::cJournal& one, const cParty::cJournal& two); bool operator==(const cParty::cEncNote& one, const cParty::cEncNote& two); +std::istream& operator>>(std::istream& in, eEncNoteType& type); +std::ostream& operator<<(std::ostream& out, eEncNoteType type); + #endif \ No newline at end of file diff --git a/osx/classes/pc.cpp b/osx/classes/pc.cpp index 4c7a9e79..01e726de 100644 --- a/osx/classes/pc.cpp +++ b/osx/classes/pc.cpp @@ -281,6 +281,7 @@ void cPlayer::writeTo(std::ostream& file){ if(items[i].variety > ITEM_TYPE_NO_ITEM){ file << "ITEM " << i << '\n'; items[i].writeTo(file); + file << '\f'; } } @@ -327,10 +328,6 @@ void cPlayer::readFrom(std::istream& file){ int i; sin >> i; sin >> status[i]; - }else if(cur == "ITEM"){ - int i; - sin >> i >> cur; - items[i].readAttrFrom(cur, sin); }else if(cur == "EQUIP"){ int i; sin >> i; @@ -356,6 +353,20 @@ void cPlayer::readFrom(std::istream& file){ else if(cur == "POISON") sin >> weap_poisoned; } + while(file) { + getline(file, cur, '\f'); + bin.str(cur); + while(bin) { + getline(bin, cur); + sin.str(cur); + sin >> cur; + if(cur == "ITEM") { + int i; + sin >> i >> cur; + items[i].readFrom(sin); + } + } + } } std::ostream& operator << (std::ostream& out, eMainStatus& e){ diff --git a/osx/classes/regtown.cpp b/osx/classes/regtown.cpp index eac978fb..eca9d293 100644 --- a/osx/classes/regtown.cpp +++ b/osx/classes/regtown.cpp @@ -13,6 +13,7 @@ #include "classes.h" #include "oldstructs.h" +#include "fileio.h" extern cScenario scenario; @@ -143,6 +144,14 @@ ter_num_t& cTinyTown::terrain(size_t x, size_t y){ return _terrain[x][y]; } +void cTinyTown::writeTerrainTo(std::ostream& file) { + writeArray(file, _terrain, 32, 32); +} + +void cTinyTown::readTerrainFrom(std::istream& file) { + readArray(file, _terrain, 32, 32); +} + rectangle& cTinyTown::room_rect(size_t i){ return _room_rect[i]; } @@ -159,6 +168,14 @@ ter_num_t& cMedTown::terrain(size_t x, size_t y){ return _terrain[x][y]; } +void cMedTown::writeTerrainTo(std::ostream& file) { + writeArray(file, _terrain, 48, 48); +} + +void cMedTown::readTerrainFrom(std::istream& file) { + readArray(file, _terrain, 48, 48); +} + rectangle& cMedTown::room_rect(size_t i){ return _room_rect[i]; } @@ -175,6 +192,14 @@ ter_num_t& cBigTown::terrain(size_t x, size_t y){ return _terrain[x][y]; } +void cBigTown::writeTerrainTo(std::ostream& file) { + writeArray(file, _terrain, 64, 64); +} + +void cBigTown::readTerrainFrom(std::istream& file) { + readArray(file, _terrain, 64, 64); +} + rectangle& cBigTown::room_rect(size_t i){ return _room_rect[i]; } diff --git a/osx/classes/regtown.h b/osx/classes/regtown.h index ad657f02..b1889c94 100644 --- a/osx/classes/regtown.h +++ b/osx/classes/regtown.h @@ -39,7 +39,8 @@ public: short max_items(); cBigTown(); - void writeTo(std::ostream& file); + void writeTerrainTo(std::ostream& file); + void readTerrainFrom(std::istream& file); }; class cMedTown : public cTown { // formerly ave_tr_type @@ -59,7 +60,8 @@ public: short max_items(); cMedTown(); - void writeTo(std::ostream& file); + void writeTerrainTo(std::ostream& file); + void readTerrainFrom(std::istream& file); }; class cTinyTown : public cTown { // formerly tiny_tr_type @@ -79,7 +81,8 @@ public: short max_items(); cTinyTown(); - void writeTo(std::ostream& file); + void writeTerrainTo(std::ostream& file); + void readTerrainFrom(std::istream& file); }; #endif \ No newline at end of file diff --git a/osx/classes/tmpltown.cpp b/osx/classes/tmpltown.cpp index c9dedf72..de14695c 100644 --- a/osx/classes/tmpltown.cpp +++ b/osx/classes/tmpltown.cpp @@ -14,7 +14,15 @@ #include "classes.h" ter_num_t& cBigTemplTown::terrain(size_t x, size_t y){ - return _terrain[0][0]; // will need to calculate the terrain somehow + return _terrain[0][0]; // TODO: will need to calculate the terrain somehow +} + +void cBigTemplTown::writeTerrainTo(std::ostream& file) { + // TODO: Write out the terrain somehow; +} + +void cBigTemplTown::readTerrainFrom(std::istream& file) { + // TODO: Read in the terrain somehow } rectangle& cBigTemplTown::room_rect(size_t i){ diff --git a/osx/classes/tmpltown.h b/osx/classes/tmpltown.h index c64f46da..5a60cdbd 100644 --- a/osx/classes/tmpltown.h +++ b/osx/classes/tmpltown.h @@ -34,7 +34,6 @@ public: }; cCityBlock blocks[15]; cTerRect ter_rects[10]; - void writeTo(std::ostream& file); }; class cBigTemplTown : public cBigTown, cTemplTown { @@ -51,7 +50,8 @@ public: short max_dim(); short max_monst(); short max_items(); - void writeTo(std::ostream& file); + void writeTerrainTo(std::ostream& file); + void readTerrainFrom(std::istream& file); }; class cMedTemplTown : public cMedTown, cTemplTown { @@ -68,7 +68,8 @@ public: short max_dim(); short max_monst(); short max_items(); - void writeTo(std::ostream& file); + void writeTerrainTo(std::ostream& file); + void readTerrainFrom(std::istream& file); }; class cTinyTemplTown : public cTinyTown, cTemplTown { @@ -85,6 +86,8 @@ public: short max_dim(); short max_monst(); short max_items(); + void writeTerrainTo(std::ostream& file); + void readTerrainFrom(std::istream& file); }; // City blocks - I want to figure out how to use these sometime. diff --git a/osx/classes/town.h b/osx/classes/town.h index c92fd7bb..b31d9e62 100644 --- a/osx/classes/town.h +++ b/osx/classes/town.h @@ -117,7 +117,8 @@ public: cTown(); cTown(short size); cTown& operator = (legacy::town_record_type& old); - void writeTo(std::ostream& file); + virtual void writeTerrainTo(std::ostream& file) = 0; + virtual void readTerrainFrom(std::istream& file) = 0; }; #endif \ No newline at end of file diff --git a/osx/classes/universe.cpp b/osx/classes/universe.cpp index 4fbcb34c..e04405d9 100644 --- a/osx/classes/universe.cpp +++ b/osx/classes/universe.cpp @@ -14,6 +14,7 @@ #include "classes.h" #include "oldstructs.h" #include "mathutil.h" +#include "fileio.h" void cCurOut::append(legacy::out_info_type& old){ for(int i = 0; i < 96; i++) @@ -705,29 +706,9 @@ ter_num_t& cCurOut::operator [] (location loc) { } void cCurOut::writeTo(std::ostream& file){ - for(int i = 0; i < 96; i++){ - file << expl[i][0]; - for(int j = 1; j < 96; j++){ - file << '\t' << int(expl[i][j]); - } - file << std::endl; - } - file << '\f'; - for(int i = 9; i < 96; i++){ - file << out[i][0]; - for(int j = 1; j < 96; j++){ - file << '\t' << out[i][j]; - } - file << std::endl; - } - file << '\f'; - for(int i = 0; i < 96; i++){ - file << out_e[i][0]; - for(int j = 1; j < 96; j++){ - file << '\t' << unsigned(out_e[i][j]); - } - file << std::endl; - } + writeArray(file, expl, 96, 96); + writeArray(file, out, 96, 96); + writeArray(file, out_e, 96, 96); // file << "OUTDOORS 0 0" << std::endl; // outdoors[0][0].writeTo(file); // file << "OUTDOORS 0 1" << std::endl; @@ -739,6 +720,12 @@ void cCurOut::writeTo(std::ostream& file){ // file << std::endl; } +void cCurOut::readFrom(std::istream& file) { + readArray(file, expl, 96, 96); + readArray(file, out, 96, 96); + readArray(file, out_e, 96, 96); +} + void cCurTown::writeTo(std::ostream& file){ file << "TOWN " << num << '\n'; file << "DIFFICULTY " << difficulty << '\n'; @@ -750,29 +737,21 @@ void cCurTown::writeTo(std::ostream& file){ if(items[i].variety > ITEM_TYPE_NO_ITEM){ file << "ITEM " << i << '\n'; items[i].writeTo(file); + file << '\f'; } file << '\f'; for(int i = 0; i < 60; i++) { if(monst[i].active > 0) { file << "CREATURE " << i << '\n'; monst[i].writeTo(file); + file << '\f'; } } file << '\f'; - for(int i = 0; i < 64; i++){ - file << fields[i][0]; - for(int j = 1; j < 64; j++) - file << '\t' << fields[i][j]; - file << std::endl; - } - file << '\f'; + file << "FIELDS\n"; + writeArray(file, fields, 64, 46); file << "SIZE " << record->max_dim() << "\n"; - for(int i = 0; i < record->max_dim(); i++){ - file << record->terrain(i,0); - for(int j = 1; j < record->max_dim(); j++) - file << '\t' << record->terrain(i,j); - file << '\n'; - } + record->writeTerrainTo(file); // TODO: Do we need to save special_spot? } @@ -795,44 +774,40 @@ void cCurTown::readFrom(std::istream& file){ sin >> in_boat; else if(cur == "AT") sin >> p_loc.x >> p_loc.y; - else if(cur == "ITEM"){ + } + while(file) { + getline(file, cur, '\f'); + bin.str(cur); + bin >> cur; + if(cur == "FIELDS") + readArray(bin, fields, 64, 64); + else if(cur == "ITEM") { int i; - sin >> i >> cur; - items[i].readAttrFrom(cur, sin); + bin >> i; + items[i].readFrom(bin); + } else if(cur == "CREATURE") { + int i; + bin >> i; + monst[i].active = true; + monst[i].readFrom(bin); + } else if(cur == "SIZE") { + int dim; + bin >> dim; + if(record != NULL) delete record; + switch(dim){ + case 32: + record = new cTinyTown; + break; + case 48: + record = new cMedTown; + break; + case 64: + record = new cBigTown; + break; + } + record->readTerrainFrom(bin); } } - getline(file, cur, '\f'); - bin.str(cur); - for(int i = 0; i < 64; i++) - for(int j = 1; j < 64; j++) - bin >> fields[i][j]; - getline(file, cur, '\f'); - bin.str(cur); - int dim; - bin >> dim; - if(record != NULL) delete record; - switch(dim){ - case 32: - record = new cTinyTown; - break; - case 48: - record = new cMedTown; - break; - case 64: - record = new cBigTown; - break; - } - for(int i = 0; i < dim; i++) - for(int j = 1; j < dim; j++) - bin >> record->terrain(i,j); - // TODO: Read population -} - - -void cCurOut::readFrom(std::istream& file){ - for(int i = 0; i < 96; i++) - for(int j = 1; j < 96; j++) - file >> out_e[i][j]; } cCurTown::cCurTown(){ diff --git a/osx/classes/vehicle.cpp b/osx/classes/vehicle.cpp index ecd343c8..c948e456 100644 --- a/osx/classes/vehicle.cpp +++ b/osx/classes/vehicle.cpp @@ -60,3 +60,22 @@ void cVehicle::writeTo(std::ostream& file) { file << "IN " << which_town << '\n'; if(property) file << "OWNED\n"; } + +void cVehicle::readFrom(std::istream& file) { + while(file) { + std::string cur; + getline(file, cur); + std::istringstream lineIn(cur); + lineIn >> cur; + if(cur == "LOCATION") + lineIn >> loc.x >> loc.y; + else if(cur == "LOCINSECTOR") + lineIn >> loc_in_sec.x >> loc_in_sec.y; + else if(cur == "SECTOR") + lineIn >> sector.x >> sector.y; + else if(cur == "IN") + lineIn >> which_town; + else if(cur == "OWNED") + property = true; + } +} diff --git a/osx/classes/vehicle.h b/osx/classes/vehicle.h index 213959bd..42cd091f 100644 --- a/osx/classes/vehicle.h +++ b/osx/classes/vehicle.h @@ -32,6 +32,7 @@ public: cVehicle& operator = (legacy::horse_record_type& old); cVehicle& operator = (legacy::boat_record_type& old); void writeTo(std::ostream& file); + void readFrom(std::istream& file); }; /* diff --git a/osx/tools/fileio.cpp b/osx/tools/fileio.cpp index aede254a..696e3a31 100644 --- a/osx/tools/fileio.cpp +++ b/osx/tools/fileio.cpp @@ -1357,3 +1357,38 @@ std::vector load_strings(std::string which){ v.push_back(s); return v; } + +std::string read_maybe_quoted_string(std::istream& from) { + std::string result; + if(from.peek() == '"' || from.peek() == '\'') { + char delim = from.get(); + getline(from, result, delim); + if(result.empty()) return result; + while(result[result.length() - 1] == '\\') { + result += delim; + std::string nextPart; + getline(from, nextPart, delim); + result += nextPart; + } + } else from >> result; + return result; +} + +std::string maybe_quote_string(std::string which) { + if(which.find(' ') == std::string::npos && which.find('\t') == std::string::npos) + return which; + if(which.find('\'') == std::string::npos) + return '\'' + which + '\''; + if(which.find('"') == std::string::npos) + return '"' + which + '"'; + std::ostringstream fmt; + std::string part; + fmt << '"'; + for(char c : which) { + if(c == '"') fmt << R"(\")"; + else fmt.put(c); + } + fmt << '"'; + return fmt.str(); +} + diff --git a/osx/tools/fileio.h b/osx/tools/fileio.h index a6a383ee..3d686e59 100644 --- a/osx/tools/fileio.h +++ b/osx/tools/fileio.h @@ -9,6 +9,8 @@ #include #include #include +#include + #include "town.h" #include "outdoors.h" @@ -29,3 +31,34 @@ bool load_party(fs::path file_to_load); bool save_party(fs::path dest_file); void init_directories(const char* exec_path); + +std::string read_maybe_quoted_string(std::istream& from); +std::string maybe_quote_string(std::string which); + +template +void writeArray(std::ostream& to, const T(* array)[D], int width, int height) { + using int_type = decltype(T() + 1); + for(int i = 0; i < width; i++) { + to << array[i][0]; + for(int j = 1; j < height; j++) + to << '\t' << int_type(array[i][j]); + to << '\n'; + } + to << '\f'; +} + +template +void readArray(std::istream& from, T(* array)[D], int width, int height) { + using int_type = decltype(T() + 1); + std::string arrayContents; + getline(from, arrayContents, '\f'); + std::istringstream arrayIn(arrayContents); + for(int i = 0; i < width; i++) { + std::string line; + getline(arrayIn, line); + std::istringstream lineIn(line); + for(int j = 0; j < height; j++) + lineIn >> array[i][j]; + if(!arrayIn) break; + } +}