[Freeciv-Dev] Re: (PR#14274) new ranking server code
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://bugs.freeciv.org/Ticket/Display.html?id=14274 >
I see that every patch that I attached to this ticket was the one that I
was committing. This patch _is_ the one I'm committing. I swear :)
o add cmdline option -R to enable
o deal with endy
-mike
Index: server/civserver.c
===================================================================
--- server/civserver.c (revision 11419)
+++ server/civserver.c (working copy)
@@ -127,6 +127,8 @@
srvarg.log_filename = option; /* Never freed. */
} else if ((option = get_option_malloc("--gamelog", argv, &inx, argc))) {
srvarg.gamelog_filename = option; /* Never freed. */
+ } else if ((option = get_option_malloc("--Ranklog", argv, &inx, argc))) {
+ srvarg.ranklog_filename = option; /* Never freed. */
} else if (is_option("--nometa", argv[inx])) {
fc_fprintf(stderr, _("Warning: the %s option is obsolete. "
"Use -m to enable the metaserver.\n"), argv[inx]);
@@ -243,6 +245,8 @@
fc_fprintf(stderr,
_(" -P, --Ppm\t\tSave ppms of the map when saving the game.\n"));
fc_fprintf(stderr, _(" -r, --read FILE\tRead startup script FILE\n"));
+ fc_fprintf(stderr,
+ _(" -R, --Ranklog FILE\tUse FILE as ranking logfile\n"));
fc_fprintf(stderr, _(" -v, --version\t\tPrint the version number\n"));
#ifdef GGZ_SERVER
fc_fprintf(stderr, _(" -z, --zone\t\tEnable GGZ mode\n"));
Index: server/score.c
===================================================================
--- server/score.c (revision 11419)
+++ server/score.c (working copy)
@@ -434,3 +434,205 @@
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.
+
+ Games ending by endyear results in a draw, we don't rank in that case.
+**************************************************************************/
+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;
+
+ /* game ending via endyear results in a draw. We don't rank. */
+ if (game.info.year > game.info.end_year) {
+ return;
+ }
+
+ /* don't output ranking info if we haven't enabled it via cmdline */
+ if (!srvarg.ranklog_filename) {
+ return;
+ }
+
+ fp = fopen(srvarg.ranklog_filename,"w");
+
+ /* don't fail silently, at least print an error */
+ if (!fp) {
+ freelog(LOG_ERROR, "couldn't open ranking log file: \"%s\"",
+ srvarg.ranklog_filename);
+ 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);
+}
+
+/**************************************************************************
+ 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 11419)
+++ server/srv_main.c (working copy)
@@ -178,6 +178,7 @@
srvarg.log_filename = NULL;
srvarg.gamelog_filename = NULL;
+ srvarg.ranklog_filename = NULL;
srvarg.load_filename[0] = '\0';
srvarg.script_filename = NULL;
srvarg.saves_pathname = "";
@@ -552,6 +553,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 +1687,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 11419)
+++ server/score.h (working copy)
@@ -21,4 +21,6 @@
void save_ppm(void);
+void rank_users(void);
+
#endif /* FC__SCORE_H */
Index: server/srv_main.h
===================================================================
--- server/srv_main.h (revision 11419)
+++ server/srv_main.h (working copy)
@@ -35,6 +35,7 @@
/* filenames */
char *log_filename;
char *gamelog_filename;
+ char *ranklog_filename;
char load_filename[512]; /* FIXME: may not be long enough? use MAX_PATH? */
char *script_filename;
char *saves_pathname;
Index: server/connecthand.c
===================================================================
--- server/connecthand.c (revision 11419)
+++ 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 11419)
+++ server/stdinhand.c (working copy)
@@ -64,6 +64,7 @@
#include "ruleset.h"
#include "sanitycheck.h"
#include "savegame.h"
+#include "score.h"
#include "sernet.h"
#include "settings.h"
#include "srv_main.h"
@@ -3636,7 +3637,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: server/savegame.c
===================================================================
--- server/savegame.c (revision 11419)
+++ server/savegame.c (working copy)
@@ -1872,6 +1872,9 @@
sz_strlcpy(plr->name, secfile_lookup_str(file, "player%d.name", plrno));
sz_strlcpy(plr->username,
secfile_lookup_str_default(file, "", "player%d.username", plrno));
+ sz_strlcpy(plr->ranked_username,
+ secfile_lookup_str_default(file, "", "player%d.ranked_username",
+ plrno));
/* 1.15 and later versions store nations by name. Try that first. */
p = secfile_lookup_str_default(file, NULL, "player%d.nation", plrno);
@@ -2691,6 +2694,8 @@
secfile_insert_str(file, plr->name, "player%d.name", plrno);
secfile_insert_str(file, plr->username, "player%d.username", plrno);
+ secfile_insert_str(file, plr->ranked_username, "player%d.ranked_username",
+ plrno);
secfile_insert_str(file, get_nation_name_orig(plr->nation),
"player%d.nation", plrno);
/* 1.15 and later won't use the race field, they key on the nation string
Index: common/player.c
===================================================================
--- common/player.c (revision 11419)
+++ common/player.c (working copy)
@@ -177,6 +177,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 11419)
+++ 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 11419)
+++ 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;
|
|