Freeciv-3.4
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
73 return nullptr;
74}
75
76/**********************************************************************/
83
84/**********************************************************************/
91{
92 fc_assert_ret_val(padvance != nullptr, -1);
93
94 return padvance - advances;
95}
96
97/**********************************************************************/
101{
102 fc_assert_ret_val(padvance != nullptr, -1);
103
104 return padvance->item_number;
105}
106
107/**********************************************************************/
111{
112 if (atype != A_FUTURE
114 /* This isn't an error; some callers depend on it. */
115 return nullptr;
116 }
117
118 return &advances[atype];
119}
120
121/**********************************************************************/
125 enum tech_req require)
126{
128 fc_assert_ret_val(tech >= A_NONE && tech < A_LAST, -1);
129 if (A_NEVER == advances[tech].require[require]) {
130 /* out of range */
131 return A_LAST;
132 }
133 return advance_number(advances[tech].require[require]);
134}
135
136/**********************************************************************/
140 enum tech_req require)
141{
142 fc_assert_ret_val(require >= 0 && require < AR_SIZE, nullptr);
143 fc_assert_ret_val(padvance != nullptr, nullptr);
144
145 return padvance->require[require];
146}
147
148/**********************************************************************/
158{
159 if (padvance == nullptr) {
160 return nullptr;
161 }
162
163 if (padvance->item_number == A_FUTURE) {
164 return padvance;
165 }
166
167 if (A_NEVER == padvance->require[AR_ONE]
168 || A_NEVER == padvance->require[AR_TWO]) {
169 return nullptr;
170 }
171
172 return padvance;
173}
174
175/**********************************************************************/
185
186/**********************************************************************/
191{
194 return padvance;
195 }
197
198 return nullptr;
199}
200
201/**********************************************************************/
206{
207 const char *qname = Qn_(name);
208
211 return padvance;
212 }
214
215 return nullptr;
216}
217
218/**********************************************************************/
222{
224 return BV_ISSET(advance_by_number(tech)->flags, flag);
225}
226
227/**********************************************************************/
231{
233 "Invalid tech_cost_style %d", game.info.tech_cost_style);
234
236 int num_reqs = 0;
237 bool min_req = TRUE;
238
240 (void) preq; /* Compiler wants us to do something with 'preq'. */
241 num_reqs++;
243 padvance->num_reqs = num_reqs;
244
245 switch (game.info.tech_cost_style) {
247 case TECH_COST_LINEAR:
249 break;
251 if (-1 != padvance->cost) {
252 min_req = FALSE;
253 break;
254 }
255 fc__fallthrough; /* No break. */
257 padvance->cost = game.info.base_tech_cost * (1.0 + num_reqs)
258 * sqrt(1.0 + num_reqs) / 2;
259 break;
261 if (-1 != padvance->cost) {
262 min_req = FALSE;
263 break;
264 }
265 fc__fallthrough; /* No break. */
268 / (1 + sqrt(sqrt(num_reqs + 1))) - 0.5);
269 break;
270 }
271
272 if (min_req && padvance->cost < game.info.min_tech_cost) {
274 }
275
276 /* Class cost */
277 if (padvance->tclass != nullptr) {
278 padvance->cost = padvance->cost * padvance->tclass->cost_pct / 100;
279 }
281}
282
283/**********************************************************************/
287{
288 return tech == A_FUTURE;
289}
290
291/**********************************************************************/
296{
297 return valid_advance(padvance) != nullptr
299}
300
301/**********************************************************************/
305const char *advance_name_translation(const struct advance *padvance)
306{
307 return name_translation_get(&padvance->name);
308}
309
310/**********************************************************************/
314const char *advance_rule_name(const struct advance *padvance)
315{
316 return rule_name_get(&padvance->name);
317}
318
319/**********************************************************************/
323{
324 int i;
325
326 for (i = 0; i < MAX_NUM_TECH_CLASSES; i++) {
327 tech_classes[i].idx = i;
329 }
330}
331
332/**********************************************************************/
336{
338 return nullptr;
339 }
340
341 return &tech_classes[idx];
342}
343
344/**********************************************************************/
349{
350 return name_translation_get(&ptclass->name);
351}
352
353/**********************************************************************/
357const char *tech_class_rule_name(const struct tech_class *ptclass)
358{
359 return rule_name_get(&ptclass->name);
360}
361
362/**********************************************************************/
367{
368 const char *qname = Qn_(name);
369 int i;
370
371 for (i = 0; i < game.control.num_tech_classes; i++) {
373
375 return ptclass;
376 }
377 }
378
379 return nullptr;
380}
381
382/**********************************************************************/
386{
387 int i;
388
389 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
391 }
392}
393
394/**********************************************************************/
398{
399 int i;
400
401 for (i = 0; i < MAX_NUM_USER_TECH_FLAGS; i++) {
403 }
404}
405
406/**********************************************************************/
409void set_user_tech_flag_name(enum tech_flag_id id, const char *name,
410 const char *helptxt)
411{
412 int tfid = id - TECH_USER_1;
413
415
416 if (user_tech_flags[tfid].name != nullptr) {
418 user_tech_flags[tfid].name = nullptr;
419 }
420
421 if (name && name[0] != '\0') {
423 }
424
425 if (user_tech_flags[tfid].helptxt != nullptr) {
426 FC_FREE(user_tech_flags[tfid].helptxt);
427 user_tech_flags[tfid].helptxt = nullptr;
428 }
429
430 if (helptxt && helptxt[0] != '\0') {
432 }
433}
434
435/**********************************************************************/
438const char *tech_flag_id_name_cb(enum tech_flag_id flag)
439{
441 return nullptr;
442 }
443
444 return user_tech_flags[flag-TECH_USER_1].name;
445}
446
447/**********************************************************************/
450const char *tech_flag_helptxt(enum tech_flag_id id)
451{
452 fc_assert(id >= TECH_USER_1 && id <= TECH_USER_LAST);
453
455}
456
457/**********************************************************************/
470
471/**********************************************************************/
474void techs_init(void)
475{
476 struct advance *a_none = &advances[A_NONE];
477 struct advance *a_future = &advances[A_FUTURE];
478 int i;
479
480 memset(advances, 0, sizeof(advances));
481 for (i = 0; i < ARRAY_SIZE(advances); i++) {
483 advances[i].ruledit_dlg = nullptr;
484 advances[i].cost = -1;
486 advances[i].tclass = 0;
487
489 }
490
491 /* Initialize dummy tech A_NONE */
492 /* TRANS: "None" tech */
493 name_set(&a_none->name, nullptr, N_("?tech:None"));
494 a_none->require[AR_ONE] = a_none;
495 a_none->require[AR_TWO] = a_none;
496 a_none->require[AR_ROOT] = A_NEVER;
497
498 name_set(&a_future->name, nullptr, "Future");
499 a_future->require[AR_ONE] = A_NEVER;
500 a_future->require[AR_TWO] = A_NEVER;
501 a_future->require[AR_ROOT] = A_NEVER;
502}
503
504/**********************************************************************/
507static void tech_free(Tech_type_id tech)
508{
509 struct advance *p = &advances[tech];
510
511 if (p->helptext != nullptr) {
513 p->helptext = nullptr;
514 }
515
516 if (p->bonus_message) {
518 p->bonus_message = nullptr;
519 }
520}
521
522/**********************************************************************/
525void techs_free(void)
526{
527 int i;
528
532
533 for (i = 0; i < ARRAY_SIZE(advances); i++) {
535 }
536}
537
538/**********************************************************************/
542{
543 return sizeof(struct advance_req_iter);
544}
545
546/**********************************************************************/
549static void *advance_req_iter_get(const struct iterator *it)
550{
551 return (void *) *ADVANCE_REQ_ITER(it)->current;
552}
553
554/**********************************************************************/
557static void advance_req_iter_next(struct iterator *it)
558{
560 const struct advance *padvance = *iter->current, *preq;
561 enum tech_req req;
562 bool new = FALSE;
563
564 for (req = AR_ONE; req < AR_SIZE; req++) {
566 if (preq != nullptr
568 && !BV_ISSET(iter->done, advance_number(preq))) {
570 if (new) {
571 *iter->end++ = preq;
572 } else {
573 *iter->current = preq;
574 new = TRUE;
575 }
576 }
577 }
578
579 if (!new) {
580 iter->current++;
581 }
582}
583
584/**********************************************************************/
587static bool advance_req_iter_valid(const struct iterator *it)
588{
589 const struct advance_req_iter *iter = ADVANCE_REQ_ITER(it);
590
591 return iter->current < iter->end;
592}
593
594/**********************************************************************/
598 const struct advance *goal)
599{
600 struct iterator *base = ITERATOR(it);
601
605
606 BV_CLR_ALL(it->done);
607 it->current = it->array;
608 *it->current = goal;
609 it->end = it->current + 1;
610
611 return base;
612}
613
614/************************************************************************/
618{
619 return sizeof(struct advance_root_req_iter);
620}
621
622/************************************************************************/
625static void *advance_root_req_iter_get(const struct iterator *it)
626{
627 return
629}
630
631/************************************************************************/
634static bool advance_root_req_iter_valid(const struct iterator *it)
635{
637
638 return iter->current < iter->end;
639}
640
641/************************************************************************/
645{
647
648 /* Precondition: either iteration has already finished, or iter->current
649 * points at a tech with an interesting root_req (which means its
650 * requirements may have more). */
651 while (advance_root_req_iter_valid(it)) {
652 const struct advance *padvance = *iter->current;
653 enum tech_req req;
654 bool new = FALSE;
655
656 for (req = AR_ONE; req < AR_SIZE; req++) {
657 const struct advance *preq
659
660 if (preq != nullptr
662 && !BV_ISSET(iter->done, advance_number(preq))) {
663
665 /* Do we need to look at this subtree at all? If it has A_NONE as
666 * root_req, further root_reqs can't propagate through it, so no. */
668 /* Yes, this subtree needs iterating over at some point, starting
669 * with preq (whose own root_req we'll consider in a bit) */
670 if (!new) {
671 *iter->current = preq;
672 new = TRUE;
673 } else {
674 *iter->end++ = preq; /* make a note for later */
675 }
676 }
677 }
678 }
679 if (!new) {
680 /* Didn't find an interesting new subtree. */
681 iter->current++;
682 }
683 /* Precondition: *current has been moved on from where we started, and
684 * it has an interesting root_req or it wouldn't be on the list; but
685 * it may be one that we've already yielded. */
688 AR_ROOT);
689 if (!BV_ISSET(iter->rootdone, root)) {
690 /* A previously unseen root_req. Stop and yield it. */
691 break;
692 } /* else keep looking */
693 }
694 }
695}
696
697/************************************************************************/
701 const struct advance *goal)
702{
703 struct iterator *base = ITERATOR(it);
704
708
709 BV_CLR_ALL(it->done);
710 BV_CLR_ALL(it->rootdone);
711 it->current = it->array;
713 /* First root_req to return is goal's own, and there may be more
714 * for next() to find. */
715 *it->current = goal;
716 it->end = it->current + 1;
717 } else {
718 /* No root_reqs -- go straight to invalid state */
719 it->end = it->current;
720 }
721
722 return base;
723}
#define BV_CLR_ALL(bv)
Definition bitvector.h:103
#define BV_SET(bv, bit)
Definition bitvector.h:89
#define BV_ISSET(bv, bit)
Definition bitvector.h:86
char * incite_cost
Definition comments.c:77
static void base(QVariant data1, QVariant data2)
Definition dialogs.cpp:2966
int Tech_type_id
Definition fc_types.h:238
#define MAX_NUM_TECH_CLASSES
Definition fc_types.h:64
#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:834
void user_flag_free(struct user_flag *flag)
Definition game.c:843
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:182
#define fc_assert_ret(condition)
Definition log.h:192
#define fc_assert(condition)
Definition log.h:177
#define fc_assert_ret_val(condition, val)
Definition log.h:195
#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:124
struct requirement_vector research_reqs
Definition tech.h:134
struct tech_class * tclass
Definition tech.h:127
double cost
Definition tech.h:147
struct advance * require[AR_SIZE]
Definition tech.h:129
char * bonus_message
Definition tech.h:142
struct strvec * helptext
Definition tech.h:137
bool inherited_root_req
Definition tech.h:130
bv_tech_flags flags
Definition tech.h:136
int num_reqs
Definition tech.h:153
Tech_type_id item_number
Definition tech.h:122
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:117
int idx
Definition tech.h:115
char * name
Definition game.h:74
char * helptxt
Definition game.h:75
int fc_strcasecmp(const char *str0, const char *str1)
Definition support.c:186
#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:79
struct advance * advance_by_number(const Tech_type_id atype)
Definition tech.c:110
const char * tech_flag_id_name_cb(enum tech_flag_id flag)
Definition tech.c:438
void tech_classes_init(void)
Definition tech.c:322
const char * tech_class_rule_name(const struct tech_class *ptclass)
Definition tech.c:357
void set_user_tech_flag_name(enum tech_flag_id id, const char *name, const char *helptxt)
Definition tech.c:409
bool is_future_tech(Tech_type_id tech)
Definition tech.c:286
static void advance_req_iter_next(struct iterator *it)
Definition tech.c:557
struct advance * valid_advance(struct advance *padvance)
Definition tech.c:157
void techs_precalc_data(void)
Definition tech.c:230
struct advance * advance_by_translated_name(const char *name)
Definition tech.c:190
bool advance_has_flag(Tech_type_id tech, enum tech_flag_id flag)
Definition tech.c:221
size_t advance_root_req_iter_sizeof(void)
Definition tech.c:617
const char * tech_class_name_translation(const struct tech_class *ptclass)
Definition tech.c:348
#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:700
struct iterator * advance_req_iter_init(struct advance_req_iter *it, const struct advance *goal)
Definition tech.c:597
static void * advance_root_req_iter_get(const struct iterator *it)
Definition tech.c:625
static void tech_free(Tech_type_id tech)
Definition tech.c:507
struct advance * advance_requires(const struct advance *padvance, enum tech_req require)
Definition tech.c:139
const char * advance_name_translation(const struct advance *padvance)
Definition tech.c:305
struct advance * valid_advance_by_number(const Tech_type_id id)
Definition tech.c:181
static bool advance_root_req_iter_valid(const struct iterator *it)
Definition tech.c:634
bool techs_have_fixed_costs(void)
Definition tech.c:465
Tech_type_id advance_required(const Tech_type_id tech, enum tech_req require)
Definition tech.c:124
struct tech_class * tech_class_by_number(const int idx)
Definition tech.c:335
void techs_init(void)
Definition tech.c:474
const char * advance_rule_name(const struct advance *padvance)
Definition tech.c:314
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:549
Tech_type_id advance_index(const struct advance *padvance)
Definition tech.c:90
const char * tech_flag_helptxt(enum tech_flag_id id)
Definition tech.c:450
static bool advance_req_iter_valid(const struct iterator *it)
Definition tech.c:587
void techs_free(void)
Definition tech.c:525
struct advance * advance_by_rule_name(const char *name)
Definition tech.c:205
static void advance_root_req_iter_next(struct iterator *it)
Definition tech.c:644
void user_tech_flags_init(void)
Definition tech.c:385
size_t advance_req_iter_sizeof(void)
Definition tech.c:541
#define ADVANCE_REQ_ITER(it)
Definition tech.c:44
struct tech_class * tech_class_by_rule_name(const char *name)
Definition tech.c:366
bool is_regular_advance(struct advance *padvance)
Definition tech.c:295
Tech_type_id advance_number(const struct advance *padvance)
Definition tech.c:100
void user_tech_flags_free(void)
Definition tech.c:397
#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:246
#define advance_req_iterate(_goal, _padvance)
Definition tech.h:297
#define MAX_NUM_USER_TECH_FLAGS
Definition tech.h:105
#define advance_iterate_all_end
Definition tech.h:277
tech_req
Definition tech.h:107
@ AR_TWO
Definition tech.h:109
@ AR_ROOT
Definition tech.h:110
@ AR_ONE
Definition tech.h:108
@ AR_SIZE
Definition tech.h:111
#define advance_iterate_all(_p)
Definition tech.h:276
#define advance_req_iterate_end
Definition tech.h:301
#define TECH_USER_LAST
Definition tech.h:103
#define A_FIRST
Definition tech.h:44
#define A_NONE
Definition tech.h:43
#define advance_iterate(_p)
Definition tech.h:273
#define advance_iterate_end
Definition tech.h:274
#define A_LAST
Definition tech.h:45
#define advance_index_iterate(_start, _index)
Definition tech.h:242