From: sam+civ@hotaru.chaosring.org
To: freeciv-dev@complete.org
Subject: Idea for giving the humand the best islands
Content-Type: text/plain; charset=utf-8
Content-Disposition: inline

For a number of reasons, this patch can not be made part of FreeCiv
proper in its present form; the idea here is that the humans get the
best islands (the islands with the most goodies) and the AI get the
not-so-good islands.  This is what Alpha Centauri does in the case of 
there being an inequality between islands.

This patch really makes sense if it is applied after applying my previous
"each player gets their own island" patch.

The main problem with this patch, like my other patches, is that this 
really should be a parameter.  Perhaps I will make some patches available
which make the tech_handicap, whether to force each player to have their
own island, and whether to give the human the best island booleans which
are set by the FreeCiv server administrator.

- Sam

--- freeciv-1.14.0-hacked/server/mapgen.c.orig	Wed Mar 12 12:53:35 2003
+++ freeciv-1.14.0-hacked/server/mapgen.c	Wed Mar 12 16:18:25 2003
@@ -1109,6 +1109,27 @@
 }
 
 /**************************************************************************
+ Comparison function that compares the goodness of two start points (how
+ good the island the two start points are on
+ *************************************************************************/
+
+static int compar_isle_goodness(const void *a,const void *b) 
+{
+   int ia, ib;
+   int x,y;
+   struct map_position *t;
+   t = (struct map_position *)a;
+   x=t->x;
+   y=t->y;
+   ia = islands[(int)map_get_continent(x, y)].goodies;
+   t = (struct map_position *)b;
+   x=t->x;
+   y=t->y;
+   ib = islands[(int)map_get_continent(x, y)].goodies;
+   return ib - ia;
+}
+
+/**************************************************************************
   where do the different races start on the map? well this function tries
   to spread them out on the different islands.
 
@@ -1195,6 +1216,11 @@
   if(dist>= map.ysize/2)
     dist= map.ysize/2;
 
+  /* If we make distance really big here (and do the check to make sure each
+     player gets their own island), we can 100% ensure that each player
+     gets their own island; dist is the minimum distance that two players
+     can be from one another on the same island */
+
   sum=0;
   for (k=0; k<=map.num_continents; k++) {
     sum += islands[k].starters;
@@ -1232,6 +1258,16 @@
   }
   map.num_start_positions = game.nplayers;
 
+  /* Sort the array so that the lowered numbered starting positions are
+     always on the best isles; this is used in conjunction with code in
+     gamehand.c to make sure that the humans get the best islands; the
+     code works best when each player gets their own island (otherwise
+     all of the humans will share the best islands and all of the AIs will
+     share the worse islands) */
+
+  qsort(map.start_positions,map.num_start_positions,
+        sizeof(struct map_position),compar_isle_goodness);
+
   free(islands);
   islands = NULL;
   return 1; /* Good map */
--- freeciv-1.14.0-hacked/server/gamehand.c.orig	Wed Mar 12 14:59:17 2003
+++ freeciv-1.14.0-hacked/server/gamehand.c	Wed Mar 12 16:18:32 2003
@@ -38,15 +38,59 @@
 {
   int i, j, x, y;
   int dx, dy;
+  int last_human_player = 0, first_ai_player;
   Unit_Type_id utype;
   int start_pos[MAX_NUM_PLAYERS]; /* indices into map.start_positions[] */
 
   if (!map.fixed_start_positions) {
-    /* except in a scenario which provides them,
-       shuffle the start positions around... */
     assert(game.nplayers==map.num_start_positions);
-    for (i=0; i<game.nplayers;i++) { /* no advantage to the romans!! */
-      j=myrand(game.nplayers);
+
+    /* We move all of the ai players after all of the humans.  This is done
+       in conjunciton with code in mapgen.c which makes sure all of the
+       starting points on good islands come before (in the 
+       map.start_positions array) all of the starting positions on bad
+       islands. 
+
+       The code assumes that each player gets their own island.
+       If not, then what this code will do is cause all of the humans
+       to share the best islands and all of the AIs to share the not-so-good
+       islands.
+
+       Note that this is an inefficient O(N^2) algorithm; with the current
+       max of 30 players, there should not be a problem */
+
+    last_human_player = game.nplayers + 1;
+
+    for(j=game.nplayers - 1; j >=0; j--) {
+        if(!game.players[j].ai.control) {
+	    last_human_player = j;
+	    break;
+	    }
+        }
+    if(last_human_player + 1< game.nplayers) {
+      for(i=0; i<last_human_player; i++) {
+        if(game.players[i].ai.control) { 
+	    /* Swap the positions */
+            x=map.start_positions[last_human_player].x;
+            y=map.start_positions[last_human_player].y;
+            map.start_positions[last_human_player].x=map.start_positions[i].x;
+            map.start_positions[last_human_player].y=map.start_positions[i].y;
+            map.start_positions[i].x=x;
+            map.start_positions[i].y=y;
+            for(j=game.nplayers - 1; j >=0 ; j--) {
+                if(!game.players[j].ai.control) {
+	            last_human_player = j;
+		    break;
+	            }
+                }
+	    }
+        }
+    }
+
+    /* except in a scenario which provides them,
+       shuffle the human's start positions around... */
+    for (i=0; i<= last_human_player;i++) { /* no advantage to the romans!! */
+      j=myrand(last_human_player + 1);
       x=map.start_positions[j].x;
       y=map.start_positions[j].y;
       map.start_positions[j].x=map.start_positions[i].x;
@@ -54,6 +98,20 @@
       map.start_positions[i].x=x;
       map.start_positions[i].y=y;
     }
+
+    /* Also shuffle all of the ai's start positions */
+    first_ai_player = last_human_player + 1;
+    for(i = first_ai_player;i < game.nplayers; i++) { 
+        j = myrand(game.nplayers - first_ai_player);
+	j += first_ai_player;
+        x=map.start_positions[j].x;
+        y=map.start_positions[j].y;
+        map.start_positions[j].x=map.start_positions[i].x;
+        map.start_positions[j].y=map.start_positions[i].y;
+        map.start_positions[i].x=x;
+        map.start_positions[i].y=y;
+    }
+    
     for(i=0; i<game.nplayers; i++) {
       start_pos[i] = i;
     } 
