<URL: http://bugs.freeciv.org/Ticket/Display.html?id=15947 >

Better fix this if 2.1 is ever to be released I suppose...

The problem was in the function below, in 2.08 there was no T_UNKNOWN 
check. I assume every tile is T_UNKNOWN when the map generator is 
generating a map causing it to make no rivers.

--------common/map.c----------
bool is_water_adjacent_to_tile(const struct tile *ptile)
{
   if (ptile->terrain != T_UNKNOWN
   ...
-----------------------------

So I fixed fill_island_rivers(..) as best I could with my rusty 
programming skills.

### Fixes / Removals
* if ((i * 3 > k * 2   --- don't know what that was trying to do, seems 
   to be cut and pasted from the terrain placing code.
* not_placed(ptile)  --- doesn't seem to do anything, another copy from 
   terrain placing code, there is already a check if the tile belongs to 
the current island's isleindex.
* Didn't have a check if the tile it's evaluating already has a river. 
This could cause it place a river twice in one tile, reducing the amount 
by around 30% on average. Possibly all the way down to 1 tile worst case 
when it placed a mouth that had nowhere to grow, given the 0.5% chance 
of creating a second river.
*2.08 hex topology island river generation used to create river loops.

### Improvements
* River mouths can now only be surrounded by 2 ocean tiles, only 1 of 
which is cardinal. This gets rid of the hideous corner / peninsular 2 or 
   3 mouthed river outlets. Makes it look more natural too, especially 
when they start from an inlet or landlocked lake. Also ensures ~90% of 
the time there are 2 directions the river can go from the mouth, pushing 
the river further inland and usually making it more than 1 tile long.

* Increased the amount of river tiles generated by 75% for the island 
generator. I figure rivers will be more important now the capital gets 
corruption and a 75% production bonus under despotism. High production 
tiles that still produce trade are best in this situation.
Also in gen1 most inland tiles are mountains / hills, it's a lot harder 
to irrigate inland gen3 islands with random terrain placement.
I really wish rivers were still a pregame option instead of having to 
turn the world into swamp and jungle.

* Increased the rivers aversion to ocean, and reduced it's windiness and 
tendency to fork. This makes it go further inland and windy forking 
rivers ain't as useful for unit movement / irrigation.

* Changed all the cardinal / percent - TRUE's & FALSE's into constants 
so the code is more readable. Just picked the m_ prefix out of thin air 
for map.h .  Should I of used #DEFINES or just commented every line like 
the generator1 river function instead ?.

* Split some checks into helper functions making the code more readable.

### Problems
* Doesn't generate proper rivers for the hex2t tileset. Although that 
tileset doesn't create proper coastlines either and uses a different hex 
layout to isophex so I'll assume my code isn't at fault.

--- Yautja

Index: common/map.h
===================================================================
--- common/map.h	(revision 12345)
+++ common/map.h	(working copy)
@@ -80,6 +80,11 @@
   TF_HEX = 8
 };
 
+static const bool m_adjacent = FALSE;
+static const bool m_cardinal = TRUE;
+static const bool m_number = FALSE;
+static const bool m_percent = TRUE;
+
 #define MAP_IS_ISOMETRIC (topo_has_flag(TF_ISO) || topo_has_flag(TF_HEX))
 
 #define CURRENT_TOPOLOGY (map.topology_id)
Index: server/generator/mapgen.c
===================================================================
--- server/generator/mapgen.c	(revision 12345)
+++ server/generator/mapgen.c	(working copy)
@@ -1470,6 +1470,35 @@
 }
 
 /**************************************************************************
+  returns true if ptile is suitable for a river mouth
+**************************************************************************/
+static bool island_river_mouth_suitability( struct tile *ptile )
+{
+  return(count_ocean_near_tile(ptile, m_cardinal, m_number) == 1
+	 && count_ocean_near_tile(ptile, m_adjacent, m_percent) <= 35
+	 && count_special_near_tile(ptile,
+				    m_adjacent, m_number, S_RIVER) == 0);
+}
+
+
+/**************************************************************************
+  returns true if river cardinal and tile is suitable for extending it
+**************************************************************************/
+static bool island_river_suitability( struct tile *ptile )
+{
+  return((count_special_near_tile(ptile, m_cardinal, m_number, S_RIVER) == 1
+	  && count_ocean_near_tile(ptile, m_cardinal, m_number) == 0)
+	 && count_ocean_near_tile(ptile, m_adjacent, m_percent) < 20
+	 && count_special_near_tile(ptile,
+				    m_adjacent, m_percent, S_RIVER) < 35
+	 /* helps with straightness, ocean avoidance and reduces forking */
+	 && ((count_special_near_tile(ptile,
+				      m_adjacent, m_percent, S_RIVER) +
+	      count_ocean_near_tile(ptile, m_adjacent, m_percent) * 2)
+	     < myrand(25) + 25));
+}
+
+/**************************************************************************
   fill an island with rivers
 **************************************************************************/
 static void fill_island_rivers(int coast, long int *bucket,
@@ -1485,30 +1514,25 @@
   i = *bucket / capac;
   i++;
   *bucket -= i * capac;
-
+  
+  /* generate 75% more rivers than generator 1 */
+  i = (i * 175) / 100;
+  
   k = i;
-  failsafe = i * (pstate->s - pstate->n) * (pstate->e - pstate->w);
+  failsafe = i * (pstate->s - pstate->n) * (pstate->e - pstate->w) * 5;
   if (failsafe < 0) {
     failsafe = -failsafe;
   }
-
+  
   while (i > 0 && (failsafe--) > 0) {
     struct tile *ptile = get_random_map_position_from_state(pstate);
     if (tile_get_continent(ptile) == pstate->isleindex
-	&& not_placed(ptile)) {
-
-      /* the first condition helps make terrain more contiguous,
-	 the second lets it avoid the coast: */
-      if ((i * 3 > k * 2 
-	   || count_special_near_tile(ptile, FALSE, TRUE, S_RIVER) > 0
-	   || myrand(100) < 50)
-	  && (!is_cardinally_adj_to_ocean(ptile) || myrand(100) < coast)) {
-	if (is_water_adjacent_to_tile(ptile)
-	    && count_ocean_near_tile(ptile, FALSE, TRUE) < 50
-            && count_special_near_tile(ptile, FALSE, TRUE, S_RIVER) < 35) {
-	  tile_set_special(ptile, S_RIVER);
-	  i--;
-	}
+	&& !tile_has_special(ptile, S_RIVER)) {
+      if ((island_river_mouth_suitability( ptile ) 
+	   && (myrand(100) < coast || i == k ))
+	  || island_river_suitability( ptile )) {
+	tile_set_special(ptile, S_RIVER);
+	i--;
       }
     }
   }
_______________________________________________
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev

Reply via email to