]> git.pond.sub.org Git - empserver/commitdiff
Provide an Empire clock with ETU resolution that is properly
authorMarkus Armbruster <armbru@pond.sub.org>
Sat, 14 Jul 2007 15:58:37 +0000 (15:58 +0000)
committerMarkus Armbruster <armbru@pond.sub.org>
Sat, 14 Jul 2007 15:58:37 +0000 (15:58 +0000)
synchronized to updates (the one based on s_p_etu isn't synchronized):
(gamestr): New members game_turn, game_tick, game_rt.
(game_ca): New selectors for them.  Restrict tick and rt to deity for
now.  We'd need xdump update the Empire clock to make them safe for
players.
(game_record_update): New.
(update_main): Call it.
(game_tick_tick, game_tick_to_now, game_step_a_tick): New, not yet
used.

include/game.h
src/lib/common/game.c [new file with mode: 0644]
src/lib/global/nsc.c
src/lib/update/main.c

index c49258eb549e6cd99dffc566df7357dc0295dc0c..877230d061d1957d0a021e624467e0c147cf3a0a 100644 (file)
 #ifndef GAME_H
 #define GAME_H
 
+#include <time.h>
+
 struct gamestr {
     /* initial part must match struct empobj */
     short ef_type;
     /* end of part matching struct empobj */
+    /*
+     * The Empire clock.
+     * Access it through game_tick_tick(), or else it'll be late.
+     */
+    short game_turn;           /* turn number */
+    short game_tick;           /* elapsed etus in this turn */
+    time_t game_rt;            /* when game_tick last ticked */
 };
 
 #define putgame() ef_write(EF_GAME, 0, ef_ptr(EF_GAME, 0))
 #define getgamep() ((struct gamestr *)ef_ptr(EF_GAME, 0))
 
+extern void game_record_update(time_t);
+extern struct gamestr *game_tick_tick(void);
+extern int game_tick_to_now(short *);
+extern int game_step_a_tick(struct gamestr *, short *);
+
 #endif
diff --git a/src/lib/common/game.c b/src/lib/common/game.c
new file mode 100644 (file)
index 0000000..7431877
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ *  Empire - A multi-player, client/server Internet based war game.
+ *  Copyright (C) 1986-2007, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ *                           Ken Stevens, Steve McClure
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ *  ---
+ *
+ *  See files README, COPYING and CREDITS in the root of the source
+ *  tree for related information and legal notices.  It is expected
+ *  that future projects/authors will amend these files as needed.
+ *
+ *  ---
+ *
+ *  game.c: Game file access
+ * 
+ *  Known contributors to this file:
+ *     Markus Armbruster, 2007
+ */
+
+/*
+ * On Empire Time:
+ *
+ * A turn is terminated by an update and consists of etu_per_update
+ * ETUs.  The Empire clock counts turns and ETUs.  When updates move
+ * around in real time (schedule change, downtime, etc.), the Empire
+ * clock automatically adapts the length of an ETU in seconds
+ * accordingly.
+ */
+
+#include <config.h>
+
+#include <math.h>
+#include "file.h"
+#include "game.h"
+#include "optlist.h"
+#include "prototypes.h"
+#include "server.h"
+
+/*
+ * Record an update in the game file, the current time is NOW.
+ */
+void
+game_record_update(time_t now)
+{
+    struct gamestr *game = getgamep();
+
+    game->game_turn++;
+    game->game_tick = 0;
+    game->game_rt = now;
+    putgame();
+}
+
+/*
+ * Return current duration of an ETU in seconds.
+ * Note: may return HUGE_VAL when the Empire clock is not ticking.
+ */
+static double
+secs_per_etu(struct gamestr *game)
+{
+    double secs;
+
+    if (!update_time[0])
+       return HUGE_VAL;        /* no update scheduled */
+
+    secs = update_time[0] - game->game_rt;
+    if (secs < 0)
+       return HUGE_VAL;        /* update seems to be late */
+    return secs / (etu_per_update - game->game_tick);
+}
+
+/*
+ * Update the Empire clock according to the current real time.
+ * Return the game struct.
+ */
+struct gamestr *
+game_tick_tick(void)
+{
+    struct gamestr *game = getgamep();
+    double dsecs, s_p_etu;
+    int detu;
+
+    dsecs = time(NULL) - game->game_rt;
+    if (CANT_HAPPEN(dsecs < 0))
+       dsecs = 0;
+    s_p_etu = secs_per_etu(game);
+    detu = (int)(dsecs / s_p_etu);
+    if (detu > 0) {
+       if (CANT_HAPPEN(game->game_tick + detu > etu_per_update))
+           detu = etu_per_update - game->game_tick;
+       game->game_tick += detu;
+       game->game_rt += detu * s_p_etu;
+       putgame();
+    }
+
+    return game;
+}
+
+/*
+ * Set ETU timestamp *TICK to the current ETU time.
+ * Return by how many ETUs it was increased.
+ */
+int
+game_tick_to_now(short *tick)
+{
+    return game_step_a_tick(game_tick_tick(), tick);
+}
+
+/*
+ * Set ETU timestamp *TICK to the ETU time recorded in the game struct.
+ * The Empire clock is not updated.
+ * Return by how many ETUs it was increased.
+ */
+int
+game_step_a_tick(struct gamestr *game, short *tick)
+{
+    int d;
+
+    d = game->game_tick - *tick;
+    if (CANT_HAPPEN(d < 0))
+       d = 0;
+    *tick = game->game_tick;
+    return d;
+}
index a1acdacf5fcb8141187a102f3c21909b71c9f657..77ff582866f6c93ca52484a40e3c60afe8ebc21e 100644 (file)
@@ -545,6 +545,10 @@ struct castr realm_ca[] = {
 };
 
 struct castr game_ca[] = {
+    {NSC_SHORT, 0, 0, offsetof(struct gamestr, game_turn), "turn", EF_BAD},
+    {NSC_SHORT, NSC_DEITY, 0, offsetof(struct gamestr, game_tick), "tick",
+     EF_BAD},
+    {NSC_TIME, NSC_DEITY, 0, offsetof(struct gamestr, game_rt), "rt", EF_BAD},
     {NSC_NOTYPE, 0, 0, 0, NULL, EF_BAD}
 };
 
index 790e59e733f5af8baabbe1b1f194df409a51e9e8..7b555c02e68cfb7e4059649ced87fe8a78d92e6a 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "budg.h"
 #include "empthread.h"
+#include "game.h"
 #include "journal.h"
 #include "player.h"
 #include "server.h"
@@ -61,6 +62,7 @@ update_main(void)
     struct natstr *np;
 
     logerror("production update (%d etus)", etu);
+    game_record_update(time(NULL));
     journal_update(etu);
 
     /* First, make sure all mobility is updated correctly. */