Skip to content

Commit

Permalink
Merge branch 'develop' into adv-beta
Browse files Browse the repository at this point in the history
  • Loading branch information
myk002 committed Sep 4, 2024
2 parents 086b14e + 3fed2b1 commit 4968b8d
Show file tree
Hide file tree
Showing 9 changed files with 65 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ repos:
args: ['--fix=lf']
- id: trailing-whitespace
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.29.1
rev: 0.29.2
hooks:
- id: check-github-workflows
- repo: https://github.com/Lucas-C/pre-commit-hooks
Expand Down
2 changes: 2 additions & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,12 @@ Template for new versions:
- `strangemood`: manually-triggered Macabre moods will now correctly request up to 3 bones/remains for the primary component instead of only 1.
- `regrass`: no longer add all compatible grass types when using ``--force`` without ``--new``
- `regrass`: ``--mud`` now converts muddy slade to grass, consistent with normal DF behavior
- `gui/pathable`: fix hang when showing trade depot wagon access and a trade depot is submerged under water

## Misc Improvements
- `sort`: can now search for stockpiles on the Places>Stockpile tab by name, number, or enabled item categories
- `gui/family-affairs`: you can start this tool by the name ``gui/pregnancy`` to start directly on the "Pregnancies" tab
- `buildingplan`: only consider building materials that can be accessed by citizens/residents
- Dreamfort: integrate with `preserve-rooms` to assign relevant rooms to nobles/adimistrators
- Dreamfort: smooth tiles under statues and other large furniture that you can't easily smooth later

