2013-01-03 16:14:16 -07:00
# include "assignJob.h"
# include "edgeCost.h"
2012-08-23 18:37:43 -06:00
# include "Core.h"
2012-12-16 14:53:02 -07:00
# include "Console.h"
2012-08-23 18:37:43 -06:00
# include "DataDefs.h"
2012-12-16 14:53:02 -07:00
# include "Export.h"
# include "PluginManager.h"
# include "Types.h"
# include "modules/Buildings.h"
# include "modules/EventManager.h"
2013-01-04 19:02:09 -07:00
# include "modules/Gui.h"
2012-12-19 16:46:46 -07:00
# include "modules/Job.h"
2012-12-16 19:44:23 -07:00
# include "modules/Maps.h"
2012-12-16 14:53:02 -07:00
# include "modules/MapCache.h"
2012-12-16 19:44:23 -07:00
# include "modules/Units.h"
2012-12-16 14:53:02 -07:00
# include "modules/World.h"
2012-12-19 16:46:46 -07:00
# include "df/body_part_raw_flags.h"
2012-08-23 18:37:43 -06:00
# include "df/building.h"
2012-12-19 16:46:46 -07:00
# include "df/building_type.h"
# include "df/caste_body_info.h"
2012-08-23 18:37:43 -06:00
# include "df/coord.h"
2013-01-03 21:18:40 -07:00
# include "df/creature_raw.h"
2012-12-19 16:46:46 -07:00
# include "df/general_ref.h"
# include "df/general_ref_building_holderst.h"
# include "df/general_ref_unit.h"
# include "df/general_ref_unit_holderst.h"
# include "df/general_ref_unit_workerst.h"
2013-05-31 17:27:22 -06:00
# include "df/global_objects.h"
2013-01-03 19:25:50 -07:00
# include "df/invasion_info.h"
2012-12-19 16:46:46 -07:00
# include "df/item.h"
# include "df/itemdef_weaponst.h"
# include "df/item_quality.h"
# include "df/item_weaponst.h"
2012-12-17 18:12:11 -07:00
# include "df/inorganic_raw.h"
2012-12-19 16:46:46 -07:00
# include "df/job.h"
# include "df/job_skill.h"
# include "df/job_type.h"
2012-08-23 18:37:43 -06:00
# include "df/map_block.h"
2012-12-17 18:12:11 -07:00
# include "df/strain_type.h"
2012-12-19 16:46:46 -07:00
# include "df/tile_building_occ.h"
# include "df/tile_occupancy.h"
2012-12-17 15:36:35 -07:00
# include "df/tiletype.h"
2012-12-17 18:12:11 -07:00
# include "df/tiletype_material.h"
2012-12-17 15:36:35 -07:00
# include "df/tiletype_shape.h"
# include "df/tiletype_shape_basic.h"
2012-12-19 16:46:46 -07:00
# include "df/ui.h"
# include "df/unit.h"
# include "df/unit_inventory_item.h"
2012-08-23 18:37:43 -06:00
# include "df/world.h"
2012-08-24 09:40:51 -06:00
2012-08-23 18:37:43 -06:00
# include <algorithm>
2012-12-17 18:44:35 -07:00
# include <ctime>
2012-12-17 15:36:35 -07:00
# include <cstdlib>
2012-12-17 12:22:45 -07:00
# include <cstring>
2012-12-17 18:12:11 -07:00
# include <iostream>
2012-08-23 18:37:43 -06:00
# include <map>
# include <set>
2012-12-16 14:53:02 -07:00
# include <vector>
2012-12-18 13:22:21 -07:00
# include <unordered_map>
2013-06-09 14:23:41 -06:00
# include <unordered_set>
2012-12-18 13:22:21 -07:00
2012-08-23 18:37:43 -06:00
using namespace std ;
using namespace DFHack ;
using namespace df : : enums ;
command_result diggingInvadersFunc ( color_ostream & out , std : : vector < std : : string > & parameters ) ;
2013-01-03 19:25:50 -07:00
void watchForJobComplete ( color_ostream & out , void * ptr ) ;
void initiateDigging ( color_ostream & out , void * ptr ) ;
int32_t manageInvasion ( color_ostream & out ) ;
2012-08-23 18:37:43 -06:00
DFHACK_PLUGIN ( " diggingInvaders " ) ;
2013-01-03 19:25:50 -07:00
//TODO: when world unloads
static int32_t lastInvasionJob = - 1 ;
2013-01-03 22:08:54 -07:00
static int32_t lastInvasionDigger = - 1 ;
2013-01-03 19:25:50 -07:00
static EventManager : : EventHandler jobCompleteHandler ( watchForJobComplete , 5 ) ;
2013-01-03 21:18:40 -07:00
static bool enabled = false ;
static unordered_set < int32_t > diggingRaces ;
2013-01-03 19:25:50 -07:00
DFhackCExport command_result plugin_init ( color_ostream & out , std : : vector < PluginCommand > & commands )
2012-08-23 18:37:43 -06:00
{
2013-01-03 19:25:50 -07:00
EventManager : : EventHandler invasionHandler ( initiateDigging , 1000 ) ;
2013-06-09 14:23:41 -06:00
EventManager : : registerListener ( EventManager : : EventType : : INVASION , invasionHandler , plugin_self ) ;
2012-08-23 18:37:43 -06:00
commands . push_back ( PluginCommand (
" diggingInvaders " , " Makes invaders dig to your dwarves. " ,
diggingInvadersFunc , false , /* true means that the command can't be used from non-interactive user interface */
2013-01-03 21:18:40 -07:00
" diggingInvaders enable \n enables the plugin \n "
" diggingInvaders disable \n disables the plugin \n "
" diggingInvaders add GOBLIN \n registers the race GOBLIN as a digging invader \n "
" diggingInvaders remove GOBLIN \n unregisters the race GOBLIN as a digging invader \n "
" diggingInvaders \n Makes invaders try to dig now. \n "
2012-08-23 18:37:43 -06:00
) ) ;
2013-01-03 20:46:17 -07:00
2012-08-23 18:37:43 -06:00
return CR_OK ;
}
DFhackCExport command_result plugin_shutdown ( color_ostream & out )
{
return CR_OK ;
}
2013-01-03 20:46:17 -07:00
DFhackCExport command_result plugin_onstatechange ( color_ostream & out , state_change_event event )
{
EventManager : : EventHandler invasionHandler ( initiateDigging , 1000 ) ;
switch ( event ) {
case DFHack : : SC_WORLD_LOADED :
//TODO: check game mode
lastInvasionJob = - 1 ;
//in case there are invaders when the game is loaded, we should check
2013-06-09 14:23:41 -06:00
EventManager : : registerTick ( invasionHandler , 10 , plugin_self ) ;
2013-01-03 20:46:17 -07:00
break ;
case DFHack : : SC_WORLD_UNLOADED :
// cleanup
break ;
default :
break ;
}
return CR_OK ;
}
2012-12-18 13:22:21 -07:00
df : : coord getRoot ( df : : coord point , unordered_map < df : : coord , df : : coord > & rootMap ) ;
2012-08-23 18:37:43 -06:00
class PointComp {
public :
2012-12-19 22:35:45 -07:00
unordered_map < df : : coord , int64_t , PointHash > * pointCost ;
PointComp ( unordered_map < df : : coord , int64_t , PointHash > * p ) : pointCost ( p ) {
2012-08-23 20:25:25 -06:00
}
2012-12-16 15:06:46 -07:00
int32_t operator ( ) ( df : : coord p1 , df : : coord p2 ) {
2012-12-16 19:44:23 -07:00
if ( p1 = = p2 ) return 0 ;
2012-12-17 12:22:45 -07:00
auto i1 = pointCost - > find ( p1 ) ;
auto i2 = pointCost - > find ( p2 ) ;
2012-08-23 20:25:25 -06:00
if ( i1 = = pointCost - > end ( ) & & i2 = = pointCost - > end ( ) )
return p1 < p2 ;
if ( i1 = = pointCost - > end ( ) )
2012-12-17 12:22:45 -07:00
return true ;
2012-08-23 20:25:25 -06:00
if ( i2 = = pointCost - > end ( ) )
2012-12-17 12:22:45 -07:00
return false ;
2012-12-19 22:35:45 -07:00
int64_t c1 = ( * i1 ) . second ;
int64_t c2 = ( * i2 ) . second ;
2012-08-23 20:25:25 -06:00
if ( c1 ! = c2 )
return c1 < c2 ;
return p1 < p2 ;
}
2012-08-23 18:37:43 -06:00
} ;
2012-12-18 13:22:21 -07:00
//bool important(df::coord pos, map<df::coord, set<Edge> >& edges, df::coord prev, set<df::coord>& importantPoints, set<Edge>& importantEdges);
2013-01-03 16:45:53 -07:00
int32_t findAndAssignInvasionJob ( color_ostream & out ) ;
2013-01-03 19:25:50 -07:00
void initiateDigging ( color_ostream & out , void * ptr ) {
//called when there's a new invasion
//TODO: check if invaders can dig
2013-01-03 22:08:54 -07:00
if ( manageInvasion ( out ) = = - 2 )
return ;
//schedule the next thing
uint32_t tick = World : : ReadCurrentTick ( ) ;
tick = tick % 1000 ;
tick = 1000 - tick ;
EventManager : : EventHandler handle ( initiateDigging , 1000 ) ;
2013-06-09 14:23:41 -06:00
EventManager : : registerTick ( handle , tick , plugin_self ) ;
2013-01-03 19:25:50 -07:00
}
2013-01-03 16:45:53 -07:00
2013-01-03 19:25:50 -07:00
void watchForJobComplete ( color_ostream & out , void * ptr ) {
2013-05-31 17:27:22 -06:00
/*
2013-01-03 16:45:53 -07:00
df : : job * job = ( df : : job * ) ptr ;
if ( job - > id ! = lastInvasionJob )
return ;
2013-06-09 14:23:41 -06:00
EventManager : : unregister ( EventManager : : EventType : : JOB_COMPLETED , jobCompleteHandler , plugin_self ) ;
2013-05-31 17:27:22 -06:00
*/
2013-01-03 16:45:53 -07:00
2013-01-03 22:35:47 -07:00
manageInvasion ( out ) ;
2013-01-03 16:45:53 -07:00
}
2012-12-16 19:44:23 -07:00
2013-01-03 19:25:50 -07:00
int32_t manageInvasion ( color_ostream & out ) {
2013-05-31 18:39:43 -06:00
//EventManager::unregisterAll(plugin_self);
2013-01-03 20:46:17 -07:00
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 ) {
2013-01-03 19:25:50 -07:00
//if the invasion is over, we're done
2013-01-03 22:43:39 -07:00
//out.print("Invasion is over. Stopping diggingInvaders.\n");
2013-01-03 22:08:54 -07:00
return - 2 ;
2013-01-03 19:25:50 -07:00
}
2013-05-31 17:27:22 -06:00
EventManager : : registerTick ( jobCompleteHandler , 1 , plugin_self ) ;
2013-01-03 16:45:53 -07:00
if ( lastInvasionJob ! = - 1 ) {
2013-01-03 22:08:54 -07:00
//check if he's still doing it
2013-05-31 17:27:22 -06:00
df : : unit * worker = df : : unit : : find ( lastInvasionDigger ) ;
//int32_t index = df::unit::binsearch_index(df::global::world->units.all, lastInvasionDigger);
if ( ! worker ) {
2013-01-03 22:08:54 -07:00
out . print ( " Error %s line %d. \n " , __FILE__ , __LINE__ ) ;
return - 1 ;
}
2013-05-31 17:27:22 -06:00
df : : job * job = worker - > job . current_job ;
2013-01-03 22:43:39 -07:00
//out.print("job id: old = %d, new = %d\n", lastInvasionJob, job == NULL ? -1 : job->id);
2013-01-03 22:35:47 -07:00
if ( job ! = NULL & & lastInvasionJob = = job - > id ) {
2013-01-03 22:43:39 -07:00
//out.print("Still working on the previous job.\n");
2013-01-03 22:08:54 -07:00
return - 1 ;
}
//return 1; //still invading, but nothing new done
2013-01-03 16:45:53 -07:00
}
2013-05-31 17:27:22 -06:00
2013-01-03 22:08:54 -07:00
int32_t unitId = findAndAssignInvasionJob ( out ) ;
if ( unitId = = - 1 ) {
2013-01-03 19:25:50 -07:00
//might need to do more digging later, after we've killed off a few locals
2013-01-03 22:43:39 -07:00
//out.print("DiggingInvaders is waiting.\n");
2013-01-03 19:25:50 -07:00
return - 1 ;
}
2013-05-31 18:39:43 -06:00
* df : : global : : pause_state = true ;
2013-01-03 16:45:53 -07:00
2013-01-03 22:08:54 -07:00
lastInvasionDigger = unitId ;
{
int32_t index = df : : unit : : binsearch_index ( df : : global : : world - > units . all , unitId ) ;
if ( index = = - 1 ) {
2013-01-05 09:06:46 -07:00
//out.print("Error %s line %d: unitId = %d, index = %d.\n", __FILE__, __LINE__, unitId, index);
2013-01-03 22:08:54 -07:00
return - 1 ;
}
lastInvasionJob = df : : global : : world - > units . all [ index ] - > job . current_job - > id ;
}
2013-01-03 16:45:53 -07:00
2013-06-09 14:23:41 -06:00
//EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, jobCompleteHandler, plugin_self);
2013-01-03 22:43:39 -07:00
//out.print("DiggingInvaders: job assigned.\n");
2013-01-03 19:25:50 -07:00
return 0 ; //did something
}
2013-01-04 19:02:09 -07:00
static df : : coord lastDebugEdgeCostPoint ;
2013-01-03 19:25:50 -07:00
command_result diggingInvadersFunc ( color_ostream & out , std : : vector < std : : string > & parameters ) {
2013-01-03 21:18:40 -07:00
for ( size_t a = 0 ; a < parameters . size ( ) ; a + + ) {
if ( parameters [ a ] = = " enable " ) {
enabled = true ;
} else if ( parameters [ a ] = = " disable " ) {
enabled = false ;
} else if ( parameters [ a ] = = " add " | | parameters [ a ] = = " remove " ) {
if ( a + 1 > = parameters . size ( ) )
return CR_WRONG_USAGE ;
string race = parameters [ a + 1 ] ;
bool foundIt = false ;
for ( size_t b = 0 ; b < df : : global : : world - > raws . creatures . all . size ( ) ; b + + ) {
df : : creature_raw * raw = df : : global : : world - > raws . creatures . all [ b ] ;
if ( race = = raw - > creature_id ) {
2013-01-03 22:43:39 -07:00
//out.print("%s = %s\n", race.c_str(), raw->creature_id.c_str());
2013-01-03 21:18:40 -07:00
if ( parameters [ a ] = = " add " ) {
diggingRaces . insert ( b ) ;
} else {
diggingRaces . erase ( b ) ;
}
foundIt = true ;
break ;
}
}
if ( ! foundIt ) {
out . print ( " Couldn't find \" %s \" \n " , race . c_str ( ) ) ;
return CR_WRONG_USAGE ;
}
a + + ;
2013-01-04 19:02:09 -07:00
} else if ( parameters [ a ] = = " setCost " ) {
if ( a + 2 > = parameters . size ( ) )
return CR_WRONG_USAGE ;
string costStr = parameters [ a + 1 ] ;
int32_t costDim = - 1 ;
2013-01-05 09:06:46 -07:00
if ( costStr = = " walk " ) {
costDim = CostDimension : : Walk ;
2013-01-04 19:02:09 -07:00
} else if ( costStr = = " destroyBuilding " ) {
costDim = CostDimension : : DestroyBuilding ;
} else if ( costStr = = " dig " ) {
costDim = CostDimension : : Dig ;
} else if ( costStr = = " destroyConstruction " ) {
costDim = CostDimension : : DestroyConstruction ;
} else {
return CR_WRONG_USAGE ;
}
int64_t value ;
stringstream asdf ( parameters [ a + 2 ] ) ;
asdf > > value ;
if ( value < = 0 )
return CR_WRONG_USAGE ;
costWeight [ costDim ] = value ;
a + = 2 ;
} else if ( parameters [ a ] = = " edgeCost " ) {
df : : coord bob = Gui : : getCursorPos ( ) ;
out . print ( " (%d,%d,%d), (%d,%d,%d): cost = %lld \n " , lastDebugEdgeCostPoint . x , lastDebugEdgeCostPoint . y , lastDebugEdgeCostPoint . z , bob . x , bob . y , bob . z , getEdgeCost ( out , lastDebugEdgeCostPoint , bob ) ) ;
lastDebugEdgeCostPoint = bob ;
}
else {
return CR_WRONG_USAGE ;
2013-01-03 21:18:40 -07:00
}
}
2013-05-31 18:39:43 -06:00
2013-01-03 21:18:40 -07:00
if ( parameters . size ( ) = = 0 )
manageInvasion ( out ) ;
2012-12-17 18:12:11 -07:00
return CR_OK ;
}
2013-01-03 16:45:53 -07:00
int32_t findAndAssignInvasionJob ( color_ostream & out ) {
2013-01-04 16:11:38 -07:00
//returns the worker id of the job created
2013-01-03 12:38:05 -07:00
2013-01-04 16:11:38 -07:00
//CoreSuspender suspend;
2012-08-23 18:37:43 -06:00
2012-12-18 13:22:21 -07:00
unordered_set < df : : coord , PointHash > invaderPts ;
unordered_set < df : : coord , PointHash > localPts ;
unordered_map < df : : coord , df : : coord , PointHash > parentMap ;
2012-12-19 22:35:45 -07:00
unordered_map < df : : coord , int64_t , PointHash > costMap ;
2012-12-18 13:22:21 -07:00
2012-12-17 11:37:02 -07:00
PointComp comp ( & costMap ) ;
set < df : : coord , PointComp > fringe ( comp ) ;
2012-08-23 20:25:25 -06:00
uint32_t xMax , yMax , zMax ;
Maps : : getSize ( xMax , yMax , zMax ) ;
xMax * = 16 ;
yMax * = 16 ;
2012-12-17 18:12:11 -07:00
MapExtras : : MapCache cache ;
2013-01-03 11:11:11 -07:00
vector < df : : unit * > invaders ;
2012-12-16 19:44:23 -07:00
2013-01-03 20:46:17 -07:00
unordered_set < uint16_t > invaderConnectivity ;
unordered_set < uint16_t > localConnectivity ;
2012-12-17 11:37:02 -07:00
2012-12-16 19:44:23 -07:00
//find all locals and invaders
2013-05-31 17:27:22 -06:00
for ( size_t a = 0 ; a < df : : global : : world - > units . all . size ( ) ; a + + ) {
df : : unit * unit = df : : global : : world - > units . all [ a ] ;
2012-12-16 19:44:23 -07:00
if ( unit - > flags1 . bits . dead )
2012-08-23 20:25:25 -06:00
continue ;
2012-12-17 11:37:02 -07:00
if ( Units : : isCitizen ( unit ) ) {
if ( localPts . find ( unit - > pos ) ! = localPts . end ( ) )
continue ;
localPts . insert ( unit - > pos ) ;
2013-01-03 20:46:17 -07:00
df : : map_block * block = Maps : : getTileBlock ( unit - > pos ) ;
localConnectivity . insert ( block - > walkable [ unit - > pos . x & 0xF ] [ unit - > pos . y & 0xF ] ) ;
2012-12-17 11:37:02 -07:00
} else if ( unit - > flags1 . bits . active_invader ) {
2013-01-03 21:18:40 -07:00
if ( diggingRaces . find ( unit - > race ) = = diggingRaces . end ( ) )
continue ;
2012-12-17 11:37:02 -07:00
if ( invaderPts . find ( unit - > pos ) ! = invaderPts . end ( ) )
continue ;
invaderPts . insert ( unit - > pos ) ;
costMap [ unit - > pos ] = 0 ;
fringe . insert ( unit - > pos ) ;
2013-01-03 11:11:11 -07:00
invaders . push_back ( unit ) ;
2013-01-03 20:46:17 -07:00
df : : map_block * block = Maps : : getTileBlock ( unit - > pos ) ;
invaderConnectivity . insert ( block - > walkable [ unit - > pos . x & 0xF ] [ unit - > pos . y & 0xF ] ) ;
2012-12-17 11:37:02 -07:00
} else {
2012-12-16 19:44:23 -07:00
continue ;
2012-12-17 11:37:02 -07:00
}
2012-08-23 20:25:25 -06:00
}
2013-01-03 11:11:11 -07:00
if ( invaders . empty ( ) ) {
2013-01-03 12:38:05 -07:00
return - 1 ;
2013-01-03 11:11:11 -07:00
}
2013-01-03 20:46:17 -07:00
//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 ;
}
2013-01-03 11:11:11 -07:00
df : : unit * firstInvader = invaders [ 0 ] ;
2013-05-31 18:39:43 -06:00
//out << firstInvader->id << endl;
//out << firstInvader->pos.x << ", " << firstInvader->pos.y << ", " << firstInvader->pos.z << endl;
//out << __LINE__ << endl;
2012-12-16 19:44:23 -07:00
2012-12-17 11:37:02 -07:00
int32_t localPtsFound = 0 ;
2012-12-18 13:22:21 -07:00
unordered_set < df : : coord , PointHash > closedSet ;
2012-12-19 22:35:45 -07:00
unordered_map < df : : coord , int32_t , PointHash > workNeeded ; //non-walking work needed to get there
2013-01-03 22:35:47 -07:00
bool foundTarget = false ;
2013-01-04 16:11:38 -07:00
int32_t edgeCount = 0 ;
2012-12-16 19:44:23 -07:00
2012-12-17 18:44:35 -07:00
clock_t t0 = clock ( ) ;
clock_t totalEdgeTime = 0 ;
2012-12-17 11:37:02 -07:00
while ( ! fringe . empty ( ) ) {
df : : coord pt = * ( fringe . begin ( ) ) ;
fringe . erase ( fringe . begin ( ) ) ;
2013-05-31 17:27:22 -06:00
//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);
2012-12-17 11:37:02 -07:00
if ( closedSet . find ( pt ) ! = closedSet . end ( ) ) {
2013-01-03 22:43:39 -07:00
out . print ( " %s, line %d: Double closure! Bad! \n " , __FILE__ , __LINE__ ) ;
2012-12-17 11:37:02 -07:00
break ;
}
2012-12-19 16:46:46 -07:00
closedSet . insert ( pt ) ;
2012-12-17 11:37:02 -07:00
if ( localPts . find ( pt ) ! = localPts . end ( ) ) {
localPtsFound + + ;
2013-01-04 19:02:09 -07:00
if ( true | | localPtsFound > = localPts . size ( ) ) {
2013-01-03 22:35:47 -07:00
foundTarget = true ;
2012-12-17 11:37:02 -07:00
break ;
2013-01-03 22:35:47 -07:00
}
2013-01-03 12:38:05 -07:00
if ( workNeeded . find ( pt ) = = workNeeded . end ( ) | | workNeeded [ pt ] = = 0 ) {
//there are still dwarves to kill that don't require digging to get to
return - 1 ;
}
2012-12-17 11:37:02 -07:00
}
2012-12-16 19:44:23 -07:00
2012-12-19 22:35:45 -07:00
int64_t myCost = costMap [ pt ] ;
2012-12-17 18:44:35 -07:00
clock_t edgeTime = clock ( ) ;
vector < Edge > * myEdges = getEdgeSet ( out , pt , cache , xMax , yMax , zMax ) ;
totalEdgeTime + = ( clock ( ) - edgeTime ) ;
for ( auto a = myEdges - > begin ( ) ; a ! = myEdges - > end ( ) ; a + + ) {
Edge & e = * a ;
2013-01-04 16:11:38 -07:00
if ( e . p1 = = df : : coord ( ) )
break ;
edgeCount + + ;
2012-12-17 18:44:35 -07:00
df : : coord & other = e . p1 ;
2012-12-17 11:37:02 -07:00
if ( other = = pt )
other = e . p2 ;
2012-12-18 13:22:21 -07:00
//if ( closedSet.find(other) != closedSet.end() )
// continue;
auto i = costMap . find ( other ) ;
if ( i ! = costMap . end ( ) ) {
2012-12-19 22:35:45 -07:00
int64_t cost = ( * i ) . second ;
2012-12-18 13:22:21 -07:00
if ( cost < = myCost + e . cost ) {
continue ;
}
fringe . erase ( ( * i ) . first ) ;
2012-08-23 20:25:25 -06:00
}
2012-12-18 13:22:21 -07:00
costMap [ other ] = myCost + e . cost ;
fringe . insert ( other ) ;
parentMap [ other ] = pt ;
2012-12-19 22:35:45 -07:00
workNeeded [ other ] = ( e . cost > 1 ? 1 : 0 ) + workNeeded [ pt ] ;
2012-08-23 20:25:25 -06:00
}
2012-12-17 18:44:35 -07:00
delete myEdges ;
2012-12-17 11:37:02 -07:00
}
2012-12-17 18:44:35 -07:00
clock_t time = clock ( ) - t0 ;
2013-05-31 18:39:43 -06:00
//out.print("time = %d, totalEdgeTime = %d, total points = %d, total edges = %d, time per point = %.3f, time per edge = %.3f, clocks/sec = %d\n", time, totalEdgeTime, closedSet.size(), edgeCount, (float)time / closedSet.size(), (float)time / edgeCount, CLOCKS_PER_SEC);
2012-12-17 11:37:02 -07:00
2013-01-03 22:35:47 -07:00
if ( ! foundTarget )
return - 1 ;
2012-12-19 16:46:46 -07:00
unordered_set < df : : coord , PointHash > requiresZNeg ;
unordered_set < df : : coord , PointHash > requiresZPos ;
2012-12-17 11:37:02 -07:00
//find important edges
2013-01-03 12:16:10 -07:00
Edge firstImportantEdge ( df : : coord ( ) , df : : coord ( ) , - 1 ) ;
2012-12-17 11:37:02 -07:00
for ( auto i = localPts . begin ( ) ; i ! = localPts . end ( ) ; i + + ) {
df : : coord pt = * i ;
if ( costMap . find ( pt ) = = costMap . end ( ) )
continue ;
if ( parentMap . find ( pt ) = = parentMap . end ( ) )
continue ;
2013-01-03 12:16:10 -07:00
//if ( workNeeded[pt] == 0 )
// continue;
2012-12-17 11:37:02 -07:00
while ( parentMap . find ( pt ) ! = parentMap . end ( ) ) {
2013-01-03 12:38:05 -07:00
//out.print("(%d,%d,%d)\n", pt.x, pt.y, pt.z);
2012-12-17 11:37:02 -07:00
df : : coord parent = parentMap [ pt ] ;
2013-01-03 11:32:50 -07:00
if ( Maps : : canStepBetween ( parent , pt ) ) {
2013-01-02 20:11:05 -07:00
} else {
2013-01-03 11:11:11 -07:00
if ( pt . x = = parent . x & & pt . y = = parent . y ) {
if ( pt . z < parent . z ) {
requiresZNeg . insert ( parent ) ;
requiresZPos . insert ( pt ) ;
} else if ( pt . z > parent . z ) {
requiresZNeg . insert ( pt ) ;
requiresZPos . insert ( parent ) ;
}
2013-01-02 20:11:05 -07:00
}
//if ( workNeeded[pt] > workNeeded[parent] ) {
2013-01-03 12:16:10 -07:00
//importantEdges.push_front(Edge(pt,parent,0));
2013-01-02 20:11:05 -07:00
//}
2013-01-03 12:16:10 -07:00
firstImportantEdge = Edge ( pt , parent , 0 ) ;
2013-01-03 22:43:39 -07:00
//out.print("(%d,%d,%d) -> (%d,%d,%d)\n", parent.x,parent.y,parent.z, pt.x,pt.y,pt.z);
2012-12-19 16:46:46 -07:00
}
2012-12-17 11:37:02 -07:00
pt = parent ;
2012-08-23 20:25:25 -06:00
}
2012-12-17 12:22:45 -07:00
break ;
2012-12-16 19:44:23 -07:00
}
2013-01-04 19:02:09 -07:00
#if 0
2012-12-19 16:46:46 -07:00
unordered_set < df : : coord , PointHash > toDelete ;
for ( auto a = requiresZNeg . begin ( ) ; a ! = requiresZNeg . end ( ) ; a + + ) {
df : : coord pos = * a ;
df : : tiletype * type = Maps : : getTileType ( pos ) ;
df : : tiletype_shape shape = ENUM_ATTR ( tiletype , shape , * type ) ;
if ( ENUM_ATTR ( tiletype_shape , passable_low , shape ) ) {
toDelete . insert ( pos ) ;
}
}
requiresZNeg . erase ( toDelete . begin ( ) , toDelete . end ( ) ) ;
toDelete . clear ( ) ;
for ( auto a = requiresZPos . begin ( ) ; a ! = requiresZPos . end ( ) ; a + + ) {
df : : coord pos = * a ;
df : : tiletype * type = Maps : : getTileType ( pos ) ;
df : : tiletype_shape shape = ENUM_ATTR ( tiletype , shape , * type ) ;
if ( ENUM_ATTR ( tiletype_shape , passable_high , shape ) ) {
toDelete . insert ( pos ) ;
}
}
requiresZPos . erase ( toDelete . begin ( ) , toDelete . end ( ) ) ;
toDelete . clear ( ) ;
2013-01-04 19:02:09 -07:00
# endif
2012-12-19 22:35:45 -07:00
2013-01-03 21:18:40 -07:00
return assignJob ( out , firstImportantEdge , parentMap , costMap , invaders , requiresZNeg , requiresZPos , cache , diggingRaces ) ;
2012-08-23 18:37:43 -06:00
}
df : : coord getRoot ( df : : coord point , map < df : : coord , df : : coord > & rootMap ) {
2012-08-23 20:25:25 -06:00
map < df : : coord , df : : coord > : : iterator i = rootMap . find ( point ) ;
if ( i = = rootMap . end ( ) ) {
rootMap [ point ] = point ;
return point ;
}
df : : coord parent = ( * i ) . second ;
if ( parent = = point )
return parent ;
df : : coord root = getRoot ( parent , rootMap ) ;
rootMap [ point ] = root ;
return root ;
2012-08-23 18:37:43 -06:00
}