From 2b7dfca21e9ac037c54dc9d5cd5dec9ec9ebd6f6 Mon Sep 17 00:00:00 2001 From: expwnent Date: Fri, 31 May 2013 19:27:22 -0400 Subject: [PATCH] diggingInvaders: cleanup, tweaks. Works for simple situations. --- plugins/diggingInvaders/diggingInvaders.cpp | 27 ++++++--- plugins/diggingInvaders/edgeCost.cpp | 62 +++++++++++++++------ 2 files changed, 62 insertions(+), 27 deletions(-) diff --git a/plugins/diggingInvaders/diggingInvaders.cpp b/plugins/diggingInvaders/diggingInvaders.cpp index b324a2564..d79f3b810 100644 --- a/plugins/diggingInvaders/diggingInvaders.cpp +++ b/plugins/diggingInvaders/diggingInvaders.cpp @@ -28,6 +28,7 @@ #include "df/general_ref_unit.h" #include "df/general_ref_unit_holderst.h" #include "df/general_ref_unit_workerst.h" +#include "df/global_objects.h" #include "df/invasion_info.h" #include "df/item.h" #include "df/itemdef_weaponst.h" @@ -171,17 +172,20 @@ void initiateDigging(color_ostream& out, void* ptr) { } void watchForJobComplete(color_ostream& out, void* ptr) { +/* df::job* job = (df::job*)ptr; if ( job->id != lastInvasionJob ) return; EventManager::unregister(EventManager::EventType::JOB_COMPLETED, jobCompleteHandler, diggingInvadersPlugin); +*/ manageInvasion(out); } int32_t manageInvasion(color_ostream& out) { + EventManager::unregisterAll(plugin_self); if ( !enabled ) { return -1; } @@ -191,14 +195,16 @@ int32_t manageInvasion(color_ostream& out) { //out.print("Invasion is over. Stopping diggingInvaders.\n"); return -2; } + EventManager::registerTick(jobCompleteHandler, 1, plugin_self); if ( lastInvasionJob != -1 ) { //check if he's still doing it - int32_t index = df::unit::binsearch_index(df::global::world->units.all, lastInvasionDigger); - if ( index == -1 ) { + df::unit* worker = df::unit::find(lastInvasionDigger); + //int32_t index = df::unit::binsearch_index(df::global::world->units.all, lastInvasionDigger); + if ( !worker ) { out.print("Error %s line %d.\n", __FILE__, __LINE__); return -1; } - df::job* job = df::global::world->units.all[index]->job.current_job; + df::job* job = worker->job.current_job; //out.print("job id: old = %d, new = %d\n", lastInvasionJob, job == NULL ? -1 : job->id); if ( job != NULL && lastInvasionJob == job->id ) { //out.print("Still working on the previous job.\n"); @@ -207,6 +213,8 @@ int32_t manageInvasion(color_ostream& out) { //return 1; //still invading, but nothing new done } + + *df::global::pause_state = true; int32_t unitId = findAndAssignInvasionJob(out); if ( unitId == -1 ) { //might need to do more digging later, after we've killed off a few locals @@ -224,7 +232,7 @@ int32_t manageInvasion(color_ostream& out) { lastInvasionJob = df::global::world->units.all[index]->job.current_job->id; } - EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, jobCompleteHandler, diggingInvadersPlugin); + //EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, jobCompleteHandler, diggingInvadersPlugin); //out.print("DiggingInvaders: job assigned.\n"); return 0; //did something } @@ -320,8 +328,8 @@ int32_t findAndAssignInvasionJob(color_ostream& out) { unordered_set localConnectivity; //find all locals and invaders - for ( size_t a = 0; a < df::global::world->units.active.size(); a++ ) { - df::unit* unit = df::global::world->units.active[a]; + for ( size_t a = 0; a < df::global::world->units.all.size(); a++ ) { + df::unit* unit = df::global::world->units.all[a]; if ( unit->flags1.bits.dead ) continue; if ( Units::isCitizen(unit) ) { @@ -363,8 +371,9 @@ int32_t findAndAssignInvasionJob(color_ostream& out) { return -1; } df::unit* firstInvader = invaders[0]; - //out << firstInvader->id << endl; - //out << firstInvader->pos.x << ", " << firstInvader->pos.y << ", " << firstInvader->pos.z << endl; + out << firstInvader->id << endl; + out << firstInvader->pos.x << ", " << firstInvader->pos.y << ", " << firstInvader->pos.z << endl; + out << __LINE__ << endl; int32_t localPtsFound = 0; unordered_set closedSet; @@ -377,7 +386,7 @@ int32_t findAndAssignInvasionJob(color_ostream& out) { while(!fringe.empty()) { df::coord pt = *(fringe.begin()); fringe.erase(fringe.begin()); - //out.print("line %d: fringe size = %d, localPtsFound = %d / %d, closedSetSize = %d\n", __LINE__, fringe.size(), localPtsFound, localPts.size(), closedSet.size()); + //out.print("line %d: fringe size = %d, localPtsFound = %d / %d, closedSetSize = %d, pt = %d,%d,%d\n", __LINE__, fringe.size(), localPtsFound, localPts.size(), closedSet.size(), pt.x,pt.y,pt.z); if ( closedSet.find(pt) != closedSet.end() ) { out.print("%s, line %d: Double closure! Bad!\n", __FILE__, __LINE__); break; diff --git a/plugins/diggingInvaders/edgeCost.cpp b/plugins/diggingInvaders/edgeCost.cpp index 7bf2f600c..2d08146dd 100644 --- a/plugins/diggingInvaders/edgeCost.cpp +++ b/plugins/diggingInvaders/edgeCost.cpp @@ -30,6 +30,11 @@ int64_t costWeight[] = { using namespace std; +/* +limitations + ramps + cave-ins +*/ int64_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2) { int32_t dx = pt2.x - pt1.x; int32_t dy = pt2.y - pt1.y; @@ -45,7 +50,12 @@ int64_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2) { df::tiletype* type2 = Maps::getTileType(pt2); df::tiletype_shape shape2 = ENUM_ATTR(tiletype, shape, *type2); - + + if ( Maps::getTileBlock(pt1)->designation[pt1.x&0xF][pt1.y&0xF].bits.flow_size >= 4 ) + return -1; + if ( Maps::getTileBlock(pt2)->designation[pt2.x&0xF][pt2.y&0xF].bits.flow_size >= 4 ) + return -1; + if ( shape2 == df::enums::tiletype_shape::EMPTY ) { return -1; } @@ -93,12 +103,13 @@ int64_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2) { } cost += costWeight[CostDimension::Dig]; } - + if ( building2 ) { + //moving up through an open bridge or a usable hatch is fine. other buildings are not bool unforbiddenHatch = false; if ( building2->getType() == df::building_type::Hatch ) { df::building_hatchst* hatch = (df::building_hatchst*)building2; - if ( hatch->door_flags.bits.forbidden ) + if ( !hatch->door_flags.bits.forbidden && !(hatch->door_flags.bits.operated_by_mechanisms&&hatch->door_flags.bits.closed) ) unforbiddenHatch = true; } bool inactiveBridge = false; @@ -126,27 +137,32 @@ int64_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2) { if ( !unforbiddenHatch && !inactiveBridge ) return -1; } - - bool forbidden = false; + + /*bool forbidden = false; if ( building2 && building2->getType() == df::building_type::Hatch ) { df::building_hatchst* hatch = (df::building_hatchst*)building2; if ( hatch->door_flags.bits.forbidden ) forbidden = true; } if ( forbidden ) - return -1; + return -1;*/ } else { bool walkable_high2 = shape2 == df::tiletype_shape::STAIR_UP || shape2 == df::tiletype_shape::STAIR_UPDOWN; if ( !walkable_high2 ) { if ( building2 || construction2 ) return -1; - + if ( shape2 != df::enums::tiletype_shape::WALL ) return -1; cost += costWeight[CostDimension::Dig]; } bool walkable_low1 = shape1 == df::tiletype_shape::STAIR_DOWN || shape1 == df::tiletype_shape::STAIR_UPDOWN; if ( !walkable_low1 ) { + //if ( building1 || construction1 ) + //return -1; + //TODO: consider ramps + if ( shape1 == df::tiletype_shape::RAMP ) + return -1; cost += costWeight[CostDimension::Dig]; } @@ -157,32 +173,42 @@ int64_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2) { if ( bridge->gate_flags.bits.closed ) { return -1; } + //open bridges moving down, standing on bad spot + if ( bridge->direction == df::building_bridgest::T_direction::Left && pt1.x == bridge->x1 ) + return -1; + if ( bridge->direction == df::building_bridgest::T_direction::Right && pt1.x == bridge->x2 ) + return -1; + if ( bridge->direction == df::building_bridgest::T_direction::Up && pt1.y == bridge->y1 ) + return -1; + if ( bridge->direction == df::building_bridgest::T_direction::Down && pt1.y == bridge->y2 ) + return -1; } - + bool forbidden = false; - if ( building1->getType() == df::building_type::Hatch ) { + if ( building1 && building1->getType() == df::building_type::Hatch ) { df::building_hatchst* hatch = (df::building_hatchst*)building1; - if ( hatch->door_flags.bits.forbidden ) + if ( hatch->door_flags.bits.forbidden || hatch->door_flags.bits.closed && hatch->door_flags.bits.operated_by_mechanisms ) forbidden = true; } - - if ( building1 && forbidden && building1->getType() == df::building_type::Hatch ) { + + if ( building1 && forbidden /*&& building1->getType() == df::building_type::Hatch*/ ) { df::coord support[] = {df::coord(pt1.x-1, pt1.y, pt1.z), df::coord(pt1.x+1,pt1.y,pt1.z), df::coord(pt1.x,pt1.y-1,pt1.z), df::coord(pt1.x,pt1.y+1,pt1.z)}; int64_t minCost = -1; for ( size_t a = 0; a < 4; a++ ) { df::tiletype* supportType = Maps::getTileType(support[a]); df::tiletype_shape shape = ENUM_ATTR(tiletype, shape, *supportType); df::tiletype_shape_basic basic = ENUM_ATTR(tiletype_shape, basic_shape, shape); - int64_t cost = 2*costWeight[CostDimension::Walk] + costWeight[CostDimension::DestroyBuilding]; + int64_t cost2 = 2*costWeight[CostDimension::Walk] + costWeight[CostDimension::DestroyBuilding]; if ( !Maps::canStepBetween(pt1, support[a]) ) { switch(basic) { case tiletype_shape_basic::Open: + //TODO: check for a hatch or a bridge: that makes it ok continue; case tiletype_shape_basic::Wall: if ( ENUM_ATTR(tiletype, material, *supportType) == df::enums::tiletype_material::CONSTRUCTION ) { - cost += costWeight[CostDimension::DestroyConstruction]; + cost2 += costWeight[CostDimension::DestroyConstruction]; } else { - cost += costWeight[CostDimension::Dig]; + cost2 += costWeight[CostDimension::Dig]; } case tiletype_shape_basic::Ramp: //TODO: check for a hatch or a bridge: that makes it ok @@ -194,11 +220,11 @@ int64_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2) { break; } if ( Buildings::findAtTile(support[a]) ) { - cost += costWeight[CostDimension::DestroyBuilding]; + cost2 += costWeight[CostDimension::DestroyBuilding]; } } - if ( minCost == -1 || cost < minCost ) - minCost = cost; + if ( minCost == -1 || cost2 < minCost ) + minCost = cost2; } if ( minCost == -1 ) return -1;