@@ -87,33 +87,61 @@ static bool activeDigging=false;
8787static unordered_set<string> diggingRaces;
8888static unordered_set<int32_t > invaderJobs;
8989static df::coord lastDebugEdgeCostPoint;
90+ unordered_map<string, DigAbilities> digAbilities;
91+
92+ static cost_t costWeightDefault[] = {
93+ // Distance
94+ 1 ,
95+ // Destroy Building
96+ 2 ,
97+ // Dig
98+ 10000 ,
99+ // DestroyRoughConstruction
100+ 1000 ,
101+ // DestroySmoothConstruction
102+ 100 ,
103+ };
104+
105+ static int32_t jobDelayDefault[] = {
106+ // Distance
107+ -1 ,
108+ // Destroy Building
109+ 1000 ,
110+ // Dig
111+ 1000 ,
112+ // DestroyRoughConstruction
113+ 1000 ,
114+ // DestroySmoothConstruction
115+ 100 ,
116+ };
90117
91118DFhackCExport command_result plugin_init (color_ostream &out, std::vector <PluginCommand> &commands)
92119{
93120 commands.push_back (PluginCommand (
94121 " diggingInvaders" , " Makes invaders dig to your dwarves." ,
95122 diggingInvadersCommand, false , /* true means that the command can't be used from non-interactive user interface */
96- " example usage:\n "
97123 " diggingInvaders 0\n disables the plugin\n "
98124 " diggingInvaders 1\n enables the plugin\n "
99125 " diggingInvaders enable\n enables the plugin\n "
100126 " diggingInvaders disable\n disables the plugin\n "
101127 " diggingInvaders add GOBLIN\n registers the race GOBLIN as a digging invader. Case-sensitive.\n "
102128 " diggingInvaders remove GOBLIN\n unregisters the race GOBLIN as a digging invader. Case-sensitive.\n "
103- " diggingInvaders setCost walk n\n sets the walk cost in the path algorithm\n "
104- " diggingInvaders setCost destroyBuilding n\n "
105- " diggingInvaders setCost dig n\n "
106- " diggingInvaders setCost destroyConstruction n\n "
107- " diggingInvaders setDelay destroyBuilding n\n adds to the job_completion_timer of destroy building jobs that are assigned to invaders\n "
108- " diggingInvaders setDelay dig n\n "
109- " diggingInvaders setDelay destroyConstruction n\n "
129+ " diggingInvaders setCost GOBLIN walk n\n sets the walk cost in the path algorithm for the race GOBLIN\n "
130+ " diggingInvaders setCost GOBLIN destroyBuilding n\n "
131+ " diggingInvaders setCost GOBLIN dig n\n "
132+ " diggingInvaders setCost GOBLIN destroyRoughConstruction n\n rough constructions are made from boulders\n "
133+ " diggingInvaders setCost GOBLIN destroySmoothConstruction n\n smooth constructions are made from blocks or bars instead of boulders\n "
134+ " diggingInvaders setDelay GOBLIN destroyBuilding n\n adds to the job_completion_timer of destroy building jobs that are assigned to invaders\n "
135+ " diggingInvaders setDelay GOBLIN dig n\n "
136+ " diggingInvaders setDelay GOBLIN destroyRoughConstruction n\n "
137+ " diggingInvaders setDelay GOBLIN destroySmoothConstruction n\n "
110138 " diggingInvaders now\n makes invaders try to dig now, if plugin is enabled\n "
111139 " diggingInvaders clear\n clears all digging invader races\n "
112140 " diggingInvaders edgesPerTick n\n makes the pathfinding algorithm work on at most n edges per tick. Set to 0 or lower to make it unlimited."
113141// " diggingInvaders\n Makes invaders try to dig now.\n"
114142 ));
115143
116- *df::global::debug_showambush = true ;
144+ // *df::global::debug_showambush = true;
117145 return CR_OK ;
118146}
119147
@@ -135,6 +163,7 @@ DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_chan
135163 case DFHack::SC_WORLD_UNLOADED :
136164 // cleanup
137165 lastInvasionJob = lastInvasionDigger = -1 ;
166+ enabled = false ;
138167 activeDigging = false ;
139168 clearDijkstra ();
140169 invaderJobs.clear ();
@@ -193,14 +222,28 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
193222 string race = parameters[a+1 ];
194223 if ( parameters[a] == " add" ) {
195224 diggingRaces.insert (race);
225+ DigAbilities& abilities = digAbilities[race];
226+ memcpy (abilities.costWeight , costWeightDefault, costDim*sizeof (cost_t ));
227+ memcpy (abilities.jobDelay , jobDelayDefault, costDim*sizeof (int32_t ));
196228 } else {
197229 diggingRaces.erase (race);
230+ digAbilities.erase (race);
198231 }
199232 a++;
233+
200234 } else if ( parameters[a] == " setCost" || parameters[a] == " setDelay" ) {
201- if ( a+2 >= parameters.size () )
235+ if ( a+3 >= parameters.size () )
202236 return CR_WRONG_USAGE ;
203- string costStr = parameters[a+1 ];
237+
238+ string raceString = parameters[a+1 ];
239+ if ( digAbilities.find (raceString) == digAbilities.end () ) {
240+ DigAbilities bob;
241+ memset (&bob, 0xFF , sizeof (bob));
242+ digAbilities[raceString] = bob;
243+ }
244+ DigAbilities& abilities = digAbilities[raceString];
245+
246+ string costStr = parameters[a+2 ];
204247 int32_t costDim = -1 ;
205248 if ( costStr == " walk" ) {
206249 costDim = CostDimension::Walk;
@@ -210,30 +253,47 @@ command_result diggingInvadersCommand(color_ostream& out, std::vector<std::strin
210253 costDim = CostDimension::DestroyBuilding;
211254 } else if ( costStr == " dig" ) {
212255 costDim = CostDimension::Dig;
213- } else if ( costStr == " destroyConstruction" ) {
214- costDim = CostDimension::DestroyConstruction;
256+ } else if ( costStr == " destroyRoughConstruction" ) {
257+ costDim = CostDimension::DestroyRoughConstruction;
258+ } else if ( costStr == " destroySmoothConstruction" ) {
259+ costDim = CostDimension::DestroySmoothConstruction;
215260 } else {
216261 return CR_WRONG_USAGE ;
217262 }
263+
218264 cost_t value;
219- stringstream asdf (parameters[a+2 ]);
265+ stringstream asdf (parameters[a+3 ]);
220266 asdf >> value;
221- if ( parameters[a] == " setCost" && value <= 0 )
222- return CR_WRONG_USAGE ;
223- if ( parameters[a] == " setCost" )
224- costWeight[costDim] = value;
225- else
226- jobDelay[costDim] = value;
227- a += 2 ;
267+ // if ( parameters[a] == "setCost" && value <= 0 )
268+ // return CR_WRONG_USAGE;
269+ if ( parameters[a] == " setCost" ) {
270+ abilities.costWeight [costDim] = value;
271+ } else {
272+ abilities.jobDelay [costDim] = value;
273+ }
274+ a += 3 ;
228275 } else if ( parameters[a] == " edgeCost" ) {
276+ if ( a+1 >= parameters.size () )
277+ return CR_WRONG_USAGE ;
278+
279+ string raceString = parameters[a+1 ];
280+
281+ if ( digAbilities.find (raceString) == digAbilities.end () ) {
282+ out.print (" Race %s does not have dig abilities assigned.\n " , raceString.c_str ());
283+ return CR_WRONG_USAGE ;
284+ }
285+ DigAbilities& abilities = digAbilities[raceString];
286+
229287 df::coord bob = Gui::getCursorPos ();
230- 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));
288+ 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, abilities ));
231289 lastDebugEdgeCostPoint = bob;
290+ a++;
232291 } else if ( parameters[a] == " now" ) {
233292 activeDigging = true ;
234293 findAndAssignInvasionJob (out, (void *)0 );
235294 } else if ( parameters[a] == " clear" ) {
236295 diggingRaces.clear ();
296+ digAbilities.clear ();
237297 } else if ( parameters[a] == " edgesPerTick" ) {
238298 if ( a+1 >= parameters.size () )
239299 return CR_WRONG_USAGE ;
@@ -335,8 +395,12 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
335395 out.print (" %s,%d: WTF? Couldn't find creature raw.\n " , __FILE__, __LINE__);
336396 continue ;
337397 }
398+ /*
338399 if ( diggingRaces.find(raw->creature_id) == diggingRaces.end() )
339400 continue;
401+ */
402+ if ( digAbilities.find (raw->creature_id ) == digAbilities.end () )
403+ continue ;
340404 if ( invaderPts.find (unit->pos ) != invaderPts.end () )
341405 continue ;
342406 // must be able to wield a pick: this is overly pessimistic
@@ -380,6 +444,14 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
380444 fringe.clear ();
381445 return ;
382446 }
447+
448+ df::creature_raw* creature_raw = df::creature_raw::find (firstInvader->race );
449+ if ( creature_raw == NULL || digAbilities.find (creature_raw->creature_id ) == digAbilities.end () ) {
450+ // inappropriate digger: no dig abilities
451+ fringe.clear ();
452+ return ;
453+ }
454+ DigAbilities& abilities = digAbilities[creature_raw->creature_id ];
383455 // TODO: check that firstInvader is an appropriate digger
384456 // out << firstInvader->id << endl;
385457 // out << firstInvader->pos.x << ", " << firstInvader->pos.y << ", " << firstInvader->pos.z << endl;
@@ -421,7 +493,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
421493
422494 cost_t myCost = costMap[pt];
423495 clock_t edgeTime = clock ();
424- vector<Edge>* myEdges = getEdgeSet (out, pt, cache, xMax, yMax, zMax);
496+ vector<Edge>* myEdges = getEdgeSet (out, pt, cache, xMax, yMax, zMax, abilities );
425497 totalEdgeTime += (clock () - edgeTime);
426498 for ( auto a = myEdges->begin (); a != myEdges->end (); a++ ) {
427499 Edge &e = *a;
@@ -476,7 +548,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
476548 while ( parentMap.find (pt) != parentMap.end () ) {
477549 // out.print("(%d,%d,%d)\n", pt.x, pt.y, pt.z);
478550 df::coord parent = parentMap[pt];
479- cost_t cost = getEdgeCost (out, parent, pt);
551+ cost_t cost = getEdgeCost (out, parent, pt, abilities );
480552 if ( cost < 0 ) {
481553 // path invalidated
482554 return ;
@@ -514,7 +586,7 @@ void findAndAssignInvasionJob(color_ostream& out, void* tickTime) {
514586 }
515587*/
516588
517- assignJob (out, firstImportantEdge, parentMap, costMap, invaders, requiresZNeg, requiresZPos, cache);
589+ assignJob (out, firstImportantEdge, parentMap, costMap, invaders, requiresZNeg, requiresZPos, cache, abilities );
518590 lastInvasionDigger = firstInvader->id ;
519591 lastInvasionJob = firstInvader->job .current_job ? firstInvader->job .current_job ->id : -1 ;
520592 invaderJobs.erase (lastInvasionJob);
0 commit comments