Complete.Org: Mailing Lists: Archives: freeciv-dev: March 2003:
[Freeciv-Dev] (PR#3751) Common class patch
Home

[Freeciv-Dev] (PR#3751) Common class patch

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: ms209290@xxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] (PR#3751) Common class patch
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Fri, 21 Mar 2003 11:47:38 -0800
Reply-to: rt@xxxxxxxxxxxxxx

[ms209290@xxxxxxxxxxxxxxxxxxx - Wed Mar 19 07:20:18 2003]:

> This patch makes the AI select a nation from the same class as 
> human-players
> I.E. If I choose English, AI won't play Mordorians.

Nice idea.

I made some small changes - particularly, nation->class can never be
NULL, so I changed that check into an assertion.  Nations with
unspecified class will end up being assigned a class of "", which will
end up being a class of its own (we don't special-case it at all).  This
isn't an issue for the default ruleset (since all nations have classes),
and should be fine for other rulesets.

I also made a few cleanups to the code (compare strcmp with 0, use
fc_malloc instead of fc_calloc, have just one free/return statement in
select_random_nation, add/change some comments).

jason

Index: server/srv_main.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/srv_main.c,v
retrieving revision 1.114
diff -u -r1.114 srv_main.c
--- server/srv_main.c   2003/02/12 22:22:35     1.114
+++ server/srv_main.c   2003/03/21 19:43:07
@@ -1546,6 +1546,69 @@
 }
 
 /**************************************************************************
+  If all players have chosen the same nation class, return
+  this class, otherwise return NULL.
+**************************************************************************/  
+static char* find_common_class(void) 
+{
+  char* class = NULL;
+  struct nation_type* nation;
+
+  players_iterate(pplayer) {
+    if (pplayer->nation == MAX_NUM_NATIONS) {
+      /* still undecided */
+      continue;  
+    }
+    nation = get_nation_by_idx(pplayer->nation);
+    assert(nation->class != NULL);
+    if (class == NULL) {
+       /* Set the class. */
+      class = nation->class;
+    } else if (strcmp(nation->class, class) != 0) {
+      /* Multiple classes are already being used. */
+      return NULL;
+    }
+  } players_iterate_end;
+
+  return class;
+}
+
+/**************************************************************************
+  Select a random available nation.  If 'class' is non-NULL, then choose
+  a nation from that class if possible.
+**************************************************************************/
+static Nation_Type_id select_random_nation(const char* class)
+{
+  Nation_Type_id* nations, selected;
+  int i, j;
+  
+  if (class == NULL) {
+    return nations_avail[myrand(num_nations_avail)];
+  }
+  
+  nations = fc_malloc(num_nations_avail * sizeof(*nations));
+  for (j = i = 0; i < num_nations_avail; i++) {
+    struct nation_type* nation = get_nation_by_idx(nations_avail[i]);
+
+    assert(nation->class != NULL);
+    if (strcmp(nation->class, class) == 0) {
+      nations[j++] = nations_avail[i];
+    }
+  }
+
+  if (j == 0) {
+    /* Pick any available nation. */
+    selected = nations_avail[myrand(num_nations_avail)];
+  } else {
+    selected = nations[myrand(j)];
+    assert(strcmp(get_nation_by_idx(selected)->class, class) == 0);
+  }
+
+  free(nations);
+  return selected;
+}
+
+/**************************************************************************
 generate_ai_players() - Selects a nation for players created with
    server's "create <PlayerName>" command.  If <PlayerName> matches
    one of the leader names for some nation, we choose that nation.
@@ -1557,6 +1620,10 @@
    than the number of players currently connected.  If so, we create the
    appropriate number of players (game.aifill - game.nplayers) from
    scratch, choosing a random nation and appropriate name for each.
+   
+   When we choose a nation randomly we try to consider only nations
+   that are in the same class as nations choosen by other players.
+   (I.e., if human player decides to play English, AI won't use Mordorians.)
 
    If the AI player name is one of the leader names for the AI player's
    nation, the player sex is set to the sex for that leader, else it
@@ -1569,10 +1636,12 @@
   char player_name[MAX_LEN_NAME];
   struct player *pplayer;
   int i, old_nplayers;
+  char* common_class;
 
   /* Select nations for AI players generated with server
    * 'create <name>' command
    */
+  common_class = find_common_class();
   for (i=0; i<game.nplayers; i++) {
     pplayer = &game.players[i];
     
@@ -1607,13 +1676,20 @@
 
     if (nation == game.playable_nation_count) {
       pplayer->nation =
-       mark_nation_as_used(nations_avail[myrand(num_nations_avail)]);
+       mark_nation_as_used(select_random_nation(common_class));
       pplayer->city_style = get_nation_city_style(pplayer->nation);
       pplayer->is_male = (myrand(2) == 1);
     }
 
     announce_ai_player(pplayer);
   }
+  
+  /* We do this again, because user could type:
+   * >create Hammurabi
+   * >set aifill 5
+   * Now we are sure that all AI-players will use historical class
+   */
+  common_class = find_common_class();
 
   /* Create and pick nation and name for AI players needed to bring the
    * total number of players to equal game.aifill
@@ -1634,7 +1710,7 @@
   }
 
   for(;game.nplayers < game.aifill;) {
-    nation = mark_nation_as_used(nations_avail[myrand(num_nations_avail)]);
+    nation = mark_nation_as_used(select_random_nation(common_class));
     pick_ai_player_name(nation, player_name);
 
     old_nplayers = game.nplayers;

[Prev in Thread] Current Thread [Next in Thread]