use nested map for SDF names to save stack space.

Update semantics of the SDF array to (row, column) form to match
the picker space

Fix #674
This commit is contained in:
2025-03-05 09:24:50 -06:00
committed by Celtic Minstrel
parent 3d48cb14e7
commit 90d5e1b778
8 changed files with 52 additions and 38 deletions

View File

@@ -968,10 +968,10 @@ void readScenarioFromXml(ticpp::Document&& data, cScenario& scenario) {
} else if(type == "sdf") {
int row, col;
edit->GetAttribute("row", &row);
if(row < 0 || row >= scenario.sdf_names.size())
if(row < 0 || row >= SDF_ROWS)
throw xBadVal(type, "row", std::to_string(row), edit->Row(), edit->Column(), fname);
edit->GetAttribute("col", &col);
if(col < 0 || col >= scenario.sdf_names[0].size())
if(col < 0 || col >= SDF_COLUMNS)
throw xBadVal(type, "col", std::to_string(col), edit->Row(), edit->Column(), fname);
edit->GetText(&scenario.sdf_names[row][col]);
} else if(type == "graphics") {

View File

@@ -39,6 +39,9 @@ namespace bp = boost::process;
const int MAX_GOLD = 30000;
const int MAX_FOOD = 25000;
const int SDF_ROWS = 350;
const int SDF_COLUMNS = 50;
inline bool str_to_bool(std::string str) {
return str == "true";
}

View File

@@ -605,3 +605,11 @@ std::string cScenario::get_feature_flag(std::string flag) {
if(iter == this->feature_flags.end()) return "";
return iter->second;
}
std::string cScenario::get_sdf_name(int row, int col) {
if(sdf_names.find(row) == sdf_names.end())
return "";
if(sdf_names[row].find(col) == sdf_names[row].end())
return "";
return sdf_names[row][col];
}

View File

@@ -39,10 +39,6 @@ struct scenario_header_flags {
enum eContentRating {G, PG, R, NC17};
// TODO: Duplicated in party.hpp
template<typename T, size_t x, size_t y>
using array2d = std::array<std::array<T, y>, x>;
// Used for finding town entrances in the outdoors
struct town_entrance_t {
location out_sec;
@@ -107,7 +103,9 @@ public:
std::vector<std::string> evt_names;
std::vector<std::string> ic_names;
std::vector<std::string> itf_names;
array2d<std::string, 350, 50> sdf_names;
std::map<int, std::map<int, std::string>> sdf_names;
std::string get_sdf_name(int row, int col);
bool adjust_diff;
bool is_legacy;
fs::path scen_file; // transient

View File

@@ -415,13 +415,13 @@ void writeScenarioToXml(ticpp::Printer&& data, cScenario& scenario) {
data.PushText(scenario.itf_names[i]);
data.CloseElement("item-typeflag");
}
for(int x = 0; x < scenario.sdf_names.size(); x++) {
for(int y = 0; y < scenario.sdf_names[x].size(); y++) {
if(scenario.sdf_names[x][y].empty()) continue;
for(int r = 0; r < SDF_ROWS; r++) {
for(int c = 0; c < SDF_COLUMNS; c++) {
if(scenario.get_sdf_name(r, c).empty()) continue;
data.OpenElement("sdf");
data.PushAttribute("row", x);
data.PushAttribute("col", y);
data.PushText(scenario.sdf_names[x][y]);
data.PushAttribute("row", r);
data.PushAttribute("col", c);
data.PushText(scenario.sdf_names[r][c]);
data.CloseElement("sdf");
}
}

View File

@@ -46,19 +46,19 @@ bool cStuffDonePicker::handle_scroll(std::string item_hit) {
if(item_hit == "up") {
if(viewport.y > 0) viewport.y -= rows;
} else if(item_hit == "down") {
if(viewport.y < scenario.sdf_names[0].size() - rows) viewport.y += rows;
if(viewport.y < SDF_ROWS - rows) viewport.y += rows;
} else if(item_hit == "left") {
if(viewport.x > 0) viewport.x -= cols;
} else if(item_hit == "right") {
if(viewport.x < scenario.sdf_names.size() - cols) viewport.x += cols;
if(viewport.x < SDF_COLUMNS - cols) viewport.x += cols;
}
if(viewport.x == 0) dlog["left"].hide();
else dlog["left"].show();
if(viewport.y == 0) dlog["up"].hide();
else dlog["up"].show();
if(viewport.x >= scenario.sdf_names.size() - cols) dlog["right"].hide();
if(viewport.x >= SDF_COLUMNS - cols) dlog["right"].hide();
else dlog["right"].show();
if(viewport.y >= scenario.sdf_names[0].size() - rows) dlog["down"].hide();
if(viewport.y >= SDF_ROWS - rows) dlog["down"].hide();
else dlog["down"].show();
fill_names();
if(!item_hit.empty()) select_active();
@@ -106,40 +106,43 @@ location cStuffDonePicker::run() {
}
void cStuffDonePicker::clamp_sdf() {
chosen_sdf.x = minmax(0, scenario.sdf_names.size() - 1, chosen_sdf.x);
chosen_sdf.y = minmax(0, scenario.sdf_names[0].size() - 1, chosen_sdf.y);
// Note: x and y in chosen_sdf are actually (c,r)
chosen_sdf.x = minmax(0, SDF_COLUMNS - 1, chosen_sdf.x);
chosen_sdf.y = minmax(0, SDF_ROWS - 1, chosen_sdf.y);
viewport.x = cols * floor(chosen_sdf.x / float(cols));
viewport.y = rows * floor(chosen_sdf.y / float(rows));
}
void cStuffDonePicker::fill_names() {
for(int x = 0; x < cols; x++) {
for(int y = 0; y < rows; y++) {
auto& field = grid->getChild("name", x, y);
for(int c = 0; c < cols; c++) {
for(int r = 0; r < rows; r++) {
auto& field = grid->getChild("name", c, r);
// Note: x and y in sdf are actually (c,r)
location sdf = viewport;
sdf.x += x;
sdf.y += y;
field.setText(scenario.sdf_names[sdf.x][sdf.y]);
if(x == 0) {
sdf.x += c;
sdf.y += r;
field.setText(scenario.get_sdf_name(sdf.y, sdf.x));
if(c == 0) {
// Add row labels
row_labels->getChild("row", 0, y).setTextToNum(sdf.y);
row_labels->getChild("row", 0, r).setTextToNum(sdf.y);
}
if(y == 0) {
if(r == 0) {
// Add column labels
col_labels->getChild("col", x, 0).setTextToNum(sdf.x);
col_labels->getChild("col", c, 0).setTextToNum(sdf.x);
}
}
}
}
void cStuffDonePicker::save_names() {
for(int x = 0; x < cols; x++) {
for(int y = 0; y < rows; y++) {
auto& field = grid->getChild("name", x, y);
for(int c = 0; c < cols; c++) {
for(int r = 0; r < rows; r++) {
auto& field = grid->getChild("name", c, r);
location sdf = viewport;
sdf.x += x;
sdf.y += y;
scenario.sdf_names[sdf.x][sdf.y] = field.getText();
sdf.x += c;
sdf.y += r;
if(!field.getText().empty())
scenario.sdf_names[sdf.y][sdf.x] = field.getText();
}
}
}

View File

@@ -16,6 +16,8 @@ class cTilemap;
class cStuffDonePicker {
cDialog dlog;
// Note: x and y in initial_sdf and chosen_sdf are actually (c, r) and must be flipped when
// indexing SDFs or their names in the scenario
location initial_sdf, chosen_sdf, viewport;
cTilemap* grid;
cTilemap* row_labels;

View File

@@ -37,8 +37,8 @@ namespace legacy {
};
// TODO: Duplicated in scenario.hpp
template<typename T, size_t x, size_t y>
using array2d = std::array<std::array<T, y>, x>;
template<typename T, size_t rows, size_t cols>
using array2d = std::array<std::array<T, cols>, rows>;
struct campaign_flag_type{
array2d<unsigned char, 25, 25> idx{};
@@ -91,7 +91,7 @@ public:
unsigned long age;
unsigned short gold;
unsigned short food;
array2d<unsigned char, 350, 50> stuff_done;
array2d<unsigned char, SDF_ROWS, SDF_COLUMNS> stuff_done;
// These used to be stored as magic SDFs
unsigned char hostiles_present;
bool easy_mode = false, less_wm = false;