Freeciv-3.1
Loading...
Searching...
No Matches
cma_core.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 2001 - R. Falke
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#ifdef HAVE_UNISTD_H
20#include <unistd.h>
21#endif
22
23/* utility */
24#include "bugs.h"
25#include "fcintl.h"
26#include "log.h"
27#include "mem.h"
28#include "shared.h" /* for MIN() */
29#include "specialist.h"
30#include "support.h"
31#include "timing.h"
32
33/* common */
34#include "city.h"
35#include "dataio.h"
36#include "events.h"
37#include "game.h"
38#include "government.h"
39#include "packets.h"
40#include "specialist.h"
41
42/* client */
43#include "attribute.h"
44#include "client_main.h"
45#include "climisc.h"
46#include "packhand.h"
47
48/* client/include */
49#include "chatline_g.h"
50#include "citydlg_g.h"
51#include "cityrep_g.h"
52#include "messagewin_g.h"
53
54/* client/agents */
55#include "agents.h"
56
57#include "cma_core.h"
58
59
60/*
61 * The CMA is an agent. The CMA will subscribe itself to all city
62 * events. So if a city changes the callback function city_changed is
63 * called. handle_city will be called from city_changed to update the
64 * given city. handle_city will call cma_query_result and
65 * apply_result_on_server to update the server city state.
66 */
67
68/****************************************************************************
69 Defines, structs, globals, forward declarations
70*****************************************************************************/
71
72#define log_apply_result log_debug
73#define log_handle_city log_debug
74#define log_handle_city2 log_debug
75#define log_results_are_equal log_debug
76
77#define SHOW_TIME_STATS FALSE
78#define SHOW_APPLY_RESULT_ON_SERVER_ERRORS FALSE
79#define ALWAYS_APPLY_AT_SERVER FALSE
80
81#define SAVED_PARAMETER_SIZE 30
82
83#define CMA_ATTR_VERSION 3
84#define CMA_ATTR_VERSION_MIN_SUPPORTED 2
85
86/*
87 * Misc statistic to analyze performance.
88 */
89static struct {
93
94/************************************************************************/
98static bool fc_results_are_equal(const struct cm_result *result1,
99 const struct cm_result *result2)
100{
101#define T(x) if (result1->x != result2->x) { \
102 log_results_are_equal(#x); \
103 return FALSE; }
104
105 T(disorder);
106 T(happy);
107
109 T(specialists[sp]);
111
113 T(surplus[ot]);
115
117 FALSE);
118 city_map_iterate(result1->city_radius_sq, cindex, x, y) {
119 if (is_free_worked_index(cindex)) {
120 continue;
121 }
122
123 if (result1->worker_positions[cindex]
124 != result2->worker_positions[cindex]) {
125 log_results_are_equal("worker_positions");
126
127 return FALSE;
128 }
130
131 return TRUE;
132
133#undef T
134}
135
136/************************************************************************/
140static struct city *check_city(int city_id, struct cm_parameter *parameter)
141{
142 struct city *pcity = game_city_by_number(city_id);
143 struct cm_parameter dummy;
144
145 if (!parameter) {
146 parameter = &dummy;
147 }
148
149 if (!pcity
150 || !cma_get_parameter(ATTR_CITY_CMA_PARAMETER, city_id, parameter)) {
151 return NULL;
152 }
153
154 if (city_owner(pcity) != client.conn.playing) {
155 cma_release_city(pcity);
156
157 return NULL;
158 }
159
160 return pcity;
161}
162
163/************************************************************************/
167static bool apply_result_on_server(struct city *pcity,
168 const struct cm_result *result)
169{
170 int first_request_id = 0, last_request_id = 0;
171 int city_radius_sq = city_map_radius_sq_get(pcity);
172 struct cm_result *current_state = cm_result_new(pcity);
173 bool success;
174 struct tile *pcenter = city_tile(pcity);
175
177 cm_result_from_main_map(current_state, pcity);
178
179 if (fc_results_are_equal(current_state, result)
181 stats.apply_result_ignored++;
182
183 return TRUE;
184 }
185
186 /* Do checks */
187 if (city_size_get(pcity) != cm_result_citizens(result)) {
188 log_error("apply_result_on_server(city %d=\"%s\") bad result!",
189 pcity->id, city_name_get(pcity));
190 cm_print_city(pcity);
191 cm_print_result(result);
192
193 return FALSE;
194 }
195
196 stats.apply_result_applied++;
197
198 log_apply_result("apply_result_on_server(city %d=\"%s\")",
199 pcity->id, city_name_get(pcity));
200
202
203 /* Remove all surplus workers */
204 city_tile_iterate_skip_free_worked(&(wld.map), city_radius_sq, pcenter,
205 ptile, idx, x, y) {
206 if (tile_worked(ptile) == pcity
207 && !result->worker_positions[idx]) {
208 log_apply_result("Removing worker at {%d,%d}.", x, y);
209
210 last_request_id =
212 pcity->id, pcity->id,
213 ptile->index);
214 if (first_request_id == 0) {
215 first_request_id = last_request_id;
216 }
217 }
219
220 /* Change the excess non-default specialists to default. */
222 int i;
223
224 if (sp == DEFAULT_SPECIALIST) {
225 continue;
226 }
227
228 for (i = 0; i < pcity->specialists[sp] - result->specialists[sp]; i++) {
229 log_apply_result("Change specialist from %d to %d.",
231 last_request_id = city_change_specialist(pcity,
233 if (first_request_id == 0) {
234 first_request_id = last_request_id;
235 }
236 }
238
239 /* now all surplus people are DEFAULT_SPECIALIST */
240
241 /* Set workers */
242 /* FIXME: This code assumes that any toggled worker will turn into a
243 * DEFAULT_SPECIALIST! */
244 city_tile_iterate_skip_free_worked(&(wld.map), city_radius_sq, pcenter, ptile, idx,
245 x, y) {
246 if (NULL == tile_worked(ptile)
247 && result->worker_positions[idx]) {
248 log_apply_result("Putting worker at {%d,%d}.", x, y);
249 fc_assert_action(city_can_work_tile(pcity, ptile), break);
250
251 last_request_id =
253 pcity->id, pcity->id, ptile->index);
254 if (first_request_id == 0) {
255 first_request_id = last_request_id;
256 }
257 }
259
260 /* Set all specialists except DEFAULT_SPECIALIST (all the unchanged
261 * ones remain as DEFAULT_SPECIALIST). */
263 int i;
264
265 if (sp == DEFAULT_SPECIALIST) {
266 continue;
267 }
268
269 for (i = 0; i < result->specialists[sp] - pcity->specialists[sp]; i++) {
270 log_apply_result("Changing specialist from %d to %d.",
272 last_request_id = city_change_specialist(pcity,
274 if (first_request_id == 0) {
275 first_request_id = last_request_id;
276 }
277 }
279
280 if (last_request_id == 0 || ALWAYS_APPLY_AT_SERVER) {
281 /*
282 * If last_request is 0 no change request was send. But it also
283 * means that the results are different or the fc_results_are_equal()
284 * test at the start of the function would be true. So this
285 * means that the client has other results for the same
286 * allocation of citizen than the server. We just send a
287 * PACKET_CITY_REFRESH to bring them in sync.
288 */
289 first_request_id = last_request_id
290 = dsend_packet_city_refresh(&client.conn, pcity->id, pcity->id);
291 stats.refresh_forced++;
292 }
293
295
296 if (last_request_id != 0) {
297 int city_id = pcity->id;
298
299 wait_for_requests("CMA", first_request_id, last_request_id);
300 if (pcity != check_city(city_id, NULL)) {
301 log_verbose("apply_result_on_server(city %d) !check_city()!", city_id);
302 return FALSE;
303 }
304 }
305
306 /* Return. */
307 cm_result_from_main_map(current_state, pcity);
308
309 success = fc_results_are_equal(current_state, result);
310 if (!success) {
311 cm_clear_cache(pcity);
312
313#if SHOW_APPLY_RESULT_ON_SERVER_ERRORS
314 log_error("apply_result_on_server(city %d=\"%s\") no match!",
315 pcity->id, city_name_get(pcity));
316
317 log_test("apply_result_on_server(city %d=\"%s\") have:",
318 pcity->id, city_name_get(pcity));
319 cm_print_city(pcity);
320 cm_print_result(current_state);
321
322 log_test("apply_result_on_server(city %d=\"%s\") want:",
323 pcity->id, city_name_get(pcity));
324 cm_print_result(result);
325#endif /* SHOW_APPLY_RESULT_ON_SERVER_ERRORS */
326 }
327
328 cm_result_destroy(current_state);
329
330 log_apply_result("apply_result_on_server() return %d.", (int) success);
331
332 return success;
333}
334
335/************************************************************************/
338static void report_stats(void)
339{
340#if SHOW_TIME_STATS
341 int total, per_mill;
342
343 total = stats.apply_result_ignored + stats.apply_result_applied;
344 per_mill = (stats.apply_result_ignored * 1000) / (total ? total : 1);
345
346 log_test("CMA: apply_result: ignored=%2d.%d%% (%d) "
347 "applied=%2d.%d%% (%d) total=%d",
348 per_mill / 10, per_mill % 10, stats.apply_result_ignored,
349 (1000 - per_mill) / 10, (1000 - per_mill) % 10,
350 stats.apply_result_applied, total);
351#endif /* SHOW_TIME_STATS */
352}
353
354/************************************************************************/
357static void release_city(int city_id)
358{
359 attr_city_set(ATTR_CITY_CMA_PARAMETER, city_id, 0, NULL);
360}
361
362/****************************************************************************
363 Algorithmic functions
364****************************************************************************/
365
366/************************************************************************/
371static void handle_city(struct city *pcity)
372{
373 struct cm_result *result = cm_result_new(pcity);
374 bool handled;
375 int i, city_id = pcity->id;
376
377 log_handle_city("handle_city(city %d=\"%s\") pos=(%d,%d) owner=%s",
378 pcity->id, city_name_get(pcity), TILE_XY(pcity->tile),
380
381 log_handle_city2("START handle city %d=\"%s\"",
382 pcity->id, city_name_get(pcity));
383
384 handled = FALSE;
385 for (i = 0; i < 5; i++) {
386 struct cm_parameter parameter;
387
388 log_handle_city2(" try %d", i);
389
390 if (pcity != check_city(city_id, &parameter)) {
391 handled = TRUE;
392 break;
393 }
394
395 cm_query_result(pcity, &parameter, result, FALSE);
396 if (!result->found_a_valid) {
397 log_handle_city2(" no valid found result");
398
399 cma_release_city(pcity);
400
401 create_event(city_tile(pcity), E_CITY_CMA_RELEASE, ftc_client,
402 _("The citizen governor can't fulfill the requirements "
403 "for %s. Passing back control."), city_link(pcity));
404 handled = TRUE;
405 break;
406 } else {
407 if (!apply_result_on_server(pcity, result)) {
408 log_handle_city2(" doesn't cleanly apply");
409 if (pcity == check_city(city_id, NULL) && i == 0) {
410 create_event(city_tile(pcity), E_CITY_CMA_RELEASE, ftc_client,
411 _("The citizen governor has gotten confused dealing "
412 "with %s. You may want to have a look."),
413 city_link(pcity));
414 }
415 } else {
416 log_handle_city2(" ok");
417 /* Everything ok */
418 handled = TRUE;
419 break;
420 }
421 }
422 }
423
424 cm_result_destroy(result);
425
426 if (!handled) {
427 fc_assert_ret(pcity == check_city(city_id, NULL));
428 log_handle_city2(" not handled");
429
430 create_event(city_tile(pcity), E_CITY_CMA_RELEASE, ftc_client,
431 _("The citizen governor has gotten confused dealing "
432 "with %s. You may want to have a look."),
433 city_link(pcity));
434
435 cma_release_city(pcity);
436
437 bugreport_request("handle_city() CMA: %s has changed multiple times.",
438 city_name_get(pcity));
439 }
440
441 log_handle_city2("END handle city=(%d)", city_id);
442}
443
444/************************************************************************/
447static void city_changed(int city_id)
448{
449 struct city *pcity = game_city_by_number(city_id);
450
451 if (pcity) {
452 cm_clear_cache(pcity);
453 handle_city(pcity);
454 }
455}
456
457/************************************************************************/
460static void city_remove(int city_id)
461{
462 release_city(city_id);
463}
464
465/************************************************************************/
468static void new_turn(void)
469{
470 report_stats();
471}
472
473/*************************** public interface ******************************/
474/************************************************************************/
477void cma_init(void)
478{
479 struct agent self;
480 struct timer *timer = stats.wall_timer;
481
482 log_debug("sizeof(struct cm_result)=%d",
483 (unsigned int) sizeof(struct cm_result));
484 log_debug("sizeof(struct cm_parameter)=%d",
485 (unsigned int) sizeof(struct cm_parameter));
486
487 /* reset cache counters */
488 memset(&stats, 0, sizeof(stats));
489
490 /* We used to just use timer_new here, but apparently cma_init can be
491 * called multiple times per client invocation so that lead to memory
492 * leaks. */
494
495 memset(&self, 0, sizeof(self));
496 strcpy(self.name, "CMA");
497 self.level = 1;
498 self.city_callbacks[CB_CHANGE] = city_changed;
499 self.city_callbacks[CB_NEW] = city_changed;
500 self.city_callbacks[CB_REMOVE] = city_remove;
501 self.turn_start_notify = new_turn;
503}
504
505/************************************************************************/
508bool cma_apply_result(struct city *pcity, const struct cm_result *result)
509{
510 fc_assert(!cma_is_city_under_agent(pcity, NULL));
511
512 if (result->found_a_valid) {
513 return apply_result_on_server(pcity, result);
514 } else {
515 return TRUE; /* ???????? */
516 }
517}
518
519/************************************************************************/
523 const struct cm_parameter *const parameter)
524{
525 log_debug("cma_put_city_under_agent(city %d=\"%s\")",
526 pcity->id, city_name_get(pcity));
527
529
530 cma_set_parameter(ATTR_CITY_CMA_PARAMETER, pcity->id, parameter);
531
532 cause_a_city_changed_for_agent("CMA", pcity);
533
534 log_debug("cma_put_city_under_agent: return");
535}
536
537/************************************************************************/
540void cma_release_city(struct city *pcity)
541{
542 release_city(pcity->id);
543 refresh_city_dialog(pcity);
545}
546
547/************************************************************************/
550bool cma_is_city_under_agent(const struct city *pcity,
551 struct cm_parameter *parameter)
552{
553 struct cm_parameter my_parameter;
554
555 if (!cma_get_parameter(ATTR_CITY_CMA_PARAMETER, pcity->id, &my_parameter)) {
556 return FALSE;
557 }
558
559 if (parameter != NULL) {
560 memcpy(parameter, &my_parameter, sizeof(struct cm_parameter));
561 }
562
563 return TRUE;
564}
565
566/************************************************************************/
573bool cma_get_parameter(enum attr_city attr, int city_id,
574 struct cm_parameter *parameter)
575{
576 size_t len;
577 char buffer[SAVED_PARAMETER_SIZE];
578 struct data_in din;
579 int version, dummy;
580
581 /* Changing this function is likely to break compatibility with old
582 * savegames that store these values. */
583
584 len = attr_city_get(attr, city_id, sizeof(buffer), buffer);
585 if (len == 0) {
586 return FALSE;
587 }
589
590 dio_input_init(&din, buffer, len);
591
592 dio_get_uint8_raw(&din, &version);
593 if (version > CMA_ATTR_VERSION && version < CMA_ATTR_VERSION_MIN_SUPPORTED) {
594 log_error("CMA data has a wrong version %d (expected %d)",
595 version, CMA_ATTR_VERSION);
596 return FALSE;
597 }
598
599 /* Initialize the parameter (includes some AI-only fields that aren't
600 * touched below). */
601 cm_init_parameter(parameter);
602
604 dio_get_sint16_raw(&din, &parameter->minimal_surplus[i]);
605 dio_get_sint16_raw(&din, &parameter->factor[i]);
607
608 dio_get_sint16_raw(&din, &parameter->happy_factor);
609 dio_get_uint8_raw(&din, &dummy); /* Dummy value; used to be factor_target. */
610 dio_get_bool8_raw(&din, &parameter->require_happy);
611 if (version > 2) {
612 dio_get_bool8_raw(&din, &parameter->max_growth);
613 }
614
615 return TRUE;
616}
617
618/************************************************************************/
621void cma_set_parameter(enum attr_city attr, int city_id,
622 const struct cm_parameter *parameter)
623{
624 char buffer[SAVED_PARAMETER_SIZE];
625 struct raw_data_out dout;
626
627 /* Changing this function is likely to break compatibility with old
628 * savegames that store these values. */
629
630 dio_output_init(&dout, buffer, sizeof(buffer));
631
633
635 dio_put_sint16_raw(&dout, parameter->minimal_surplus[i]);
636 dio_put_sint16_raw(&dout, parameter->factor[i]);
638
639 dio_put_sint16_raw(&dout, parameter->happy_factor);
640 dio_put_uint8_raw(&dout, 0); /* Dummy value; used to be factor_target. */
641 dio_put_bool8_raw(&dout, parameter->require_happy);
642 dio_put_bool8_raw(&dout, parameter->max_growth);
643
645
646 attr_city_set(attr, city_id, SAVED_PARAMETER_SIZE, buffer);
647}
void wait_for_requests(const char *agent_name, int first_request_id, int last_request_id)
Definition agents.c:735
void cause_a_city_changed_for_agent(const char *name_of_calling_agent, struct city *pcity)
Definition agents.c:786
void register_agent(const struct agent *agent)
Definition agents.c:378
@ CB_NEW
Definition agents.h:37
@ CB_REMOVE
Definition agents.h:37
@ CB_CHANGE
Definition agents.h:37
size_t attr_city_get(enum attr_city what, int city_id, size_t max_data_length, void *data)
Definition attribute.c:491
void attr_city_set(enum attr_city what, int city_id, size_t data_length, const void *const data)
Definition attribute.c:482
attr_city
Definition attribute.h:37
@ ATTR_CITY_CMA_PARAMETER
Definition attribute.h:38
void bugreport_request(const char *reason_format,...)
Definition bugs.c:31
const char * city_name_get(const struct city *pcity)
Definition city.c:1111
int city_map_radius_sq_get(const struct city *pcity)
Definition city.c:132
bool city_can_work_tile(const struct city *pcity, const struct tile *ptile)
Definition city.c:1425
#define city_tile(_pcity_)
Definition city.h:544
static citizens city_size_get(const struct city *pcity)
Definition city.h:549
#define city_tile_iterate_skip_free_worked(_nmap, _radius_sq, _city_tile, _tile, _index, _x, _y)
Definition city.h:206
#define output_type_iterate(output)
Definition city.h:812
#define city_owner(_pcity_)
Definition city.h:543
#define city_tile_iterate_skip_free_worked_end
Definition city.h:214
#define city_map_iterate_end
Definition city.h:169
#define city_map_iterate(_radius_sq, _index, _x, _y)
Definition city.h:165
#define is_free_worked_index(city_tile_index)
Definition city.h:847
#define output_type_iterate_end
Definition city.h:818
int city_change_specialist(struct city *pcity, Specialist_type_id from, Specialist_type_id to)
void refresh_city_dialog(struct city *pcity)
void city_report_dialog_update_city(struct city *pcity)
static struct ai_type * self
Definition classicai.c:46
struct civclient client
void create_event(struct tile *ptile, enum event_type event, const struct ft_color color, const char *format,...)
Definition climisc.c:1075
void cm_clear_cache(struct city *pcity)
Definition cm.c:320
void cm_init_parameter(struct cm_parameter *dest)
Definition cm.c:2178
struct cm_result * cm_result_new(struct city *pcity)
Definition cm.c:343
void cm_result_from_main_map(struct cm_result *result, const struct city *pcity)
Definition cm.c:2256
void cm_result_destroy(struct cm_result *result)
Definition cm.c:366
void cm_print_result(const struct cm_result *result)
Definition cm.c:2464
void cm_query_result(struct city *pcity, const struct cm_parameter *param, struct cm_result *result, bool negative_ok)
Definition cm.c:2118
int cm_result_citizens(const struct cm_result *result)
Definition cm.c:2247
void cm_print_city(const struct city *pcity)
Definition cm.c:2426
#define ALWAYS_APPLY_AT_SERVER
Definition cma_core.c:79
int refresh_forced
Definition cma_core.c:91
#define T(x)
#define log_handle_city
Definition cma_core.c:73
static struct city * check_city(int city_id, struct cm_parameter *parameter)
Definition cma_core.c:140
#define CMA_ATTR_VERSION_MIN_SUPPORTED
Definition cma_core.c:84
static void report_stats(void)
Definition cma_core.c:338
#define SAVED_PARAMETER_SIZE
Definition cma_core.c:81
#define log_results_are_equal
Definition cma_core.c:75
#define log_handle_city2
Definition cma_core.c:74
bool cma_is_city_under_agent(const struct city *pcity, struct cm_parameter *parameter)
Definition cma_core.c:550
static struct @126 stats
static void city_changed(int city_id)
Definition cma_core.c:447
int apply_result_ignored
Definition cma_core.c:91
static void release_city(int city_id)
Definition cma_core.c:357
struct timer * wall_timer
Definition cma_core.c:90
void cma_put_city_under_agent(struct city *pcity, const struct cm_parameter *const parameter)
Definition cma_core.c:522
static void city_remove(int city_id)
Definition cma_core.c:460
static void new_turn(void)
Definition cma_core.c:468
static void handle_city(struct city *pcity)
Definition cma_core.c:371
int apply_result_applied
Definition cma_core.c:91
bool cma_get_parameter(enum attr_city attr, int city_id, struct cm_parameter *parameter)
Definition cma_core.c:573
static bool apply_result_on_server(struct city *pcity, const struct cm_result *result)
Definition cma_core.c:167
static bool fc_results_are_equal(const struct cm_result *result1, const struct cm_result *result2)
Definition cma_core.c:98
void cma_release_city(struct city *pcity)
Definition cma_core.c:540
#define CMA_ATTR_VERSION
Definition cma_core.c:83
void cma_set_parameter(enum attr_city attr, int city_id, const struct cm_parameter *parameter)
Definition cma_core.c:621
bool cma_apply_result(struct city *pcity, const struct cm_result *result)
Definition cma_core.c:508
#define log_apply_result
Definition cma_core.c:72
void cma_init(void)
Definition cma_core.c:477
void connection_do_buffer(struct connection *pc)
Definition connection.c:323
void connection_do_unbuffer(struct connection *pc)
Definition connection.c:335
void dio_put_bool8_raw(struct raw_data_out *dout, bool value)
Definition dataio_raw.c:381
void dio_output_init(struct raw_data_out *dout, void *destination, size_t dest_size)
Definition dataio_raw.c:171
void dio_put_uint8_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:265
void dio_put_sint16_raw(struct raw_data_out *dout, int value)
Definition dataio_raw.c:361
bool dio_get_sint16_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:751
bool dio_get_uint8_raw(struct data_in *din, int *dest)
Definition dataio_raw.c:572
bool dio_get_bool8_raw(struct data_in *din, bool *dest)
Definition dataio_raw.c:661
size_t dio_output_used(struct raw_data_out *dout)
Definition dataio_raw.c:184
void dio_input_init(struct data_in *din, const void *src, size_t src_size)
Definition dataio_raw.c:202
#define _(String)
Definition fcintl.h:67
const struct ft_color ftc_client
const char * city_link(const struct city *pcity)
struct world wld
Definition game.c:58
struct city * game_city_by_number(int id)
Definition game.c:102
#define fc_assert_ret(condition)
Definition log.h:191
#define log_test
Definition log.h:136
#define log_verbose(message,...)
Definition log.h:109
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define fc_assert_action(condition, action)
Definition log.h:187
#define log_debug(message,...)
Definition log.h:115
#define log_error(message,...)
Definition log.h:103
const char * nation_rule_name(const struct nation_type *pnation)
Definition nation.c:137
struct nation_type * nation_of_city(const struct city *pcity)
Definition nation.c:453
int dsend_packet_city_make_worker(struct connection *pc, int city_id16, int city_id32, int tile_id)
int dsend_packet_city_make_specialist(struct connection *pc, int city_id16, int city_id32, int tile_id)
int dsend_packet_city_refresh(struct connection *pc, int city_id16, int city_id32)
int len
Definition packhand.c:125
struct specialist specialists[SP_MAX]
Definition specialist.c:30
#define specialist_type_iterate_end
Definition specialist.h:79
#define specialist_type_iterate(sp)
Definition specialist.h:73
#define DEFAULT_SPECIALIST
Definition specialist.h:43
Definition agents.h:40
char name[MAX_LEN_NAME]
Definition ai.h:51
Definition city.h:309
int id
Definition city.h:315
citizens specialists[SP_MAX]
Definition city.h:324
struct tile * tile
Definition city.h:311
struct connection conn
Definition client_main.h:96
int factor[O_LAST]
Definition cm.h:47
bool max_growth
Definition cm.h:42
bool require_happy
Definition cm.h:43
int minimal_surplus[O_LAST]
Definition cm.h:41
int happy_factor
Definition cm.h:48
Definition cm.h:52
bool found_a_valid
Definition cm.h:54
bool * worker_positions
Definition cm.h:59
int city_radius_sq
Definition cm.h:58
citizens specialists[SP_MAX]
Definition cm.h:60
struct player * playing
Definition connection.h:156
Definition tile.h:49
Definition timing.c:81
struct civ_map map
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define tile_worked(_tile)
Definition tile.h:113
#define TILE_XY(ptile)
Definition tile.h:42
struct timer * timer_renew(struct timer *t, enum timer_timetype type, enum timer_use use)
Definition timing.c:176
@ TIMER_ACTIVE
Definition timing.h:45
@ TIMER_USER
Definition timing.h:41