1 /***********************************************************************
2  Freeciv - Copyright (C) 2005 - The Freeciv Project
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 /* utility */
19 #include "fcintl.h"
20 #include "log.h"
21 #include "string_vector.h"
22 
23 /* common */
24 #include "city.h"
25 #include "effects.h"
26 #include "game.h"
27 
28 #include "specialist.h"
29 
30 struct specialist specialists[SP_MAX];
31 int default_specialist;
32 
33 /****************************************************************************
34   Initialize data for specialists.
35 ****************************************************************************/
specialists_init(void)36 void specialists_init(void)
37 {
38   int i;
39 
40   for (i = 0; i < ARRAY_SIZE(specialists); i++) {
41     struct specialist *p = &specialists[i];
42 
43     p->item_number = i;
44 
45     requirement_vector_init(&p->reqs);
46   }
47 }
48 
49 /****************************************************************************
50   Free data for specialists.
51 ****************************************************************************/
specialists_free(void)52 void specialists_free(void)
53 {
54   int i;
55 
56   for (i = 0; i < ARRAY_SIZE(specialists); i++) {
57     struct specialist *p = &specialists[i];
58 
59     requirement_vector_free(&p->reqs);
60     if (NULL != p->helptext) {
61       strvec_destroy(p->helptext);
62       p->helptext = NULL;
63     }
64   }
65 }
66 
67 /**************************************************************************
68   Return the number of specialist_types.
69 **************************************************************************/
specialist_count(void)70 Specialist_type_id specialist_count(void)
71 {
72   return game.control.num_specialist_types;
73 }
74 
75 /****************************************************************************
76   Return the specialist index.
77 
78   Currently same as specialist_number(), paired with specialist_count()
79   indicates use as an array index.
80 ****************************************************************************/
specialist_index(const struct specialist * sp)81 Specialist_type_id specialist_index(const struct specialist *sp)
82 {
83   fc_assert_ret_val(NULL != sp, -1);
84   return sp - specialists;
85 }
86 
87 /****************************************************************************
88   Return the specialist item_number.
89 ****************************************************************************/
specialist_number(const struct specialist * sp)90 Specialist_type_id specialist_number(const struct specialist *sp)
91 {
92   fc_assert_ret_val(NULL != sp, -1);
93   return sp->item_number;
94 }
95 
96 /****************************************************************************
97   Return the specialist pointer for the given number.
98 ****************************************************************************/
specialist_by_number(const Specialist_type_id id)99 struct specialist *specialist_by_number(const Specialist_type_id id)
100 {
101   if (id < 0 || id >= game.control.num_specialist_types) {
102     return NULL;
103   }
104   return &specialists[id];
105 }
106 
107 /****************************************************************************
108   Return the specialist type with the given (untranslated!) rule name.
109   Returns NULL if none match.
110 ****************************************************************************/
specialist_by_rule_name(const char * name)111 struct specialist *specialist_by_rule_name(const char *name)
112 {
113   const char *qname = Qn_(name);
114 
115   specialist_type_iterate(i) {
116     struct specialist *sp = specialist_by_number(i);
117     if (0 == fc_strcasecmp(specialist_rule_name(sp), qname)) {
118       return sp;
119     }
120   } specialist_type_iterate_end;
121 
122   return NULL;
123 }
124 
125 /****************************************************************************
126   Return the specialist type with the given (translated, plural) name.
127   Returns NULL if none match.
128 ****************************************************************************/
specialist_by_translated_name(const char * name)129 struct specialist *specialist_by_translated_name(const char *name)
130 {
131   specialist_type_iterate(i) {
132     struct specialist *sp = specialist_by_number(i);
133     if (0 == strcmp(specialist_plural_translation(sp), name)) {
134       return sp;
135     }
136   } specialist_type_iterate_end;
137 
138   return NULL;
139 }
140 
141 /**************************************************************************
142   Return the (untranslated) rule name of the specialist type.
143   You don't have to free the return pointer.
144 **************************************************************************/
specialist_rule_name(const struct specialist * sp)145 const char *specialist_rule_name(const struct specialist *sp)
146 {
147   return rule_name_get(&sp->name);
148 }
149 
150 /**************************************************************************
151   Return the (translated, plural) name of the specialist type.
152   You don't have to free the return pointer.
153 **************************************************************************/
specialist_plural_translation(const struct specialist * sp)154 const char *specialist_plural_translation(const struct specialist *sp)
155 {
156   return name_translation_get(&sp->name);
157 }
158 
159 /**************************************************************************
160   Return the (translated) abbreviation of the specialist type.
161   You don't have to free the return pointer.
162 **************************************************************************/
specialist_abbreviation_translation(const struct specialist * sp)163 const char *specialist_abbreviation_translation(const struct specialist *sp)
164 {
165   return name_translation_get(&sp->abbreviation);
166 }
167 
168 /****************************************************************************
169   Return a string containing all the specialist abbreviations, for instance
170   "E/S/T".
171   You don't have to free the return pointer.
172 ****************************************************************************/
specialists_abbreviation_string(void)173 const char *specialists_abbreviation_string(void)
174 {
175   static char buf[5 * SP_MAX];
176 
177   buf[0] = '\0';
178 
179   specialist_type_iterate(sp) {
180     char *separator = (buf[0] == '\0') ? "" : "/";
181 
182     cat_snprintf(buf, sizeof(buf), "%s%s", separator,
183                  specialist_abbreviation_translation(specialist_by_number(sp)));
184   } specialist_type_iterate_end;
185 
186   return buf;
187 }
188 
189 /****************************************************************************
190   Return a string showing the number of specialists in the array.
191 
192   For instance with a city with (0,3,1) specialists call
193 
194     specialists_string(pcity->specialists);
195 
196   and you'll get "0/3/1".
197 ****************************************************************************/
specialists_string(const citizens * specialist_list)198 const char *specialists_string(const citizens *specialist_list)
199 {
200   static char buf[5 * SP_MAX];
201 
202   buf[0] = '\0';
203 
204   specialist_type_iterate(sp) {
205     char *separator = (buf[0] == '\0') ? "" : "/";
206 
207     cat_snprintf(buf, sizeof(buf), "%s%d", separator, specialist_list[sp]);
208   } specialist_type_iterate_end;
209 
210   return buf;
211 }
212 
213 /****************************************************************************
214   Return the output for the specialist type with this output type.
215 ****************************************************************************/
get_specialist_output(const struct city * pcity,Specialist_type_id sp,Output_type_id otype)216 int get_specialist_output(const struct city *pcity,
217 			  Specialist_type_id sp, Output_type_id otype)
218 {
219   struct specialist *pspecialist = &specialists[sp];
220   struct output_type *poutput = get_output_type(otype);
221 
222   return get_city_specialist_output_bonus(pcity, pspecialist, poutput,
223 					  EFT_SPECIALIST_OUTPUT);
224 }
225