2014-03-24 23:33:50 +01:00
|
|
|
var PETRA = function(m)
|
|
|
|
{
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This class makes a worker do as instructed by the economy manager
|
|
|
|
*/
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
m.Worker = function(ent)
|
|
|
|
{
|
2014-03-24 23:33:50 +01:00
|
|
|
this.ent = ent;
|
|
|
|
this.baseID = 0;
|
|
|
|
};
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
m.Worker.prototype.update = function(baseManager, gameState)
|
|
|
|
{
|
2014-04-03 22:48:54 +02:00
|
|
|
if (!this.ent.position())
|
2014-03-24 23:33:50 +01:00
|
|
|
return;
|
2014-04-03 22:48:54 +02:00
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
// If we are waiting for a transport or we are sailing, just wait
|
|
|
|
if (this.ent.getMetadata(PlayerID, "transport") !== undefined)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// If we're fighting or hunting, let's not start gathering
|
|
|
|
if (this.ent.unitAIState().split(".")[1] === "COMBAT")
|
|
|
|
return;
|
|
|
|
|
2014-03-24 23:33:50 +01:00
|
|
|
// Okay so we have a few tasks.
|
|
|
|
// If we're gathering, we'll check that we haven't run idle.
|
2014-05-18 13:34:36 +02:00
|
|
|
// And we'll also check that we're gathering a resource we want to gather.
|
|
|
|
|
|
|
|
this.baseID = baseManager.ID;
|
|
|
|
var subrole = this.ent.getMetadata(PlayerID, "subrole");
|
2014-03-24 23:33:50 +01:00
|
|
|
|
|
|
|
if (subrole === "gatherer")
|
|
|
|
{
|
|
|
|
if (this.ent.isIdle())
|
|
|
|
{
|
|
|
|
// if we aren't storing resources or it's the same type as what we're about to gather,
|
|
|
|
// let's just pick a new resource.
|
|
|
|
// TODO if we already carry the max we can -> returnresources
|
|
|
|
if (!this.ent.resourceCarrying() || this.ent.resourceCarrying().length === 0 ||
|
|
|
|
this.ent.resourceCarrying()[0].type === this.ent.getMetadata(PlayerID, "gather-type"))
|
|
|
|
{
|
|
|
|
this.startGathering(gameState, baseManager);
|
|
|
|
}
|
|
|
|
else if (!this.returnResources(gameState)) // try to deposit resources
|
|
|
|
{
|
|
|
|
// no dropsite, abandon old resources and start gathering new ones
|
|
|
|
this.startGathering(gameState, baseManager);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (this.ent.unitAIState().split(".")[1] === "GATHER")
|
|
|
|
{
|
|
|
|
// we're already gathering. But let's check from time to time if there is nothing better
|
|
|
|
// in case UnitAI did something bad
|
|
|
|
if (this.ent.unitAIOrderData().length)
|
|
|
|
{
|
|
|
|
var supplyId = this.ent.unitAIOrderData()[0]["target"];
|
|
|
|
var supply = gameState.getEntityById(supplyId);
|
|
|
|
if (supply && !supply.hasClass("Field") && !supply.hasClass("Animal")
|
|
|
|
&& supplyId !== this.ent.getMetadata(PlayerID, "supply"))
|
|
|
|
{
|
|
|
|
var nbGatherers = supply.resourceSupplyGatherers().length
|
|
|
|
+ m.GetTCGatherer(gameState, supplyId);
|
|
|
|
if ((nbGatherers > 0 && supply.resourceSupplyAmount()/nbGatherers < 40))
|
|
|
|
{
|
|
|
|
m.RemoveTCGatherer(gameState, supplyId);
|
|
|
|
this.startGathering(gameState, baseManager);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
var gatherType = this.ent.getMetadata(PlayerID, "gather-type");
|
|
|
|
var nearby = baseManager.dropsiteSupplies[gatherType]["nearby"];
|
|
|
|
var isNearby = nearby.some(function(sup) {
|
|
|
|
if (sup.id === supplyId)
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
if (nearby.length === 0 || isNearby)
|
|
|
|
this.ent.setMetadata(PlayerID, "supply", supplyId);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m.RemoveTCGatherer(gameState, supplyId);
|
|
|
|
this.startGathering(gameState, baseManager);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-06-10 15:45:23 +02:00
|
|
|
else if (this.ent.unitAIState() === "INDIVIDUAL.RETURNRESOURCE.APPROACHING"
|
|
|
|
&& gameState.ai.playedTurn % 10 === 0)
|
|
|
|
{
|
|
|
|
// Check from time to time that UnitAI does not send us to an inaccessible dropsite
|
|
|
|
var dropsite = gameState.getEntityById(this.ent.unitAIOrderData()[0]["target"]);
|
|
|
|
if (dropsite && dropsite.position())
|
|
|
|
{
|
|
|
|
var access = gameState.ai.accessibility.getAccessValue(this.ent.position());
|
|
|
|
var goalAccess = dropsite.getMetadata(PlayerID, "access");
|
|
|
|
if (!goalAccess || dropsite.hasClass("Elephant"))
|
|
|
|
{
|
|
|
|
goalAccess = gameState.ai.accessibility.getAccessValue(dropsite.position());
|
|
|
|
dropsite.setMetadata(PlayerID, "access", goalAccess);
|
|
|
|
}
|
|
|
|
if (access !== goalAccess)
|
|
|
|
this.returnResources(gameState);
|
|
|
|
}
|
|
|
|
}
|
2014-03-24 23:33:50 +01:00
|
|
|
}
|
|
|
|
else if (subrole === "builder")
|
|
|
|
{
|
|
|
|
if (this.ent.unitAIState().split(".")[1] === "REPAIR")
|
|
|
|
return;
|
|
|
|
// okay so apparently we aren't working.
|
|
|
|
// Unless we've been explicitely told to keep our role, make us idle.
|
|
|
|
var target = gameState.getEntityById(this.ent.getMetadata(PlayerID, "target-foundation"));
|
|
|
|
if (!target || (target.foundationProgress() === undefined && target.needsRepair() === false))
|
|
|
|
{
|
|
|
|
this.ent.setMetadata(PlayerID, "subrole", "idle");
|
|
|
|
this.ent.setMetadata(PlayerID, "target-foundation", undefined);
|
|
|
|
// If worker elephant, move away to avoid being trapped in between constructions
|
|
|
|
if (this.ent.hasClass("Elephant"))
|
|
|
|
this.moveAway(baseManager, gameState);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-06-10 15:45:23 +02:00
|
|
|
var access = gameState.ai.accessibility.getAccessValue(this.ent.position());
|
|
|
|
var goalAccess = target.getMetadata(PlayerID, "access");
|
|
|
|
if (!goalAccess)
|
|
|
|
{
|
|
|
|
goalAccess = gameState.ai.accessibility.getAccessValue(target.position());
|
|
|
|
target.setMetadata(PlayerID, "access", goalAccess);
|
|
|
|
}
|
|
|
|
if (access === goalAccess)
|
2014-05-18 13:34:36 +02:00
|
|
|
this.ent.repair(target);
|
|
|
|
else
|
2014-06-10 15:45:23 +02:00
|
|
|
gameState.ai.HQ.navalManager.requireTransport(gameState, this.ent, access, goalAccess, target.position());
|
2014-03-24 23:33:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (subrole === "hunter")
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
var lastHuntSearch = this.ent.getMetadata(PlayerID, "lastHuntSearch");
|
2014-06-24 20:31:36 +02:00
|
|
|
if (this.ent.isIdle() && (!lastHuntSearch || (gameState.ai.elapsedTime - lastHuntSearch) > 20))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
if (!this.startHunting(gameState))
|
|
|
|
{
|
|
|
|
// nothing to hunt around. Try another region if any
|
|
|
|
var nowhereToHunt = true;
|
|
|
|
for (var i in gameState.ai.HQ.baseManagers)
|
|
|
|
{
|
|
|
|
var base = gameState.ai.HQ.baseManagers[i];
|
|
|
|
if (!base.anchor || !base.anchor.position())
|
|
|
|
continue;
|
|
|
|
var basePos = base.anchor.position();
|
|
|
|
if (this.startHunting(gameState, basePos))
|
|
|
|
{
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
|
|
|
var access = gameState.ai.accessibility.getAccessValue(this.ent.position());
|
|
|
|
if (base.accessIndex === access)
|
|
|
|
this.ent.move(basePos[0], basePos[1]);
|
|
|
|
else
|
|
|
|
gameState.ai.HQ.navalManager.requireTransport(gameState, this.ent, access, base.accessIndex, basePos);
|
|
|
|
nowhereToHunt = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (nowhereToHunt)
|
2014-06-24 20:31:36 +02:00
|
|
|
this.ent.setMetadata(PlayerID, "lastHuntSearch", gameState.ai.elapsedTime);
|
2014-05-18 13:34:36 +02:00
|
|
|
}
|
|
|
|
}
|
2014-06-10 15:45:23 +02:00
|
|
|
else if (gameState.ai.playedTurn % 10 === 0) // Perform some checks from time to time
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
2014-06-10 15:45:23 +02:00
|
|
|
if (this.ent.unitAIState().split(".")[1] === "GATHER"
|
|
|
|
|| this.ent.unitAIState().split(".")[1] === "RETURNRESOURCE")
|
|
|
|
{
|
|
|
|
// we may have drifted towards ennemy territory during the hunt, if yes go home
|
|
|
|
var territoryOwner = gameState.ai.HQ.territoryMap.getOwner(this.ent.position());
|
|
|
|
if (territoryOwner != 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
|
|
|
|
this.startHunting(gameState);
|
|
|
|
else if (this.ent.unitAIState() === "INDIVIDUAL.RETURNRESOURCE.APPROACHING")
|
|
|
|
{
|
|
|
|
// Check that UnitAI does not send us to an inaccessible dropsite
|
|
|
|
var dropsite = gameState.getEntityById(this.ent.unitAIOrderData()[0]["target"]);
|
|
|
|
if (dropsite && dropsite.position())
|
|
|
|
{
|
|
|
|
var access = gameState.ai.accessibility.getAccessValue(this.ent.position());
|
|
|
|
var goalAccess = dropsite.getMetadata(PlayerID, "access");
|
|
|
|
if (!goalAccess || dropsite.hasClass("Elephant"))
|
|
|
|
{
|
|
|
|
goalAccess = gameState.ai.accessibility.getAccessValue(dropsite.position());
|
|
|
|
dropsite.setMetadata(PlayerID, "access", goalAccess);
|
|
|
|
}
|
|
|
|
if (access !== goalAccess)
|
|
|
|
this.returnResources(gameState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-18 13:34:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (subrole === "fisher")
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
|
|
|
if (this.ent.isIdle())
|
2014-05-18 13:34:36 +02:00
|
|
|
this.startFishing(gameState);
|
|
|
|
else // if we have drifted towards ennemy territory during the fishing, go home
|
2014-03-27 23:10:03 +01:00
|
|
|
{
|
|
|
|
var territoryOwner = gameState.ai.HQ.territoryMap.getOwner(this.ent.position());
|
|
|
|
if (territoryOwner != 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
|
2014-05-18 13:34:36 +02:00
|
|
|
this.startFishing(gameState);
|
2014-03-27 23:10:03 +01:00
|
|
|
}
|
2014-03-24 23:33:50 +01:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
m.Worker.prototype.startGathering = function(gameState, baseManager)
|
|
|
|
{
|
|
|
|
var resource = this.ent.getMetadata(PlayerID, "gather-type");
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
// If we are gathering food, try to hunt first
|
|
|
|
if (resource === "food" && this.startHunting(gameState))
|
2014-03-24 23:33:50 +01:00
|
|
|
return true;
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
var findSupply = function(ent, supplies) {
|
2014-03-24 23:33:50 +01:00
|
|
|
var ret = false;
|
2014-05-18 13:34:36 +02:00
|
|
|
for (var i = 0; i < supplies.length; ++i)
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
|
|
|
// exhausted resource, remove it from this list
|
2014-05-18 13:34:36 +02:00
|
|
|
if (!supplies[i].ent || !gameState.getEntityById(supplies[i].id))
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
2014-05-18 13:34:36 +02:00
|
|
|
supplies.splice(i--, 1);
|
2014-03-24 23:33:50 +01:00
|
|
|
continue;
|
|
|
|
}
|
2014-05-18 13:34:36 +02:00
|
|
|
if (m.IsSupplyFull(gameState, supplies[i].ent) === true)
|
2014-03-24 23:33:50 +01:00
|
|
|
continue;
|
|
|
|
// check if available resource is worth one additionnal gatherer (except for farms)
|
2014-05-18 13:34:36 +02:00
|
|
|
var nbGatherers = supplies[i].ent.resourceSupplyGatherers().length
|
|
|
|
+ m.GetTCGatherer(gameState, supplies[i].id);
|
|
|
|
if (supplies[i].ent.resourceSupplyType()["specific"] !== "grain"
|
|
|
|
&& nbGatherers > 0 && supplies[i].ent.resourceSupplyAmount()/(1+nbGatherers) < 40)
|
2014-03-24 23:33:50 +01:00
|
|
|
continue;
|
|
|
|
// not in ennemy territory
|
2014-05-18 13:34:36 +02:00
|
|
|
var territoryOwner = gameState.ai.HQ.territoryMap.getOwner(supplies[i].ent.position());
|
2014-03-24 23:33:50 +01:00
|
|
|
if (territoryOwner != 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
|
|
|
|
continue;
|
2014-05-18 13:34:36 +02:00
|
|
|
m.AddTCGatherer(gameState, supplies[i].id);
|
|
|
|
ent.setMetadata(PlayerID, "supply", supplies[i].id);
|
|
|
|
ret = supplies[i].ent;
|
2014-03-24 23:33:50 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
};
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
var self = this;
|
|
|
|
var access = gameState.ai.accessibility.getAccessValue(this.ent.position());
|
|
|
|
var navalManager = gameState.ai.HQ.navalManager;
|
|
|
|
var supply;
|
2014-03-24 23:33:50 +01:00
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
// first look in our own base if accessible from our present position
|
|
|
|
if (baseManager.accessIndex === access)
|
|
|
|
{
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = findSupply(this.ent, baseManager.dropsiteSupplies[resource]["nearby"])))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
this.ent.gather(supply);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
// --> for food, try to gather from fields if any, otherwise build one if any
|
|
|
|
if (resource === "food")
|
|
|
|
{
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = this.gatherNearestField(gameState, this.baseID)))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
this.ent.gather(supply);
|
|
|
|
return true;
|
|
|
|
}
|
2014-05-20 00:09:44 +02:00
|
|
|
else if ((supply = this.buildAnyField(gameState, this.baseID)))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
this.ent.repair(supply);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = findSupply(this.ent, baseManager.dropsiteSupplies[resource]["medium"])))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
this.ent.gather(supply);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// So if we're here we have checked our whole base for a proper resource (or it was not accessible)
|
|
|
|
// --> check other bases directly accessible
|
2014-03-24 23:33:50 +01:00
|
|
|
for each (var base in gameState.ai.HQ.baseManagers)
|
|
|
|
{
|
|
|
|
if (base.ID === this.baseID)
|
|
|
|
continue;
|
2014-05-18 13:34:36 +02:00
|
|
|
if (base.accessIndex !== access)
|
|
|
|
continue;
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = findSupply(this.ent, base.dropsiteSupplies[resource]["nearby"])))
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
2014-05-18 13:34:36 +02:00
|
|
|
this.ent.gather(supply);
|
2014-03-24 23:33:50 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2014-05-18 13:34:36 +02:00
|
|
|
if (resource === "food") // --> for food, try to gather from fields if any, otherwise build one if any
|
|
|
|
{
|
|
|
|
for each (var base in gameState.ai.HQ.baseManagers)
|
|
|
|
{
|
|
|
|
if (base.ID === this.baseID)
|
|
|
|
continue;
|
|
|
|
if (base.accessIndex !== access)
|
|
|
|
continue;
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = this.gatherNearestField(gameState, base.ID)))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
|
|
|
this.ent.gather(supply);
|
|
|
|
return true;
|
|
|
|
}
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = this.buildAnyField(gameState, base.ID)))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
|
|
|
this.ent.repair(supply);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-03-24 23:33:50 +01:00
|
|
|
for each (var base in gameState.ai.HQ.baseManagers)
|
|
|
|
{
|
|
|
|
if (base.ID === this.baseID)
|
|
|
|
continue;
|
2014-05-18 13:34:36 +02:00
|
|
|
if (base.accessIndex !== access)
|
|
|
|
continue;
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = findSupply(this.ent, base.dropsiteSupplies[resource]["medium"])))
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
2014-05-18 13:34:36 +02:00
|
|
|
this.ent.gather(supply);
|
2014-03-24 23:33:50 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
// Okay may-be we haven't found any appropriate dropsite anywhere.
|
|
|
|
// Try to help building one if any accessible foundation available
|
2014-03-24 23:33:50 +01:00
|
|
|
var foundations = gameState.getOwnFoundations().toEntityArray();
|
|
|
|
var shouldBuild = foundations.some(function(foundation) {
|
2014-05-18 13:34:36 +02:00
|
|
|
if (!foundation || foundation.getMetadata(PlayerID, "access") !== access)
|
2014-03-24 23:33:50 +01:00
|
|
|
return false;
|
2014-05-18 13:34:36 +02:00
|
|
|
if (foundation.resourceDropsiteTypes() && foundation.resourceDropsiteTypes().indexOf(resource) !== -1)
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
2014-05-18 13:34:36 +02:00
|
|
|
if (foundation.getMetadata(PlayerID, "base") !== self.baseID)
|
|
|
|
self.ent.setMetadata(PlayerID, "base", foundation.getMetadata(PlayerID, "base"));
|
|
|
|
self.ent.setMetadata(PlayerID, "target-foundation", foundation.id());
|
2014-03-24 23:33:50 +01:00
|
|
|
self.ent.repair(foundation);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
if (shouldBuild)
|
|
|
|
return true;
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
// Still nothing ... try bases which need a transport
|
|
|
|
for each (var base in gameState.ai.HQ.baseManagers)
|
|
|
|
{
|
|
|
|
if (base.accessIndex === access)
|
|
|
|
continue;
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = findSupply(this.ent, base.dropsiteSupplies[resource]["nearby"])))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
if (base.ID !== this.baseID)
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
|
|
|
navalManager.requireTransport(gameState, this.ent, access, base.accessIndex, supply.position());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (resource === "food") // --> for food, try to gather from fields if any, otherwise build one if any
|
|
|
|
{
|
|
|
|
for each (var base in gameState.ai.HQ.baseManagers)
|
|
|
|
{
|
|
|
|
if (base.accessIndex === access)
|
|
|
|
continue;
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = this.gatherNearestField(gameState, base.ID)))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
if (base.ID !== this.baseID)
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
|
|
|
navalManager.requireTransport(gameState, this.ent, access, base.accessIndex, supply.position());
|
|
|
|
return true;
|
|
|
|
}
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = this.buildAnyField(gameState, base.ID)))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
if (base.ID !== this.baseID)
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
|
|
|
navalManager.requireTransport(gameState, this.ent, access, base.accessIndex, supply.position());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for each (var base in gameState.ai.HQ.baseManagers)
|
|
|
|
{
|
|
|
|
if (base.accessIndex === access)
|
|
|
|
continue;
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = findSupply(this.ent, base.dropsiteSupplies[resource]["medium"])))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
if (base.ID !== this.baseID)
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
|
|
|
navalManager.requireTransport(gameState, this.ent, access, base.accessIndex, supply.position());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Okay so we haven't found any appropriate dropsite anywhere.
|
|
|
|
// Try to help building one if any non-accessible foundation available
|
|
|
|
var foundations = gameState.getOwnFoundations().toEntityArray();
|
|
|
|
var shouldBuild = foundations.some(function(foundation) {
|
|
|
|
if (!foundation || foundation.getMetadata(PlayerID, "access") === access)
|
|
|
|
return false;
|
|
|
|
if (foundation.resourceDropsiteTypes() && foundation.resourceDropsiteTypes().indexOf(resource) !== -1)
|
|
|
|
{
|
|
|
|
if (foundation.getMetadata(PlayerID, "base") !== self.baseID)
|
|
|
|
self.ent.setMetadata(PlayerID, "base", foundation.getMetadata(PlayerID, "base"));
|
|
|
|
self.ent.setMetadata(PlayerID, "target-foundation", foundation.id());
|
|
|
|
navalManager.requireTransport(gameState, self.ent, access, base.accessIndex, foundation.position());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
if (shouldBuild)
|
2014-03-24 23:33:50 +01:00
|
|
|
return true;
|
2014-05-18 13:34:36 +02:00
|
|
|
|
|
|
|
// Still nothing, we look now for faraway resources, first in the accessible ones, then in the others
|
|
|
|
if (baseManager.accessIndex === access)
|
|
|
|
{
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = findSupply(this.ent, baseManager.dropsiteSupplies[resource]["faraway"])))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
this.ent.gather(supply);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2014-03-24 23:33:50 +01:00
|
|
|
for each (var base in gameState.ai.HQ.baseManagers)
|
|
|
|
{
|
|
|
|
if (base.ID === this.baseID)
|
|
|
|
continue;
|
2014-05-18 13:34:36 +02:00
|
|
|
if (base.accessIndex !== access)
|
|
|
|
continue;
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = findSupply(this.ent, base.dropsiteSupplies[resource]["faraway"])))
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
2014-05-18 13:34:36 +02:00
|
|
|
this.ent.gather(supply);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for each (var base in gameState.ai.HQ.baseManagers)
|
|
|
|
{
|
|
|
|
if (base.accessIndex === access)
|
|
|
|
continue;
|
2014-05-20 00:09:44 +02:00
|
|
|
if ((supply = findSupply(this.ent, base.dropsiteSupplies[resource]["faraway"])))
|
2014-05-18 13:34:36 +02:00
|
|
|
{
|
|
|
|
if (base.ID !== this.baseID)
|
|
|
|
this.ent.setMetadata(PlayerID, "base", base.ID);
|
|
|
|
navalManager.requireTransport(gameState, this.ent, access, base.accessIndex, supply.position());
|
2014-03-24 23:33:50 +01:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-03 22:48:54 +02:00
|
|
|
// If we are here, we have nothing left to gather ... certainly no more resources of this type
|
|
|
|
gameState.ai.HQ.lastFailedGather[resource] = gameState.ai.playedTurn;
|
|
|
|
if (gameState.ai.HQ.Config.debug > 1)
|
2014-03-26 22:07:47 +01:00
|
|
|
warn(" >>>>> worker with gather-type " + resource + " with nothing to gather ");
|
2014-04-03 22:48:54 +02:00
|
|
|
this.ent.setMetadata(PlayerID, "subrole", "idle");
|
2014-03-24 23:33:50 +01:00
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
// Makes the worker deposit the currently carried resources at the closest accessible dropsite
|
2014-03-24 23:33:50 +01:00
|
|
|
m.Worker.prototype.returnResources = function(gameState)
|
|
|
|
{
|
|
|
|
if (!this.ent.resourceCarrying() || this.ent.resourceCarrying().length === 0 || !this.ent.position())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
var resource = this.ent.resourceCarrying()[0].type;
|
|
|
|
var self = this;
|
|
|
|
|
|
|
|
var closestDropsite = undefined;
|
2014-05-18 13:34:36 +02:00
|
|
|
var distmin = Math.min();
|
|
|
|
var access = gameState.ai.accessibility.getAccessValue(this.ent.position());
|
|
|
|
gameState.getOwnDropsites(resource).forEach(function(dropsite) {
|
|
|
|
if (!dropsite.position() || dropsite.getMetadata(PlayerID, "access") !== access)
|
|
|
|
return;
|
|
|
|
var dist = API3.SquareVectorDistance(self.ent.position(), dropsite.position());
|
|
|
|
if (dist > distmin)
|
|
|
|
return;
|
|
|
|
distmin = dist;
|
|
|
|
closestDropsite = dropsite;
|
2014-03-24 23:33:50 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
if (!closestDropsite)
|
|
|
|
return false;
|
|
|
|
this.ent.returnResources(closestDropsite);
|
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
// if position is given, we only check if we could hunt from this position but do nothing
|
|
|
|
// otherwise the position of the entity is taken, and if something is found, we directly start the hunt
|
|
|
|
m.Worker.prototype.startHunting = function(gameState, position)
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
|
|
|
var resources = gameState.getHuntableSupplies();
|
|
|
|
if (resources.length === 0)
|
|
|
|
return false;
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
if (position)
|
|
|
|
var entPosition = position;
|
|
|
|
else
|
|
|
|
var entPosition = this.ent.position();
|
|
|
|
|
2014-03-24 23:33:50 +01:00
|
|
|
var nearestSupplyDist = Math.min();
|
|
|
|
var nearestSupply = undefined;
|
|
|
|
|
|
|
|
var isCavalry = this.ent.hasClass("Cavalry");
|
|
|
|
var isRanged = this.ent.hasClass("Ranged");
|
2014-05-18 13:34:36 +02:00
|
|
|
var foodDropsites = gameState.getOwnDropsites("food");
|
|
|
|
var access = gameState.ai.accessibility.getAccessValue(entPosition);
|
2014-03-24 23:33:50 +01:00
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
var nearestDropsiteDist = function(supply) {
|
2014-03-24 23:33:50 +01:00
|
|
|
var distMin = 1000000;
|
|
|
|
var pos = supply.position();
|
2014-05-18 13:34:36 +02:00
|
|
|
foodDropsites.forEach(function (dropsite) {
|
|
|
|
if (!dropsite.position() || dropsite.getMetadata(PlayerID, "access") !== access)
|
2014-03-24 23:33:50 +01:00
|
|
|
return;
|
|
|
|
var dist = API3.SquareVectorDistance(pos, dropsite.position());
|
|
|
|
if (dist < distMin)
|
|
|
|
distMin = dist;
|
|
|
|
});
|
|
|
|
return distMin;
|
|
|
|
};
|
|
|
|
|
|
|
|
resources.forEach(function(supply)
|
|
|
|
{
|
|
|
|
if (!supply.position())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (supply.getMetadata(PlayerID, "inaccessible") === true)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (m.IsSupplyFull(gameState, supply) === true)
|
|
|
|
return;
|
|
|
|
// check if available resource is worth one additionnal gatherer (except for farms)
|
|
|
|
var nbGatherers = supply.resourceSupplyGatherers().length
|
|
|
|
+ m.GetTCGatherer(gameState, supply.id());
|
|
|
|
if (nbGatherers > 0 && supply.resourceSupplyAmount()/(1+nbGatherers) < 40)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Only cavalry and range units should hunt fleeing animals
|
|
|
|
if (!supply.hasClass("Domestic") && !isCavalry && !isRanged)
|
|
|
|
return;
|
2014-05-18 13:34:36 +02:00
|
|
|
|
2014-03-24 23:33:50 +01:00
|
|
|
// quickscope accessbility check
|
2014-05-18 13:34:36 +02:00
|
|
|
if (!gameState.ai.accessibility.pathAvailable(gameState, entPosition, supply.position(), false, true))
|
2014-03-24 23:33:50 +01:00
|
|
|
return;
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
var supplyAccess = gameState.ai.accessibility.getAccessValue(supply.position());
|
|
|
|
if (supplyAccess !== access)
|
|
|
|
return;
|
|
|
|
|
2014-03-24 23:33:50 +01:00
|
|
|
// measure the distance to the resource
|
|
|
|
var dist = API3.SquareVectorDistance(entPosition, supply.position());
|
|
|
|
// Only cavalry should hunt faraway
|
|
|
|
if (!isCavalry && dist > 25000)
|
|
|
|
return;
|
|
|
|
|
2014-06-24 20:31:36 +02:00
|
|
|
// some simple accessibility check: if they're in an inaccessible square, we won't gather from them.
|
|
|
|
// (happen only at start of the game, as animals should not be able to walk to an inaccessible area)
|
|
|
|
// TODO as the animal can move, check again from time to time
|
|
|
|
if (supply.setMetadata(PlayerID, "inaccessible") === undefined)
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
|
|
|
var fakeMap = new API3.Map(gameState.sharedScript, gameState.getMap().data);
|
2014-04-03 22:48:54 +02:00
|
|
|
var mapPos = fakeMap.gamePosToMapPos(supply.position());
|
|
|
|
var id = mapPos[0] + fakeMap.width*mapPos[1];
|
|
|
|
if (gameState.sharedScript.passabilityClasses["pathfinderObstruction"] & gameState.getMap().data[id])
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
|
|
|
supply.setMetadata(PlayerID, "inaccessible", true)
|
|
|
|
return;
|
|
|
|
}
|
2014-06-24 20:31:36 +02:00
|
|
|
else
|
|
|
|
supply.setMetadata(PlayerID, "inaccessible", false)
|
2014-03-24 23:33:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// Avoid ennemy territory
|
2014-03-26 22:07:47 +01:00
|
|
|
var territoryOwner = gameState.ai.HQ.territoryMap.getOwner(supply.position());
|
2014-03-24 23:33:50 +01:00
|
|
|
if (territoryOwner != 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
|
|
|
|
return;
|
|
|
|
|
|
|
|
var dropsiteDist = nearestDropsiteDist(supply);
|
|
|
|
if (dropsiteDist > 35000)
|
|
|
|
return;
|
2014-05-18 13:34:36 +02:00
|
|
|
// Only cavalry should hunt far from dropsite (specially for non domestic animals which flee)
|
2014-03-24 23:33:50 +01:00
|
|
|
if (!isCavalry && (dropsiteDist > 10000 || ((dropsiteDist > 7000 || territoryOwner == 0 ) && !supply.hasClass("Domestic"))))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (dist < nearestSupplyDist)
|
|
|
|
{
|
|
|
|
nearestSupplyDist = dist;
|
|
|
|
nearestSupply = supply;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
if (nearestSupply)
|
|
|
|
{
|
|
|
|
if (position)
|
|
|
|
return true;
|
|
|
|
m.AddTCGatherer(gameState, nearestSupply.id());
|
|
|
|
this.ent.gather(nearestSupply);
|
|
|
|
this.ent.setMetadata(PlayerID, "supply", nearestSupply.id());
|
|
|
|
this.ent.setMetadata(PlayerID, "target-foundation", undefined);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
m.Worker.prototype.startFishing = function(gameState)
|
|
|
|
{
|
|
|
|
if (!this.ent.position())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// So here we're doing it basic. We check what we can hunt, we hunt it. No fancies.
|
|
|
|
|
|
|
|
var resources = gameState.getFishableSupplies();
|
|
|
|
if (resources.length === 0)
|
|
|
|
{
|
2014-06-10 15:27:49 +02:00
|
|
|
gameState.ai.HQ.navalManager.resetFishingBoats(gameState);
|
2014-05-18 13:34:36 +02:00
|
|
|
this.ent.destroy();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
var nearestSupplyDist = Math.min();
|
|
|
|
var nearestSupply = undefined;
|
|
|
|
|
|
|
|
var entPosition = this.ent.position();
|
|
|
|
var fisherSea = this.ent.getMetadata(PlayerID, "sea");
|
|
|
|
var docks = gameState.getOwnStructures().filter(API3.Filters.and(API3.Filters.byClass("Dock"), API3.Filters.not(API3.Filters.isFoundation())));
|
|
|
|
|
|
|
|
var nearestDropsiteDist = function(supply) {
|
|
|
|
var distMin = 1000000;
|
|
|
|
var pos = supply.position();
|
|
|
|
docks.forEach(function (dock) {
|
|
|
|
if (!dock.position() || dock.getMetadata(PlayerID, "sea") !== fisherSea)
|
|
|
|
return;
|
|
|
|
var dist = API3.SquareVectorDistance(pos, dock.position());
|
|
|
|
if (dist < distMin)
|
|
|
|
distMin = dist;
|
|
|
|
});
|
|
|
|
return distMin;
|
|
|
|
};
|
|
|
|
|
|
|
|
resources.forEach(function(supply)
|
|
|
|
{
|
|
|
|
if (!supply.position())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (m.IsSupplyFull(gameState, supply) === true)
|
|
|
|
return;
|
|
|
|
// check if available resource is worth one additionnal gatherer (except for farms)
|
|
|
|
var nbGatherers = supply.resourceSupplyGatherers().length
|
|
|
|
+ m.GetTCGatherer(gameState, supply.id());
|
|
|
|
if (nbGatherers > 0 && supply.resourceSupplyAmount()/(1+nbGatherers) < 40)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// check that it is accessible
|
|
|
|
if (!supply.getMetadata(PlayerID, "sea"))
|
|
|
|
supply.setMetadata(PlayerID, "sea", gameState.ai.accessibility.getAccessValue(supply.position(), true));
|
|
|
|
if (supply.getMetadata(PlayerID, "sea") !== fisherSea)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// measure the distance to the resource
|
|
|
|
var dist = API3.SquareVectorDistance(entPosition, supply.position());
|
|
|
|
if (dist > 40000)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Avoid ennemy territory
|
|
|
|
var territoryOwner = gameState.ai.HQ.territoryMap.getOwner(supply.position());
|
|
|
|
if (territoryOwner != 0 && !gameState.isPlayerAlly(territoryOwner)) // player is its own ally
|
|
|
|
return;
|
|
|
|
|
|
|
|
var dropsiteDist = nearestDropsiteDist(supply);
|
|
|
|
if (dropsiteDist > 35000)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (dist < nearestSupplyDist)
|
|
|
|
{
|
|
|
|
nearestSupplyDist = dist;
|
|
|
|
nearestSupply = supply;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2014-03-24 23:33:50 +01:00
|
|
|
if (nearestSupply)
|
|
|
|
{
|
|
|
|
m.AddTCGatherer(gameState, nearestSupply.id());
|
|
|
|
this.ent.gather(nearestSupply);
|
|
|
|
this.ent.setMetadata(PlayerID, "supply", nearestSupply.id());
|
|
|
|
this.ent.setMetadata(PlayerID, "target-foundation", undefined);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2014-05-18 13:34:36 +02:00
|
|
|
if (this.ent.getMetadata(PlayerID,"subrole") === "fisher")
|
2014-03-24 23:33:50 +01:00
|
|
|
this.ent.setMetadata(PlayerID, "subrole", "idle");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
m.Worker.prototype.getResourceType = function(type){
|
|
|
|
if (!type || !type.generic)
|
|
|
|
return undefined;
|
|
|
|
|
|
|
|
if (type.generic === "treasure")
|
|
|
|
return type.specific;
|
|
|
|
else
|
|
|
|
return type.generic;
|
|
|
|
};
|
|
|
|
|
|
|
|
m.Worker.prototype.getGatherRate = function(gameState) {
|
|
|
|
if (this.ent.getMetadata(PlayerID,"subrole") !== "gatherer")
|
|
|
|
return 0;
|
|
|
|
var rates = this.ent.resourceGatherRates();
|
|
|
|
|
|
|
|
if (this.ent.unitAIOrderData().length && this.ent.unitAIState().split(".")[1] === "GATHER" && this.ent.unitAIOrderData()[0]["target"])
|
|
|
|
{
|
|
|
|
var ress = gameState.getEntityById(this.ent.unitAIOrderData()[0]["target"]);
|
|
|
|
if (!ress)
|
|
|
|
return 0;
|
|
|
|
var type = ress.resourceSupplyType();
|
|
|
|
if (type.generic == "treasure")
|
|
|
|
return 1000;
|
|
|
|
var tstring = type.generic + "." + type.specific;
|
|
|
|
if (rates[tstring])
|
|
|
|
return rates[tstring];
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
m.Worker.prototype.gatherNearestField = function(gameState, baseID)
|
|
|
|
{
|
2014-03-24 23:33:50 +01:00
|
|
|
var self = this;
|
2014-05-18 13:34:36 +02:00
|
|
|
var ownFields = gameState.getOwnEntitiesByType(gameState.applyCiv("structures/{civ}_field"), true).filter(API3.Filters.byMetadata(PlayerID, "base", baseID));
|
|
|
|
var bestFarmEnt = false;
|
2014-03-24 23:33:50 +01:00
|
|
|
var bestFarmDist = 10000000;
|
|
|
|
|
|
|
|
ownFields.forEach(function (field) {
|
|
|
|
if (m.IsSupplyFull(gameState, field) === true)
|
|
|
|
return;
|
|
|
|
var dist = API3.SquareVectorDistance(field.position(), self.ent.position());
|
|
|
|
if (dist < bestFarmDist)
|
|
|
|
{
|
|
|
|
bestFarmEnt = field;
|
|
|
|
bestFarmDist = dist;
|
|
|
|
}
|
|
|
|
});
|
2014-05-18 13:34:36 +02:00
|
|
|
if (bestFarmEnt)
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
|
|
|
m.AddTCGatherer(gameState, bestFarmEnt.id());
|
|
|
|
this.ent.setMetadata(PlayerID, "supply", bestFarmEnt.id());
|
|
|
|
}
|
2014-05-18 13:34:36 +02:00
|
|
|
return bestFarmEnt;
|
2014-03-24 23:33:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* WARNING with the present options of AI orders, the unit will not gather after building the farm.
|
|
|
|
* This is done by calling the gatherNearestField function when construction is completed.
|
|
|
|
*/
|
2014-05-18 13:34:36 +02:00
|
|
|
m.Worker.prototype.buildAnyField = function(gameState, baseID)
|
|
|
|
{
|
2014-03-24 23:33:50 +01:00
|
|
|
var self = this;
|
|
|
|
var foundations = gameState.getOwnFoundations();
|
2014-05-18 13:34:36 +02:00
|
|
|
var baseFoundations = foundations.filter(API3.Filters.byMetadata(PlayerID, "base", baseID));
|
2014-03-24 23:33:50 +01:00
|
|
|
|
|
|
|
var maxGatherers = gameState.getTemplate(gameState.applyCiv("structures/{civ}_field")).maxGatherers();
|
|
|
|
|
2014-05-18 13:34:36 +02:00
|
|
|
var bestFarmEnt = false;
|
2014-03-24 23:33:50 +01:00
|
|
|
var bestFarmDist = 10000000;
|
|
|
|
baseFoundations.forEach(function (found) {
|
|
|
|
if (found.hasClass("Field")) {
|
|
|
|
var current = found.getBuildersNb();
|
|
|
|
if (current === undefined || current >= maxGatherers)
|
|
|
|
return;
|
|
|
|
var dist = API3.SquareVectorDistance(found.position(), self.ent.position());
|
|
|
|
if (dist < bestFarmDist)
|
|
|
|
{
|
|
|
|
bestFarmEnt = found;
|
|
|
|
bestFarmDist = dist;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2014-05-18 13:34:36 +02:00
|
|
|
return bestFarmEnt;
|
2014-03-24 23:33:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
// Workers elephant should move away from the buildings they've built to avoid being trapped in between constructions
|
|
|
|
// For the time being, we move towards the nearest gatherer (providing him a dropsite)
|
|
|
|
m.Worker.prototype.moveAway = function(baseManager, gameState){
|
|
|
|
var gatherers = baseManager.workersBySubrole(gameState, "gatherer").toEntityArray();
|
|
|
|
var pos = this.ent.position();
|
|
|
|
var dist = Math.min();
|
|
|
|
var destination = pos;
|
2014-05-30 17:24:19 +02:00
|
|
|
for (var gatherer of gatherers)
|
2014-03-24 23:33:50 +01:00
|
|
|
{
|
2014-05-30 17:24:19 +02:00
|
|
|
if (!gatherer.position() || gatherer.getMetadata(PlayerID, "transport") !== undefined)
|
2014-03-24 23:33:50 +01:00
|
|
|
continue;
|
2014-05-30 17:24:19 +02:00
|
|
|
if (gatherer.isIdle())
|
|
|
|
continue;
|
|
|
|
var distance = API3.SquareVectorDistance(pos, gatherer.position());
|
2014-03-24 23:33:50 +01:00
|
|
|
if (distance > dist)
|
|
|
|
continue;
|
|
|
|
dist = distance;
|
2014-05-30 17:24:19 +02:00
|
|
|
destination = gatherer.position();
|
2014-03-24 23:33:50 +01:00
|
|
|
}
|
|
|
|
this.ent.move(destination[0], destination[1]);
|
|
|
|
};
|
|
|
|
|
|
|
|
return m;
|
|
|
|
}(PETRA);
|