Ticket #969: ai_buildrestrictions-09282011.patch
File ai_buildrestrictions-09282011.patch, 19.5 KB (added by , 13 years ago) |
---|
-
binaries/data/mods/public/simulation/ai/jubot/gamestate.js
43 43 return new Resources(this.playerData.resourceCounts); 44 44 }, 45 45 46 get Map: function()46 getPassabilityMap: function() 47 47 { 48 return this.ai. map;48 return this.ai.passabilityMap; 49 49 }, 50 50 51 51 getPassabilityClassMask: function(name) … … 55 55 return this.ai.passabilityClasses[name]; 56 56 }, 57 57 58 getTerritoryMap: function() 59 { 60 return this.ai.territoryMap; 61 }, 62 58 63 getOwnEntities: (function() 59 64 { 60 65 return new EntityCollection(this.ai, this.ai._ownEntities); -
binaries/data/mods/public/simulation/ai/jubot/plan-building.js
146 146 147 147 var cellSize = 4; // size of each tile 148 148 149 // First, find all tiles that are far enough away from obstructions:149 var template = gameState.getTemplate(this.type); 150 150 151 var map = gameState.getMap(); 152 151 // Find all tiles in valid territory that are far enough away from obstructions: 152 var passabilityMap = gameState.getPassabilityMap(); 153 var territoryMap = gameState.getTerritoryMap(); 154 const TERRITORY_PLAYER_MASK = 0x7F; 153 155 var obstructionMask = gameState.getPassabilityClassMask("foundationObstruction"); 154 // Only accept valid land tiles (we don't handle docks yet)155 obstructionMask |= gameState.getPassabilityClassMask("building-land");156 156 157 var obstructionTiles = new Uint16Array(map.data.length); 158 for (var i = 0; i < map.data.length; ++i) 159 obstructionTiles[i] = (map.data[i] & obstructionMask) ? 0 : 65535; 157 if (passabilityMap.data.length != territoryMap.data.length) 158 error("passability and territory data are not matched!"); 160 159 161 // Engine.DumpImage("tiles0.png", obstructionTiles, map.width, map.height, 64); 160 // See BuildRestrictions.js 161 switch(template.buildPlacementType()) 162 { 163 case "shore": 164 obstructionMask |= gameState.getPassabilityClassMask("building-shore"); 165 break; 166 case "land": 167 default: 168 obstructionMask |= gameState.getPassabilityClassMask("building-land"); 169 } 162 170 163 this.expandInfluences(obstructionTiles, map.width, map.height); 171 var playerID = gameState.getPlayerID(); 172 var buildOwn = template.hasBuildTerritory("own"); 173 var buildAlly = template.hasBuildTerritory("ally"); 174 var buildNeutral = template.hasBuildTerritory("neutral"); 175 var buildEnemy = template.hasBuildTerritory("enemy"); 164 176 177 var obstructionTiles = new Uint16Array(passabilityMap.data.length); 178 for (var i = 0; i < passabilityMap.data.length; ++i) 179 { 180 var tilePlayer = (territoryMap.data[i] & TERRITORY_PLAYER_MASK); 181 var validTerritory = ( 182 (!buildOwn || tilePlayer == playerID) && 183 (!buildAlly || gameState.isPlayerAlly(tilePlayer)) && 184 (!buildEnemy || gameState.isPlayerEnemy(tilePlayer)) && 185 (!buildNeutral || tilePlayer == 0) 186 ); 187 obstructionTiles[i] = ((passabilityMap.data[i] & obstructionMask) || !validTerritory) ? 0 : 65535; 188 } 189 190 // Engine.DumpImage("tiles0.png", obstructionTiles, passabilityMap.width, passabilityMap.height, 64); 191 192 this.expandInfluences(obstructionTiles, passabilityMap.width, passabilityMap.height); 193 194 // TODO: handle distance restrictions for e.g. CivCentres 195 165 196 // Compute each tile's closeness to friendly structures: 166 197 167 var friendlyTiles = new Uint16Array( map.data.length);198 var friendlyTiles = new Uint16Array(passabilityMap.data.length); 168 199 169 200 gameState.getOwnEntities().forEach(function(ent) { 170 201 if (ent.hasClass("Structure")) … … 176 207 var pos = ent.position(); 177 208 var x = Math.round(pos[0] / cellSize); 178 209 var z = Math.round(pos[1] / cellSize); 179 self.addInfluence(friendlyTiles, map.width, map.height, x, z, infl);210 self.addInfluence(friendlyTiles, passabilityMap.width, passabilityMap.height, x, z, infl); 180 211 } 181 212 }); 182 213 … … 190 221 // var pos = ent.position(); 191 222 // var x = Math.round(pos[0] / cellSize); 192 223 // var z = Math.round(pos[1] / cellSize); 193 // self.subtractInfluence(friendlyTiles, map.width, map.height, x, z, infl);224 // self.subtractInfluence(friendlyTiles, passabilityMap.width, passabilityMap.height, x, z, infl); 194 225 // } 195 226 // }); 196 227 197 228 198 229 // Find target building's approximate obstruction radius, 199 230 // and expand by a bit to make sure we're not too close 200 var template = gameState.getTemplate(this.type);201 231 var radius = Math.ceil(template.obstructionRadius() / cellSize) + 1; 202 232 203 233 // Find the best non-obstructed tile 204 234 var bestIdx = 0; 205 235 var bestVal = -1; 206 for (var i = 0; i < map.data.length; ++i)236 for (var i = 0; i < passabilityMap.data.length; ++i) 207 237 { 208 238 if (obstructionTiles[i] > radius) 209 239 { … … 220 250 } 221 251 } 222 252 } 223 var x = ((bestIdx % map.width) + 0.5) * cellSize;224 var z = (Math.floor(bestIdx / map.width) + 0.5) * cellSize;253 var x = ((bestIdx % passabilityMap.width) + 0.5) * cellSize; 254 var z = (Math.floor(bestIdx / passabilityMap.width) + 0.5) * cellSize; 225 255 226 // Engine.DumpImage("tiles1.png", obstructionTiles, map.width, map.height, 32);227 // Engine.DumpImage("tiles2.png", friendlyTiles, map.width, map.height, 256);256 // Engine.DumpImage("tiles1.png", obstructionTiles, passabilityMap.width, passabilityMap.height, 32); 257 // Engine.DumpImage("tiles2.png", friendlyTiles, passabilityMap.width, passabilityMap.height, 256); 228 258 259 // TODO: special dock placement requirements 260 229 261 // Fixed angle to match fixed starting cam 230 262 var angle = 0.75*Math.PI; 231 263 -
binaries/data/mods/public/simulation/ai/jubot/plan-buildingecon.js
148 148 149 149 var cellSize = 4; // size of each tile 150 150 151 // First, find all tiles that are far enough away from obstructions:151 var template = gameState.getTemplate(this.type); 152 152 153 var map = gameState.getMap(); 154 153 // Find all tiles in valid territory that are far enough away from obstructions: 154 var passabilityMap = gameState.getPassabilityMap(); 155 var territoryMap = gameState.getTerritoryMap(); 156 const TERRITORY_PLAYER_MASK = 0x7F; 155 157 var obstructionMask = gameState.getPassabilityClassMask("foundationObstruction"); 156 // Only accept valid land tiles (we don't handle docks yet)157 obstructionMask |= gameState.getPassabilityClassMask("building-land");158 158 159 var obstructionTiles = new Uint16Array(map.data.length); 160 for (var i = 0; i < map.data.length; ++i) 161 obstructionTiles[i] = (map.data[i] & obstructionMask) ? 0 : 65535; 159 if (passabilityMap.data.length != territoryMap.data.length) 160 error("passability and territory data are not matched!"); 162 161 163 // Engine.DumpImage("tiles0.png", obstructionTiles, map.width, map.height, 64); 162 // See BuildRestrictions.js 163 switch(template.buildPlacementType()) 164 { 165 case "shore": 166 obstructionMask |= gameState.getPassabilityClassMask("building-shore"); 167 break; 168 case "land": 169 default: 170 obstructionMask |= gameState.getPassabilityClassMask("building-land"); 171 } 164 172 165 this.expandInfluences(obstructionTiles, map.width, map.height); 173 var playerID = gameState.getPlayerID(); 174 var buildOwn = template.hasBuildTerritory("own"); 175 var buildAlly = template.hasBuildTerritory("ally"); 176 var buildNeutral = template.hasBuildTerritory("neutral"); 177 var buildEnemy = template.hasBuildTerritory("enemy"); 166 178 179 var obstructionTiles = new Uint16Array(passabilityMap.data.length); 180 for (var i = 0; i < passabilityMap.data.length; ++i) 181 { 182 var tilePlayer = (territoryMap.data[i] & TERRITORY_PLAYER_MASK); 183 var validTerritory = ( 184 (!buildOwn || tilePlayer == playerID) && 185 (!buildAlly || gameState.isPlayerAlly(tilePlayer)) && 186 (!buildEnemy || gameState.isPlayerEnemy(tilePlayer)) && 187 (!buildNeutral || tilePlayer == 0) 188 ); 189 obstructionTiles[i] = ((passabilityMap.data[i] & obstructionMask) || !validTerritory) ? 0 : 65535; 190 } 191 192 // Engine.DumpImage("tiles0.png", obstructionTiles, passabilityMap.width, passabilityMap.height, 64); 193 194 this.expandInfluences(obstructionTiles, passabilityMap.width, passabilityMap.height); 195 196 // TODO: handle distance restrictions for e.g. CivCentres 197 167 198 // Compute each tile's closeness to friendly structures: 168 199 169 var friendlyTiles = new Uint16Array( map.data.length);200 var friendlyTiles = new Uint16Array(passabilityMap.data.length); 170 201 var infl = 100; 171 202 var pos = this.resourceposition; 172 203 var x = Math.round(pos[0] / cellSize); 173 204 var z = Math.round(pos[1] / cellSize); 174 self.addInfluence(friendlyTiles, map.width, map.height, x, z, infl);205 self.addInfluence(friendlyTiles, passabilityMap.width, passabilityMap.height, x, z, infl); 175 206 176 207 //Look at making sure we're a long way from enemy civ centres as well. 177 208 … … 184 215 // Find the best non-obstructed tile 185 216 var bestIdx = 0; 186 217 var bestVal = -1; 187 for (var i = 0; i < map.data.length; ++i)218 for (var i = 0; i < passabilityMap.data.length; ++i) 188 219 { 189 220 if (obstructionTiles[i] > radius) 190 221 { … … 201 232 } 202 233 } 203 234 } 204 var x = ((bestIdx % map.width) + 0.5) * cellSize;205 var z = (Math.floor(bestIdx / map.width) + 0.5) * cellSize;235 var x = ((bestIdx % passabilityMap.width) + 0.5) * cellSize; 236 var z = (Math.floor(bestIdx / passabilityMap.width) + 0.5) * cellSize; 206 237 207 // Engine.DumpImage("tiles1.png", obstructionTiles, map.width, map.height, 32);208 // Engine.DumpImage("tiles2.png", friendlyTiles, map.width, map.height, 256);238 // Engine.DumpImage("tiles1.png", obstructionTiles, passabilityMap.width, passabilityMap.height, 32); 239 // Engine.DumpImage("tiles2.png", friendlyTiles, passabilityMap.width, passabilityMap.height, 256); 209 240 210 241 // Fixed angle to match fixed starting cam 211 242 var angle = 0.75*Math.PI; … … 225 256 226 257 // First, find all tiles that are far enough away from obstructions: 227 258 228 var map = gameState.getMap();259 var passabilityMap = gameState.getPassabilityMap(); 229 260 230 261 var obstructionMask = gameState.getPassabilityClassMask("foundationObstruction"); 231 262 // Only accept valid land tiles (we don't handle docks yet) 232 263 obstructionMask |= gameState.getPassabilityClassMask("building-land"); 233 264 234 var obstructionTiles = new Uint16Array( map.data.length);235 for (var i = 0; i < map.data.length; ++i)236 obstructionTiles[i] = ( map.data[i] & obstructionMask) ? 0 : 65535;265 var obstructionTiles = new Uint16Array(passabilityMap.data.length); 266 for (var i = 0; i < passabilityMap.data.length; ++i) 267 obstructionTiles[i] = (passabilityMap.data[i] & obstructionMask) ? 0 : 65535; 237 268 238 // Engine.DumpImage("tiles0.png", obstructionTiles, map.width, map.height, 64);269 // Engine.DumpImage("tiles0.png", obstructionTiles, passabilityMap.width, passabilityMap.height, 64); 239 270 240 this.expandInfluences(obstructionTiles, map.width, map.height);271 this.expandInfluences(obstructionTiles, passabilityMap.width, passabilityMap.height); 241 272 242 273 // Compute each tile's closeness to friendly structures: 243 274 244 var friendlyTiles = new Uint16Array( map.data.length);275 var friendlyTiles = new Uint16Array(passabilityMap.data.length); 245 276 246 277 gameState.getOwnEntities().forEach(function(ent) { 247 278 if (ent.hasClass("Structure")) … … 253 284 var pos = ent.position(); 254 285 var x = Math.round(pos[0] / cellSize); 255 286 var z = Math.round(pos[1] / cellSize); 256 self.addInfluence(friendlyTiles, map.width, map.height, x, z, infl);287 self.addInfluence(friendlyTiles, passabilityMap.width, passabilityMap.height, x, z, infl); 257 288 } 258 289 }); 259 290 260 291 //Look at making sure we're a long way from enemy civ centres as well. 261 292 262 // var enemyTiles = new Uint16Array( map.data.length);293 // var enemyTiles = new Uint16Array(passabilityMap.data.length); 263 294 // 264 295 // var foetargets = gameState.entities.filter(function(ent) { 265 296 // return (ent.isEnemy()); … … 271 302 // var pos = ent.position(); 272 303 // var x = Math.round(pos[0] / cellSize); 273 304 // var z = Math.round(pos[1] / cellSize); 274 // self.addInfluence(enemyTiles, map.width, map.height, x, z, infl);305 // self.addInfluence(enemyTiles, passabilityMap.width, passabilityMap.height, x, z, infl); 275 306 // } 276 307 // }); 277 308 … … 284 315 // Find the best non-obstructed tile 285 316 var bestIdx = 0; 286 317 var bestVal = -1; 287 for (var i = 0; i < map.data.length; ++i)318 for (var i = 0; i < passabilityMap.data.length; ++i) 288 319 { 289 320 if (obstructionTiles[i] > radius) 290 321 { … … 301 332 } 302 333 } 303 334 } 304 var x = ((bestIdx % map.width) + 0.5) * cellSize;305 var z = (Math.floor(bestIdx / map.width) + 0.5) * cellSize;335 var x = ((bestIdx % passabilityMap.width) + 0.5) * cellSize; 336 var z = (Math.floor(bestIdx / passabilityMap.width) + 0.5) * cellSize; 306 337 307 // Engine.DumpImage("tiles1.png", obstructionTiles, map.width, map.height, 32);308 // Engine.DumpImage("tiles2.png", friendlyTiles, map.width, map.height, 256);338 // Engine.DumpImage("tiles1.png", obstructionTiles, passabilityMap.width, passabilityMap.height, 32); 339 // Engine.DumpImage("tiles2.png", friendlyTiles, passabilityMap.width, passabilityMap.height, 256); 309 340 310 341 // Randomise the angle a little, to look less artificial 311 342 //var angle = Math.PI + (Math.random()*2-1) * Math.PI/24; -
binaries/data/mods/public/simulation/ai/testbot/gamestate.js
38 38 return new Resources(this.playerData.resourceCounts); 39 39 }, 40 40 41 get Map: function()41 getPassabilityMap: function() 42 42 { 43 return this.ai. map;43 return this.ai.passabilityMap; 44 44 }, 45 45 46 46 getPassabilityClassMask: function(name) … … 50 50 return this.ai.passabilityClasses[name]; 51 51 }, 52 52 53 getTerritoryMap: function() 54 { 55 return this.ai.territoryMap; 56 }, 57 53 58 getOwnEntities: (function() 54 59 { 55 60 return new EntityCollection(this.ai, this.ai._ownEntities); … … 231 236 232 237 isEntityAlly: function(ent) 233 238 { 234 return ent && ent.owner !== undefined && this.playerData.isAlly[ent.owner];239 return (ent && ent.owner !== undefined && this.playerData.isAlly[ent.owner]); 235 240 }, 236 241 237 242 isEntityEnemy: function(ent) 238 243 { 239 return ent && ent.owner !== undefined && this.playerData.isEnemy[ent.owner];244 return (ent && ent.owner !== undefined && this.playerData.isEnemy[ent.owner]); 240 245 }, 241 246 242 247 isEntityOwn: function(ent) -
binaries/data/mods/public/simulation/ai/testbot/plan-building.js
124 124 125 125 var cellSize = 4; // size of each tile 126 126 127 // First, find all tiles that are far enough away from obstructions:127 var template = gameState.getTemplate(this.type); 128 128 129 var map = gameState.getMap(); 130 129 // Find all tiles in valid territory that are far enough away from obstructions: 130 var passabilityMap = gameState.getPassabilityMap(); 131 var territoryMap = gameState.getTerritoryMap(); 132 const TERRITORY_PLAYER_MASK = 0x7F; 131 133 var obstructionMask = gameState.getPassabilityClassMask("foundationObstruction"); 132 // Only accept valid land tiles (we don't handle docks yet)133 obstructionMask |= gameState.getPassabilityClassMask("building-land");134 134 135 var obstructionTiles = new Uint16Array(map.data.length); 136 for (var i = 0; i < map.data.length; ++i) 137 obstructionTiles[i] = (map.data[i] & obstructionMask) ? 0 : 65535; 135 if (passabilityMap.data.length != territoryMap.data.length) 136 error("passability and territory data are not matched!"); 138 137 139 // Engine.DumpImage("tiles0.png", obstructionTiles, map.width, map.height, 64); 138 // See BuildRestrictions.js 139 switch(template.buildPlacementType()) 140 { 141 case "shore": 142 obstructionMask |= gameState.getPassabilityClassMask("building-shore"); 143 break; 144 case "land": 145 default: 146 obstructionMask |= gameState.getPassabilityClassMask("building-land"); 147 } 140 148 141 this.expandInfluences(obstructionTiles, map.width, map.height); 149 var playerID = gameState.getPlayerID(); 150 var buildOwn = template.hasBuildTerritory("own"); 151 var buildAlly = template.hasBuildTerritory("ally"); 152 var buildNeutral = template.hasBuildTerritory("neutral"); 153 var buildEnemy = template.hasBuildTerritory("enemy"); 142 154 155 var obstructionTiles = new Uint16Array(passabilityMap.data.length); 156 for (var i = 0; i < passabilityMap.data.length; ++i) 157 { 158 var tilePlayer = (territoryMap.data[i] & TERRITORY_PLAYER_MASK); 159 var validTerritory = ( 160 (!buildOwn || tilePlayer == playerID) && 161 (!buildAlly || gameState.isPlayerAlly(tilePlayer)) && 162 (!buildEnemy || gameState.isPlayerEnemy(tilePlayer)) && 163 (!buildNeutral || tilePlayer == 0) 164 ); 165 obstructionTiles[i] = ((passabilityMap.data[i] & obstructionMask) || !validTerritory) ? 0 : 65535; 166 } 167 168 // Engine.DumpImage("obstruction"+playerID+".png", obstructionTiles, passabilityMap.width, passabilityMap.height, 64); 169 170 this.expandInfluences(obstructionTiles, passabilityMap.width, passabilityMap.height); 171 172 // TODO: handle distance restrictions for e.g. CivCentres 173 143 174 // Compute each tile's closeness to friendly structures: 144 175 145 var friendlyTiles = new Uint16Array( map.data.length);176 var friendlyTiles = new Uint16Array(passabilityMap.data.length); 146 177 147 178 gameState.getOwnEntities().forEach(function(ent) { 148 179 if (ent.hasClass("Structure")) … … 154 185 var pos = ent.position(); 155 186 var x = Math.round(pos[0] / cellSize); 156 187 var z = Math.round(pos[1] / cellSize); 157 self.addInfluence(friendlyTiles, map.width, map.height, x, z, infl);188 self.addInfluence(friendlyTiles, passabilityMap.width, passabilityMap.height, x, z, infl); 158 189 } 159 190 }); 160 191 161 192 // Find target building's approximate obstruction radius, 162 193 // and expand by a bit to make sure we're not too close 163 var template = gameState.getTemplate(this.type);164 194 var radius = Math.ceil(template.obstructionRadius() / cellSize) + 2; 165 195 166 196 // Find the best non-obstructed tile 167 197 var bestIdx = 0; 168 198 var bestVal = -1; 169 for (var i = 0; i < map.data.length; ++i)199 for (var i = 0; i < passabilityMap.data.length; ++i) 170 200 { 171 201 if (obstructionTiles[i] > radius) 172 202 { … … 178 208 } 179 209 } 180 210 } 181 var x = ((bestIdx % map.width) + 0.5) * cellSize;182 var z = (Math.floor(bestIdx / map.width) + 0.5) * cellSize;211 var x = ((bestIdx % passabilityMap.width) + 0.5) * cellSize; 212 var z = (Math.floor(bestIdx / passabilityMap.width) + 0.5) * cellSize; 183 213 184 // Engine.DumpImage(" tiles1.png", obstructionTiles, map.width, map.height, 32);185 // Engine.DumpImage(" tiles2.png", friendlyTiles, map.width, map.height, 256);214 // Engine.DumpImage("influences"+playerID+".png", obstructionTiles, passabilityMap.width, passabilityMap.height, 32); 215 // Engine.DumpImage("friendly"+playerID+".png", friendlyTiles, passabilityMap.width, passabilityMap.height, 256); 186 216 217 // TODO: special dock placement requirements 218 187 219 // Fixed angle to match fixed starting cam 188 220 var angle = 0.75*Math.PI; 189 221