Complete.Org: Mailing Lists: Archives: freeciv-dev: December 2005:
[Freeciv-Dev] Re: (PR#14274) new ranking server code
Home

[Freeciv-Dev] Re: (PR#14274) new ranking server code

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Subject: [Freeciv-Dev] Re: (PR#14274) new ranking server code
From: "Mike Kaufman" <kaufman@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 20 Dec 2005 21:31:44 -0800
Reply-to: bugs@xxxxxxxxxxx

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

here's the final version of the patch to be committed.

-mike

Index: server/score.c
===================================================================
--- server/score.c      (revision 11364)
+++ server/score.c      (working copy)
@@ -407,3 +407,97 @@
 
   fclose(fp);
 }
+
+/**************************************************************************
+  At the end of a game, figure the winners and losers of the game and
+  output to a suitable place.
+
+  The definition of winners and losers: a winner is one who is alive at the
+  end of the game and has not surrendered, or in the case of a team game, 
+  is alive or a teammate is alive and has not surrendered. A loser is
+  surrendered or dead. Exception: the winner of the spacerace and his 
+  teammates will win of course.
+
+  Barbarians do not count as winners or losers.
+**************************************************************************/
+void rank_users(void)
+{
+  FILE *fp;
+  int i;
+  enum victory_state { VS_NONE, VS_LOSER, VS_WINNER };
+  enum victory_state plr_state[MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS];
+  struct player *spacerace_winner = NULL;
+
+  fp = fopen("ranking.log","w");
+
+  /* oh well, we can fail silently */
+  if (!fp) {
+    return;
+  }
+
+  /* initialize plr_state */
+  for (i = 0; i < MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS; i++) {
+    plr_state[i] = VS_NONE;
+  }
+
+  /* do we have a spacerace winner? */
+  players_iterate(pplayer) {
+    if (pplayer->spaceship.state == SSHIP_ARRIVED) {
+      spacerace_winner = pplayer;
+      break;
+    }
+  } players_iterate_end;
+
+  /* make this easy: if we have a spacerace winner, then treat all others
+   * who are still alive as surrendered */
+  if (spacerace_winner) {
+    players_iterate(pplayer) {
+      if (pplayer != spacerace_winner) {
+        pplayer->surrendered = TRUE;
+      }
+    } players_iterate_end;
+  }
+
+  /* first pass: locate those alive who haven't surrendered, set them to win;
+   * barbarians won't count, and everybody else is a loser for now. */
+  players_iterate(pplayer) {
+    if (is_barbarian(pplayer)) {
+      plr_state[pplayer->player_no] = VS_NONE;
+    } else if (pplayer->is_alive && !pplayer->surrendered) {
+      plr_state[pplayer->player_no] = VS_WINNER;
+    } else {
+      plr_state[pplayer->player_no] = VS_LOSER;
+    }
+  } players_iterate_end;
+
+  /* second pass: find the teammates of those winners, they win too. */
+  players_iterate(pplayer) {
+    if (plr_state[pplayer->player_no] == VS_WINNER) {
+      players_iterate(aplayer) {
+        if (aplayer->team == pplayer->team) {
+          plr_state[aplayer->player_no] = VS_WINNER;
+        }
+      } players_iterate_end;
+    }
+  } players_iterate_end;
+
+  /* write out ranking information to file */
+  fprintf(fp, "turns: %d\n", game.info.turn);
+  fprintf(fp, "winners: ");
+  players_iterate(pplayer) {
+    if (plr_state[pplayer->player_no] == VS_WINNER) {
+      fprintf(fp, "%s (%s,%s), ", pplayer->ranked_username, pplayer->name,
+                                  pplayer->username);
+    }
+  } players_iterate_end;
+  fprintf(fp, "\nlosers: ");
+  players_iterate(pplayer) {
+    if (plr_state[pplayer->player_no] == VS_LOSER) {
+      fprintf(fp, "%s (%s,%s), ", pplayer->ranked_username, pplayer->name,
+                                  pplayer->username);
+    }
+  } players_iterate_end;
+  fprintf(fp, "\n");
+
+  fclose(fp);
+}
Index: server/srv_main.c
===================================================================
--- server/srv_main.c   (revision 11364)
+++ server/srv_main.c   (working copy)
@@ -552,6 +552,16 @@
     } players_iterate_end;
   }
 
