Digging Invaders: when assigning a job, get rid of old one. Handle loading and unloading. Optimizations for when invaders can already reach someone.

develop
expwnent 2013-01-03 22:46:17 -05:00
parent ed6dcf9589
commit 0fecdfadb1
2 changed files with 73 additions and 3 deletions

@ -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<df::coord,df::coord,PointHash> parentMap, unordered_map<df::coord,int64_t,PointHash>& costMap, vector<df::unit*>& invaders, unordered_set<df::coord,PointHash>& requiresZNeg, unordered_set<df::coord,PointHash>& requiresZPos, MapExtras::MapCache& cache) {
df::unit* firstInvader = invaders[0];
@ -59,6 +78,7 @@ int32_t assignJob(color_ostream& out, Edge firstImportantEdge, unordered_map<df:
df::general_ref_unit_workerst* workerRef = new df::general_ref_unit_workerst;
workerRef->unit_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_map<df:
workerRef->unit_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_map<df:
job->general_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();

@ -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 <PluginCommand> &commands)
{
@ -88,8 +89,7 @@ DFhackCExport command_result plugin_init (color_ostream &out, std::vector <Plugi
// Extended help string. Used by CR_WRONG_USAGE and the help command:
"EXTRA HELP STRINGGNGNGNGNGNNGG.\n"
));
return CR_OK;
}
@ -98,6 +98,27 @@ DFhackCExport command_result plugin_shutdown ( color_ostream &out )
return CR_OK;
}
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event event)
{
EventManager::EventHandler invasionHandler(initiateDigging, 1000);
switch (event) {
case DFHack::SC_WORLD_LOADED:
out.print("Game loaded.\n");
//TODO: check game mode
lastInvasionJob = -1;
//in case there are invaders when the game is loaded, we should check
EventManager::registerTick(invasionHandler, 10, diggingInvadersPlugin);
break;
case DFHack::SC_WORLD_UNLOADED:
out.print("Game unloaded.\n");
// cleanup
break;
default:
break;
}
return CR_OK;
}
df::coord getRoot(df::coord point, unordered_map<df::coord, df::coord>& 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<df::unit*> invaders;
unordered_set<uint16_t> invaderConnectivity;
unordered_set<uint16_t> 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;