 |
|
ahenobarb
|
|
Is there any SLIC function/method to determine if a city is on the same land mass as another object (city, unit, map square)?
|
|
|  |
 |
|  |
 |
|
Locutus
|
|
ACS CTP1/2 Manager & Civ4 Co-Manager
|
 |
Hengelo, The Netherlands
Nov 1999 time: 06:28
|
|
You can write a function yourself. I was working on this myself but other affairs have been keeping me busy.
The idea is simple: at the start of the game, cycle through the entire map from top-left to bottom-right, row-by-row, and assign a continent ID to every tile. For each tile, check if the tiles above it and left of it happen to be of the same type (where valid types are land and water) and if so, copy their ID. If not, assign a new, unique ID to this tile. Give land continents positive values as ID and 'water continents' negative ones, so that you can easily determine the difference between bodies of water and bodies of land (you may not have an immediate use for it now, but you might in the future).
If several neighbouring tiles are of the same type but have different IDs, then two parts of the same continent were apparently seperated by water (or land, if it's a body of water) and incorrectly got different IDs. So then cycle through the part of the map you already finished again and replace obsolete IDs with the correct ones (e.g. if continent 3 and continent 5 turn out to be the same continent, replace all 5s with 3s (or vice versa)).
The only problem with this code could be that it might add a lot of workload: you'll be doing a *lot* of calls to TerrainType and CreateLocation functions, which may slow down the game quite a bit. Of course, the good thing is that you only have to do this once per game (or rather, once per /reloadslic), after that you can store the 'continent map' and write your own functions to take advantage of it (in case of checking if 2 things are on the same continent, simply check the continent IDs of their tile).
I was actually thinking of combining this continent mapping with other mappings, such a threat mapping and desire mapping, but that's still in the brainstorm phase. It could make it more interesting though: 1 slowdown at the start of the game would give you a whole set of mappings to write AI code on for the rest of the game, without considerable delays (hopefully).
There are a couple of issues I was still working out, but those are details. I probably won't get around to writing this before the end of June, so if you're in a hurry feel free to implement this algorithm in SLIC yourself.
Here's some pseudocode to represent the above (can't guarantee this is functional, but it should be close and apart from replace_all_with_lowest() fairly easy to convert to actual SLIC). Note that you actually need a double loop to cycle through all map tiles (x and y).
code: current_ID = 1;
loop (maptiles) {
current_tile = <next tile>;
if (is_land(current_tile)) {
loop (neighbours) {
if (is_land(neighbour)) {
continent_ID[current_tile] = continent_ID(neighbour);
}
if (multiple_land_IDs_found) {
replace_all_with_lowest();
}
}
if (continent_ID[current_tile] = 0) {
current_ID++;
continent_ID[current_tile] = current_ID;
}
} else {
loop (neighbours) {
if (!is_land(neighbour)) {
continent_ID[current_tile] = continent_ID(neighbour);
}
if (multiple_land_IDs_found) {
replace_all_with_lowest();
}
}
if (continent_ID[current_tile] = 0) {
current_ID++;
continent_ID[current_tile] = -1*current_ID;
}
}
}
Last edited by Locutus on 28-05-2003 at 23:32
|
|
|  |
 |
|
Martin Gühmann
|
 |
