]> git.pond.sub.org Git - empserver/blob - src/lib/common/game.c
Update copyright notice
[empserver] / src / lib / common / game.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2015, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                Ken Stevens, Steve McClure, Markus Armbruster
5  *
6  *  Empire is free software: you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation, either version 3 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  *  ---
20  *
21  *  See files README, COPYING and CREDITS in the root of the source
22  *  tree for related information and legal notices.  It is expected
23  *  that future projects/authors will amend these files as needed.
24  *
25  *  ---
26  *
27  *  game.c: Game file access
28  *
29  *  Known contributors to this file:
30  *     Markus Armbruster, 2007-2009
31  */
32
33 /*
34  * On Empire Time:
35  *
36  * An Empire turn is terminated by an update.  The Empire clock counts
37  * turns and ETUs, i.e. it ticks etu_per_update times per turn.  When
38  * updates move around in real time (schedule change, downtime, etc.),
39  * the Empire clock automatically adapts the duration of an ETU
40  * accordingly.
41  */
42
43 #include <config.h>
44
45 #include <math.h>
46 #include "file.h"
47 #include "game.h"
48 #include "optlist.h"
49 #include "server.h"
50
51 /*
52  * Enable / disable updates
53  */
54 void
55 game_ctrl_update(int enable)
56 {
57     struct gamestr *game = getgamep();
58
59     game->game_upd_disable = !enable;
60     putgame();
61 }
62
63 /*
64  * Are updates disabled?
65  */
66 int
67 updates_disabled(void)
68 {
69     return getgamep()->game_upd_disable;
70 }
71
72 /*
73  * Enable / disable play
74  */
75 void
76 game_ctrl_play(int enable)
77 {
78     struct gamestr *game = getgamep();
79
80     game->game_down = !enable;
81     putgame();
82 }
83
84 /*
85  * Is playing enabled?
86  */
87 int
88 game_play_disabled(void)
89 {
90     return getgamep()->game_down;
91 }
92
93 /*
94  * Notice that a player broke sanctuary.
95  * This starts the Empire clock if it hasn't been started yet.
96  */
97 void
98 game_note_bsanct(void)
99 {
100     struct gamestr *game = getgamep();
101
102     if (game->game_rt == 0) {
103         game->game_rt = time(NULL);
104         putgame();
105     }
106 }
107
108 /*
109  * Record an update in the game file, the current time is NOW.
110  * This starts the Empire clock if it hasn't been started yet.
111  */
112 void
113 game_record_update(time_t now)
114 {
115     struct gamestr *game = getgamep();
116
117     game->game_turn++;
118     game->game_tick = 0;
119     game->game_rt = now;
120     putgame();
121 }
122
123 /*
124  * Return current duration of an ETU in seconds.
125  * Note: may return HUGE_VAL when the Empire clock is not ticking.
126  */
127 static double
128 secs_per_etu(struct gamestr *game)
129 {
130     double secs;
131
132     if (!game->game_rt || !update_time[0])
133         return HUGE_VAL;        /* not started or no update scheduled */
134
135     secs = update_time[0] - game->game_rt;
136     if (secs < 0)
137         return HUGE_VAL;        /* update seems to be late */
138     return secs / (etu_per_update - game->game_tick);
139 }
140
141 /*
142  * Update the Empire clock according to the current real time.
143  * Return the game struct.
144  */
145 struct gamestr *
146 game_tick_tick(void)
147 {
148     struct gamestr *game = getgamep();
149     double dsecs, s_p_etu;
150     int detu;
151
152     dsecs = time(NULL) - game->game_rt;
153     if (CANT_HAPPEN(dsecs < 0))
154         dsecs = 0;
155     s_p_etu = secs_per_etu(game);
156     detu = (int)(dsecs / s_p_etu);
157     if (detu > 0) {
158         if (CANT_HAPPEN(game->game_tick + detu > etu_per_update))
159             detu = etu_per_update - game->game_tick;
160         game->game_tick += detu;
161         game->game_rt += detu * s_p_etu;
162         putgame();
163     }
164
165     return game;
166 }
167
168 /*
169  * Set ETU timestamp *TICK to the current ETU time.
170  * Return by how many ETUs it was increased.
171  */
172 int
173 game_tick_to_now(short *tick)
174 {
175     return game_step_a_tick(game_tick_tick(), tick);
176 }
177
178 /*
179  * Set ETU timestamp *TICK to the ETU time recorded in the game struct.
180  * The Empire clock is not updated.
181  * Return by how many ETUs it was increased.
182  */
183 int
184 game_step_a_tick(struct gamestr *game, short *tick)
185 {
186     int etu;
187
188     etu = game->game_tick - *tick;
189     if (CANT_HAPPEN(etu < 0))
190         etu = 0;
191     *tick = game->game_tick;
192     return etu;
193 }
194
195 /*
196  * Reset ETU timestamp *TICK to zero.
197  * Return how many ETUs it had left until etu_per_update.
198  */
199 int
200 game_reset_tick(short *tick)
201 {
202     int etu;
203
204     etu = etu_per_update - *tick;
205     if (CANT_HAPPEN(etu < 0))
206         etu = 0;
207     *tick = 0;
208     return etu;
209 }