This patch adds territory support for JuBot, which is the main thing to get it up to date for the next alpha. More advanced features are in development but some will probably have to wait until Christmas/Early 2012.

This was SVN commit r10560.
This commit is contained in:
James Baillie 2011-11-19 13:44:56 +00:00
parent 20df816fbc
commit f80f1fb86b
4 changed files with 379 additions and 108 deletions

View File

@ -21,10 +21,9 @@ var EconomyManager = Class({
};
},
checkBuildingList: function (gameState) {
villageBuildingList: function (gameState) {
if (gameState.displayCiv() == "hele"){
this.targetBuildings = [
this.villageBuildings = [
{
"template": "structures/{civ}_scout_tower",
"priority": 105,
@ -41,10 +40,123 @@ var EconomyManager = Class({
"count": 1,
},
{
"template": "structures/{civ}_scout_tower",
"priority": 90,
"count": 3,
"template": "structures/{civ}_field",
"priority": 70,
"count": 2,
},
];
}
// Celt building list
else if (gameState.displayCiv() == "celt"){
this.villageBuildings = [
{
"template": "structures/{civ}_scout_tower",
"priority": 105,
"count": 1,
},
{
"template": "structures/{civ}_field",
"priority": 103,
"count": 1,
},
{
"template": "structures/{civ}_barracks",
"priority": 101,
"count": 1,
},
{
"template": "structures/{civ}_field",
"priority": 70,
"count": 2,
},
];
}
// Carthage building list
else if (gameState.displayCiv() == "cart"){
this.villageBuildings = [
{
"template": "structures/{civ}_scout_tower",
"priority": 105,
"count": 1,
},
{
"template": "structures/{civ}_field",
"priority": 103,
"count": 1,
},
{
"template": "structures/{civ}_barracks",
"priority": 101,
"count": 1,
},
{
"template": "structures/{civ}_field",
"priority": 70,
"count": 2,
},
];
}
// Celt building list
else if (gameState.displayCiv() == "iber"){
this.villageBuildings = [
{
"template": "structures/{civ}_scout_tower",
"priority": 105,
"count": 1,
},
{
"template": "structures/{civ}_field",
"priority": 103,
"count": 1,
},
{
"template": "structures/{civ}_barracks",
"priority": 101,
"count": 1,
},
{
"template": "structures/{civ}_field",
"priority": 70,
"count": 2,
},
];
}
// Fallback option just in case
else {
this.villageBuildings = [
{
"template": "structures/{civ}_scout_tower",
"priority": 105,
"count": 1,
},
{
"template": "structures/{civ}_field",
"priority": 100,
"count": 2,
},
{
"template": "structures/{civ}_barracks",
"priority": 99,
"count": 1,
},
{
"template": "structures/{civ}_scout_tower",
"priority": 60,
"count": 4,
},
{
"template": "structures/{civ}_field",
"priority": 40,
"count": 5,
},
];
}
},
checkBuildingList: function (gameState) {
if (gameState.displayCiv() == "hele"){
this.targetBuildings = [
{
"template": "structures/hele_gymnasion",
"priority": 80,
@ -60,11 +172,6 @@ var EconomyManager = Class({
"priority": 60,
"count": 1,
},
{
"template": "structures/{civ}_scout_tower",
"priority": 50,
"count": 5,
},
{
"template": "structures/{civ}_field",
"priority": 40,
@ -75,11 +182,6 @@ var EconomyManager = Class({
// Celt building list
else if (gameState.displayCiv() == "celt"){
this.targetBuildings = [
{
"template": "structures/{civ}_field",
"priority": 100,
"count": 1,
},
{
"template": "structures/{civ}_barracks",
"priority": 90,
@ -90,31 +192,11 @@ var EconomyManager = Class({
"priority": 80,
"count": 1,
},
{
"template": "structures/{civ}_scout_tower",
"priority": 60,
"count": 3,
},
{
"template": "structures/{civ}_field",
"priority": 40,
"count": 3,
},
];
}
// Carthage building list
else if (gameState.displayCiv() == "cart"){
this.targetBuildings = [
{
"template": "structures/{civ}_field",
"priority": 100,
"count": 1,
},
{
"template": "structures/{civ}_barracks",
"priority": 100,
"count": 1,
},
{
"template": "structures/cart_fortress",
"priority": 80,
@ -125,11 +207,6 @@ var EconomyManager = Class({
"priority": 75,
"count": 1,
},
{
"template": "structures/{civ}_scout_tower",
"priority": 70,
"count": 3,
},
{
"template": "structures/cart_embassy_celtic",
"priority": 50,
@ -145,52 +222,22 @@ var EconomyManager = Class({
"priority": 50,
"count": 1,
},
{
"template": "structures/{civ}_field",
"priority": 40,
"count": 3,
},
];
}
// Celt building list
else if (gameState.displayCiv() == "iber"){
this.targetBuildings = [
{
"template": "structures/{civ}_field",
"priority": 100,
"count": 1,
},
{
"template": "structures/{civ}_barracks",
"priority": 100,
"count": 1,
},
{
"template": "structures/iber_fortress",
"priority": 80,
"count": 1,
},
{
"template": "structures/{civ}_scout_tower",
"priority": 70,
"count": 3,
},
{
"template": "structures/{civ}_field",
"priority": 40,
"count": 3,
},
];
}
// Fallback option just in case
else {
this.targetBuildings = [
{
"template": "structures/{civ}_scout_tower",
"priority": 105,
"count": 1,
},
{
"template": "structures/{civ}_field",
"priority": 100,
@ -244,17 +291,47 @@ var EconomyManager = Class({
if (gameState.findFoundations().length > 0)
return;
// START BY GETTING ALL CCs UP TO SMALL VILLAGE LEVEL
for each (var building in this.villageBuildings)
{
var numBuildings = gameState.countEntitiesAndQueuedWithType(gameState.applyCiv(building.template));
var wantedtotal = building.count * numCCs;
// If we have too few, build another
if (numBuildings < wantedtotal && building.template != gameState.applyCiv("structures/{civ}_field"))
{
planGroups.economyConstruction.addPlan(building.priority,
new BuildingConstructionPlan(gameState, building.template, 1)
);
return;
}
else if (numBuildings < wantedtotal && building.template == gameState.applyCiv("structures/{civ}_field"))
{
planGroups.economyConstruction.addPlan(building.priority,
new BuildingConstructionPlanResources(gameState, building.template, 1)
);
return;
}
}
// THEN BUILD THE MAIN BASE INTO A TOWN
for each (var building in this.targetBuildings)
{
var numBuildings = gameState.countEntitiesAndQueuedWithType(gameState.applyCiv(building.template));
// If we have too few, build another
if (numBuildings < building.count)
if (numBuildings < building.count && building.template != gameState.applyCiv("structures/{civ}_field"))
{
planGroups.economyConstruction.addPlan(building.priority,
new BuildingConstructionPlan(gameState, building.template, 1)
);
return;
}
else if (numBuildings < building.count && building.template == gameState.applyCiv("structures/{civ}_field"))
{
planGroups.economyConstruction.addPlan(building.priority,
new BuildingConstructionPlanResources(gameState, building.template, 1)
);
return;
}
}
},
@ -400,8 +477,8 @@ var EconomyManager = Class({
var targets = gameState.entities.filter(function(enten) {
var foeposition = enten.position();
if (foeposition){
var dist = VectorDistance(foeposition, currentPosition);
return (enten.isEnemy() && enten.owner()!= 0 && dist < 50);
var dist = SquareVectorDistance(foeposition, currentPosition);
return (enten.isEnemy() && enten.owner()!= 0 && dist < 2500);
}
else {
return false;
@ -466,7 +543,7 @@ var EconomyManager = Class({
// Make sure there's actually some of that type
if (!resourceSupplies[type])
continue;
// The types are food wood stone metal
// Pick the closest one.
// TODO: we should care about distance to dropsites, not (just) to the worker,
// and gather rates of workers
@ -481,39 +558,66 @@ var EconomyManager = Class({
if (supply.entity.hasClass("SeaCreature"))
return;
var distcheck = 1000000;
var supplydistcheck = 1000000;
var distcheck = 10000000000;
var supplydistcheck = 100000000000;
gameState.getOwnEntities().forEach(function(centre) {
if (centre.hasClass("CivCentre"))
{
var centrePosition = centre.position();
var currentsupplydistcheck = VectorDistance(supply.position, centrePosition);
var currentsupplydistcheck = SquareVectorDistance(supply.position, centrePosition);
if (currentsupplydistcheck < currentsupplydistcheck){
supplydistcheck = currentsupplydistcheck;
}
var currentdistcheck = VectorDistance(supply.position, centrePosition);
var currentdistcheck = SquareVectorDistance(supply.position, centrePosition);
if (currentdistcheck < distcheck){
distcheck = currentdistcheck;
}
// Skip targets that are far too far away (e.g. in the enemy base)
}
else if (centre.hasClass("Economic"))
else if (centre.hasClass("DropsiteFood") && type == "food")
{
var centrePosition = centre.position();
var currentsupplydistcheck = VectorDistance(supply.position, centrePosition);
var currentsupplydistcheck = SquareVectorDistance(supply.position, centrePosition);
if (currentsupplydistcheck < currentsupplydistcheck){
supplydistcheck = currentsupplydistcheck;
}
// Skip targets that are far too far away (e.g. in the enemy base)
}
else if (centre.hasClass("DropsiteWood") && type == "wood")
{
var centrePosition = centre.position();
var currentsupplydistcheck = SquareVectorDistance(supply.position, centrePosition);
if (currentsupplydistcheck < currentsupplydistcheck){
supplydistcheck = currentsupplydistcheck;
}
// Skip targets that are far too far away (e.g. in the enemy base)
}
else if (centre.hasClass("DropsiteStone") && type == "stone")
{
var centrePosition = centre.position();
var currentsupplydistcheck = SquareVectorDistance(supply.position, centrePosition);
if (currentsupplydistcheck < currentsupplydistcheck){
supplydistcheck = currentsupplydistcheck;
}
// Skip targets that are far too far away (e.g. in the enemy base)
}
else if (centre.hasClass("DropsiteMetal") && type == "metal")
{
var centrePosition = centre.position();
var currentsupplydistcheck = SquareVectorDistance(supply.position, centrePosition);
if (currentsupplydistcheck < currentsupplydistcheck){
supplydistcheck = currentsupplydistcheck;
}
// Skip targets that are far too far away (e.g. in the enemy base)
}
});
if (distcheck > 500)
if (distcheck > 250000)
return;
var dist = VectorDistance(supply.position, workerPosition);
var dist = SquareVectorDistance(supply.position, workerPosition);
// Skip targets that are far too far away (e.g. in the enemy base)
if (dist > 500)
if (dist > 250000)
return;
supplies.push({ dist: dist, entity: supply.entity });
@ -526,36 +630,77 @@ var EconomyManager = Class({
return false;
});
if (type == "food"){
var whatshallwebuild = "structures/{civ}_farmstead"
}
else {
var whatshallwebuild = "structures/{civ}_mill"
}
// Start gathering
if (supplies.length)
{
// THIS SHOULD BE A GLOBAL VARIABLE
var currentposformill = supplies[0].entity.position();
var distcheckoldII = 10000;
var distcheckoldII = 1000000000;
// CHECK DISTANCE
gameState.getOwnEntities().forEach(function(centre) {
if (centre.hasClass("CivCentre") || centre.hasClass("Economic"))
if (centre.hasClass("CivCentre"))
{
var centrePosition = centre.position();
var distcheckII = VectorDistance(currentposformill, centrePosition);
var distcheckII = SquareVectorDistance(currentposformill, centrePosition);
if (distcheckII < distcheckoldII){
distcheckoldII = distcheckII;
}
}
else if (centre.hasClass("DropsiteFood") && type == "food")
{
var centrePosition = centre.position();
var distcheckII = SquareVectorDistance(currentposformill, centrePosition);
if (distcheckII < distcheckoldII){
distcheckoldII = distcheckII;
}
}
else if (centre.hasClass("DropsiteWood") && type == "wood")
{
var centrePosition = centre.position();
var distcheckII = SquareVectorDistance(currentposformill, centrePosition);
if (distcheckII < distcheckoldII){
distcheckoldII = distcheckII;
}
}
else if (centre.hasClass("DropsiteMetal") && type == "metal")
{
var centrePosition = centre.position();
var distcheckII = SquareVectorDistance(currentposformill, centrePosition);
if (distcheckII < distcheckoldII){
distcheckoldII = distcheckII;
}
}
else if (centre.hasClass("DropsiteStone") && type == "stone")
{
var centrePosition = centre.position();
var distcheckII = SquareVectorDistance(currentposformill, centrePosition);
if (distcheckII < distcheckoldII){
distcheckoldII = distcheckII;
}
}
});
var foundationsyes = false;
if (gameState.findFoundations().length > 2){
if (gameState.findFoundations().length > 1){
foundationsyes = false;
}
else{
foundationsyes = true;
}
//warn(type + " is the resource and " + distcheckoldII + " is the distance.");
if (distcheckoldII > 60 && foundationsyes == true){
if (distcheckoldII > 5000 && foundationsyes == true){
//JuBotAI.prototype.chat("Building Mill");
planGroups.economyConstruction.addPlan(80,
new BuildingConstructionPlanEcon(gameState, "structures/{civ}_mill", 1, currentposformill)
planGroups.economyConstruction.addPlan(150,
new BuildingConstructionPlanEcon(gameState, whatshallwebuild, 1, currentposformill)
);
//JuBotAI.prototype.chat("Gathering");
ent.gather(supplies[0].entity);
@ -647,6 +792,7 @@ var EconomyManager = Class({
//this.buildRegroup(gameState, planGroups)
this.checkBuildingList(gameState);
this.villageBuildingList(gameState);
this.reassignRolelessUnits(gameState);

View File

@ -203,8 +203,8 @@ var MilitaryAttackManager = Class({
var targets = gameState.entities.filter(function(ent) {
var foeposition = ent.position();
if (foeposition){
var dist = VectorDistance(foeposition, currentPosition);
return (ent.isEnemy() && ent.owner()!= 0 && dist < 50);
var dist = SquareVectorDistance(foeposition, currentPosition);
return (ent.isEnemy() && ent.owner()!= 0 && dist < 2500);
}
else {
return false;
@ -223,6 +223,52 @@ var MilitaryAttackManager = Class({
});
},
CombatAnalyser: function(gameState, planGroups, startunit)
{
var centrepoint = startunit.position();
var targets = gameState.entities.filter(function(squeak) {
var currentPosition = squeak.position();
if (currentPosition){
var dist = SquareVectorDistance(foeposition, currentPosition);
return (dist < 2500);
}
else {
return false;
}
});
if (targets.length)
{
var forest = 0;
var foeTot = 0;
var foeCav = 0;
var foeInf = 0;
var foeBow = 0;
var foeRangeCav = 0;
targets.forEach(function(item) {
if (item.hasClass("ForestPlant")){
forest += 1;
}
if (item.isEnemy() && item.owner != 0 && item.hasClass("Infantry") && item.hasClass("Melee")){
foeTot += 1;
foeInf += 1;
}
if (item.isEnemy() && item.owner != 0 && item.hasClass("Infantry" && item.hasClass("Ranged"))){
foeTot += 1;
foeBow += 1;
}
if (item.isEnemy() && item.owner != 0 && item.hasClass("Cavalry") && item.hasClass("Melee")){
foeTot += 1;
foeCav += 1;
}
if (item.isEnemy() && item.owner != 0 && item.hasClass("Cavalry" && item.hasClass("Ranged"))){
foeTot += 1;
foeRangeCav += 1;
}
});
}
},
combatcheckMilitia: function(gameState, planGroups, assaultgroup)
{
var regroupneeded = gameState.getOwnEntitiesWithRole(assaultgroup);
@ -232,8 +278,8 @@ var MilitaryAttackManager = Class({
var targets = gameState.entities.filter(function(ent) {
var foeposition = ent.position();
if (foeposition){
var dist = VectorDistance(foeposition, currentPosition);
return (ent.isEnemy() && ent.owner()!= 0 && dist < 50);
var dist = SquareVectorDistance(foeposition, currentPosition);
return (ent.isEnemy() && ent.owner()!= 0 && dist < 2500);
}
else {
return false;
@ -243,8 +289,8 @@ var MilitaryAttackManager = Class({
var ownbuildings = gameState.getOwnEntities().filter(function(ent) {
var foeposition = ent.position();
if (foeposition){
var dist = VectorDistance(foeposition, currentPosition);
return (dist < 50 && ent.hasClass("Village"));
var dist = SquareVectorDistance(foeposition, currentPosition);
return (dist < 2500 && ent.hasClass("Village"));
}
else {
return false;
@ -252,12 +298,17 @@ var MilitaryAttackManager = Class({
});
if (targets.length >= 5 && ownbuildings.length > 0){
regroupneeded.forEach(function(person) {
var position = targets.toEntityArray()[0].position();
var ourposition = person.position();
var distance = SquareVectorDistance(position, ourposition);
if (distance <= 22500){
var targetrandomiser = Math.floor(Math.random()*targets.length);
var target = targets.toEntityArray()[targetrandomiser];
var targetPos = target.position();
// TODO: this should be an attack-move command
person.move(targetPos[0], targetPos[1]);
person.setMetadata("role", "militiafighter");
}
});
}
});

View File

@ -200,10 +200,24 @@ var BuildingConstructionPlan = Class({
gameState.getOwnEntities().forEach(function(ent) {
if (ent.hasClass("Structure"))
{
var infl = 32;
var infl = 15;
if (ent.hasClass("CivCentre"))
infl *= 5;
{
infl = infl*5;
}
else if (ent.hasClass("Village"))
{
infl = 0;
}
else if (ent.hasClass("Economic"))
{
infl = 20;
}
else
{
infl = 0;
}
var pos = ent.position();
var x = Math.round(pos[0] / cellSize);
var z = Math.round(pos[1] / cellSize);

View File

@ -3,6 +3,9 @@ var BuildingConstructionPlanEcon = Class({
_init: function(gameState, type, indno, resourcepos)
{
this.type = gameState.applyCiv(type);
this.resourceposition = resourcepos;
this.pos = this.findGoodPosition(gameState);
var template = gameState.getTemplate(this.type);
if (!template)
@ -10,9 +13,8 @@ var BuildingConstructionPlanEcon = Class({
this.invalidTemplate = true;
return;
}
this.cost = new Resources(template.cost());
this.resourceposition = resourcepos;
},
canExecute: function(gameState)
@ -37,7 +39,6 @@ var BuildingConstructionPlanEcon = Class({
// do the building themselves - all we care about is that there is
// some unit that can start the foundation
var pos = this.findGoodPosition(gameState);
//Check distance from Pos to CC - we don't want to get too far from the centre, for now.
// THIS SHOULD BE A GLOBAL VARIABLE
//var distcheckold = 10000;
@ -56,7 +57,7 @@ var BuildingConstructionPlanEcon = Class({
//});
//Distcheck is thus the distance to the nearest CC - we only build if it's low enough.
///if (distcheckold < 400){
builders[0].construct(this.type, pos.x, pos.z, pos.angle);
builders[0].construct(this.type, this.pos.x, this.pos.z, this.pos.angle);
//}
//else {
//var pos = this.findGoodPositionOldStyle(gameState);
@ -188,7 +189,6 @@ var BuildingConstructionPlanEcon = Class({
);
obstructionTiles[i] = (invalidTerritory || (passabilityMap.data[i] & obstructionMask)) ? 0 : 65535;
}
// Engine.DumpImage("tiles0.png", obstructionTiles, passabilityMap.width, passabilityMap.height, 64);
this.expandInfluences(obstructionTiles, passabilityMap.width, passabilityMap.height);
@ -198,7 +198,7 @@ var BuildingConstructionPlanEcon = Class({
// Compute each tile's closeness to friendly structures:
var friendlyTiles = new Uint16Array(passabilityMap.data.length);
var infl = 100;
var infl = 25;
var pos = this.resourceposition;
var x = Math.round(pos[0] / cellSize);
var z = Math.round(pos[1] / cellSize);
@ -228,10 +228,69 @@ var BuildingConstructionPlanEcon = Class({
{
bestVal = v;
bestIdx = i;
//JuBotAI.prototype.chat("BestVal is " + bestVal + ", and bestIdx is " + bestIdx + ".");
}
}
}
//warn("BestVal is " + bestVal + ", and bestIdx is " + bestIdx + ".");
if (bestVal <= 5) {
//warn("Trying to build Civ Centre");
this.type = gameState.applyCiv("structures/{civ}_civil_centre");
var playerID = gameState.getPlayerID();
var buildOwn = template.hasBuildTerritory("own");
var buildAlly = template.hasBuildTerritory("ally");
var buildNeutral = template.hasBuildTerritory("neutral");
var buildEnemy = template.hasBuildTerritory("enemy");
// Since this is for CCs, only refrain from building on actual enemy territory.
var obstructionTilesII = new Uint16Array(passabilityMap.data.length);
for (var i = 0; i < passabilityMap.data.length; ++i)
{
var tilePlayer = (territoryMap.data[i] & TERRITORY_PLAYER_MASK);
var invalidTerritory = (
(!buildEnemy && gameState.isPlayerEnemy(tilePlayer) && tilePlayer !=0)
);
obstructionTilesII[i] = (invalidTerritory || (passabilityMap.data[i] & obstructionMask)) ? 0 : 65535;
}
// Engine.DumpImage("tiles0.png", obstructionTiles, passabilityMap.width, passabilityMap.height, 64);
this.expandInfluences(obstructionTilesII, passabilityMap.width, passabilityMap.height);
// TODO: handle distance restrictions for e.g. CivCentres
// Compute each tile's closeness to friendly structures:
var friendlyTiles = new Uint16Array(passabilityMap.data.length);
var infl = 50;
var pos = this.resourceposition;
var x = Math.round(pos[0] / cellSize);
var z = Math.round(pos[1] / cellSize);
self.addInfluence(friendlyTiles, passabilityMap.width, passabilityMap.height, x, z, infl);
var template = gameState.getTemplate(this.type);
var radius = Math.ceil(template.obstructionRadius() / cellSize) + 1;
var bestIdx = 0;
var bestVal = -1;
for (var i = 0; i < passabilityMap.data.length; ++i)
{
if (obstructionTilesII[i] > radius)
{
var v = friendlyTiles[i];
//var foe = enemyTiles[i];
//JuBotAI.prototype.chat(v);
//JuBotAI.prototype.chat(i);
//JuBotAI.prototype.chat(foe);
if (v >= bestVal)
{
bestVal = v;
bestIdx = i;
}
}
}
//warn("For CC, BestVal is " + bestVal + ", and bestIdx is " + bestIdx + ".");
}
var x = ((bestIdx % passabilityMap.width) + 0.5) * cellSize;
var z = (Math.floor(bestIdx / passabilityMap.width) + 0.5) * cellSize;
@ -242,6 +301,7 @@ var BuildingConstructionPlanEcon = Class({
var angle = 0.75*Math.PI;
return {
"canbuild": true,
"x": x,
"z": z,
"angle": angle