Expand Down
2 changes: 1 addition & 1 deletion library/LuaApi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2181,7 +2181,7 @@ static int units_getUnitsInBox(lua_State *state) {
int z2 = luaL_checkint(state, 6);

bool ok = false;
if (lua_isnil(state, 7)) // Default filter
if (lua_gettop(state) < 7 || lua_isnil(state, 7)) // Default filter
ok = Units::getUnitsInBox(units, x1, y1, z1, x2, y2, z2);
else {
luaL_checktype(state, 7, LUA_TFUNCTION);
Expand Down
2 changes: 1 addition & 1 deletion library/xml
5 changes: 5 additions & 0 deletions plugins/buildingplan/buildingplan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ void PlannedBuilding::remove(color_ostream &out) {

static const int32_t CYCLE_TICKS = 599; // twice per game day
static int32_t cycle_timestamp = 0; // world->frame_counter at last cycle
int32_t walkability_timestamp = -1; // world->frame_counter at last update of walkability groups

static int get_num_filters(color_ostream &out, BuildingTypeKey key) {
int num_filters = 0;
Expand Down Expand Up @@ -192,6 +193,7 @@ static DefaultItemFilters & get_item_filters(color_ostream &out, const BuildingT
}

static command_result do_command(color_ostream &out, vector<string> &parameters);
void update_walkability_groups();
void buildingplan_cycle(color_ostream &out, Tasks &tasks,
unordered_map<int32_t, PlannedBuilding> &planned_buildings, bool unsuspend_on_finalize);

Expand Down Expand Up @@ -280,6 +282,7 @@ DFhackCExport command_result plugin_load_world_data (color_ostream &out) {

DFhackCExport command_result plugin_load_site_data (color_ostream &out) {
cycle_timestamp = 0;
walkability_timestamp = -1;
config = World::GetPersistentSiteData(CONFIG_KEY);

if (!config.isValid()) {
Expand Down Expand Up @@ -679,6 +682,8 @@ static int scanAvailableItems(color_ostream &out, df::building_type type, int16_
filter.setMaxQuality(df::item_quality::Artifact);
}

update_walkability_groups(); // ensure that itemPassesScreen is accurate

int count = 0;
for (auto vector_id : vector_ids) {
auto other_id = ENUM_ATTR(job_item_vector_id, other, vector_id);
Expand Down
1 change: 1 addition & 0 deletions plugins/buildingplan/buildingplan.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ typedef std::map<df::job_item_vector_id, std::map<std::string, Bucket>> Tasks;

extern const std::string FILTER_CONFIG_KEY;
extern const std::string BLD_CONFIG_KEY;
extern int32_t walkability_timestamp;

enum ConfigValues {
CONFIG_BLOCKS = 1,
Expand Down
31 changes: 29 additions & 2 deletions plugins/buildingplan/buildingplan_cycle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "modules/Job.h"
#include "modules/Maps.h"
#include "modules/Materials.h"
#include "modules/Units.h"

#include "df/building_actual.h"
#include "df/building_design.h"
Expand Down Expand Up @@ -45,13 +46,37 @@ struct BadFlags {
}
};

// cache of walkability groups that have citizens in them
static std::unordered_set<uint16_t> accessible_walkability_groups;

void update_walkability_groups(){

// ensure that we update at most once per tick
auto frame_counter = df::global::world->frame_counter;
if (frame_counter == walkability_timestamp)
return;
else
walkability_timestamp = frame_counter;

accessible_walkability_groups.clear();
auto get_group = [](df::unit *unit){
auto group = Maps::getWalkableGroup(Units::getPosition(unit));
if (group != 0)
{
accessible_walkability_groups.insert(group);
}
};
Units::forCitizens(get_group);
}

// This is tricky. we want to choose an item that can be brought to the job site, but that's not
// necessarily the same as job->pos. it could be many tiles off in any direction (e.g. for bridges), or
// up or down (e.g. for stairs). For now, just return if the item is on a walkable tile.
// up or down (e.g. for stairs). For now, just return if the item is in the same walkability group
// as a citizen or resident
static bool isAccessible(color_ostream& out, df::item* item) {
df::coord item_pos = Items::getPosition(item);
uint16_t walkability_group = Maps::getWalkableGroup(item_pos);
bool is_walkable = walkability_group != 0;
bool is_walkable = accessible_walkability_groups.contains(walkability_group);
TRACE(cycle, out).print("item %d in walkability_group %u at (%d,%d,%d) is %saccessible from job site\n",
item->id, walkability_group, item_pos.x, item_pos.y, item_pos.z, is_walkable ? "(probably) " : "not ");
return is_walkable;
Expand Down Expand Up @@ -380,6 +405,8 @@ void buildingplan_cycle(color_ostream &out, Tasks &tasks,
"running buildingplan cycle for %zu registered buildings\n",
planned_buildings.size());

update_walkability_groups();

for (auto it = tasks.begin(); it != tasks.end(); ) {
auto vector_id = it->first;
// we could make this a set, but it's only a few elements
Expand Down
37 changes: 24 additions & 13 deletions plugins/pathable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,25 +134,29 @@ static void paintScreenPathable(df::coord target, bool show_hidden = false) {
});
}

static bool get_depot_coords(unordered_set<df::coord> * depot_coords) {
static bool get_depot_coords(color_ostream &out, unordered_set<df::coord> * depot_coords) {
CHECK_NULL_POINTER(depot_coords);

depot_coords->clear();
for (auto bld : world->buildings.other.TRADE_DEPOT)
for (auto bld : world->buildings.other.TRADE_DEPOT){
DEBUG(log,out).print("found depot at (%d, %d, %d)\n", bld->centerx, bld->centery, bld->z);
depot_coords->emplace(bld->centerx, bld->centery, bld->z);
}

return !depot_coords->empty();
}

static bool get_pathability_groups(unordered_set<uint16_t> * depot_pathability_groups,
static bool get_pathability_groups(color_ostream &out, unordered_set<uint16_t> * depot_pathability_groups,
const unordered_set<df::coord> & depot_coords)
{
CHECK_NULL_POINTER(depot_pathability_groups);

for (auto pos : depot_coords) {
auto wgroup = Maps::getWalkableGroup(pos);
if (wgroup)
if (wgroup) {
DEBUG(log,out).print("walkability group at (%d, %d, %d) is %d\n", pos.x, pos.y, pos.z, wgroup);
depot_pathability_groups->emplace(wgroup);
}
}
return !depot_pathability_groups->empty();
}
Expand All @@ -177,12 +181,12 @@ static bool get_entry_tiles(unordered_set<df::coord> * entry_tiles, const unorde
return found;
}

static bool getDepotAccessibleByAnimals() {
static bool getDepotAccessibleByAnimals(color_ostream &out) {
unordered_set<df::coord> depot_coords;
if (!get_depot_coords(&depot_coords))
if (!get_depot_coords(out, &depot_coords))
return false;
unordered_set<uint16_t> depot_pathability_groups;
if (!get_pathability_groups(&depot_pathability_groups, depot_coords))
if (!get_pathability_groups(out, &depot_pathability_groups, depot_coords))
return false;
return get_entry_tiles(NULL, depot_pathability_groups);
}
Expand Down Expand Up @@ -263,20 +267,27 @@ static void check_wagon_tile(FloodCtx & ctx, const df::coord & pos) {
// - wagons can only move in orthogonal directions
// - if three adjacent tiles are in the same pathability group, then they are traversible by a wagon
// - a wagon needs a single ramp to move elevations as long as the adjacent tiles are walkable
static bool wagon_flood(unordered_set<df::coord> * wagon_path, const df::coord & depot_pos,
// TODO: cannot traverse doors, up stairs, or up/down stairs
static bool wagon_flood(color_ostream &out, unordered_set<df::coord> * wagon_path, const df::coord & depot_pos,
const unordered_set<df::coord> & entry_tiles)
{
bool found = false;
unordered_set<df::coord> temp_wagon_path;
FloodCtx ctx(Maps::getWalkableGroup(depot_pos), wagon_path ? *wagon_path : temp_wagon_path, entry_tiles);

if (!ctx.wgroup)
return false;

bool found = false;
ctx.wagon_path.emplace(depot_pos);
ctx.seen.emplace(depot_pos);
ctx.search_edge.emplace(depot_pos);
while (!ctx.search_edge.empty()) {
df::coord pos = ctx.search_edge.top();
ctx.search_edge.pop();

TRACE(log,out).print("checking tile: (%d, %d, %d); pathability group: %d\n", pos.x, pos.y, pos.z,
Maps::getWalkableGroup(pos));

if (entry_tiles.contains(pos)) {
found = true;
if (!wagon_path)
Expand All @@ -296,22 +307,22 @@ static bool wagon_flood(unordered_set<df::coord> * wagon_path, const df::coord &
static unordered_set<df::coord> wagon_path;
static unordered_set<df::coord> entry_tiles;

static bool getDepotAccessibleByWagons(bool cache_scan_for_painting) {
static bool getDepotAccessibleByWagons(color_ostream &out, bool cache_scan_for_painting) {
if (cache_scan_for_painting) {
entry_tiles.clear();
wagon_path.clear();
}
unordered_set<df::coord> depot_coords;
if (!get_depot_coords(&depot_coords))
if (!get_depot_coords(out, &depot_coords))
return false;
unordered_set<uint16_t> depot_pathability_groups;
if (!get_pathability_groups(&depot_pathability_groups, depot_coords))
if (!get_pathability_groups(out, &depot_pathability_groups, depot_coords))
return false;
if (!get_entry_tiles(&entry_tiles, depot_pathability_groups))
return false;
bool found_edge = false;
for (auto depot_pos : depot_coords) {
if (wagon_flood(cache_scan_for_painting ? &wagon_path : NULL, depot_pos, entry_tiles)) {
if (wagon_flood(out, cache_scan_for_painting ? &wagon_path : NULL, depot_pos, entry_tiles)) {
found_edge = true;
if (!cache_scan_for_painting)
break;
Expand Down
2 changes: 1 addition & 1 deletion scripts

0 comments on commit 4968b8d

Please sign in to comment.