continents API
continents API
@Per - would it be possible to expose continent data via the JS API?
Rough initial pondering...
enumContinents()
Would return an array of continent objects.
A continent object (I've no idea what the C++ data structure looks like so just guessing here) would contain:
.id = unique id for the continent
.tiles = [...] // array of map tiles
Map tile object
.x and .y = coords of the tile
.z = altitude of the tile from sea level (so a -ve number of below sea level)
.terrain = type of terrain on tile
.joins = [...] // array of which other continents the tile connects to, or null (ie. no array) if it doesn't connect
Use cases
This would allow AI developers to build defences at continent intersections.
It will also allow AIs to adapt to the map more easily - eg. by knowing that a lot of the map is covered in water continents, the AI can focus more on hover propulsion strategies.
It will allow the AI to detect unreachable continents that have sufficient tiles to build some defences on (eg. sesnor and some arty) and then send trucks via transports to build them.
It will enable the AI to find alternate routes, which might be much longer, to get to an enemy base and choose to use them if the normal routes are proving too risky.
It will allow AIs to better place defences / sensors - eg. AA sites on top of hills where they have good coverage of airspace, and missile sites behind hills where enemy tanks have trouble shooting at them.
Rough initial pondering...
enumContinents()
Would return an array of continent objects.
A continent object (I've no idea what the C++ data structure looks like so just guessing here) would contain:
.id = unique id for the continent
.tiles = [...] // array of map tiles
Map tile object
.x and .y = coords of the tile
.z = altitude of the tile from sea level (so a -ve number of below sea level)
.terrain = type of terrain on tile
.joins = [...] // array of which other continents the tile connects to, or null (ie. no array) if it doesn't connect
Use cases
This would allow AI developers to build defences at continent intersections.
It will also allow AIs to adapt to the map more easily - eg. by knowing that a lot of the map is covered in water continents, the AI can focus more on hover propulsion strategies.
It will allow the AI to detect unreachable continents that have sufficient tiles to build some defences on (eg. sesnor and some arty) and then send trucks via transports to build them.
It will enable the AI to find alternate routes, which might be much longer, to get to an enemy base and choose to use them if the normal routes are proving too risky.
It will allow AIs to better place defences / sensors - eg. AA sites on top of hills where they have good coverage of airspace, and missile sites behind hills where enemy tanks have trouble shooting at them.
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO
-- https://warzone.atlassian.net/wiki/display/GO
Re: continents API
Or... it could just be an enumTiles([continent]) function and that function would return an array of all map tiles:
.x, .y, .z = obvious
.continent = id of continent the tile is on or null if not applicable
.isWater = is this tile water? true/false
.isCliff = is this tile a cliff? true/false
At the start of a game the AI could then build it's own data model from that, deciding where choke points are, etc.
For example, NoQ's clustering code could be modified to identify clusters of tiles that join continents or ramps etc. And then the AI could build defences accordingly and so on.
.x, .y, .z = obvious
.continent = id of continent the tile is on or null if not applicable
.isWater = is this tile water? true/false
.isCliff = is this tile a cliff? true/false
At the start of a game the AI could then build it's own data model from that, deciding where choke points are, etc.
For example, NoQ's clustering code could be modified to identify clusters of tiles that join continents or ramps etc. And then the AI could build defences accordingly and so on.
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO
-- https://warzone.atlassian.net/wiki/display/GO
Re: continents API
My intuition is that if you start iterating over individual tiles like that, you've gone off the deep end and won't be able to run your AI without creating significant stutter no matter how you slice and dice it. But I haven't tested this.
It seems to be operating on the wrong level of abstraction.
It seems to be operating on the wrong level of abstraction.
Re: continents API
Well, AIs are going to need some way of knowing where choke points are, and where the high ground is.
In terms of iterating over the array, it's a one-time task at the very start of the game. It might take a couple seconds longer before the game actually starts (if I'm doing lots of crazy stuff in that iteration). After that, there is zero lag for the end-user.
The enumTiles() in my second post above seems the simplest approach, and would give JS scripter everything they need to do some pretty neat stuff.
Also, in terms of abstraction, whatever happens AI scripters are eventually going to have to find some way to get that data whether it's provided by the JS API directly or not... For example, if there isn't an enumTiles() that provides the data, then the only choice for scripters will be something like this:
Obviously, there would be all sorts of additional cruft in that code, because I'd have to wait for game data to sync between players, thus need lots of timers, etc. The user would see a herd of droids all over the map for a split second, then lots of explosions as they all self-destruct.
enumTiles() seems a much better solution IMHO. If it provided a nested array like I'm creating in the code above, it could just expose that array to the scripting engines = all scripts instantly have the array with the info they need from the start of the game. Then they can just look up tile data using:
tileAtXY = tiles[x][y];
This way, you can completely ditch the enumTiles() - just have a tiles global that's a nested array containing tile objects.
Scripters can happily add their own properties to the contained tile objects, it doesn't matter that they won't be persisted because they'll be created whenever eventStartLevel() gets triggered.
In terms of iterating over the array, it's a one-time task at the very start of the game. It might take a couple seconds longer before the game actually starts (if I'm doing lots of crazy stuff in that iteration). After that, there is zero lag for the end-user.
The enumTiles() in my second post above seems the simplest approach, and would give JS scripter everything they need to do some pretty neat stuff.
Also, in terms of abstraction, whatever happens AI scripters are eventually going to have to find some way to get that data whether it's provided by the JS API directly or not... For example, if there isn't an enumTiles() that provides the data, then the only choice for scripters will be something like this:
Code: Select all
// over-simplified pseudo-code
var tiles;
function placeTestDroid(land,x,y) {
// can't remember the id's for body, propulsion off top of my head so just imagine <whatever> is correct value heh
addDroid(me,x,y,"testDroid",<body>,(land) ? <wheels> : <hover>, ...);
return enumDroid(me).pop(); // this prolly won't work because i need to wait for game sync
}
function eventStartLevel() {
// initialise my tiles array
tiles = new Array(mapWidth);
// these droids work out where I can get to
var landDroid = enumDroid(me).pop();
var hoverDroid = placeTestDroid(false,landDroid.x,landDroid.y);
// now go through each tile
for (var w = 0; w<mapWidth; w++) {
tiles[w] = new Array(mapHeight);
for (var h = 0; h<mapHeight; h++) {
var tile = {x:w, y:h, land:false, water:false};
if (droidCanReach(landDroid,(w*128)+1,(h*128)+1)) { // it's a land tile that I can reach
tile.land=true;
tile.z = placeTestDroid(true,(w*128)+1,(h*128)+1)).z;
} else if (droidCanReach(hoverDroid,(w*128)+1,(h*128)+1)) { // it's a water tile that I can reach
tile.water=true;
tile.z = placeTestDroid(true,(w*128)+1,(h*128)+1)).z;
}
tiles[w][h] = tile;
}
}
var droids = enumDroids(me);
for (var d = 0; d<droids.length; d++) {
if (droids[d].name.indexOf("test")>-1) {
orderDroid(droids[d],12); // self destruct
}
}
}
enumTiles() seems a much better solution IMHO. If it provided a nested array like I'm creating in the code above, it could just expose that array to the scripting engines = all scripts instantly have the array with the info they need from the start of the game. Then they can just look up tile data using:
tileAtXY = tiles[x][y];
This way, you can completely ditch the enumTiles() - just have a tiles global that's a nested array containing tile objects.
Scripters can happily add their own properties to the contained tile objects, it doesn't matter that they won't be persisted because they'll be created whenever eventStartLevel() gets triggered.
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO
-- https://warzone.atlassian.net/wiki/display/GO
Re: continents API
I was told the map creators do this with gatewaysaubergine wrote:Well, AIs are going to need some way of knowing where choke points are, and where the high ground is.
In terms of iterating over the array, it's a one-time task at the very start of the game. It might take a couple seconds longer before the game actually starts (if I'm doing lots of crazy stuff in that iteration). After that, there is zero lag for the end-user.
The enumTiles() in my second post above seems the simplest approach, and would give JS scripter everything they need to do some pretty neat stuff.
Also, in terms of abstraction, whatever happens AI scripters are eventually going to have to find some way to get that data whether it's provided by the JS API directly or not... For example, if there isn't an enumTiles() that provides the data, then the only choice for scripters will be something like this:
Obviously, there would be all sorts of additional cruft in that code, because I'd have to wait for game data to sync between players, thus need lots of timers, etc. The user would see a herd of droids all over the map for a split second, then lots of explosions as they all self-destruct.Code: Select all
// over-simplified pseudo-code var tiles; function placeTestDroid(land,x,y) { // can't remember the id's for body, propulsion off top of my head so just imagine <whatever> is correct value heh addDroid(me,x,y,"testDroid",<body>,(land) ? <wheels> : <hover>, ...); return enumDroid(me).pop(); // this prolly won't work because i need to wait for game sync } function eventStartLevel() { // initialise my tiles array tiles = new Array(mapWidth); // these droids work out where I can get to var landDroid = enumDroid(me).pop(); var hoverDroid = placeTestDroid(false,landDroid.x,landDroid.y); // now go through each tile for (var w = 0; w<mapWidth; w++) { tiles[w] = new Array(mapHeight); for (var h = 0; h<mapHeight; h++) { var tile = {x:w, y:h, land:false, water:false}; if (droidCanReach(landDroid,(w*128)+1,(h*128)+1)) { // it's a land tile that I can reach tile.land=true; tile.z = placeTestDroid(true,(w*128)+1,(h*128)+1)).z; } else if (droidCanReach(hoverDroid,(w*128)+1,(h*128)+1)) { // it's a water tile that I can reach tile.water=true; tile.z = placeTestDroid(true,(w*128)+1,(h*128)+1)).z; } tiles[w][h] = tile; } } var droids = enumDroids(me); for (var d = 0; d<droids.length; d++) { if (droids[d].name.indexOf("test")>-1) { orderDroid(droids[d],12); // self destruct } } }
enumTiles() seems a much better solution IMHO. If it provided a nested array like I'm creating in the code above, it could just expose that array to the scripting engines = all scripts instantly have the array with the info they need from the start of the game. Then they can just look up tile data using:
tileAtXY = tiles[x][y];
This way, you can completely ditch the enumTiles() - just have a tiles global that's a nested array containing tile objects.
Scripters can happily add their own properties to the contained tile objects, it doesn't matter that they won't be persisted because they'll be created whenever eventStartLevel() gets triggered.
Re: continents API
So, imagine yourself as the AI for a moment. The only thing you know is where the gateways are near your base ..if the map maker remembered to add some gateways to their map. The rest of the map is invisible to you: You can't see rivers or lakes, mountains or valleys, cliffs or plains. Now, what's the best route to the enemy base? Where should you place your sensors and artillery? When your droids come under enemy fire, where do they retreat to? Where do you set an ambush point?
That's why AIs need data about tiles/continents. It will take some time for scripters to work out how to best use the data, but that's never going to happen if the data is not available in the first place.
That's why AIs need data about tiles/continents. It will take some time for scripters to work out how to best use the data, but that's never going to happen if the data is not available in the first place.
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO
-- https://warzone.atlassian.net/wiki/display/GO
Re: continents API
I think the best way is for map makers (and/or script makers, for existing maps) to annotate their maps better, with a greater variety of zone types than just gateways. Another idea I've been toying with is to add separate scriptlets to each map to calculate best positions and approaches for various placements, such as artillery, initial defense, etc, based on team setups and base settings and so on.
Also lacking is a way to understand and manipulate a droid's path better. I've been thinking of how to iterate over a droid's path, and check the calculated danger and threat information over its span.
Also lacking is a way to understand and manipulate a droid's path better. I've been thinking of how to iterate over a droid's path, and check the calculated danger and threat information over its span.
Re: continents API
What i'd like to have is, at least, an ability to query individual tiles (something like tileInfo(x,y), that will return a single object containing information about tile at (x,y), like .z, .continent, .isWater, .isCliff, isOccupied, isSafe, whatever) and/or a check if two points belong to one continent (onOneContinent(x1,y1,x2,y2), or, even better, lengthOfPath(x1,y1,x2,y2) as a path-aware version of distBetweenTwoPoints(x1,y1,x2,y2,[ignoreSeas]), returning Infinity for points that can't be connected) Even if i'm not planning to query all tiles at once, this could still be useful.
That could be really cool (:I've been thinking of how to iterate over a droid's path, and check the calculated danger and threat information over its span.
Maps | Tower Defense | NullBot AI | More NullBot AI | Scavs | More Scavs | Tilesets | Walkthrough | JSCam
- Rman Virgil
- Professional

- Posts: 3812
- Joined: 25 Sep 2006, 01:06
- Location: USA
Re: continents API
Per wrote:I think the best way is for map makers (and/or script makers, for existing maps) to annotate their maps better, with a greater variety of zone types than just gateways.......
Navigation Mesh... sounds a bit like & a related thought:
viewtopic.php?f=33&t=5574&p=95584#p95584
.
.
Impact = C x (R + E + A + T + E)
Contrast
Reach
Exposure
Articulation
Trust
Echo
.
Impact = C x (R + E + A + T + E)
Contrast
Reach
Exposure
Articulation
Trust
Echo
.
Re: continents API
@Per: Relying on map makers to provide info on their maps for AIs seems like a very strange way to go about things. How many map makers have written an AI and thus know what sort of info the AI needs? NoQ and ... uhm, that's it? What might seem perfectly logical to a map maker looking at things with human eyes might be completely bonkers from the perspective of an AI script. And what if map makers make a mistake or just forget to add the data in? It seems like a very hit and miss approach to me, and certainly not anything an AI could rely on too much.
Having a global called "tiles" that's a 2D array of tile objects would be perfect for scripters and provide all the info we need. All that data is surely available in the game engine and will be there regardless of who made the map or what the map contains. And as it's just pumped in to the JS env once at game init, I don't see how it's going to cause any notable performance issues - most AIs will just look up tiles in the array on an as-needed basis (tileXY = tiles[x][y] is very fast and simple way to get at the relevant tile object).
If AIs want to do additional processing on that array, and that causes stutter, then really its up to the AI developer to fix that unless you're planning to write the AIs for them? The tiles array might be used in unexpected ways, or just plain wrong ways, and indeed I imagine lots of early attempts to make use of it will fail horribly as scripters experiment with ways to use it, but over time it will greatly widen the opportunities for innovation in scripts and provide clear use cases for future JS API functions.
Having a global called "tiles" that's a 2D array of tile objects would be perfect for scripters and provide all the info we need. All that data is surely available in the game engine and will be there regardless of who made the map or what the map contains. And as it's just pumped in to the JS env once at game init, I don't see how it's going to cause any notable performance issues - most AIs will just look up tiles in the array on an as-needed basis (tileXY = tiles[x][y] is very fast and simple way to get at the relevant tile object).
If AIs want to do additional processing on that array, and that causes stutter, then really its up to the AI developer to fix that unless you're planning to write the AIs for them? The tiles array might be used in unexpected ways, or just plain wrong ways, and indeed I imagine lots of early attempts to make use of it will fail horribly as scripters experiment with ways to use it, but over time it will greatly widen the opportunities for innovation in scripts and provide clear use cases for future JS API functions.
"Dedicated to discovering Warzone artefacts, and sharing them freely for the benefit of the community."
-- https://warzone.atlassian.net/wiki/display/GO
-- https://warzone.atlassian.net/wiki/display/GO


