Digging invaders: buildings can only be destroyed orthogonally, made path cost deal with hatches and raised bridges, but did NOT yet make job assignment deal with them.

develop
expwnent 2013-01-05 11:06:46 -05:00
parent a7d6cf5157
commit 3c7ca2ad71
3 changed files with 108 additions and 7 deletions

@ -218,7 +218,7 @@ int32_t manageInvasion(color_ostream& out) {
{
int32_t index = df::unit::binsearch_index(df::global::world->units.all, unitId);
if ( index == -1 ) {
out.print("Error %s line %d: unitId = %d, index = %d.\n", __FILE__, __LINE__, unitId, index);
//out.print("Error %s line %d: unitId = %d, index = %d.\n", __FILE__, __LINE__, unitId, index);
return -1;
}
lastInvasionJob = df::global::world->units.all[index]->job.current_job->id;
@ -264,8 +264,8 @@ command_result diggingInvadersFunc(color_ostream& out, std::vector<std::string>&
return CR_WRONG_USAGE;
string costStr = parameters[a+1];
int32_t costDim = -1;
if ( costStr == "distance" ) {
costDim = CostDimension::Distance;
if ( costStr == "walk" ) {
costDim = CostDimension::Walk;
} else if ( costStr == "destroyBuilding" ) {
costDim = CostDimension::DestroyBuilding;
} else if ( costStr == "dig" ) {

@ -5,6 +5,9 @@
#include "modules/MapCache.h"
#include "df/building.h"
#include "df/building_bridgest.h"
#include "df/building_hatchst.h"
#include "df/building_type.h"
#include "df/coord.h"
#include "df/map_block.h"
#include "df/tile_building_occ.h"
@ -31,7 +34,7 @@ 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;
int32_t dz = pt2.z - pt1.z;
int64_t cost = costWeight[CostDimension::Distance];
int64_t cost = costWeight[CostDimension::Walk];
if ( Maps::canStepBetween(pt1, pt2) ) {
return cost;
@ -51,8 +54,11 @@ int64_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2) {
return -1;
df::building* building2 = Buildings::findAtTile(pt2);
if ( building2 )
if ( building2 ) {
cost += costWeight[CostDimension::DestroyBuilding];
if ( dx*dx + dy*dy > 1 )
return -1;
}
bool construction2 = ENUM_ATTR(tiletype, material, *type2) == df::enums::tiletype_material::CONSTRUCTION;
if ( construction2 )
@ -87,6 +93,48 @@ int64_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2) {
}
cost += costWeight[CostDimension::Dig];
}
if ( building2 ) {
bool unforbiddenHatch = false;
if ( building2->getType() == df::building_type::Hatch ) {
df::building_hatchst* hatch = (df::building_hatchst*)building2;
if ( hatch->door_flags.bits.forbidden )
unforbiddenHatch = true;
}
bool inactiveBridge = false;
if ( building2->getType() == df::building_type::Bridge ) {
df::building_bridgest* bridge = (df::building_bridgest*)building2;
bool xMin = pt2.x == bridge->x1;
bool xMax = pt2.x == bridge->x2;
bool yMin = pt2.y == bridge->y1;
bool yMax = pt2.y == bridge->y2;
if ( !bridge->gate_flags.bits.closed ) {
//if it's open, we could still be in the busy part of it
if ( bridge->direction == df::building_bridgest::T_direction::Left && !xMin ) {
inactiveBridge = true;
} else if ( bridge->direction == df::building_bridgest::T_direction::Right && !xMax ) {
inactiveBridge = true;
} else if ( bridge->direction == df::building_bridgest::T_direction::Up && !yMax ) {
inactiveBridge = true;
} else if ( bridge->direction == df::building_bridgest::T_direction::Down && !yMin ) {
inactiveBridge = true;
} else if ( bridge->direction == df::building_bridgest::T_direction::Retracting ) {
inactiveBridge = true;
}
}
}
if ( !unforbiddenHatch && !inactiveBridge )
return -1;
}
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;
} else {
bool walkable_high2 = shape2 == df::tiletype_shape::STAIR_UP || shape2 == df::tiletype_shape::STAIR_UPDOWN;
if ( !walkable_high2 ) {
@ -101,6 +149,59 @@ int64_t getEdgeCost(color_ostream& out, df::coord pt1, df::coord pt2) {
if ( !walkable_low1 ) {
cost += costWeight[CostDimension::Dig];
}
df::building* building1 = Buildings::findAtTile(pt1);
//if you're moving down, and you're on a bridge, and that bridge is lowered, then you can't do it
if ( building1 && building1->getType() == df::building_type::Bridge ) {
df::building_bridgest* bridge = (df::building_bridgest*)building2;
if ( bridge->gate_flags.bits.closed
}
bool forbidden = false;
if ( building1->getType() == df::building_type::Hatch ) {
df::building_hatchst* hatch = (df::building_hatchst*)building1;
if ( hatch->door_flags.bits.forbidden )
forbidden = true;
}
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];
if ( !Maps::canStepBetween(pt1, support[a]) ) {
switch(basic) {
case tiletype_shape_basic::Open:
continue;
case tiletype_shape_basic::Wall:
if ( ENUM_ATTR(tiletype, material, *supportType) == df::enums::tiletype_material::CONSTRUCTION ) {
cost += costWeight[CostDimension::DestroyConstruction];
} else {
cost += costWeight[CostDimension::Dig];
}
case tiletype_shape_basic::Ramp:
//TODO: check for a hatch or a bridge: that makes it ok
if ( shape == df::enums::tiletype_shape::RAMP_TOP ) {
continue;
}
case tiletype_shape_basic::Stair:
case tiletype_shape_basic::Floor:
break;
}
if ( Buildings::findAtTile(support[a]) ) {
cost += costWeight[CostDimension::DestroyBuilding];
}
}
if ( minCost == -1 || cost < minCost )
minCost = cost;
}
if ( minCost == -1 )
return -1;
cost += minCost;
}
}
} else {
//nonvertical
@ -117,7 +218,7 @@ int64_t getEdgeCostOld(color_ostream& out, df::coord pt1, df::coord pt2) {
int32_t dx = pt2.x - pt1.x;
int32_t dy = pt2.y - pt1.y;
int32_t dz = pt2.z - pt1.z;
int64_t cost = costWeight[CostDimension::Distance];
int64_t cost = costWeight[CostDimension::Walk];
if ( false ) {
if ( Maps::canStepBetween(pt1,pt2) )

@ -13,7 +13,7 @@
//cost is [path cost, building destruction cost, dig cost, construct cost]. Minimize constructions, then minimize dig cost, then minimize path cost.
enum CostDimension {
Distance,
Walk,
DestroyBuilding,
Dig,
DestroyConstruction,