protect against bad tree data

develop
Myk Taylor 2023-02-03 12:52:50 -08:00
parent 972df67eee
commit f2521c4a5c
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
1 changed files with 73 additions and 43 deletions

@ -327,17 +327,24 @@ static bool is_protected(const df::plant * plant, PersistentDataItem &c) {
} }
static int32_t estimate_logs(const df::plant *plant) { static int32_t estimate_logs(const df::plant *plant) {
if (!plant->tree_info)
return 0;
//adapted from code by aljohnston112 @ github //adapted from code by aljohnston112 @ github
df::plant_tree_tile** tiles = plant->tree_info->body; df::plant_tree_tile** tiles = plant->tree_info->body;
df::plant_tree_tile* tilesRow;
int trunks = 0; if (!tiles)
return 0;
int32_t trunks = 0;
const int32_t area = plant->tree_info->dim_y * plant->tree_info->dim_x;
for (int i = 0; i < plant->tree_info->body_height; i++) { for (int i = 0; i < plant->tree_info->body_height; i++) {
tilesRow = tiles[i]; df::plant_tree_tile* tilesRow = tiles[i];
for (int j = 0; j < plant->tree_info->dim_y*plant->tree_info->dim_x; j++) { if (!tilesRow)
return 0; // tree data is corrupt; let's not touch it
for (int j = 0; j < area; j++)
trunks += tilesRow[j].bits.trunk; trunks += tilesRow[j].bits.trunk;
} }
}
return trunks; return trunks;
} }
@ -386,41 +393,19 @@ static void bucket_watched_burrows(color_ostream & out,
typedef multimap<int, df::plant *, std::greater<int>> TreesBySize; typedef multimap<int, df::plant *, std::greater<int>> TreesBySize;
// returns the number of trees that were newly marked static int32_t scan_tree(color_ostream & out, df::plant *plant, int32_t *expected_yield,
static int32_t scan_trees(color_ostream & out, int32_t *expected_yield,
TreesBySize *designatable_trees_by_size, bool designate_clearcut, TreesBySize *designatable_trees_by_size, bool designate_clearcut,
const vector<df::unit *> &citizens, int32_t *accessible_trees = NULL, const vector<df::unit *> &citizens, int32_t *accessible_trees,
int32_t *inaccessible_trees = NULL, int32_t *designated_trees = NULL, int32_t *inaccessible_trees, int32_t *designated_trees, int32_t *accessible_yield,
int32_t *accessible_yield = NULL, map<int32_t, int32_t> *tree_counts,
map<int32_t, int32_t> *tree_counts = NULL, map<int32_t, int32_t> *designated_tree_counts,
map<int32_t, int32_t> *designated_tree_counts = NULL) { map<int, PersistentDataItem *> &clearcut_burrows,
TRACE(cycle,out).print("scanning trees\n"); map<int, PersistentDataItem *> &chop_burrows) {
int32_t newly_marked = 0;
if (accessible_trees)
*accessible_trees = 0;
if (inaccessible_trees)
*inaccessible_trees = 0;
if (designated_trees)
*designated_trees = 0;
if (expected_yield)
*expected_yield = 0;
if (accessible_yield)
*accessible_yield = 0;
if (tree_counts)
tree_counts->clear();
if (designated_tree_counts)
designated_tree_counts->clear();
map<int, PersistentDataItem *> clearcut_burrows, chop_burrows;
bucket_watched_burrows(out, clearcut_burrows, chop_burrows);
for (auto plant : world->plants.all) {
TRACE(cycle,out).print(" scanning tree at %d,%d,%d\n", TRACE(cycle,out).print(" scanning tree at %d,%d,%d\n",
plant->pos.x, plant->pos.y, plant->pos.z); plant->pos.x, plant->pos.y, plant->pos.z);
if (!is_valid_tree(plant)) if (!is_valid_tree(plant))
continue; return 0;
bool accessible = is_accessible_tree(plant->pos, citizens); bool accessible = is_accessible_tree(plant->pos, citizens);
int32_t yield = estimate_logs(plant); int32_t yield = estimate_logs(plant);
@ -441,9 +426,10 @@ static int32_t scan_trees(color_ostream & out, int32_t *expected_yield,
bucket_tree(plant, designate_clearcut, &designated, &can_chop, tree_counts, bucket_tree(plant, designate_clearcut, &designated, &can_chop, tree_counts,
designated_tree_counts, clearcut_burrows, chop_burrows); designated_tree_counts, clearcut_burrows, chop_burrows);
int32_t ret = 0;
if (designated) { if (designated) {
if (!was_designated) if (!was_designated)
++newly_marked; ret = 1;
if (designated_trees) if (designated_trees)
++*designated_trees; ++*designated_trees;
if (expected_yield) if (expected_yield)
@ -452,8 +438,52 @@ static int32_t scan_trees(color_ostream & out, int32_t *expected_yield,
if (designatable_trees_by_size) if (designatable_trees_by_size)
designatable_trees_by_size->emplace(yield, plant); designatable_trees_by_size->emplace(yield, plant);
} }
return ret;
} }
// returns the number of trees that were newly marked
static int32_t scan_trees(color_ostream & out, int32_t *expected_yield,
TreesBySize *designatable_trees_by_size, bool designate_clearcut,
const vector<df::unit *> &citizens, int32_t *accessible_trees = NULL,
int32_t *inaccessible_trees = NULL, int32_t *designated_trees = NULL,
int32_t *accessible_yield = NULL,
map<int32_t, int32_t> *tree_counts = NULL,
map<int32_t, int32_t> *designated_tree_counts = NULL) {
TRACE(cycle,out).print("scanning trees\n");
int32_t newly_marked = 0;
if (accessible_trees)
*accessible_trees = 0;
if (inaccessible_trees)
*inaccessible_trees = 0;
if (designated_trees)
*designated_trees = 0;
if (expected_yield)
*expected_yield = 0;
if (accessible_yield)
*accessible_yield = 0;
if (tree_counts)
tree_counts->clear();
if (designated_tree_counts)
designated_tree_counts->clear();
map<int, PersistentDataItem *> clearcut_burrows, chop_burrows;
bucket_watched_burrows(out, clearcut_burrows, chop_burrows);
for (auto plant : world->plants.tree_dry)
newly_marked += scan_tree(out, plant, expected_yield, designatable_trees_by_size,
designate_clearcut, citizens, accessible_trees,
inaccessible_trees, designated_trees, accessible_yield,
tree_counts, designated_tree_counts,
clearcut_burrows, chop_burrows);
for (auto plant : world->plants.tree_wet)
newly_marked += scan_tree(out, plant, expected_yield, designatable_trees_by_size,
designate_clearcut, citizens, accessible_trees,
inaccessible_trees, designated_trees, accessible_yield,
tree_counts, designated_tree_counts,
clearcut_burrows, chop_burrows);
return newly_marked; return newly_marked;
} }