+  /* find out if users attached to players have been attached to those players
+   * for long enough. The first user to do so becomes "associated" to that
+   * player for ranking purposes. */
+  players_iterate(pplayer) {
+    if (strcmp(pplayer->ranked_username, ANON_USER_NAME) == 0
+        && pplayer->user_turns++ > TURNS_NEEDED_TO_RANK) {
+      sz_strlcpy(pplayer->ranked_username, pplayer->username);
+    }
+  } players_iterate_end;
+
   /* See if the value of fog of war has changed */
   if (is_new_turn && game.info.fogofwar != game.fogofwar_old) {
     if (game.info.fogofwar) {
@@ -1676,7 +1686,9 @@
     (void) send_server_info_to_metaserver(META_REFRESH);
 
     if (server_state != GAME_OVER_STATE && check_for_game_over()) {
-      server_state=GAME_OVER_STATE;
+      server_state = GAME_OVER_STATE;
+      /* this goes here, because we don't rank users after an /endgame */
+      rank_users();
     }
   }
 
Index: server/score.h
===================================================================
--- server/score.h      (revision 11364)
+++ server/score.h      (working copy)
@@ -21,4 +21,6 @@
 
 void save_ppm(void);
 
+void rank_users(void);
+
 #endif /* FC__SCORE_H */
Index: server/connecthand.c
===================================================================
--- server/connecthand.c        (revision 11364)
+++ server/connecthand.c        (working copy)
@@ -437,6 +437,7 @@
 
   if (!pconn->observer) {
     sz_strlcpy(pplayer->username, pconn->username);
+    pplayer->user_turns = 0; /* reset for a new user */
     pplayer->is_connected = TRUE;
   }
 
Index: server/stdinhand.c
===================================================================
--- server/stdinhand.c  (revision 11364)
+++ server/stdinhand.c  (working copy)
@@ -63,6 +63,7 @@
 #include "ruleset.h"
 #include "sanitycheck.h"
 #include "savegame.h"
+#include "score.h"
 #include "sernet.h"
 #include "settings.h"
 #include "srv_main.h"
@@ -3635,7 +3636,6 @@
                    caller->player->name);
     caller->player->surrendered = TRUE;
     if (check_for_game_over()) {
-      server_state = GAME_OVER_STATE;
       force_end_of_sniff = TRUE;
     }
     return TRUE;
Index: common/player.c
===================================================================
--- common/player.c     (revision 11364)
+++ common/player.c     (working copy)
@@ -176,6 +176,8 @@
 
   sz_strlcpy(plr->name, ANON_PLAYER_NAME);
   sz_strlcpy(plr->username, ANON_USER_NAME);
+  sz_strlcpy(plr->ranked_username, ANON_USER_NAME);
+  plr->user_turns = 0;
   plr->is_male = TRUE;
   plr->government = NULL;
   plr->target_government = NULL;
Index: common/player.h
===================================================================
--- common/player.h     (revision 11364)
+++ common/player.h     (working copy)
@@ -157,6 +157,8 @@
   int player_no;
   char name[MAX_LEN_NAME];
   char username[MAX_LEN_NAME];
+  char ranked_username[MAX_LEN_NAME]; /* the user who will be ranked */
+  int user_turns;            /* number of turns this user has played */
   bool is_male;
   struct government *government; /* may be NULL in pregame */
   struct government *target_government; /* may be NULL */
Index: common/game.h
===================================================================
--- common/game.h       (revision 11364)
+++ common/game.h       (working copy)
@@ -50,6 +50,10 @@
 #define CONTAMINATION_POLLUTION 1
 #define CONTAMINATION_FALLOUT   2
 
+/* The number of turns that the first user needs to be attached to a 
+ * player for that user to be ranked as that player */
+#define TURNS_NEEDED_TO_RANK 10
+
 struct civ_game {
   struct packet_game_info info;
   struct government *government_when_anarchy;

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