Implements plugin: channel-safely v0.5

develop
Josh Cooper 2022-11-06 15:59:30 -08:00
parent c2d346fc84
commit e5dbaac85d
6 changed files with 85 additions and 28 deletions

@ -1,4 +1,5 @@
#include <channel-groups.h> #include <channel-groups.h>
#include <tile-cache.h>
#include <inlines.h> #include <inlines.h>
#include <modules/Maps.h> #include <modules/Maps.h>
#include <df/block_square_event_designation_priorityst.h> #include <df/block_square_event_designation_priorityst.h>
@ -91,18 +92,12 @@ void ChannelGroups::add(const df::coord &map_pos) {
// puts the "add" in "ChannelGroups::add" // puts the "add" in "ChannelGroups::add"
group->emplace(map_pos); group->emplace(map_pos);
DEBUG(groups).print(" = group[%d] of (" COORD ") is size: %zu\n", group_index, COORDARGS(map_pos), group->size()); DEBUG(groups).print(" = group[%d] of (" COORD ") is size: %zu\n", group_index, COORDARGS(map_pos), group->size());
// ERR(groups).print("\n\n\nDEBUG MAPPINGS:\n");
// debug_map();
// DEBUG(groups).flush();
// we may have performed a merge, so we update all the `coord -> group index` mappings // we may have performed a merge, so we update all the `coord -> group index` mappings
for (auto &wpos: *group) { for (auto &wpos: *group) {
groups_map[wpos] = group_index; groups_map[wpos] = group_index;
} }
DEBUG(groups).print(" <- add() exits, there are %zu mappings\n", groups_map.size()); DEBUG(groups).print(" <- add() exits, there are %zu mappings\n", groups_map.size());
// ERR(groups).print("\n\n\nDEBUG MAPPINGS:\n");
// debug_map();
// DEBUG(groups).flush();
} }
// scans a single tile for channel designations // scans a single tile for channel designations
@ -120,7 +115,8 @@ void ChannelGroups::scan_one(const df::coord &map_pos) {
} }
} }
} }
} else if (isOpenTerrain(block->tiletype[lx][ly])) { } else if (TileCache::Get().hasChanged(map_pos, block->tiletype[lx][ly])) {
TileCache::Get().uncache(map_pos);
remove(map_pos); remove(map_pos);
} }
} }
@ -145,6 +141,9 @@ void ChannelGroups::scan() {
remove(pos); remove(pos);
} }
static std::default_random_engine RNG(0);
static std::bernoulli_distribution optimizing(0.75); // fixing OpenSpace as designated
DEBUG(groups).print(" scan()\n"); DEBUG(groups).print(" scan()\n");
// foreach block // foreach block
for (int32_t z = mapz - 1; z >= 0; --z) { for (int32_t z = mapz - 1; z >= 0; --z) {
@ -153,7 +152,7 @@ void ChannelGroups::scan() {
// the block // the block
if (df::map_block* block = Maps::getBlock(bx, by, z)) { if (df::map_block* block = Maps::getBlock(bx, by, z)) {
// skip this block? // skip this block?
if (!block->flags.bits.designated && !group_blocks.count(block)) { if (!block->flags.bits.designated && !group_blocks.count(block) && optimizing(RNG)) {
continue; continue;
} }
// foreach tile // foreach tile
@ -162,7 +161,13 @@ void ChannelGroups::scan() {
for (int16_t ly = 0; ly < 16; ++ly) { for (int16_t ly = 0; ly < 16; ++ly) {
// the tile, check if it has a channel designation // the tile, check if it has a channel designation
df::coord map_pos((bx * 16) + lx, (by * 16) + ly, z); df::coord map_pos((bx * 16) + lx, (by * 16) + ly, z);
if (is_dig_designation(block->designation[lx][ly])) { if (TileCache::Get().hasChanged(map_pos, block->tiletype[lx][ly])) {
remove(map_pos);
if (jobs.count(map_pos)) {
jobs.erase(map_pos);
}
block->designation[lx][ly].bits.dig = df::tile_dig_designation::No;
} else if (is_dig_designation(block->designation[lx][ly])) {
for (df::block_square_event* event: block->block_events) { for (df::block_square_event* event: block->block_events) {
if (auto evT = virtual_cast<df::block_square_event_designation_priorityst>(event)) { if (auto evT = virtual_cast<df::block_square_event_designation_priorityst>(event)) {
// we want to let the user keep some designations free of being managed // we want to let the user keep some designations free of being managed
@ -170,18 +175,17 @@ void ChannelGroups::scan() {
if (evT->priority[lx][ly] < 1000 * config.ignore_threshold) { if (evT->priority[lx][ly] < 1000 * config.ignore_threshold) {
if (empty_group) { if (empty_group) {
group_blocks.emplace(block); group_blocks.emplace(block);
empty_group = false;
} }
TRACE(groups).print(" adding (" COORD ")\n", COORDARGS(map_pos)); TRACE(groups).print(" adding (" COORD ")\n", COORDARGS(map_pos));
add(map_pos); add(map_pos);
empty_group = false;
} }
} }
} }
} else if (isOpenTerrain(block->tiletype[lx][ly])) {
remove(map_pos);
} }
} }
} }
// erase the block if we didn't find anything iterating through it
if (empty_group) { if (empty_group) {
group_blocks.erase(block); group_blocks.erase(block);
} }
@ -196,6 +200,7 @@ void ChannelGroups::scan() {
void ChannelGroups::clear() { void ChannelGroups::clear() {
debug_map(); debug_map();
WARN(groups).print(" <- clearing groups\n"); WARN(groups).print(" <- clearing groups\n");
group_blocks.clear();
free_spots.clear(); free_spots.clear();
groups_map.clear(); groups_map.clear();
for(size_t i = 0; i < groups.size(); ++i) { for(size_t i = 0; i < groups.size(); ++i) {

@ -1,4 +1,5 @@
#include <channel-manager.h> #include <channel-manager.h>
#include <tile-cache.h>
#include <inlines.h> #include <inlines.h>
#include <df/block_square_event_designation_priorityst.h> #include <df/block_square_event_designation_priorityst.h>
@ -69,8 +70,11 @@ bool ChannelManager::manage_one(const Group &group, const df::coord &map_pos, bo
} }
// if activating designation, check if it is safe to dig or not a channel designation // if activating designation, check if it is safe to dig or not a channel designation
if (!is_channel_designation(block->designation[Coord(local)]) || is_safe_to_dig_down(map_pos)) { if (!is_channel_designation(block->designation[Coord(local)]) || is_safe_to_dig_down(map_pos)) {
tile_occupancy.bits.dig_marked = marker_mode; if (!block->flags.bits.designated) {
return marker_mode; block->flags.bits.designated = true;
}
tile_occupancy.bits.dig_marked = false;
TileCache::Get().cache(map_pos, block->tiletype[Coord(local)]);
} }
return false; return false;
@ -85,7 +89,9 @@ bool ChannelManager::manage_one(const Group &group, const df::coord &map_pos, bo
if (has_group_above(groups, map_pos) || !is_safe_to_dig_down(map_pos)) { if (has_group_above(groups, map_pos) || !is_safe_to_dig_down(map_pos)) {
DEBUG(manager).print(" has_groups_above: setting marker mode\n"); DEBUG(manager).print(" has_groups_above: setting marker mode\n");
tile_occupancy.bits.dig_marked = true; tile_occupancy.bits.dig_marked = true;
if (jobs.count(map_pos)) {
jobs.erase(map_pos); jobs.erase(map_pos);
}
WARN(manager).print(" <- manage_one() exits normally\n"); WARN(manager).print(" <- manage_one() exits normally\n");
return true; return true;
} }
@ -104,4 +110,6 @@ bool ChannelManager::manage_one(const Group &group, const df::coord &map_pos, bo
void ChannelManager::mark_done(const df::coord &map_pos) { void ChannelManager::mark_done(const df::coord &map_pos) {
groups.remove(map_pos); groups.remove(map_pos);
jobs.erase(map_pos);
TileCache::Get().uncache(map_pos);
} }

@ -53,6 +53,7 @@ Updated: Nov. 6 2022
#include <plugin.h> #include <plugin.h>
#include <inlines.h> #include <inlines.h>
#include <channel-manager.h> #include <channel-manager.h>
#include <tile-cache.h>
#include <Debug.h> #include <Debug.h>
#include <LuaTools.h> #include <LuaTools.h>
@ -211,23 +212,23 @@ namespace CSP {
INFO(monitor).print("JobCompletedEvent()\n"); INFO(monitor).print("JobCompletedEvent()\n");
auto job = (df::job*) job_ptr; auto job = (df::job*) job_ptr;
// we only care if the job is a channeling one // we only care if the job is a channeling one
if (is_dig_job(job)) { if (ChannelManager::Get().groups.count(job->pos)) {
// untrack job/worker // untrack job/worker
active_workers.erase(job->id); active_workers.erase(job->id);
// check job outcome // check job outcome
auto block = Maps::getTileBlock(job->pos);
df::coord local(job->pos); df::coord local(job->pos);
auto block = Maps::getTileBlock(local);
local.x = local.x % 16; local.x = local.x % 16;
local.y = local.y % 16; local.y = local.y % 16;
const auto &type = block->tiletype[Coord(local)];
// verify completion // verify completion
if (isOpenTerrain(block->tiletype[local.x][local.y]) if (TileCache::Get().hasChanged(job->pos, type)) {
|| block->designation[local.x][local.y].bits.dig != df::enums::tile_dig_designation::Channel) {
// the job can be considered done // the job can be considered done
df::coord below(job->pos); df::coord below(job->pos);
below.z--; below.z--;
WARN(monitor).print(" -> Marking tile done and managing the group below.\n"); WARN(monitor).print(" -> Marking tile done and managing the group below.\n");
// mark done and manage below // mark done and manage below
Maps::getTileDesignation(job->pos)->bits.traffic = df::tile_traffic::Normal; block->designation[Coord(local)].bits.traffic = df::tile_traffic::Normal;
ChannelManager::Get().mark_done(job->pos); ChannelManager::Get().mark_done(job->pos);
ChannelManager::Get().manage_group(below); ChannelManager::Get().manage_group(below);
ChannelManager::Get().debug(); ChannelManager::Get().debug();
@ -247,16 +248,18 @@ namespace CSP {
TRACE(monitor).print("OnUpdate()\n"); TRACE(monitor).print("OnUpdate()\n");
UnpauseEvent(); UnpauseEvent();
if (config.insta_dig) {
TRACE(monitor).print(" -> evaluate dignow queue\n"); TRACE(monitor).print(" -> evaluate dignow queue\n");
for (const df::coord &pos: dignow_queue) { for (const df::coord &pos: dignow_queue) {
if (!has_unit(Maps::getTileOccupancy(pos))) { if (!has_unit(Maps::getTileOccupancy(pos))) {
out.print("channel-safely: insta-dig: Digging now!\n");
dig_now(out, pos); dig_now(out, pos);
} else { } else {
// todo: teleport? // todo: teleport?
//Units::teleport() //Units::teleport()
} }
} }
TRACE(monitor).print("OnUpdate() exits\n"); }
} }
if (config.monitor_active && tick - last_monitor_tick >= config.monitor_freq) { if (config.monitor_active && tick - last_monitor_tick >= config.monitor_freq) {
last_monitor_tick = tick; last_monitor_tick = tick;
@ -311,6 +314,7 @@ namespace CSP {
} }
} }
} }
TRACE(monitor).print("OnUpdate() exits\n");
} }
} }
} }

@ -22,6 +22,7 @@ private:
public: public:
void load_channel_jobs(); void load_channel_jobs();
void clear(); void clear();
int count(const df::coord &map_pos) const { return jobs.count(map_pos); }
Jobs::iterator erase(const df::coord &map_pos); Jobs::iterator erase(const df::coord &map_pos);
Jobs::const_iterator find(const df::coord &map_pos) const; Jobs::const_iterator find(const df::coord &map_pos) const;
Jobs::const_iterator begin() const; Jobs::const_iterator begin() const;

@ -44,6 +44,10 @@ inline bool is_channel_job(const df::job* job) {
return job->job_type == df::job_type::DigChannel; return job->job_type == df::job_type::DigChannel;
} }
inline bool is_group_job(const ChannelGroups &groups, const df::job* job) {
return groups.count(job->pos);
}
inline bool is_dig_designation(const df::tile_designation &designation) { inline bool is_dig_designation(const df::tile_designation &designation) {
return designation.bits.dig != df::tile_dig_designation::No; return designation.bits.dig != df::tile_dig_designation::No;
} }

@ -0,0 +1,35 @@
#pragma once
#include <modules/Maps.h>
#include <df/coord.h>
#include <df/tiletype.h>
#include <map>
class TileCache {
private:
TileCache() = default;
std::map<df::coord, df::tiletype> locations;
public:
static TileCache& Get() {
static TileCache instance;
return instance;
}
void cache(const df::coord &pos, df::tiletype type) {
locations.emplace(pos, type);
}
void uncache(const df::coord &pos) {
locations.erase(pos);
}
bool hasChanged(const df::coord &pos, const df::tiletype &type) {
if (locations.count(pos)) {
if (type != locations.find(pos)->second){
return true;
}
}
return false;
}
};