diggingInvaders: cleanup, tweaks. Works for simple situations.

develop
expwnent 2013-05-31 19:27:22 -04:00
parent f8261348ff
commit 2b7dfca21e
2 changed files with 62 additions and 27 deletions

@ -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<uint16_t> 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<df::coord,PointHash> 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;

@ -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;