Jump to content

#643 - Add current gatherers count


Recommended Posts

Looking to tackle this one since it seems fairly easy once I know if functionality exists for the player and the file locations.

In any of the economy.js files we have the following function which allows the AI to query the number of workers gathering each resource so it can allocate more as necessary.

// Pick the resource which most needs another worker

EconomyManager.prototype.pickMostNeededResources = function(gameState) {

var self = this;

// Find what resource type we're most in need of

...

var numGatherers = {};

for ( var type in this.gatherWeights){

numGatherers[type] = gameState.updatingCollection("workers-gathering-" + type,

Filters.byMetadata("gather-type", type), gameState.getOwnEntitiesByRole("worker")).length;

}

...

};

The part I'm interested in is:

var numGatherers = {};

for ( var type in this.gatherWeights){

numGatherers[type] = gameState.updatingCollection("workers-gathering-" + type,

Filters.byMetadata("gather-type", type), gameState.getOwnEntitiesByRole("worker")).length;

}

I dug around a bit but I couldn't seem to find anything related to this for us, the human player. Does anyone know where something like this would be found, or where I would need to go to add in this functionality so it can be queried in session.js and output to the display?

Link to comment
Share on other sites

I dug around a bit but I couldn't seem to find anything related to this for us, the human player. Does anyone know where something like this would be found, or where I would need to go to add in this functionality so it can be queried in session.js and output to the display?

The AI stuff is completely separate so won't help you with this. I would take a look at StatisticsTracker.js in the components folder, it is pretty similar to what you want to do.

Link to comment
Share on other sites

I would consider looking at the code for the "Find Idle Workers" button (Added in commit #9140.) Perhaps you could re-purpose the code to checking to see if the worker is gathering instead of idle, then add to an appropriate counter.

I think the hard part would be checking to see if the worker is gathering a certain resource. I'll see if I can find something that would help there.

Also, you need to consider trade carts and ships. Even though they aren't gatherers, they still deposit resources. You could just put a //todo line in the code I suppose...

Edited by gudo
Link to comment
Share on other sites

I would consider looking at the code for the "Find Idle Workers" button (Added in commit #9140.) Perhaps you could re-purpose the code to checking to see if the worker is gathering instead of idle, then add to an appropriate counter.

I think the hard part would be checking to see if the worker is gathering a certain resource. I'll see if I can find something that would help there.

Also, you need to consider trade carts and ships. Even though they aren't gatherers, they still deposit resources. You could just put a //todo line in the code I suppose...

That was helpful. Looking to things like efficiency and edge cases I'm not sure about a few things, commented in the code.

First, I put together this code which gets all of a player's units, cycles through them and finds the workers. If the worker is actively gathering (set in ResourceGatherer.PerformGather(target)), add them to the count, if not, remove them.


var rangeMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
var playerEntities = rangeMan.GetEntitiesByPlayer(player); #1

// cycle through all entities
// TODO: filter to just workers
for each (var ent in playerEntities)
{
var cmpResourceGatherer = Engine.QueryInterface(ent, IID_ResourceGatherer);
if ( cmpResourceGatherer != null )
{
// if not idle, check to see what we're gathering
// TODO: doesn't count garrisoning as idle (any other situations?) #3
// TODO: what about "Trade", "FishingBoat", "CitizenSoldier", "Healer"? #2
if ( !isIdleUnit(ent, "Female") )
{

Now for the clarification and optimization.

1) Is there any better way to get all of a player's units of a certain type? There was no other function such as GetWorkerEntitiesByPlayer which could immediately filter the list. And I'm somewhat worried since this is being called every time we update the player display (which could get ugly if there are lots [100+] units at the end of a game).

2) How do we want to handle the other types of units? Should trade carts be handled based on what type of resource they're moving? (I haven't looked into the trade carts and their functionality, I'm just guessing they can trade any type of resource). As for fishing boats, should they be counted as food gatherers too? Third, are citizensoldiers basically workers but their food cost is converted to metal (or something like that?)? And finally, for the healer, I assume they're not allowed to carry resources, correct?

3) My current implementation handles the unit becoming idle and being removed correctly from the count. It doesn't work though when units become garrisoned (are there any other situations that can cause a worker to not gather [besides death]? Where would these functions be? I see a Command.js file, is this the right one?).

Link to comment
Share on other sites

Nice progress so far :)

1) Take a loot at Identity.js line 103. Perhaps you could first filter your list for all entities with the class "worker". If I remember correctly, all entities with "worker" can gather resources. (Females aren't the only gathers, "CitizenSolider" can do it too.) If it's not the case that all entities that can gather resources have a common class, I would propose adding the "gatherer" class say, and looking for that. Or, you could look for entities with class "worker" || "female" || "citizensoldier" || "fishingboat"

2) We should handle Females, CitizenSoldiers, and FishingBoats all the same. Check and see if the entity is gathering. If it is, add it to the count. No need to complicate things. I would try and get basic functionality working for basic gathering units before worrying about the edge cases (trade carts, units collecting loot, and abilities that give resources eg Satrapy Tribute.)

