From 0fecdfadb1cd5fd3c82416b3d1718747de850e42 Mon Sep 17 00:00:00 2001 From: expwnent Date: Thu, 3 Jan 2013 22:46:17 -0500 Subject: [PATCH] Digging Invaders: when assigning a job, get rid of old one. Handle loading and unloading. Optimizations for when invaders can already reach someone. --- plugins/diggingInvaders/assignJob.cpp | 22 +++++++++ plugins/diggingInvaders/diggingInvaders.cpp | 54 +++++++++++++++++++-- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/plugins/diggingInvaders/assignJob.cpp b/plugins/diggingInvaders/assignJob.cpp index a11717f8a..7943c4418 100644 --- a/plugins/diggingInvaders/assignJob.cpp +++ b/plugins/diggingInvaders/assignJob.cpp @@ -20,6 +20,25 @@ #include "df/unit.h" #include "df/unit_inventory_item.h" +void getRidOfOldJob(df::unit* unit) { + if ( unit->job.current_job == NULL ) { + return; + } + + df::job* job = unit->job.current_job; + unit->job.current_job = NULL; + if ( job->list_link->prev != NULL ) { + job->list_link->prev->next = job->list_link->next; + } + if ( job->list_link->next != NULL ) { + job->list_link->next->prev = job->list_link->prev; + } + //TODO: consider building pointers? + //for now, just let the memory leak TODO: fix + //delete job->list_link; + //delete job; +} + int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map parentMap, unordered_map& costMap, vector& invaders, unordered_set& requiresZNeg, unordered_set& requiresZPos, MapExtras::MapCache& cache) { df::unit* firstInvader = invaders[0]; @@ -59,6 +78,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_mapunit_id = firstInvader->id; job->general_refs.push_back(workerRef); + getRidOfOldJob(firstInvader); firstInvader->job.current_job = job; firstInvader->path.path.x.clear(); firstInvader->path.path.y.clear(); @@ -84,6 +104,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_mapunit_id = firstInvader->id; job->general_refs.push_back(workerRef); job->pos = pt2; + getRidOfOldJob(firstInvader); firstInvader->job.current_job = job; firstInvader->path.path.x.clear(); firstInvader->path.path.y.clear(); @@ -120,6 +141,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_mapgeneral_refs.push_back(ref); firstInvader->job.hunt_target = NULL; firstInvader->job.destroy_target = NULL; + getRidOfOldJob(firstInvader); firstInvader->job.current_job = job; firstInvader->path.path.x.clear(); firstInvader->path.path.y.clear(); diff --git a/plugins/diggingInvaders/diggingInvaders.cpp b/plugins/diggingInvaders/diggingInvaders.cpp index 1f7fc8e89..143fdcb6a 100644 --- a/plugins/diggingInvaders/diggingInvaders.cpp +++ b/plugins/diggingInvaders/diggingInvaders.cpp @@ -75,6 +75,7 @@ DFHACK_PLUGIN("diggingInvaders"); static int32_t lastInvasionJob=-1; static EventManager::EventHandler jobCompleteHandler(watchForJobComplete, 5); static Plugin* diggingInvadersPlugin; +static bool enabled=true; DFhackCExport command_result plugin_init (color_ostream &out, std::vector &commands) { @@ -88,8 +89,7 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector & rootMap); class PointComp { @@ -149,8 +170,13 @@ void watchForJobComplete(color_ostream& out, void* ptr) { } int32_t manageInvasion(color_ostream& out) { - if ( df::global::ui->invasions.list[df::global::ui->invasions.next_id-1]->flags.bits.active == 0 ) { + if ( !enabled ) { + return -1; + } + int32_t lastInvasion = df::global::ui->invasions.next_id-1; + if ( lastInvasion < 0 || df::global::ui->invasions.list[lastInvasion]->flags.bits.active == 0 ) { //if the invasion is over, we're done + out.print("Invasion is over. Stopping diggingInvaders.\n"); return -1; } if ( lastInvasionJob != -1 ) { @@ -162,12 +188,14 @@ int32_t manageInvasion(color_ostream& out) { //might need to do more digging later, after we've killed off a few locals EventManager::EventHandler checkPeriodically(initiateDigging, 1000); EventManager::registerTick(checkPeriodically, checkPeriodically.freq, diggingInvadersPlugin); + out.print("DiggingInvaders is waiting.\n"); return -1; } lastInvasionJob = jobId; EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, jobCompleteHandler, diggingInvadersPlugin); + out.print("DiggingInvaders: job assigned.\n"); return 0; //did something } @@ -197,6 +225,9 @@ int32_t findAndAssignInvasionJob(color_ostream& out) { MapExtras::MapCache cache; vector invaders; + + unordered_set invaderConnectivity; + unordered_set localConnectivity; //TODO: look for invaders with buildingdestroyer:3 //find all locals and invaders @@ -208,6 +239,8 @@ int32_t findAndAssignInvasionJob(color_ostream& out) { if ( localPts.find(unit->pos) != localPts.end() ) continue; localPts.insert(unit->pos); + df::map_block* block = Maps::getTileBlock(unit->pos); + localConnectivity.insert(block->walkable[unit->pos.x&0xF][unit->pos.y&0xF]); } else if ( unit->flags1.bits.active_invader ) { if ( invaderPts.find(unit->pos) != invaderPts.end() ) continue; @@ -215,6 +248,8 @@ int32_t findAndAssignInvasionJob(color_ostream& out) { costMap[unit->pos] = 0; fringe.insert(unit->pos); invaders.push_back(unit); + df::map_block* block = Maps::getTileBlock(unit->pos); + invaderConnectivity.insert(block->walkable[unit->pos.x&0xF][unit->pos.y&0xF]); } else { continue; } @@ -223,6 +258,19 @@ int32_t findAndAssignInvasionJob(color_ostream& out) { if ( invaders.empty() ) { return -1; } + + //if local connectivity is not disjoint from invader connectivity, no digging required + bool overlap = false; + for ( auto a = localConnectivity.begin(); a != localConnectivity.end(); a++ ) { + uint16_t conn = *a; + if ( invaderConnectivity.find(conn) == invaderConnectivity.end() ) + continue; + overlap = true; + break; + } + if ( overlap ) { + return -1; + } df::unit* firstInvader = invaders[0]; out << firstInvader->id << endl; out << firstInvader->pos.x << ", " << firstInvader->pos.y << ", " << firstInvader->pos.z << endl;