Freeciv-3.2
Loading...
Searching...
No Matches
tech.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 <stdlib.h> /* exit */
19#include <string.h>
20#include <math.h>
21
22/* utility */
23#include "fcintl.h"
24#include "iterator.h"
25#include "log.h"
26#include "mem.h" /* free */
27#include "shared.h" /* ARRAY_SIZE */
28#include "string_vector.h"
29#include "support.h"
30
31/* common */
32#include "game.h"
33#include "research.h"
34
35#include "tech.h"
36
37
39 struct iterator base;
41 const struct advance *array[A_LAST];
42 const struct advance **current, **end;
43};
44#define ADVANCE_REQ_ITER(it) ((struct advance_req_iter *) it)
45
47 struct iterator base;
49 const struct advance *array[A_LAST];
50 const struct advance **current, **end;
51};
52#define ADVANCE_ROOT_REQ_ITER(it) ((struct advance_root_req_iter *) it)
53
54/* the advances array is now setup in:
55 * server/ruleset.c (for the server)
56 * client/packhand.c (for the client)
57 */
59
61
63
64/**********************************************************************/
67const struct advance *advance_array_last(void)
68{
69 if (game.control.num_tech_types > 0) {
71 }
72 return NULL;
73}
74
75/**********************************************************************/
82
83/**********************************************************************/
94
95/**********************************************************************/
99{
101 return padvance->item_number;
102}
103
104/**********************************************************************/
108{
109 if (atype != A_FUTURE
111 /* This isn't an error; some callers depend on it. */
112 return NULL;
113 }
114
115 return &advances[atype];
116}
117
118/**********************************************************************/
122 enum tech_req require)
123{
125 fc_assert_ret_val(tech >= A_NONE && tech < A_LAST, -1);
126 if (A_NEVER == advances[tech].require[require]) {
127 /* out of range */
128 return A_LAST;
129 }
130 return advance_number(advances[tech].require[require]);
131}
132
133/**********************************************************************/
137 enum tech_req require)
138{
141 return padvance->require[require];
142}
143
144/**********************************************************************/
153{
154 if (padvance == NULL) {
155 return NULL;
156 }
157
158 if (padvance->item_number == A_FUTURE) {
159 return padvance;
160 }
161
162 if (A_NEVER == padvance->require[AR_ONE]
163 || A_NEVER == padvance->require[AR_TWO]) {
164 return NULL;
165 }
166
167 return padvance;
168}
169
170/**********************************************************************/
180
181/**********************************************************************/
186{
189 return padvance;
190 }
192
193 return NULL;
194}
195
196/**********************************************************************/
201{
202 const char *qname = Qn_(name);
203
206 return padvance;
207 }
209
210 return NULL;
211}
212
213/**********************************************************************/
217{
219 return BV_ISSET(advance_by_number(tech)->flags, flag);
220}
221
222/**********************************************************************/
226{
228 "Invalid tech_cost_style %d", game.info.tech_cost_style);
229
231 int num_reqs = 0;
232 bool min_req = TRUE;
233
235 (void) preq; /* Compiler wants us to do something with 'preq'. */
236 num_reqs++;
238 padvance->num_reqs = num_reqs;
239
240 switch (game.info.tech_cost_style) {
242 case TECH_COST_LINEAR:
244 break;
246 if (-1 != padvance->cost) {
247 min_req = FALSE;
248 break;
249 }
250 fc__fallthrough; /* No break. */
252 padvance->cost = game.info.base_tech_cost * (1.0 + num_reqs)
253 * sqrt(1.0 + num_reqs) / 2;
254 break;
256 if (-1 != padvance->cost) {
257 min_req = FALSE;
258 break;
259 }
260 fc__fallthrough; /* No break. */
263 / (1 + sqrt(sqrt(num_reqs + 1))) - 0.5);
264 break;
265 }
266
267 if (min_req && padvance->cost < game.info.min_tech_cost) {
269 }
270
271 /* Class cost */
272 if (padvance->tclass != NULL) {
273 padvance->cost = padvance->cost * padvance->tclass->cost_pct / 100;
274 }
276}
277
278/**********************************************************************/
282{
283 return tech == A_FUTURE;
284}
285
286/**********************************************************************/
290const char *advance_name_translation(const struct advance *padvance)
291{
292 return name_translation_get(&padvance->name);
293}
294
295/**********************************************************************/
299const char *advance_rule_name(const struct advance *padvance)
300{
301 return rule_name_get(&padvance->name);
302}
303
304/**********************************************************************/
308{
309 int i;
310
311 for (i = 0; i < MAX_NUM_TECH_CLASSES; i++) {
312 tech_classes[i].idx = i;
314 }
315}
316
317/**********************************************************************/
321{
323 return NULL;
324 }
325
326 return &tech_classes[idx];
327}
328
329/**********************************************************************/
334{
335 return name_translation_get(&ptclass->name);
336}
337
338/**********************************************************************/
342const char *tech_class_rule_name(const struct tech_class *ptclass)
343{
344 return rule_name_get(&ptclass->name);
345}
346
347/**********************************************************************/
352{
353 const char *qname = Qn_(name);
354 int i;
355
356 for (i = 0; i < game.control.num_tech_classes; i++) {
358
360 return ptclass;
361 }
362 }
363
364 return NULL;
365}
366
367/**********************************************************************/
371{
372 int i;
373
374 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
376 }
377}
378
379/**********************************************************************/
383{
384 int i;
385
386 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
388 }
389}
390
391/**********************************************************************/
394void set_user_tech_flag_name(enum tech_flag_id id, const char *name,
395 const char *helptxt)
396{
397 int tfid = id - TECH_USER_1;
398
400
401 if (user_tech_flags[tfid].name != NULL) {
404 }
405
406 if (name && name[0] != '\0') {
408 }
409
410 if (user_tech_flags[tfid].helptxt != NULL) {
411 FC_FREE(user_tech_flags[tfid].helptxt);
413 }
414
415 if (helptxt && helptxt[0] != '\0') {
417 }
418}
419
420/**********************************************************************/
423const char *tech_flag_id_name_cb(enum tech_flag_id flag)
424{
426 return NULL;
427 }
428
429 return user_tech_flags[flag-TECH_USER_1].name;
430}
431
432/**********************************************************************/
435const char *tech_flag_helptxt(enum tech_flag_id id)
436{
437 fc_assert(id >= TECH_USER_1 && id <= TECH_USER_LAST);
438
440}
441
442/**********************************************************************/
455
456/**********************************************************************/
459void techs_init(void)
460{
461 struct advance *a_none = &advances[A_NONE];
462 struct advance *a_future = &advances[A_FUTURE];
463 int i;
464
465 memset(advances, 0, sizeof(advances));
466 for (i = 0; i < ARRAY_SIZE(advances); i++) {
469 advances[i].cost = -1;
471 advances[i].tclass = 0;
472
474 }
475
476 /* Initialize dummy tech A_NONE */
477 /* TRANS: "None" tech */
478 name_set(&a_none->name, NULL, N_("?tech:None"));
479 a_none->require[AR_ONE] = a_none;
480 a_none->require[AR_TWO] = a_none;
481 a_none->require[AR_ROOT] = A_NEVER;
482
483 name_set(&a_future->name, NULL, "Future");
484 a_future->require[AR_ONE] = A_NEVER;
485 a_future->require[AR_TWO] = A_NEVER;
486 a_future->require[AR_ROOT] = A_NEVER;
487}
488
489/**********************************************************************/
492static void tech_free(Tech_type_id tech)
493{
494 struct advance *p = &advances[tech];
495
496 if (NULL != p->helptext) {
498 p->helptext = NULL;
499 }
500
501 if (p->bonus_message) {
503 p->bonus_message = NULL;
504 }
505}
506
507/**********************************************************************/
510void techs_free(void)
511{
512 int i;
513
517
518 for (i = 0; i < ARRAY_SIZE(advances); i++) {
520 }
521}
522
523/**********************************************************************/
527{
528 return sizeof(struct advance_req_iter);
529}
530
531/**********************************************************************/
534static void *advance_req_iter_get(const struct iterator *it)
535{
536 return (void *) *ADVANCE_REQ_ITER(it)->current;
537}
538
539/**********************************************************************/
542static void advance_req_iter_next(struct iterator *it)
543{
545 const struct advance *padvance = *iter->current, *preq;
546 enum tech_req req;
547 bool new = FALSE;
548
549 for (req = AR_ONE; req < AR_SIZE; req++) {
551 if (NULL != preq
553 && !BV_ISSET(iter->done, advance_number(preq))) {
555 if (new) {
556 *iter->end++ = preq;
557 } else {
558 *iter->current = preq;
559 new = TRUE;
560 }
561 }
562 }
563
564 if (!new) {
565 iter->current++;
566 }
567}
568
569/**********************************************************************/
572static bool advance_req_iter_valid(const struct iterator *it)
573{
574 const struct advance_req_iter *iter = ADVANCE_REQ_ITER(it);
575
576 return iter->current < iter->end;
577}
578
579/**********************************************************************/
583 const struct advance *goal)
584{
585 struct iterator *base = ITERATOR(it);
586
590
591 BV_CLR_ALL(it->done);
592 it->current = it->array;
593 *it->current = goal;
594 it->end = it->current + 1;
595
596 return base;
597}
598
599/************************************************************************/
603{
604 return sizeof(struct advance_root_req_iter);
605}
606
607/************************************************************************/
610static void *advance_root_req_iter_get(const struct iterator *it)
611{
612 return
614}
615
616/************************************************************************/
619static bool advance_root_req_iter_valid(const struct iterator *it)
620{
622
623 return iter->current < iter->end;
624}
625
626/************************************************************************/
630{
632
633 /* Precondition: either iteration has already finished, or iter->current
634 * points at a tech with an interesting root_req (which means its
635 * requirements may have more). */
636 while (advance_root_req_iter_valid(it)) {
637 const struct advance *padvance = *iter->current;
638 enum tech_req req;
639 bool new = FALSE;
640
641 for (req = AR_ONE; req < AR_SIZE; req++) {
642 const struct advance *preq
644
645 if (NULL != preq
647 && !BV_ISSET(iter->done, advance_number(preq))) {
648
650 /* Do we need to look at this subtree at all? If it has A_NONE as
651 * root_req, further root_reqs can't propagate through it, so no. */
653 /* Yes, this subtree needs iterating over at some point, starting
654 * with preq (whose own root_req we'll consider in a bit) */
655 if (!new) {
656 *iter->current = preq;
657 new = TRUE;
658 } else {
659 *iter->end++ = preq; /* make a note for later */
660 }
661 }
662 }
663 }
664 if (!new) {
665 /* Didn't find an interesting new subtree. */
666 iter->current++;
667 }
668 /* Precondition: *current has been moved on from where we started, and
669 * it has an interesting root_req or it wouldn't be on the list; but
670 * it may be one that we've already yielded. */
673 AR_ROOT);
674 if (!BV_ISSET(iter->rootdone, root)) {
675 /* A previously unseen root_req. Stop and yield it. */
676 break;
677 } /* else keep looking */
678 }
679 }
680}
681
682/************************************************************************/
686 const struct advance *goal)
687{
688 struct iterator *base = ITERATOR(it);
689
693
694 BV_CLR_ALL(it->done);
695 BV_CLR_ALL(it->rootdone);
696 it->current = it->array;
698 /* First root_req to return is goal's own, and there may be more
699 * for next() to find. */
700 *it->current = goal;
701 it->end = it->current + 1;
702 } else {
703 /* No root_reqs -- go straight to invalid state */
704 it->end = it->current;
705 }
706
707 return base;
708}
#define BV_CLR_ALL(bv)
Definition bitvector.h:95
#define BV_SET(bv, bit)
Definition bitvector.h:81
#define BV_ISSET(bv, bit)
Definition bitvector.h:78
char * incite_cost
Definition comments.c:75
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2931
int Tech_type_id
Definition fc_types.h:377
#define MAX_NUM_TECH_CLASSES
Definition fc_types.h:63
#define Qn_(String)
Definition fcintl.h:89
#define N_(String)
Definition fcintl.h:69
void user_flag_init(struct user_flag *flag)
Definition game.c:824
void user_flag_free(struct user_flag *flag)
Definition game.c:833
struct civ_game game
Definition game.c:62
const char * name
Definition inputfile.c:127
#define ITERATOR(p)
Definition iterator.h:37
#define fc_assert_msg(condition, message,...)
Definition log.h:181
#define fc_assert_ret(condition)
Definition log.h:191
#define fc_assert(condition)
Definition log.h:176
#define fc_assert_ret_val(condition, val)
Definition log.h:194
#define FC_FREE(ptr)
Definition mem.h:41
#define fc_strdup(str)
Definition mem.h:43
static void name_set(struct name_translation *ptrans, const char *domain, const char *vernacular_name)
static const char * rule_name_get(const struct name_translation *ptrans)
static const char * name_translation_get(const struct name_translation *ptrans)
#define ARRAY_SIZE(x)
Definition shared.h:85
void strvec_destroy(struct strvec *psv)
bv_techs done
Definition tech.c:40
const struct advance ** end
Definition tech.c:42
const struct advance ** current
Definition tech.c:42
struct iterator base
Definition tech.c:39
const struct advance * array[A_LAST]
Definition tech.c:41
const struct advance * array[A_LAST]
Definition tech.c:49
const struct advance ** current
Definition tech.c:50
bv_techs rootdone
Definition tech.c:48
bv_techs done
Definition tech.c:48
const struct advance ** end
Definition tech.c:50
struct iterator base
Definition tech.c:47
void * ruledit_dlg
Definition tech.h:127
struct requirement_vector research_reqs
Definition tech.h:137
struct tech_class * tclass
Definition tech.h:130
double cost
Definition tech.h:150
struct advance * require[AR_SIZE]
Definition tech.h:132
char * bonus_message
Definition tech.h:145
struct strvec * helptext
Definition tech.h:140
bool inherited_root_req
Definition tech.h:133
bv_tech_flags flags
Definition tech.h:139
int num_reqs
Definition tech.h:156
Tech_type_id item_number
Definition tech.h:125
struct packet_ruleset_control control
Definition game.h:83
struct packet_game_info info
Definition game.h:89
enum tech_leakage_style tech_leakage
enum tech_cost_style tech_cost_style
bool ruledit_disabled
Definition tech.h:120
int idx
Definition tech.h:118
char * name
Definition game.h:74
char * helptxt
Definition game.h:75
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:189
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
#define fc__fallthrough
Definition support.h:119
Tech_type_id advance_count_real(void)
Definition tech.c:78
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:107
const char * tech_flag_id_name_cb(enum tech_flag_id flag)
Definition tech.c:423
void tech_classes_init(void)
Definition tech.c:307
const char * tech_class_rule_name(const struct tech_class *ptclass)
Definition tech.c:342
void set_user_tech_flag_name(enum tech_flag_id id, const char *name, const char *helptxt)
Definition tech.c:394
bool is_future_tech(Tech_type_id tech)
Definition tech.c:281
static void advance_req_iter_next(struct iterator *it)
Definition tech.c:542
struct advance * valid_advance(struct advance *padvance)
Definition tech.c:152
void techs_precalc_data(void)
Definition tech.c:225
struct advance * advance_by_translated_name(const char *name)
Definition tech.c:185
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:216
size_t advance_root_req_iter_sizeof(void)
Definition tech.c:602
const char * tech_class_name_translation(const struct tech_class *ptclass)
Definition tech.c:333
#define ADVANCE_ROOT_REQ_ITER(it)
Definition tech.c:52
static struct user_flag user_tech_flags[MAX_NUM_USER_TECH_FLAGS]
Definition tech.c:62
struct advance advances[A_ARRAY_SIZE]
Definition tech.c:58
struct iterator * advance_root_req_iter_init(struct advance_root_req_iter *it, const struct advance *goal)
Definition tech.c:685
struct iterator * advance_req_iter_init(struct advance_req_iter *it, const struct advance *goal)
Definition tech.c:582
static void * advance_root_req_iter_get(const struct iterator *it)
Definition tech.c:610
static void tech_free(Tech_type_id tech)
Definition tech.c:492
struct advance * advance_requires(const struct advance *padvance, enum tech_req require)
Definition tech.c:136
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:290
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:176
static bool advance_root_req_iter_valid(const struct iterator *it)
Definition tech.c:619
bool techs_have_fixed_costs(void)
Definition tech.c:450
Tech_type_id advance_required(const Tech_type_id tech, enum tech_req require)
Definition tech.c:121
struct tech_class * tech_class_by_number(const int idx)
Definition tech.c:320
void techs_init(void)
Definition tech.c:459
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:299
struct tech_class tech_classes[MAX_NUM_TECH_CLASSES]
Definition tech.c:60
const struct advance * advance_array_last(void)
Definition tech.c:67
static void * advance_req_iter_get(const struct iterator *it)
Definition tech.c:534
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:89
const char * tech_flag_helptxt(enum tech_flag_id id)
Definition tech.c:435
static bool advance_req_iter_valid(const struct iterator *it)
Definition tech.c:572
void techs_free(void)
Definition tech.c:510
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:200
static void advance_root_req_iter_next(struct iterator *it)
Definition tech.c:629
void user_tech_flags_init(void)
Definition tech.c:370
size_t advance_req_iter_sizeof(void)
Definition tech.c:526
#define ADVANCE_REQ_ITER(it)
Definition tech.c:44
struct tech_class * tech_class_by_rule_name(const char *name)
Definition tech.c:351
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:98
void user_tech_flags_free(void)
Definition tech.c:382
#define A_ARRAY_SIZE
Definition tech.h:47
#define A_FUTURE
Definition tech.h:46
#define A_NEVER
Definition tech.h:51
#define advance_index_iterate_end
Definition tech.h:248
#define advance_req_iterate(_goal, _padvance)
Definition tech.h:299
#define MAX_NUM_USER_TECH_FLAGS
Definition tech.h:108
#define advance_iterate_all_end
Definition tech.h:279
tech_req
Definition tech.h:110
@ AR_TWO
Definition tech.h:112
@ AR_ROOT
Definition tech.h:113
@ AR_ONE
Definition tech.h:111
@ AR_SIZE
Definition tech.h:114
#define advance_iterate_all(_p)
Definition tech.h:278
#define advance_req_iterate_end
Definition tech.h:303
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:275
#define advance_iterate_end
Definition tech.h:276
#define A_LAST
Definition tech.h:45
#define advance_index_iterate(_start, _index)
Definition tech.h:244