Freeciv-3.3: /fast/freeciv/nightly/main/client/global_worklist.c Source File

Freeciv-3.3

Loading...
Searching...
No Matches
global_worklist.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#ifdef HAVE_CONFIG_H
14#include <fc_config.h>
15#endif
16
17#include <stdarg.h>
18
19/* utility */
20#include "fcintl.h"
21#include "log.h"
22#include "mem.h"
23#include "registry.h"
24#include "shared.h"
25#include "support.h"
26
27/* common */
28#include "fc_types.h"
29#include "requirements.h"
30#include "worklist.h"
31
32/* client */
33#include "client_main.h"
34
35#include "global_worklist.h"
36
37 enum global_worklist_status {
38 /* Means we have a list of kind of universal and their name, but we
39 * don't know the id they could have on the server's ruleset. In this
40 * case, we use the unbuilt part and not the worklist one. */
41 STATUS_UNBUILT,
42
43 /* Means this worklist is plainly usable at running time. */
44 STATUS_WORKLIST
45};
46
47
48/* The global worklist structure. */
49 struct global_worklist {
50 int id;
51 char name[MAX_LEN_NAME];
52 enum global_worklist_status status;
53 union {
54 struct {
55 int length;
56 struct uni_name {
57 char *kind;
58 char *name;
59 } entries[MAX_LEN_WORKLIST];
60 } unbuilt;
61 struct worklist worklist;
62 };
63};
64
65static bool global_worklist_load(struct section_file *file,
66 const char *path, ...)
67 fc__attribute((__format__ (__printf__, 2, 3)));
68 static void global_worklist_save(const struct global_worklist *pgwl,
69 struct section_file *file, int fill_until,
70 const char *path, ...)
71 fc__attribute((__format__ (__printf__, 4, 5)));
72
73/*******************************************************************/
76 void global_worklists_init(void)
77{
78 if (!client.worklists) {
79 client.worklists = global_worklist_list_new();
80 }
81}
82
83/*******************************************************************/
86 void global_worklists_free(void)
87{
88 if (client.worklists) {
89 global_worklists_iterate_all(pgwl) {
90 global_worklist_destroy(pgwl);
91 } global_worklists_iterate_all_end;
92 global_worklist_list_destroy(client.worklists);
93 client.worklists = NULL;
94 }
95}
96
97/*******************************************************************/
100 void global_worklists_build(void)
101{
102 global_worklists_iterate_all(pgwl) {
103 if (pgwl->status == STATUS_UNBUILT) {
104 struct worklist worklist;
105 struct uni_name *puni_name;
106 int i;
107
108 /* Build a worklist. */
109 worklist_init(&worklist);
110 for (i = 0; i < pgwl->unbuilt.length; i++) {
111 struct universal source;
112
113 puni_name = pgwl->unbuilt.entries + i;
114 source = universal_by_rule_name(puni_name->kind, puni_name->name);
115 if (source.kind == universals_n_invalid()) {
116 /* This worklist is not valid on this ruleset.
117 * N.B.: Don't remove it to resave it in client rc file. */
118 break;
119 } else {
120 worklist_append(&worklist, &source);
121 }
122 }
123
124 if (worklist_length(&worklist) != pgwl->unbuilt.length) {
125 /* Somewhat in this worklist is not supported by the current
126 * ruleset. Don't try to build it, but keep it for later save. */
127 continue;
128 }
129
130 /* Now the worklist is built, change status. */
131 for (i = 0; i < pgwl->unbuilt.length; i++) {
132 puni_name = pgwl->unbuilt.entries + i;
133 free(puni_name->kind);
134 free(puni_name->name);
135 }
136 pgwl->status = STATUS_WORKLIST;
137 worklist_copy(&pgwl->worklist, &worklist);
138 }
139 } global_worklists_iterate_all_end;
140}
141
142/*******************************************************************/
145 void global_worklists_unbuild(void)
146{
147 global_worklists_iterate_all(pgwl) {
148 if (pgwl->status == STATUS_WORKLIST) {
149 struct worklist worklist;
150 struct uni_name *puni_name;
151 int i;
152
153 /* Copy before over-write. */
154 worklist_copy(&worklist, &pgwl->worklist);
155 pgwl->status = STATUS_UNBUILT;
156
157 pgwl->unbuilt.length = worklist_length(&worklist);
158 for (i = 0; i < worklist_length(&worklist); i++) {
159 puni_name = pgwl->unbuilt.entries + i;
160 puni_name->kind =
161 fc_strdup(universal_type_rule_name(worklist.entries + i));
162 puni_name->name =
163 fc_strdup(universal_rule_name(worklist.entries + i));
164 }
165 }
166 } global_worklists_iterate_all_end;
167}
168
169/*******************************************************************/
173 int global_worklists_number(void)
174{
175 int count = 0;
176
177 global_worklists_iterate(pgwl) {
178 count++;
179 } global_worklists_iterate_end;
180
181 return count;
182}
183
184/*******************************************************************/
187static struct global_worklist *
188global_worklist_alloc(enum global_worklist_status type)
189{
190 static int last_id = 0;
191 struct global_worklist *pgwl = fc_calloc(1, sizeof(struct global_worklist));
192
193 pgwl->id = ++last_id;
194 pgwl->status = type;
195
196 /* Specific initializer. */
197 switch (pgwl->status) {
198 case STATUS_UNBUILT:
199 /* All members set to 0 by fc_calloc. */
200 break;
201 case STATUS_WORKLIST:
202 worklist_init(&pgwl->worklist);
203 break;
204 }
205
206 global_worklist_list_append(client.worklists, pgwl);
207
208 return pgwl;
209}
210
211/*******************************************************************/
214 void global_worklist_destroy(struct global_worklist *pgwl)
215{
216 fc_assert_ret(NULL != pgwl);
217
218 global_worklist_list_remove(client.worklists, pgwl);
219
220 /* Specific descturctor. */
221 switch (pgwl->status) {
222 case STATUS_UNBUILT:
223 {
224 struct uni_name *puni_name;
225 int i;
226
227 for (i = 0; i < pgwl->unbuilt.length; i++) {
228 puni_name = pgwl->unbuilt.entries + i;
229 free(puni_name->kind);
230 free(puni_name->name);
231 }
232 }
233 break;
234 case STATUS_WORKLIST:
235 break;
236 }
237
238 free(pgwl);
239}
240
241/*******************************************************************/
244 struct global_worklist *global_worklist_new(const char *name)
245{
246 struct global_worklist *pgwl = global_worklist_alloc(STATUS_WORKLIST);
247
248 global_worklist_set_name(pgwl, name);
249 return pgwl;
250}
251
252/*******************************************************************/
255 bool global_worklist_is_valid(const struct global_worklist *pgwl)
256{
257 return pgwl && pgwl->status == STATUS_WORKLIST;
258}
259
260/*******************************************************************/
263 bool global_worklist_set(struct global_worklist *pgwl,
264 const struct worklist *pwl)
265{
266 if (pgwl && pgwl->status == STATUS_WORKLIST && pwl) {
267 worklist_copy(&pgwl->worklist, pwl);
268 return TRUE;
269 }
270 return FALSE;
271}
272
273/*******************************************************************/
276 const struct worklist *global_worklist_get(const struct global_worklist *pgwl)
277{
278 if (pgwl && pgwl->status == STATUS_WORKLIST) {
279 return &pgwl->worklist;
280 } else {
281 return NULL;
282 }
283}
284
285/*******************************************************************/
288 int global_worklist_id(const struct global_worklist *pgwl)
289{
290 fc_assert_ret_val(NULL != pgwl, -1);
291 return pgwl->id;
292}
293
294/*******************************************************************/
298 struct global_worklist *global_worklist_by_id(int id)
299{
300 global_worklists_iterate_all(pgwl) {
301 if (pgwl->id == id) {
302 return pgwl;
303 }
304 } global_worklists_iterate_all_end;
305
306 return NULL;
307}
308
309/*******************************************************************/
312 void global_worklist_set_name(struct global_worklist *pgwl,
313 const char *name)
314{
315 if (name) {
316 sz_strlcpy(pgwl->name, name);
317 }
318}
319
320/*******************************************************************/
323 const char *global_worklist_name(const struct global_worklist *pgwl)
324{
325 fc_assert_ret_val(NULL != pgwl, NULL);
326 return pgwl->name;
327}
328
329/*******************************************************************/
333 static bool global_worklist_load(struct section_file *file,
334 const char *path, ...)
335{
336 struct global_worklist *pgwl;
337 const char *kind;
338 const char *name;
339 char path_str[1024];
340 va_list ap;
341 int i, length;
342
343 /* The first part of the registry path is taken from the varargs to the
344 * function. */
345 va_start(ap, path);
346 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
347 va_end(ap);
348
349 length = secfile_lookup_int_default(file, -1, "%s.wl_length", path_str);
350 if (length == -1) {
351 /* Not set. */
352 return FALSE;
353 }
354 length = MIN(length, MAX_LEN_WORKLIST);
355 pgwl = global_worklist_alloc(STATUS_UNBUILT);
356 global_worklist_set_name(pgwl,
357 secfile_lookup_str_default(file, _("(noname)"),
358 "%s.wl_name",
359 path_str));
360
361 for (i = 0; i < length; i++) {
362 kind = secfile_lookup_str_default(file, NULL, "%s.wl_kind%d",
363 path_str, i);
364
365 if (!kind) {
366 /* before 2.2.0 unit production was indicated by flag. */
367 bool is_unit = secfile_lookup_bool_default(file, FALSE,
368 "%s.wl_is_unit%d",
369 path_str, i);
370 kind = universals_n_name(is_unit ? VUT_UTYPE : VUT_IMPROVEMENT);
371 }
372
373 name = secfile_lookup_str_default(file, NULL, "%s.wl_value%d",
374 path_str, i);
375 if (NULL == kind || '\0' == kind[0] || NULL == name || '\0' == name[0]) {
376 break;
377 } else {
378 pgwl->unbuilt.entries[i].kind = fc_strdup(kind);
379 pgwl->unbuilt.entries[i].name = fc_strdup(name);
380 pgwl->unbuilt.length++;
381 }
382 }
383
384 return TRUE;
385}
386
387/*******************************************************************/
390 void global_worklists_load(struct section_file *file)
391{
392 int i;
393
394 /* Clear the current global worklists. */
395 global_worklists_iterate_all(pgwl) {
396 global_worklist_destroy(pgwl);
397 } global_worklists_iterate_all_end;
398
399 for (i = 0; global_worklist_load(file, "worklists.worklist%d", i); i++) {
400 /* Nothing to do more. */
401 }
402
403 if (C_S_RUNNING <= client_state()) {
404 /* We need to build the worklists immediately. */
405 global_worklists_build();
406 }
407}
408
409/*******************************************************************/
412 static void global_worklist_save(const struct global_worklist *pgwl,
413 struct section_file *file, int fill_until,
414 const char *path, ...)
415{
416 char path_str[1024];
417 int i = 0;
418 va_list ap;
419
420 /* The first part of the registry path is taken from the varargs to the
421 * function. */
422 va_start(ap, path);
423 fc_vsnprintf(path_str, sizeof(path_str), path, ap);
424 va_end(ap);
425
426 secfile_insert_str(file, pgwl->name, "%s.wl_name", path_str);
427
428 switch (pgwl->status) {
429 case STATUS_UNBUILT:
430 secfile_insert_int(file, pgwl->unbuilt.length,
431 "%s.wl_length", path_str);
432 for (i = 0; i < pgwl->unbuilt.length; i++) {
433 secfile_insert_str(file, pgwl->unbuilt.entries[i].kind,
434 "%s.wl_kind%d", path_str, i);
435 secfile_insert_str(file, pgwl->unbuilt.entries[i].name,
436 "%s.wl_value%d", path_str, i);
437 }
438 break;
439 case STATUS_WORKLIST:
440 secfile_insert_int(file, worklist_length(&pgwl->worklist),
441 "%s.wl_length", path_str);
442 for (i = 0; i < pgwl->unbuilt.length; i++) {
443 secfile_insert_str(file,
444 universal_type_rule_name(pgwl->worklist.entries + i),
445 "%s.wl_kind%d", path_str, i);
446 secfile_insert_str(file,
447 universal_rule_name(pgwl->worklist.entries + i),
448 "%s.wl_value%d", path_str, i);
449 }
450 break;
451 }
452
453 /* We want to keep savegame in tabular format, so each line has to be
454 * of equal length. Fill table up to maximum worklist size. */
455 while (i < fill_until) {
456 secfile_insert_str(file, "", "%s.wl_kind%d", path_str, i);
457 secfile_insert_str(file, "", "%s.wl_value%d", path_str, i);
458 i++;
459 }
460}
461
462/*******************************************************************/
465 void global_worklists_save(struct section_file *file)
466{
467 int max_length = 0;
468 int i = 0;
469
470 /* We want to keep savegame in tabular format, so each line has to be
471 * of equal length. So we need to know about the biggest worklist. */
472 global_worklists_iterate_all(pgwl) {
473 switch (pgwl->status) {
474 case STATUS_UNBUILT:
475 max_length = MAX(max_length, pgwl->unbuilt.length);
476 break;
477 case STATUS_WORKLIST:
478 max_length = MAX(max_length, worklist_length(&pgwl->worklist));
479 break;
480 }
481 } global_worklists_iterate_all_end;
482
483 global_worklists_iterate_all(pgwl) {
484 global_worklist_save(pgwl, file, max_length,
485 "worklists.worklist%d", i++);
486 } global_worklists_iterate_all_end;
487}
client
struct civclient client
Definition client_main.c:150
client_state
enum client_states client_state(void)
Definition client_main.c:1026
client_main.h
C_S_RUNNING
@ C_S_RUNNING
Definition client_main.h:47
incite_cost
char * incite_cost
Definition comments.c:74
fc_types.h
MAX_LEN_NAME
#define MAX_LEN_NAME
Definition fc_types.h:66
fcintl.h
_
#define _(String)
Definition fcintl.h:67
global_worklist_by_id
struct global_worklist * global_worklist_by_id(int id)
Definition global_worklist.c:298
global_worklist_alloc
static struct global_worklist * global_worklist_alloc(enum global_worklist_status type)
Definition global_worklist.c:188
global_worklist_set
bool global_worklist_set(struct global_worklist *pgwl, const struct worklist *pwl)
Definition global_worklist.c:263
global_worklist_name
const char * global_worklist_name(const struct global_worklist *pgwl)
Definition global_worklist.c:323
global_worklist_id
int global_worklist_id(const struct global_worklist *pgwl)
Definition global_worklist.c:288
global_worklist_status
global_worklist_status
Definition global_worklist.c:37
STATUS_WORKLIST
@ STATUS_WORKLIST
Definition global_worklist.c:44
STATUS_UNBUILT
@ STATUS_UNBUILT
Definition global_worklist.c:41
global_worklists_number
int global_worklists_number(void)
Definition global_worklist.c:173
global_worklist_is_valid
bool global_worklist_is_valid(const struct global_worklist *pgwl)
Definition global_worklist.c:255
global_worklist_destroy
void global_worklist_destroy(struct global_worklist *pgwl)
Definition global_worklist.c:214
global_worklist_save
static bool static void global_worklist_save(const struct global_worklist *pgwl, struct section_file *file, int fill_until, const char *path,...) fc__attribute((__format__(__printf__
Definition global_worklist.c:412
global_worklists_build
void global_worklists_build(void)
Definition global_worklist.c:100
global_worklist_load
static bool global_worklist_load(struct section_file *file, const char *path,...) fc__attribute((__format__(__printf__
Definition global_worklist.c:333
global_worklist_get
const struct worklist * global_worklist_get(const struct global_worklist *pgwl)
Definition global_worklist.c:276
global_worklists_init
static bool static void void global_worklists_init(void)
Definition global_worklist.c:76
global_worklists_load
void global_worklists_load(struct section_file *file)
Definition global_worklist.c:390
global_worklists_free
void global_worklists_free(void)
Definition global_worklist.c:86
global_worklist_new
struct global_worklist * global_worklist_new(const char *name)
Definition global_worklist.c:244
global_worklists_unbuild
void global_worklists_unbuild(void)
Definition global_worklist.c:145
global_worklists_save
void global_worklists_save(struct section_file *file)
Definition global_worklist.c:465
global_worklist_set_name
void global_worklist_set_name(struct global_worklist *pgwl, const char *name)
Definition global_worklist.c:312
global_worklist.h
global_worklists_iterate_all_end
#define global_worklists_iterate_all_end
Definition global_worklist.h:60
global_worklists_iterate_all
#define global_worklists_iterate_all(pgwl)
Definition global_worklist.h:57
global_worklists_iterate
#define global_worklists_iterate(pgwl)
Definition global_worklist.h:65
global_worklists_iterate_end
#define global_worklists_iterate_end
Definition global_worklist.h:68
source
static GtkWidget * source
Definition gotodlg.c:58
type
GType type
Definition repodlgs.c:1313
name
const char * name
Definition inputfile.c:127
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
fc_assert_ret_val
#define fc_assert_ret_val(condition, val)
Definition log.h:194
mem.h
fc_calloc
#define fc_calloc(n, esz)
Definition mem.h:38
fc_strdup
#define fc_strdup(str)
Definition mem.h:43
registry.h
secfile_lookup_bool_default
bool secfile_lookup_bool_default(const struct section_file *secfile, bool def, const char *path,...)
Definition registry_ini.c:1900
secfile_lookup_int_default
int secfile_lookup_int_default(const struct section_file *secfile, int def, const char *path,...)
Definition registry_ini.c:2000
secfile_lookup_str_default
const char * secfile_lookup_str_default(const struct section_file *secfile, const char *def, const char *path,...)
Definition registry_ini.c:2205
secfile_insert_int
#define secfile_insert_int(secfile, value, path,...)
Definition registry_ini.h:116
secfile_insert_str
#define secfile_insert_str(secfile, string, path,...)
Definition registry_ini.h:170
universal_rule_name
const char * universal_rule_name(const struct universal *psource)
Definition requirements.c:6800
universal_type_rule_name
const char * universal_type_rule_name(const struct universal *psource)
Definition requirements.c:7313
universal_by_rule_name
struct universal universal_by_rule_name(const char *kind, const char *value)
Definition requirements.c:236
requirements.h
shared.h
MIN
#define MIN(x, y)
Definition shared.h:55
MAX
#define MAX(x, y)
Definition shared.h:54
civclient::worklists
struct global_worklist_list * worklists
Definition client_main.h:97
global_worklist
Definition global_worklist.c:49
global_worklist::kind
char * kind
Definition global_worklist.c:57
global_worklist::length
int length
Definition global_worklist.c:55
global_worklist::unbuilt
struct global_worklist::@131::@133 unbuilt
global_worklist::entries
struct global_worklist::@131::@133::uni_name entries[MAX_LEN_WORKLIST]
global_worklist::status
enum global_worklist_status status
Definition global_worklist.c:52
global_worklist::id
int id
Definition global_worklist.c:50
global_worklist::name
char * name
Definition global_worklist.c:58
global_worklist::name
char name[MAX_LEN_NAME]
Definition global_worklist.c:51
section_file
Definition section_file.h:36
section_file::entries
struct entry_hash * entries
Definition section_file.h:49
section_file::name
char * name
Definition section_file.h:37
universal
Definition fc_types.h:908
worklist
Definition worklist.h:28
worklist::entries
struct universal entries[MAX_LEN_WORKLIST]
Definition worklist.h:30
fc_vsnprintf
int fc_vsnprintf(char *str, size_t n, const char *format, va_list ap)
Definition support.c:886
support.h
sz_strlcpy
#define sz_strlcpy(dest, src)
Definition support.h:189
fc__attribute
#define fc__attribute(x)
Definition support.h:99
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
worklist_copy
void worklist_copy(struct worklist *dst, const struct worklist *src)
Definition worklist.c:112
worklist_init
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
worklist_append
bool worklist_append(struct worklist *pwl, const struct universal *prod)
Definition worklist.c:147
worklist_length
int worklist_length(const struct worklist *pwl)
Definition worklist.c:57
worklist.h
MAX_LEN_WORKLIST
#define MAX_LEN_WORKLIST
Definition worklist.h:24