Freeciv-3.3: /fast/freeciv/nightly/main/server/spacerace.c Source File

Freeciv-3.3

Loading...
Searching...
No Matches
spacerace.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <string.h>
19
20/* utility */
21#include "fcintl.h"
22#include "log.h"
23#include "shared.h"
24
25/* common */
26#include "calendar.h"
27#include "events.h"
28#include "game.h"
29#include "nation.h"
30#include "packets.h"
31#include "spaceship.h"
32
33/* server */
34#include "plrhand.h"
35#include "notify.h"
36#include "srv_main.h"
37
38#include "spacerace.h"
39
40/**********************************************************************/
46 void spaceship_calc_derived(struct player_spaceship *ship)
47{
48 int i;
49 /* these are how many are connected: */
50 int fuel = 0;
51 int propulsion = 0;
52 int habitation = 0;
53 int life_support = 0;
54 int solar_panels = 0;
55
56 fc_assert_ret(ship->structurals <= NUM_SS_STRUCTURALS);
57 fc_assert_ret(ship->components <= NUM_SS_COMPONENTS);
58 fc_assert_ret(ship->modules <= NUM_SS_MODULES);
59
60 ship->mass = 0;
61 ship->support_rate = ship->energy_rate =
62 ship->success_rate = ship->travel_time = 0.0;
63
64 for (i = 0; i < NUM_SS_STRUCTURALS; i++) {
65 if (BV_ISSET(ship->structure, i)) {
66 ship->mass += (i < 6) ? 200 : 100;
67 /* s0 to s3 are heavier; actually in Civ1 its a bit stranger
68 than this, but not worth figuring out --dwp */
69 }
70 }
71 for (i = 0; i < ship->fuel; i++) {
72 if (BV_ISSET(ship->structure, components_info[i * 2].required)) {
73 fuel++;
74 }
75 }
76 for (i = 0; i < ship->propulsion; i++) {
77 if (BV_ISSET(ship->structure, components_info[i * 2 + 1].required)) {
78 propulsion++;
79 }
80 }
81 for (i = 0; i < ship->habitation; i++) {
82 if (BV_ISSET(ship->structure, modules_info[i * 3].required)) {
83 habitation++;
84 }
85 }
86 for (i = 0; i < ship->life_support; i++) {
87 if (BV_ISSET(ship->structure, modules_info[i * 3 + 1].required)) {
88 life_support++;
89 }
90 }
91 for (i = 0; i < ship->solar_panels; i++) {
92 if (BV_ISSET(ship->structure, modules_info[i * 3 + 2].required)) {
93 solar_panels++;
94 }
95 }
96
97 ship->mass += 1600 * (habitation + life_support)
98 + 400 * (solar_panels + propulsion + fuel);
99
100 ship->population = habitation * 10000;
101
102 if (habitation > 0) {
103 ship->support_rate = life_support / (double) habitation;
104 }
105 if (life_support + habitation > 0) {
106 ship->energy_rate = 2.0 * solar_panels / (double)(life_support+habitation);
107 }
108 if (fuel>0 && propulsion>0) {
109 ship->success_rate =
110 MIN(ship->support_rate, 1.0) * MIN(ship->energy_rate, 1.0);
111 }
112
113 /* The Success% can be less by up to a few % in some cases
114 (I think if P != F or if P and/or F too small (eg <= 2?) ?)
115 but probably not worth worrying about.
116 Actually, the Civ1 manual suggests travel time is relevant. --dwp
117 */
118
119 ship->travel_time = ship->mass * game.server.spaceship_travel_pct
120 / 100 / (200.0 * MIN(propulsion,fuel) + 20.0);
121
122}
123
124/**********************************************************************/
129 void send_spaceship_info(struct player *src, struct conn_list *dest)
130{
131 if (!dest) {
132 dest = game.est_connections;
133 }
134
135 players_iterate(pplayer) {
136 if (!src || pplayer == src) {
137 struct packet_spaceship_info info;
138 struct player_spaceship *ship = &pplayer->spaceship;
139
140 info.player_num = player_number(pplayer);
141 info.sship_state = ship->state;
142 info.structurals = ship->structurals;
143 info.components = ship->components;
144 info.modules = ship->modules;
145 info.fuel = ship->fuel;
146 info.propulsion = ship->propulsion;
147 info.habitation = ship->habitation;
148 info.life_support = ship->life_support;
149 info.solar_panels = ship->solar_panels;
150 info.launch_year = ship->launch_year;
151 info.population = ship->population;
152 info.mass = ship->mass;
153 info.support_rate = ship->support_rate;
154 info.energy_rate = ship->energy_rate;
155 info.success_rate = ship->success_rate;
156 info.travel_time = ship->travel_time;
157 info.structure = ship->structure;
158
159 lsend_packet_spaceship_info(dest, &info);
160 }
161 } players_iterate_end;
162}
163
164/**********************************************************************/
167 void handle_spaceship_launch(struct player *pplayer)
168{
169 struct player_spaceship *ship = &pplayer->spaceship;
170 int arrival;
171
172 if (!player_primary_capital(pplayer)) {
173 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
174 _("You need to have a capital in order to launch "
175 "your spaceship."));
176 return;
177 }
178 if (ship->state >= SSHIP_LAUNCHED) {
179 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
180 _("Your spaceship is already launched!"));
181 return;
182 }
183 if (ship->state != SSHIP_STARTED
184 || ship->success_rate == 0.0) {
185 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
186 _("Your spaceship can't be launched yet!"));
187 return;
188 }
189
190 ship->state = SSHIP_LAUNCHED;
191 ship->launch_year = game.info.year;
192 arrival = ship->launch_year + (int) ship->travel_time;
193
194 notify_player(NULL, NULL, E_SPACESHIP, ftc_server,
195 _("The %s have launched a spaceship! "
196 "It is estimated to arrive at Alpha Centauri in %s."),
197 nation_plural_for_player(pplayer),
198 textyear(arrival));
199
200 send_spaceship_info(pplayer, NULL);
201}
202
203/**********************************************************************/
206 void handle_spaceship_place(struct player *pplayer,
207 enum spaceship_place_type type, int num)
208{
209 (void) do_spaceship_place(pplayer, ACT_REQ_PLAYER, type, num);
210}
211
212/**********************************************************************/
215 bool do_spaceship_place(struct player *pplayer, enum action_requester from,
216 enum spaceship_place_type type, int num)
217{
218 struct player_spaceship *ship = &pplayer->spaceship;
219
220 if (ship->state == SSHIP_NONE) {
221 if (from == ACT_REQ_PLAYER) {
222 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
223 _("Spaceship action received,"
224 " but you don't have a spaceship!"));
225 }
226
227 return FALSE;
228 }
229
230 if (ship->state >= SSHIP_LAUNCHED) {
231 if (from == ACT_REQ_PLAYER) {
232 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
233 _("You can't modify your spaceship after launch!"));
234 }
235
236 return FALSE;
237 }
238
239 if (type == SSHIP_PLACE_STRUCTURAL) {
240 if (num < 0 || num >= NUM_SS_STRUCTURALS
241 || BV_ISSET(ship->structure, num)) {
242 return FALSE;
243 }
244 if (num_spaceship_structurals_placed(ship) >= ship->structurals) {
245 if (from == ACT_REQ_PLAYER) {
246 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
247 _("You don't have any unplaced Space Structurals!"));
248 }
249
250 return FALSE;
251 }
252 if (num != 0
253 && !BV_ISSET(ship->structure, structurals_info[num].required)) {
254 if (from == ACT_REQ_PLAYER) {
255 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
256 _("That Space Structural would not be connected!"));
257 }
258
259 return FALSE;
260 }
261
262 BV_SET(ship->structure, num);
263 spaceship_calc_derived(ship);
264 send_spaceship_info(pplayer, NULL);
265 return TRUE;
266 }
267
268 if (type == SSHIP_PLACE_FUEL) {
269 if (ship->fuel != num - 1) {
270 return FALSE;
271 }
272 if (ship->fuel + ship->propulsion >= ship->components) {
273 if (from == ACT_REQ_PLAYER) {
274 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
275 _("You don't have any unplaced Space Components!"));
276 }
277
278 return FALSE;
279 }
280 if (num > NUM_SS_COMPONENTS/2) {
281 if (from == ACT_REQ_PLAYER) {
282 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
283 _("Your spaceship already has"
284 " the maximum number of Fuel Components!"));
285 }
286
287 return FALSE;
288 }
289
290 ship->fuel++;
291 spaceship_calc_derived(ship);
292 send_spaceship_info(pplayer, NULL);
293 return TRUE;
294 }
295
296 if (type == SSHIP_PLACE_PROPULSION) {
297 if (ship->propulsion != num - 1) {
298 return FALSE;
299 }
300 if (ship->fuel + ship->propulsion >= ship->components) {
301 if (from == ACT_REQ_PLAYER) {
302 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
303 _("You don't have any unplaced"
304 " Space Components!"));
305 }
306
307 return FALSE;
308 }
309 if (num > NUM_SS_COMPONENTS/2) {
310 if (from == ACT_REQ_PLAYER) {
311 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
312 _("Your spaceship already has the"
313 " maximum number of Propulsion Components!"));
314 }
315
316 return FALSE;
317 }
318
319 ship->propulsion++;
320 spaceship_calc_derived(ship);
321 send_spaceship_info(pplayer, NULL);
322 return TRUE;
323 }
324
325 if (type == SSHIP_PLACE_HABITATION) {
326 if (ship->habitation != num - 1) {
327 return FALSE;
328 }
329 if (ship->habitation + ship->life_support + ship->solar_panels
330 >= ship->modules) {
331 if (from == ACT_REQ_PLAYER) {
332 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
333 _("You don't have any unplaced Space Modules!"));
334 }
335
336 return FALSE;
337 }
338 if (num > NUM_SS_MODULES / 3) {
339 if (from == ACT_REQ_PLAYER) {
340 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
341 _("Your spaceship already has the"
342 " maximum number of Habitation Modules!"));
343 }
344
345 return FALSE;
346 }
347
348 ship->habitation++;
349 spaceship_calc_derived(ship);
350 send_spaceship_info(pplayer, NULL);
351 return TRUE;
352 }
353
354 if (type == SSHIP_PLACE_LIFE_SUPPORT) {
355 if (ship->life_support != num - 1) {
356 return FALSE;
357 }
358 if (ship->habitation + ship->life_support + ship->solar_panels
359 >= ship->modules) {
360 if (from == ACT_REQ_PLAYER) {
361 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
362 _("You don't have any unplaced Space Modules!"));
363 }
364
365 return FALSE;
366 }
367 if (num > NUM_SS_MODULES / 3) {
368 if (from == ACT_REQ_PLAYER) {
369 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
370 _("Your spaceship already has the"
371 " maximum number of Life Support Modules!"));
372 }
373
374 return FALSE;
375 }
376
377 ship->life_support++;
378 spaceship_calc_derived(ship);
379 send_spaceship_info(pplayer, NULL);
380 return TRUE;
381 }
382
383 if (type == SSHIP_PLACE_SOLAR_PANELS) {
384 if (ship->solar_panels != num - 1) {
385 return FALSE;
386 }
387 if (ship->habitation + ship->life_support + ship->solar_panels
388 >= ship->modules) {
389 if (from == ACT_REQ_PLAYER) {
390 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
391 _("You don't have any unplaced Space Modules!"));
392 }
393
394 return FALSE;
395 }
396 if (num > NUM_SS_MODULES / 3) {
397 if (from == ACT_REQ_PLAYER) {
398 notify_player(pplayer, NULL, E_SPACESHIP, ftc_server,
399 _("Your spaceship already has the"
400 " maximum number of Solar Panel Modules!"));
401 }
402
403 return FALSE;
404 }
405
406 ship->solar_panels++;
407 spaceship_calc_derived(ship);
408 send_spaceship_info(pplayer, NULL);
409 return TRUE;
410 }
411
412 log_error("Received unknown spaceship place type %d from %s",
413 type, player_name(pplayer));
414 return FALSE;
415}
416
417/**********************************************************************/
420 void spaceship_arrived(struct player *pplayer)
421{
422 notify_player(NULL, NULL, E_SPACESHIP, ftc_server,
423 _("The %s spaceship has arrived at Alpha Centauri."),
424 nation_adjective_for_player(pplayer));
425 pplayer->spaceship.state = SSHIP_ARRIVED;
426}
427
428/**********************************************************************/
431 void spaceship_lost(struct player *pplayer)
432{
433 notify_player(NULL, NULL, E_SPACESHIP, ftc_server,
434 _("Without guidance from the capital, the %s "
435 "spaceship is lost!"),
436 nation_adjective_for_player(pplayer));
437 spaceship_init(&pplayer->spaceship);
438 send_spaceship_info(pplayer, NULL);
439}
440
441/**********************************************************************/
446 double spaceship_arrival(const struct player *pplayer)
447{
448 const struct player_spaceship *ship = &pplayer->spaceship;
449
450 return ship->launch_year + ship->travel_time;
451}
452
453/**********************************************************************/
460 int rank_spaceship_arrival(struct player **result)
461{
462 int n = 0, i;
463
464 shuffled_players_iterate(pplayer) {
465 struct player_spaceship *ship = &pplayer->spaceship;
466
467 if (ship->state == SSHIP_LAUNCHED) {
468 result[n++] = pplayer;
469 }
470 } shuffled_players_iterate_end;
471
472 /* An insertion sort will do; n is probably small, and we need a
473 * stable sort to preserve the shuffled order for tie-breaking, so can't
474 * use qsort() */
475 for (i = 1; i < n; i++) {
476 int j;
477 for (j = i;
478 j > 0
479 && spaceship_arrival(result[j-1]) > spaceship_arrival(result[j]);
480 j--) {
481 struct player *tmp = result[j];
482 result[j] = result[j-1];
483 result[j-1] = tmp;
484 }
485 }
486
487 return n;
488}
n
#define n
Definition astring.c:77
BV_SET
#define BV_SET(bv, bit)
Definition bitvector.h:81
BV_ISSET
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
textyear
const char * textyear(int year)
Definition calendar.c:120
calendar.h
incite_cost
char * incite_cost
Definition comments.c:74
events.h
spaceship_place_type
spaceship_place_type
Definition fc_types.h:1277
SSHIP_PLACE_PROPULSION
@ SSHIP_PLACE_PROPULSION
Definition fc_types.h:1280
SSHIP_PLACE_STRUCTURAL
@ SSHIP_PLACE_STRUCTURAL
Definition fc_types.h:1278
SSHIP_PLACE_LIFE_SUPPORT
@ SSHIP_PLACE_LIFE_SUPPORT
Definition fc_types.h:1282
SSHIP_PLACE_SOLAR_PANELS
@ SSHIP_PLACE_SOLAR_PANELS
Definition fc_types.h:1283
SSHIP_PLACE_FUEL
@ SSHIP_PLACE_FUEL
Definition fc_types.h:1279
SSHIP_PLACE_HABITATION
@ SSHIP_PLACE_HABITATION
Definition fc_types.h:1281
fcintl.h
_
#define _(String)
Definition fcintl.h:67
ftc_server
const struct ft_color ftc_server
Definition featured_text.c:77
game
struct civ_game game
Definition game.c:61
game.h
type
GType type
Definition repodlgs.c:1313
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
log_error
#define log_error(message,...)
Definition log.h:103
nation_adjective_for_player
const char * nation_adjective_for_player(const struct player *pplayer)
Definition nation.c:169
nation_plural_for_player
const char * nation_plural_for_player(const struct player *pplayer)
Definition nation.c:178
nation.h
notify_player
void notify_player(const struct player *pplayer, const struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition notify.c:292
notify.h
packets.h
lsend_packet_spaceship_info
void lsend_packet_spaceship_info(struct conn_list *dest, const struct packet_spaceship_info *packet)
Definition packets_gen.c:46971
player_number
int player_number(const struct player *pplayer)
Definition player.c:837
player_name
const char * player_name(const struct player *pplayer)
Definition player.c:895
player_primary_capital
struct city * player_primary_capital(const struct player *pplayer)
Definition player.c:1337
players_iterate_end
#define players_iterate_end
Definition player.h:539
players_iterate
#define players_iterate(_pplayer)
Definition player.h:534
plrhand.h
shuffled_players_iterate_end
#define shuffled_players_iterate_end
Definition plrhand.h:108
shuffled_players_iterate
#define shuffled_players_iterate(NAME_pplayer)
Definition plrhand.h:98
shared.h
MIN
#define MIN(x, y)
Definition shared.h:55
rank_spaceship_arrival
int rank_spaceship_arrival(struct player **result)
Definition spacerace.c:460
spaceship_lost
void spaceship_lost(struct player *pplayer)
Definition spacerace.c:431
do_spaceship_place
bool do_spaceship_place(struct player *pplayer, enum action_requester from, enum spaceship_place_type type, int num)
Definition spacerace.c:215
spaceship_arrival
double spaceship_arrival(const struct player *pplayer)
Definition spacerace.c:446
spaceship_calc_derived
void spaceship_calc_derived(struct player_spaceship *ship)
Definition spacerace.c:46
send_spaceship_info
void send_spaceship_info(struct player *src, struct conn_list *dest)
Definition spacerace.c:129
handle_spaceship_place
void handle_spaceship_place(struct player *pplayer, enum spaceship_place_type type, int num)
Definition spacerace.c:206
handle_spaceship_launch
void handle_spaceship_launch(struct player *pplayer)
Definition spacerace.c:167
spaceship_arrived
void spaceship_arrived(struct player *pplayer)
Definition spacerace.c:420
spacerace.h
num_spaceship_structurals_placed
int num_spaceship_structurals_placed(const struct player_spaceship *ship)
Definition spaceship.c:113
spaceship_init
void spaceship_init(struct player_spaceship *ship)
Definition spaceship.c:96
structurals_info
const struct sship_part_info structurals_info[NUM_SS_STRUCTURALS]
Definition spaceship.c:23
modules_info
const struct sship_part_info modules_info[NUM_SS_MODULES]
Definition spaceship.c:77
components_info
const struct sship_part_info components_info[NUM_SS_COMPONENTS]
Definition spaceship.c:58
spaceship.h
NUM_SS_MODULES
#define NUM_SS_MODULES
Definition spaceship.h:89
NUM_SS_COMPONENTS
#define NUM_SS_COMPONENTS
Definition spaceship.h:88
NUM_SS_STRUCTURALS
#define NUM_SS_STRUCTURALS
Definition spaceship.h:87
SSHIP_ARRIVED
@ SSHIP_ARRIVED
Definition spaceship.h:85
SSHIP_STARTED
@ SSHIP_STARTED
Definition spaceship.h:84
SSHIP_LAUNCHED
@ SSHIP_LAUNCHED
Definition spaceship.h:85
SSHIP_NONE
@ SSHIP_NONE
Definition spaceship.h:84
srv_main.h
civ_game::spaceship_travel_pct
int spaceship_travel_pct
Definition game.h:179
civ_game::est_connections
struct conn_list * est_connections
Definition game.h:97
civ_game::info
struct packet_game_info info
Definition game.h:89
civ_game::server
struct civ_game::@31::@35 server
packet_game_info::year
int year
Definition packets_gen.h:247
packet_spaceship_info
Definition packets_gen.h:928
packet_spaceship_info::sship_state
int sship_state
Definition packets_gen.h:930
packet_spaceship_info::propulsion
int propulsion
Definition packets_gen.h:935
packet_spaceship_info::habitation
int habitation
Definition packets_gen.h:936
packet_spaceship_info::mass
int mass
Definition packets_gen.h:941
packet_spaceship_info::life_support
int life_support
Definition packets_gen.h:937
packet_spaceship_info::structure
bv_spaceship_structure structure
Definition packets_gen.h:942
packet_spaceship_info::structurals
int structurals
Definition packets_gen.h:931
packet_spaceship_info::fuel
int fuel
Definition packets_gen.h:934
packet_spaceship_info::population
int population
Definition packets_gen.h:940
packet_spaceship_info::success_rate
float success_rate
Definition packets_gen.h:945
packet_spaceship_info::player_num
int player_num
Definition packets_gen.h:929
packet_spaceship_info::launch_year
int launch_year
Definition packets_gen.h:939
packet_spaceship_info::travel_time
float travel_time
Definition packets_gen.h:946
packet_spaceship_info::energy_rate
float energy_rate
Definition packets_gen.h:944
packet_spaceship_info::solar_panels
int solar_panels
Definition packets_gen.h:938
packet_spaceship_info::support_rate
float support_rate
Definition packets_gen.h:943
packet_spaceship_info::modules
int modules
Definition packets_gen.h:933
packet_spaceship_info::components
int components
Definition packets_gen.h:932
player_spaceship
Definition spaceship.h:94
player_spaceship::state
enum spaceship_state state
Definition spaceship.h:108
player_spaceship::launch_year
int launch_year
Definition spaceship.h:109
player
Definition player.h:249
player::spaceship
struct player_spaceship spaceship
Definition player.h:286
sship_part_info::required
int required
Definition spaceship.h:121
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47