3)Hmmm... I recall that quantum solved a problem with garrisoning in qBot by checking to see if an entity's position was defined.

There are many cases that would cause a worker to quit gathering. It could be converted, or tasked to build, repair, attack, etc. And what do we do if the worker is tasked to gather a different resource? It sounds like you're making a list of entities, then updating the list. Why not just start the count from scratch every time we update the player display? Then we wouldn't have to worry about such things. It shouldn't be too resource intense if we can filter the entities to be checked. Or we can update the list every 3rd time the display is updated.

Link to comment
Share on other sites

I wouldn't count any of the edge cases mentioned (trade, is the one I'm least certain about since they do after all increase the amount of that resource steadily over time; units gathering loot, mainly because it's done as a side effect of fighting, but also because it only happens every now and then and not steadily; buildings, well, mostly because they're not units =) and their "gathering" is also indirect in a sense). Mainly because the current gatherer count is useful as a tool to see if you gather enough of each resource for your current goals, thus something that comes in irregularly like loot (and to a lesser degree trade as the resources are only "deposited" once the trade cart reaches the market, which can be quite a while in between if the markets are far away from each other) or cannot be changed like the Satrapy tribute, isn't all that relevant to be included imho.

Link to comment
Share on other sites

Nice progress so far :)

1) Take a loot at Identity.js line 103. Perhaps you could first filter your list for all entities with the class "worker". If I remember correctly, all entities with "worker" can gather resources. (Females aren't the only gathers, "CitizenSolider" can do it too.) If it's not the case that all entities that can gather resources have a common class, I would propose adding the "gatherer" class say, and looking for that. Or, you could look for entities with class "worker" || "female" || "citizensoldier" || "fishingboat"

2) We should handle Females, CitizenSoldiers, and FishingBoats all the same. Check and see if the entity is gathering. If it is, add it to the count. No need to complicate things. I would try and get basic functionality working for basic gathering units before worrying about the edge cases (trade carts, units collecting loot, and abilities that give resources eg Satrapy Tribute.)

3)Hmmm... I recall that quantum solved a problem with garrisoning in qBot by checking to see if an entity's position was defined.

There are many cases that would cause a worker to quit gathering. It could be converted, or tasked to build, repair, attack, etc. And what do we do if the worker is tasked to gather a different resource? It sounds like you're making a list of entities, then updating the list. Why not just start the count from scratch every time we update the player display? Then we wouldn't have to worry about such things. It shouldn't be too resource intense if we can filter the entities to be checked. Or we can update the list every 3rd time the display is updated.

1. That should take care of the multiple units that can gather.

2. Done aside from trade carts, but that can be added in later if needed (I wouldn't consider them a standard worker).

3. I repurposed part of isIdleUnit to make something specific for idle workers, which now handles garrisoned units. To clarify, what I'm doing is, each time we update the player display, gathering a list of all units the player owns. Then, go through that list and check to see if it's a worker and if so, check which type of resource it is gathering and add it to the count (starting from scratch every time the screen updates, not modifying a continuous count). Now everything works except for situations where the units are told to go do something else (but don't become idle). Where are these commands sent to each entity (say I want him to switch from gathering to building, where is the unit told this, which file?). Once I know where that is, I can mark the unit as not gathering which should handle all of the other cases. Is this in the Command.js file I mentioned earlier?

Link to comment
Share on other sites

I checked it out, looks good and works well. Just thought a few very minor changes that could be made to your patch.

In your modified Commands.js, as of r11620 there is a new class "Citizen" that should let you replace

if ( cmpIdentity.HasClass("Worker") || cmpIdentity.HasClass("Female") ||  
cmpIdentity.HasClass("CitizenSoldier") || cmpIdentity.HasClass("FishingBoat") )

with

if ( cmpIdentity.HasClass("Citizen") || cmpIdentity.HasClass("FishingBoat") ) 

Also, an extra space between the resource amount and worker count would help with readability. Though depending on the resolution of ticket 1349, you might be using "Worker" instead of "Citizen"

Edited by gudo
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...