Berlin, Germany
Mar 2001 time: 06:28
|
|
What about this stuff? 
code:
////////////////////////////////////////////////////////
//MG_ComputeContinents //
// //
//Parameter: location_t theLoc //
//A location //
//Parameter: int_t GetID //
//Determinzes what the function returns. //
// //
//Return Value: //
//Returns a continent ID if GetID == 1, that is unique//
//for each coherent mass of Land or of water. If the //
//continent is a land mass the return value is //
//positive, if it is a water mass the return value is //
//negative. //
//If GetID == 0 it returns the size of the continent //
//of that theLoc is part of. //
//if GetID == 2 it returns the number of continents on//
//the whole map. Else it returns the same value as //
//GetID == 1. //
// //
//Remarks: //
//MG_IsLand needs to be modified if you change the //
//number of terrains in the terrain.txt. //
////////////////////////////////////////////////////////
int_f MG_ComputeContinents(location_t theLoc, int_t GetID){
int_t IsInitialized;
int_t i;
int_t q;
int_t r;
int_t MGContinentIDs[];//GetMapWidth() * GetMapHeight()
int_t MGContinentSizes[];
int_t MGLastID;
location_t MGIDLoc;
location_t MGLoc1;
location_t MGLoc2;
int_t MGGetID;
MGGetID = GetID;
MGIDLoc = theLoc;
if(!IsInitialized){
IsInitialized = 1;
MGLastID = 1;
for(i = 0; i < GetMapWidth() * GetMapHeight(); i = i + 1){
MGContinentIDs[i] = 0;
}
location_t MGSameLocs[];
location_t MGDifferentLocs[];
int_t indexS;
int_t indexD;
indexS = 1;
indexD = 1;
MakeLocation(MGLoc1, 0, 0);
MGDifferentLocs[0] = MGLoc1;
q = 0;
r = 0;
while(q < MGDifferentLocs.#){
MGLoc1 = MGDifferentLocs[q];
q = q + 1;
if(MGContinentIDs[MGLoc1.x + MGLoc1.y * GetMapWidth()] == 0){
MGSameLocs[indexS] = MGLoc1;
indexS = indexS + 1;
while(MGSameLocs.# > r){
MGLoc1 = MGSameLocs[r];
r = r + 1;
if(MGContinentIDs[MGLoc1.x + MGLoc1.y * GetMapWidth()] == 0){
if(MG_IsLand(MGLoc1)){
MGContinentIDs[MGLoc1.x + MGLoc1.y * GetMapWidth()] = MGLastID;
}
else{
MGContinentIDs[MGLoc1.x + MGLoc1.y * GetMapWidth()] = -1 * MGLastID;
}
for(i = 0; i < 8; i = i + 1){
if(GetNeighbor(MGLoc1, i, MGLoc2)){
if(MGContinentIDs[MGLoc2.x + MGLoc2.y * GetMapWidth()] == 0){
// if(MG_IsLand(MGLoc2) == MG_IsLand(MGLoc1)){
if(MG_IsLand(MGLoc2) == (MGContinentIDs[MGLoc1.x + MGLoc1.y * GetMapWidth()] > 0)){
MGSameLocs[indexS] = MGLoc2;
indexS = indexS + 1;
}
else{
MGDifferentLocs[indexD] = MGLoc2;
indexD = indexD + 1;
}
}
}
}
}
}
MGLastID = MGLastID + 1;
}
}
MGContinentSizes[MGLastID - 1] = 0;
for(i = 0; i < MGContinentIDs.#; i = i + 1){
if(MGContinentIDs[i] > 0){
MGContinentSizes[MGContinentIDs[i]] = MGContinentSizes[MGContinentIDs[i]] + 1;
}
elseif(MGContinentIDs[i] < 0){
MGContinentSizes[-MGContinentIDs[i]] = MGContinentSizes[-MGContinentIDs[i]] - 1;
}
}
}
if(GetID == 1){
return MGContinentIDs[MGIDLoc.x + MGIDLoc.y * GetMapWidth()];
}
elseif(GetID == 0){
int_t MGCon;
MGCon = MGContinentIDs[MGIDLoc.x + MGIDLoc.y * GetMapWidth()];
if(MGCon > 0){
return MGContinentSizes[MGCon];
}
elseif(MGCon < 0){
return MGContinentSizes[-MGCon];
}
}
elseif(GetID == 2){
return MGContinentSizes.#;
}
else{
return MGContinentIDs[MGIDLoc.x + MGIDLoc.y * GetMapWidth()];
}
}
////////////////////////////////////////////////////////
//MG_AreOnSameContinent //
// //
//Parameter: location_t firstLoc //
//A location //
//Parameter: location_t secondLoc //
//A location //
// //
//Return Value: //
//Returns 1 if both locations are on the same //
//continent, otherwise it returns 0. //
// //
//Remarks: //
//MG_IsLand needs to be modified if you change the //
//number of terrains in the terrain.txt. //
////////////////////////////////////////////////////////
int_f MG_AreOnSameContinent(location_t firstLoc, location_t secondLoc){
location_t MGFirstLoc;
location_t MGSecondLoc;
MGFirstLoc = firstLoc;
MGSecondLoc = secondLoc;
return (MG_ComputeContinents(MGFirstLoc, 1) == MG_ComputeContinents(MGSecondLoc, 1));
}
////////////////////////////////////////////////////////
//MG_GetContinentID //
// //
//Parameter: location_t theLoc //
// //
//Return Value: //
//The continent ID of theLoc's continent. //
// //
//Remarks: //
//MG_IsLand needs to be modified if you change the //
//number of terrains in the terrain.txt. //
////////////////////////////////////////////////////////
int_f MG_GetContinentID(location_t theLoc){
location_t MGLoc;
MGLoc = theLoc;
return MG_ComputeContinents(MGLoc, 1);
}
////////////////////////////////////////////////////////
//MG_GetContinentSize //
// //
//Parameter: location_t theLoc //
// //
//Return Value: //
//The continent size of theLoc's continent. //
// //
//Remarks: //
//MG_IsLand needs to be modified if you change the //
//number of terrains in the terrain.txt. //
////////////////////////////////////////////////////////
int_f MG_GetContinentSize(location_t theLoc){
location_t MGLoc;
MGLoc = theLoc;
return MG_ComputeContinents(MGLoc, 0);
}
////////////////////////////////////////////////////////
//MG_GetNumberOfContinents //
// //
//Parameter: none //
// //
//Return Value: //
//The number of continents on the map. //
// //
//Remarks: //
//MG_IsLand needs to be modified if you change the //
//number of terrains in the terrain.txt. //
////////////////////////////////////////////////////////
int_f MG_GetNumberOfContinents(){
location_t MGLoc;
MakeLocation(MGLoc, 0, 0);
return MG_ComputeContinents(MGLoc, 2);
}
-Martin
|
|
|  |
 |
|  |
 |
|  |
All times are GMT. The time now is 05:28. Apolyton Time is 00:28. |
top of page
|
| archivepost |
|
Forum Rules:
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
|
HTML code is ON
vB code is ON
Smilies are ON
[IMG] code is ON
|
|
|
|
|
|