@@ -309,9 +309,8 @@ Dictionary TerrainGen::generate(
309309 (Cardinal Neighbors Only)
310310
311311 *****************************************************/
312- int neighborRadius = 1 ; // 3x3 neighborhood (cardinal only)
313312 int threshold = 2 ; // Minimum matching neighbors to preserve center
314- int iterations = 1 ; // Number of CA generations to apply
313+ int iterations = 2 ; // Number of CA generations to apply
315314
316315 vector<vector<int >> curr = heightMap;
317316 vector<vector<int >> next = heightMap;
@@ -321,6 +320,24 @@ Dictionary TerrainGen::generate(
321320 { 0 , -1 }, { 0 , 1 }, { -1 , 0 }, { 1 , 0 }
322321 };
323322
323+ // Height Map is a double grid
324+ // +----+----+----+----+
325+ // | z1 | z2 | y1 | y2 |
326+ // +----+----+----+----+
327+ // | z3 | z4 | y3 | y5 |
328+ // +----+----+----+----+
329+ // | x1 | x2 | w1 | w2 |
330+ // +----+----+----+----+
331+ // | x3 | x4 | w3 | w4 |
332+ // +----+----+----+----+
333+ //
334+ // Eventually the map will be reduced to :
335+ // +----+----+
336+ // | z | y |
337+ // +----+----+
338+ // | x | w |
339+ // +----+----+
340+
324341 for (int it = 0 ; it < iterations; ++it) {
325342 bool anyChanged = false ;
326343
@@ -395,80 +412,84 @@ Dictionary TerrainGen::generate(
395412
396413 *****************************************************/
397414
415+ int caCcount = 2 ;
416+
398417 if (waterRemoval >= 10 .0f ) {
399418 // Clamp percentage
400419 if (waterRemoval > 100 .0f )
401420 waterRemoval = 100 .0f ;
402421 if (waterRemoval < 0 .0f )
403422 waterRemoval = 0 .0f ;
404423
405- vector<vector<bool >> visited (heightx2, vector<bool >(widthx2, false ));
424+ for (int iter = 0 ; iter < caCcount; iter++) {
425+ vector<vector<bool >> visited (heightx2, vector<bool >(widthx2, false ));
406426
407- for (int y = 0 ; y < heightx2; y++) {
408- for (int x = 0 ; x < widthx2; x++) {
409- if (heightMap[y][x] != 0 || visited[y][x])
410- continue ;
427+ for (int y = 0 ; y < heightx2; y++) {
428+ for (int x = 0 ; x < widthx2; x++) {
429+ if (heightMap[y][x] != 0 || visited[y][x])
430+ continue ;
411431
412- // Manual stack flood fill
413- vector<pair<int , int >> stack;
414- vector<pair<int , int >> region;
415- stack.push_back (make_pair (x, y));
416- visited[y][x] = true ;
417-
418- while (!stack.empty ()) {
419- pair<int , int > current = stack.back ();
420- stack.pop_back ();
421- int cx = current.first ;
422- int cy = current.second ;
423- region.push_back (current);
424-
425- for (int d = 0 ; d < 4 ; d++) {
426- int nx = cx + dx[d];
427- int ny = cy + dy[d];
428- if (nx < 0 || ny < 0 || nx >= widthx2 || ny >= heightx2)
429- continue ;
430- if (visited[ny][nx])
431- continue ;
432- if (heightMap[ny][nx] != 0 )
433- continue ;
434- visited[ny][nx] = true ;
435- stack.push_back (make_pair (nx, ny));
432+ // Manual stack flood fill
433+ vector<pair<int , int >> stack;
434+ vector<pair<int , int >> region;
435+ stack.push_back (make_pair (x, y));
436+ visited[y][x] = true ;
437+
438+ while (!stack.empty ()) {
439+ pair<int , int > current = stack.back ();
440+ stack.pop_back ();
441+ int cx = current.first ;
442+ int cy = current.second ;
443+ region.push_back (current);
444+
445+ for (int d = 0 ; d < 4 ; d++) {
446+ int nx = cx + dx[d];
447+ int ny = cy + dy[d];
448+ if (nx < 0 || ny < 0 || nx >= widthx2 || ny >= heightx2)
449+ continue ;
450+ if (visited[ny][nx])
451+ continue ;
452+ if (heightMap[ny][nx] != 0 )
453+ continue ;
454+ visited[ny][nx] = true ;
455+ stack.push_back (make_pair (nx, ny));
456+ }
436457 }
437- }
438458
439- // Determine how many cells to flip
440- int regionSize = region.size ();
441- int toFlip = (int )(regionSize * (waterRemoval / 100 .0f ));
442- if (toFlip <= 0 )
443- continue ;
459+ // Determine how many cells to flip
460+ int regionSize = region.size ();
461+ int toFlip = (int )(regionSize * (waterRemoval / 100 .0f ));
462+ if (toFlip <= 0 )
463+ continue ;
444464
445- // Rank by proximity to edge
446- vector<pair<int , pair<int , int >>> candidates;
447- for (int i = 0 ; i < regionSize; i++) {
448- int rx = region[i].first ;
449- int ry = region[i].second ;
450- int distX = min (rx, widthx2 - 1 - rx);
451- int distY = min (ry, heightx2 - 1 - ry);
452- int edgeDist = min (distX, distY);
453- candidates.push_back (make_pair (edgeDist, region[i]));
454- }
465+ // Rank by proximity to edge
466+ vector<pair<int , pair<int , int >>> candidates;
467+ for (int i = 0 ; i < regionSize; i++) {
468+ int rx = region[i].first ;
469+ int ry = region[i].second ;
470+ int distX = min (rx, widthx2 - 1 - rx);
471+ int distY = min (ry, heightx2 - 1 - ry);
472+ int edgeDist = min (distX, distY);
473+ candidates.push_back (make_pair (edgeDist, region[i]));
474+ }
455475
456- // Bubble sort
457- for (int i = 0 ; i < (int )candidates.size (); i++) {
458- for (int j = i + 1 ; j < (int )candidates.size (); j++) {
459- if (candidates[j].first < candidates[i].first ) {
460- pair<int , pair<int , int >> temp = candidates[i];
461- candidates[i] = candidates[j];
462- candidates[j] = temp;
476+ // Bubble sort
477+ for (int i = 0 ; i < (int )candidates.size (); i++) {
478+ for (int j = i + 1 ; j < (int )candidates.size (); j++) {
479+ if (candidates[j].first < candidates[i].first ) {
480+ pair<int , pair<int , int >> temp = candidates[i];
481+ candidates[i] = candidates[j];
482+ candidates[j] = temp;
483+ }
463484 }
464485 }
465- }
466486
467- // Flip top N water cells to land
468- for (int i = 0 ; i < toFlip && i < (int )candidates.size (); i++) {
469- int fx = candidates[i].second .first ;
470- int fy = candidates[i].second .second ;
471- heightMap[fy][fx] = 1 ;
487+ // Flip top N water cells to land
488+ for (int i = 0 ; i < toFlip && i < (int )candidates.size (); i++) {
489+ int fx = candidates[i].second .first ;
490+ int fy = candidates[i].second .second ;
491+ heightMap[fy][fx] = 1 ;
492+ }
472493 }
473494 }
474495 }
@@ -798,7 +819,7 @@ Dictionary TerrainGen::generate(
798819 // | n3 | n4 | | 1 | 1 | | 2 | 2 |
799820 // +----+----+ +---+---+ +---+---+
800821 //
801- if (n1 == n2 && n2 == n3 && n3 == n4 && n1 > 0 && n2 > 0 && n3 > 0 && n4 > 0 ) {
822+ if (n1 == n2 && n2 == n3 && n3 == n4 && n1 == n4 && n1 > 0 && n2 > 0 && n3 > 0 && n4 > 0 ) {
802823 tileMap[x][y] = GROUND;
803824 }
804825
@@ -1072,7 +1093,9 @@ Dictionary TerrainGen::generate(
10721093 //
10731094 //
10741095 //
1075- // Phase 2 : Determine the Tile's Rotation
1096+ // Phase 2 : Corrections & Rotations
1097+ //
1098+ // Description: Determine the Tile's Rotation and correct tiles
10761099 //
10771100 // Models: Ramp Corner's/ Cliff Corner's / Water Corner's start with HIGH at (−Z, +X)
10781101 // i.e., NE corner.
@@ -1087,11 +1110,12 @@ Dictionary TerrainGen::generate(
10871110 // | m6 | m7 | m8 |
10881111 // +----+----+----+
10891112 //
1113+
10901114 for (int x = 0 ; x < width; x++) {
10911115 for (int y = 0 ; y < height; y++) {
10921116 int c_height = elevationMap[x][y];
10931117 int tile_id = myGridMap->get_cell_item (Vector3i (x, c_height, y));
1094- if (tile_id == -1 || tile_id == WATER || tile_id == GROUND)
1118+ if (tile_id == -1 || tile_id == GROUND)
10951119 continue ;
10961120
10971121 auto in_bounds = [&](int gx, int gy) {
@@ -1107,6 +1131,10 @@ Dictionary TerrainGen::generate(
11071131 return myGridMap->get_cell_item (Vector3i (gx, h, gy));
11081132 };
11091133
1134+ auto isWaterLike = [&](TileType t) {
1135+ return t == WATER || t == WATER_EDGE || t == WATER_CORNER || t == WATER_CORNER_INNER;
1136+ };
1137+
11101138 int rotation_val = NORTH; // default face −Z
11111139
11121140 //
@@ -1151,6 +1179,31 @@ Dictionary TerrainGen::generate(
11511179 int nwHeight = safe_height (x - 1 , y + 1 , c_height);
11521180 int nwTile = safe_tile_at (x - 1 , y + 1 ); // m1
11531181
1182+ //
1183+ // Water Tiles
1184+ //
1185+
1186+ bool nWater = isWaterLike (static_cast <TileType>(nTile));
1187+ bool sWater = isWaterLike (static_cast <TileType>(sTile ));
1188+ bool eWater = isWaterLike (static_cast <TileType>(eTile));
1189+ bool wWater = isWaterLike (static_cast <TileType>(wTile));
1190+ bool neWater = isWaterLike (static_cast <TileType>(neTile));
1191+ bool nwWater = isWaterLike (static_cast <TileType>(nwTile));
1192+ bool seWater = isWaterLike (static_cast <TileType>(seTile));
1193+ bool swWater = isWaterLike (static_cast <TileType>(swTile));
1194+
1195+ if (isWaterLike (static_cast <TileType>(tile_id))) {
1196+ int waterNeighbors =
1197+ nWater + sWater + eWater + wWater +
1198+ neWater + nwWater + seWater + swWater;
1199+
1200+ // Fully surrounded by water
1201+ if (waterNeighbors == 8 ) {
1202+ tile_id = WATER;
1203+ rotation_val = 0 ;
1204+ }
1205+ }
1206+
11541207 if (tile_id == RAMP || tile_id == CLIFF || tile_id == WATER_EDGE) {
11551208 // +----+----+----+
11561209 // | m1 | m2 | m3 |
0 commit comments