Freeciv21
Develop your civilization from humble roots to a global empire
events.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2023 Freeciv21 and Freeciv
3 \_ \ / __/ contributors. This file is part of Freeciv21.
4  _\ \ / /__ Freeciv21 is free software: you can redistribute it
5  \___ \____/ __/ and/or modify it under the terms of the GNU General
6  \_ _/ Public License as published by the Free Software
7  | @ @ \_ Foundation, either version 3 of the License,
8  | or (at your option) any later version.
9  _/ /\ You should have received a copy of the GNU
10  /o) (o/\ \_ General Public License along with Freeciv21.
11  \_____/ / If not, see https://www.gnu.org/licenses/.
12  \____/ ********************************************************/
13 
14 #include <cstdlib>
15 
16 // utility
17 #include "fcintl.h"
18 #include "log.h"
19 #include "shared.h"
20 #include "support.h"
21 
22 #include "events.h"
23 
37  E_S_XYZZY
38 };
39 
40 /*
41  * Information about all event sections, matching the enum above.
42  */
43 static const char *event_sections[] = {
44  /* TRANS: This and following strings are prefixes for event names, which
45  * replace %s. For instance, "Technology: Selected New Goal". */
46  N_("Technology: %s"), N_("Improvement: %s"), N_("City: %s"),
47  N_("Diplomat Action: %s"), N_("Enemy Diplomat: %s"), N_("Global: %s"),
48  N_("Hut: %s"), N_("Nation: %s"), N_("Treaty: %s"), N_("Unit: %s"),
49  // TRANS: "Vote" as a process
50  N_("Vote: %s"), N_("Wonder: %s"), nullptr};
51 
52 #define GEN_EV(event, section, descr) \
53  { \
54 #event, nullptr, section, descr, nullptr, event \
55  }
56 
57 /*
58  * Holds information about all event types. The entries don't have
59  * to be sorted.
60  * Every E_* event defined in common/events.h should have an entry here.
61  */
62 static struct {
63  const char *enum_name;
64  char *tag_name;
65  enum event_section_n esn;
66  const char *descr_orig;
67  const char *full_descr;
68  enum event_type event;
69 } events[] = {
70  /* TRANS: this and following strings are names for events which cause the
71  * server to generate messages. They are used in configuring how the
72  * client handles the different types of messages. Some of them will be
73  * displayed with prefixes, such as "Technology: Learned From Great
74  * Library". */
75  GEN_EV(E_TECH_GAIN, E_S_ADVANCE, N_("Acquired a New Tech")),
76  GEN_EV(E_TECH_LEARNED, E_S_ADVANCE, N_("Learned a New Tech")),
77  GEN_EV(E_TECH_GOAL, E_S_ADVANCE, N_("Selected a New Goal")),
78  GEN_EV(E_TECH_LOST, E_S_ADVANCE, N_("Lost a Tech")),
79  GEN_EV(E_TECH_EMBASSY, E_S_ADVANCE,
80  N_("Other Player Gained / Lost a Tech")),
81  GEN_EV(E_IMP_BUY, E_S_BUILD, N_("Bought")),
82  GEN_EV(E_IMP_BUILD, E_S_BUILD, N_("Built")),
83  GEN_EV(E_IMP_AUCTIONED, E_S_BUILD, N_("Forced to Sell")),
84  GEN_EV(E_IMP_AUTO, E_S_BUILD, N_("New Improvement Selected")),
85  GEN_EV(E_IMP_SOLD, E_S_BUILD, N_("Sold")),
86  GEN_EV(E_CITY_CANTBUILD, E_S_CITY, N_("Building Unavailable Item")),
87  GEN_EV(E_CITY_LOST, E_S_CITY, N_("Captured / Destroyed")),
88  GEN_EV(E_CITY_LOVE, E_S_CITY, N_("Celebrating")),
89  GEN_EV(E_CITY_DISORDER, E_S_CITY, N_("Civil Disorder")),
90  GEN_EV(E_CITY_FAMINE, E_S_CITY, N_("Famine")),
91  GEN_EV(E_CITY_FAMINE_FEARED, E_S_CITY, N_("Famine Feared")),
92  GEN_EV(E_CITY_GROWTH, E_S_CITY, N_("Growth")),
93  GEN_EV(E_CITY_MAY_SOON_GROW, E_S_CITY, N_("May Soon Grow")),
94  GEN_EV(E_CITY_IMPROVEMENT, E_S_CITY, N_("Needs Improvement to Grow")),
95  GEN_EV(E_CITY_IMPROVEMENT_BLDG, E_S_CITY,
96  N_("Needs Improvement to Grow, Being Built")),
97  GEN_EV(E_CITY_NORMAL, E_S_CITY, N_("Normal")),
98  GEN_EV(E_CITY_NUKED, E_S_CITY, N_("Nuked")),
99  GEN_EV(E_CITY_CMA_RELEASE, E_S_CITY,
100  N_("Released from Citizen Governor")),
101  GEN_EV(E_CITY_GRAN_THROTTLE, E_S_CITY, N_("Suggest Throttling Growth")),
102  GEN_EV(E_CITY_TRANSFER, E_S_CITY, N_("Transfer")),
103  GEN_EV(E_CITY_BUILD, E_S_CITY, N_("Was Built")),
104  GEN_EV(E_CITY_PLAGUE, E_S_CITY, N_("Has Plague")),
105  GEN_EV(E_CITY_RADIUS_SQ, E_S_CITY, N_("City Map changed")),
106  GEN_EV(E_WORKLIST, E_S_CITY, N_("Worklist Events")),
107  GEN_EV(E_CITY_PRODUCTION_CHANGED, E_S_CITY, N_("Production Changed")),
108  GEN_EV(E_DISASTER, E_S_CITY, N_("Disaster")),
109  GEN_EV(E_MY_DIPLOMAT_BRIBE, E_S_D_ME, N_("Bribe")),
110  GEN_EV(E_DIPLOMATIC_INCIDENT, E_S_D_ME, N_("Caused Incident")),
111  GEN_EV(E_MY_DIPLOMAT_ESCAPE, E_S_D_ME, N_("Escape")),
112  GEN_EV(E_MY_DIPLOMAT_EMBASSY, E_S_D_ME, N_("Embassy")),
113  GEN_EV(E_MY_DIPLOMAT_FAILED, E_S_D_ME, N_("Failed")),
114  GEN_EV(E_MY_DIPLOMAT_INCITE, E_S_D_ME, N_("Incite")),
115  GEN_EV(E_MY_DIPLOMAT_POISON, E_S_D_ME, N_("Poison")),
116  GEN_EV(E_MY_DIPLOMAT_SABOTAGE, E_S_D_ME, N_("Sabotage")),
117  GEN_EV(E_MY_DIPLOMAT_THEFT, E_S_D_ME, N_("Theft")),
118  GEN_EV(E_MY_SPY_STEAL_GOLD, E_S_D_ME, N_("Gold Theft")),
119  GEN_EV(E_MY_SPY_STEAL_MAP, E_S_D_ME, N_("Map Theft")),
120  GEN_EV(E_MY_SPY_NUKE, E_S_D_ME, N_("Suitcase Nuke")),
121  GEN_EV(E_ENEMY_DIPLOMAT_BRIBE, E_S_D_THEM, N_("Bribe")),
122  GEN_EV(E_ENEMY_DIPLOMAT_EMBASSY, E_S_D_THEM, N_("Embassy")),
123  GEN_EV(E_ENEMY_DIPLOMAT_FAILED, E_S_D_THEM, N_("Failed")),
124  GEN_EV(E_ENEMY_DIPLOMAT_INCITE, E_S_D_THEM, N_("Incite")),
125  GEN_EV(E_ENEMY_DIPLOMAT_POISON, E_S_D_THEM, N_("Poison")),
126  GEN_EV(E_ENEMY_DIPLOMAT_SABOTAGE, E_S_D_THEM, N_("Sabotage")),
127  GEN_EV(E_ENEMY_DIPLOMAT_THEFT, E_S_D_THEM, N_("Theft")),
128  GEN_EV(E_ENEMY_SPY_STEAL_GOLD, E_S_D_THEM, N_("Gold Theft")),
129  GEN_EV(E_ENEMY_SPY_STEAL_MAP, E_S_D_THEM, N_("Map Theft")),
130  GEN_EV(E_ENEMY_SPY_NUKE, E_S_D_THEM, N_("Suitcase Nuke")),
131  GEN_EV(E_GLOBAL_ECO, E_S_GLOBAL, N_("Eco-Disaster")),
132  GEN_EV(E_NUKE, E_S_GLOBAL, N_("Nuke Detonated")),
133  GEN_EV(E_HUT_BARB, E_S_HUT, N_("Barbarians in a Hut Roused")),
134  GEN_EV(E_HUT_CITY, E_S_HUT, N_("City Founded from a Hut")),
135  GEN_EV(E_HUT_GOLD, E_S_HUT, N_("Gold Found in a Hut")),
136  GEN_EV(E_HUT_BARB_KILLED, E_S_HUT, N_("Killed by Barbarians in a Hut")),
137  GEN_EV(E_HUT_MERC, E_S_HUT, N_("Mercenaries Found in a Hut")),
138  GEN_EV(E_HUT_SETTLER, E_S_HUT, N_("Settlers Found in a Hut")),
139  GEN_EV(E_HUT_TECH, E_S_HUT, N_("Tech Found in a Hut")),
140  GEN_EV(E_HUT_BARB_CITY_NEAR, E_S_HUT, N_("Unit Spared by Barbarians")),
141  GEN_EV(E_ACHIEVEMENT, E_S_NATION, N_("Achievements")),
142  GEN_EV(E_UPRISING, E_S_NATION, N_("Barbarian Uprising")),
143  GEN_EV(E_CIVIL_WAR, E_S_NATION, N_("Civil War")),
144  GEN_EV(E_ANARCHY, E_S_NATION, N_("Collapse to Anarchy")),
145  GEN_EV(E_FIRST_CONTACT, E_S_NATION, N_("First Contact")),
146  GEN_EV(E_NEW_GOVERNMENT, E_S_NATION, N_("Learned New Government")),
147  GEN_EV(E_LOW_ON_FUNDS, E_S_NATION, N_("Low Funds")),
148  GEN_EV(E_POLLUTION, E_S_NATION, N_("Pollution")),
149  GEN_EV(E_REVOLT_DONE, E_S_NATION, N_("Revolution Ended")),
150  GEN_EV(E_REVOLT_START, E_S_NATION, N_("Revolution Started")),
151  GEN_EV(E_SPACESHIP, E_S_NATION, N_("Spaceship Events")),
152  GEN_EV(E_TREATY_ALLIANCE, E_S_TREATY, N_("Alliance")),
153  GEN_EV(E_TREATY_BROKEN, E_S_TREATY, N_("Broken")),
154  GEN_EV(E_TREATY_CEASEFIRE, E_S_TREATY, N_("Cease-fire")),
155  GEN_EV(E_TREATY_EMBASSY, E_S_TREATY, N_("Embassy")),
156  GEN_EV(E_TREATY_PEACE, E_S_TREATY, N_("Peace")),
157  GEN_EV(E_TREATY_SHARED_VISION, E_S_TREATY, N_("Shared Vision")),
158  GEN_EV(E_UNIT_LOST_ATT, E_S_UNIT, N_("Attack Failed")),
159  GEN_EV(E_UNIT_TIE_ATT, E_S_UNIT, N_("Attack Tied")),
160  GEN_EV(E_UNIT_WIN_ATT, E_S_UNIT, N_("Attack Succeeded")),
161  GEN_EV(E_UNIT_BOMB_ATT, E_S_UNIT, N_("Attacker Bombarding")),
162  GEN_EV(E_UNIT_BUY, E_S_UNIT, N_("Bought")),
163  GEN_EV(E_UNIT_BUILT, E_S_UNIT, N_("Built")),
164  GEN_EV(E_UNIT_LOST_DEF, E_S_UNIT, N_("Defender Destroyed")),
165  GEN_EV(E_UNIT_TIE_DEF, E_S_UNIT, N_("Defender Tied")),
166  GEN_EV(E_UNIT_WIN_DEF, E_S_UNIT, N_("Defender Survived")),
167  GEN_EV(E_UNIT_BOMB_DEF, E_S_UNIT, N_("Defender Bombarded")),
168  GEN_EV(E_UNIT_BECAME_VET, E_S_UNIT, N_("Promoted to Veteran")),
169  GEN_EV(E_UNIT_LOST_MISC, E_S_UNIT, N_("Lost Outside Battle")),
170  GEN_EV(E_UNIT_UPGRADED, E_S_UNIT, N_("Production Upgraded")),
171  GEN_EV(E_UNIT_RELOCATED, E_S_UNIT, N_("Relocated")),
172  GEN_EV(E_UNIT_ORDERS, E_S_UNIT, N_("Orders / Goto Events")),
173  GEN_EV(E_UNIT_BUILT_POP_COST, E_S_UNIT,
174  N_("Built Unit with Population Cost")),
175  GEN_EV(E_UNIT_WAS_EXPELLED, E_S_UNIT, N_("Was Expelled")),
176  GEN_EV(E_UNIT_DID_EXPEL, E_S_UNIT, N_("Did Expel")),
177  GEN_EV(E_UNIT_ACTION_FAILED, E_S_UNIT, N_("Action Failed")),
178  GEN_EV(E_UNIT_WAKE, E_S_UNIT, N_("Sentried Units Awaken")),
179  // TRANS: "vote" as a process
180  GEN_EV(E_VOTE_NEW, E_S_VOTE, N_("New Vote")),
181  // TRANS: "Vote" as a process
182  GEN_EV(E_VOTE_RESOLVED, E_S_VOTE, N_("Vote Resolved")),
183  // TRANS: "Vote" as a process
184  GEN_EV(E_VOTE_ABORTED, E_S_VOTE, N_("Vote Canceled")),
185  GEN_EV(E_WONDER_BUILD, E_S_WONDER, N_("Finished")),
186  GEN_EV(E_WONDER_OBSOLETE, E_S_WONDER, N_("Made Obsolete")),
187  GEN_EV(E_WONDER_STARTED, E_S_WONDER, N_("Started")),
188  GEN_EV(E_WONDER_STOPPED, E_S_WONDER, N_("Stopped")),
189  GEN_EV(E_WONDER_WILL_BE_BUILT, E_S_WONDER, N_("Will Finish Next Turn")),
190  GEN_EV(E_AI_DEBUG, E_S_XYZZY, N_("AI Debug Messages")),
191  GEN_EV(E_BROADCAST_REPORT, E_S_XYZZY, N_("Broadcast Report")),
192  GEN_EV(E_CARAVAN_ACTION, E_S_XYZZY, N_("Caravan Actions")),
193  GEN_EV(E_CHAT_ERROR, E_S_XYZZY, N_("Chat Error Messages")),
194  GEN_EV(E_CHAT_MSG, E_S_XYZZY, N_("Chat Messages")),
195  GEN_EV(E_CONNECTION, E_S_XYZZY, N_("Connect / Disconnect Messages")),
196  GEN_EV(E_DIPLOMACY, E_S_XYZZY, N_("Diplomatic Message")),
197  GEN_EV(E_BAD_COMMAND, E_S_XYZZY, N_("Error Message from Bad Command")),
198  GEN_EV(E_GAME_END, E_S_XYZZY, N_("Game Ended")),
199  GEN_EV(E_GAME_START, E_S_XYZZY, N_("Game Started")),
200  GEN_EV(E_NATION_SELECTED, E_S_XYZZY, N_("Nation Selected")),
201  GEN_EV(E_DESTROYED, E_S_XYZZY, N_("Player Destroyed")),
202  GEN_EV(E_REPORT, E_S_XYZZY, N_("Report")),
203  GEN_EV(E_LOG_FATAL, E_S_XYZZY, N_("Server Aborting")),
204  GEN_EV(E_LOG_ERROR, E_S_XYZZY, N_("Server Problems")),
205  GEN_EV(E_MESSAGE_WALL, E_S_XYZZY, N_("Message from Server Operator")),
206  GEN_EV(E_SETTING, E_S_XYZZY, N_("Server Settings Changed")),
207  GEN_EV(E_TURN_BELL, E_S_XYZZY, N_("Turn Bell")),
208  GEN_EV(E_SCRIPT, E_S_XYZZY, N_("Scenario / Ruleset Script Message")),
209  // TRANS: Event name for when the game year changes.
210  GEN_EV(E_NEXT_YEAR, E_S_XYZZY, N_("Year Advance")),
211  GEN_EV(E_DEPRECATION_WARNING, E_S_XYZZY,
212  N_("Deprecated Modpack Syntax Warnings")),
213  GEN_EV(E_SPONTANEOUS_EXTRA, E_S_XYZZY, N_("Extra Appears / Disappears")),
214  GEN_EV(E_UNIT_ILLEGAL_ACTION, E_S_UNIT, N_("Unit Illegal Action")),
215  GEN_EV(E_UNIT_ESCAPED, E_S_UNIT, N_("Unit Escaped")),
216  GEN_EV(E_BEGINNER_HELP, E_S_XYZZY, N_("Help for Beginners")),
217  GEN_EV(E_MY_UNIT_DID_HEAL, E_S_UNIT, N_("Unit Did Heal")),
218  GEN_EV(E_MY_UNIT_WAS_HEALED, E_S_UNIT, N_("Unit Was Healed")),
219  GEN_EV(E_MULTIPLIER, E_S_NATION, N_("Multiplier Changed")),
220  GEN_EV(E_UNIT_ACTION_ACTOR_SUCCESS, E_S_UNIT, N_("Your Unit Did")),
221  GEN_EV(E_UNIT_ACTION_ACTOR_FAILURE, E_S_UNIT, N_("Your Unit Failed")),
222  GEN_EV(E_UNIT_ACTION_TARGET_HOSTILE, E_S_UNIT, N_("Unit Did to You")),
223  GEN_EV(E_UNIT_ACTION_TARGET_OTHER, E_S_UNIT, N_("Unit Did")),
224  /* The sound system also generates "e_game_quit", although there's no
225  * corresponding identifier E_GAME_QUIT. */
226 };
227 
228 /*
229  * Maps from enum event_type to indexes of events[]. Set by
230  * events_init.
231  */
232 static int event_to_index[E_COUNT];
233 
234 enum event_type sorted_events[E_COUNT];
235 
239 const char *get_event_message_text(enum event_type event)
240 {
241  fc_assert_ret_val(event_type_is_valid(event), nullptr);
242 
244  return events[event_to_index[event]].full_descr;
245  }
246 
247  qCritical("unknown event %d", event);
248  return "UNKNOWN EVENT"; /* FIXME: Should be marked for translation?
249  * we get non-translated in log message. */
250 }
251 
256 static int compar_event_message_texts(const void *i1, const void *i2)
257 {
258  const enum event_type *j1 = static_cast<const event_type *>(i1);
259  const enum event_type *j2 = static_cast<const event_type *>(i2);
260 
263 }
264 
268 const char *get_event_tag(enum event_type event)
269 {
270  fc_assert_ret_val(event_type_is_valid(event), nullptr);
271 
273  return events[event_to_index[event]].tag_name;
274  }
275  qCritical("unknown event %d", event);
276  return nullptr;
277 }
278 
284 {
285  int i;
286 
287  for (i = 0; i < ARRAY_SIZE(event_to_index); i++) {
288  event_to_index[i] = 0;
289  }
290 
291  for (i = 0; i < E_COUNT; i++) {
292  int j;
293 
294  if (E_S_XYZZY > events[i].esn) {
295  const char *event_format = Q_(event_sections[events[i].esn]);
296  int l = 1 + qstrlen(event_format) + qstrlen(_(events[i].descr_orig));
297 
298  // Need a temporary because full_descr is a const char *
299  char *tmp = new char[l];
300  fc_snprintf(tmp, l, event_format, _(events[i].descr_orig));
301  events[i].full_descr = tmp;
302  } else {
303  // No section part
304  events[i].full_descr = _(events[i].descr_orig);
305  }
306 
307  event_to_index[events[i].event] = i;
308  events[i].tag_name = fc_strdup(events[i].enum_name);
309  for (j = 0; j < qstrlen(events[i].tag_name); j++) {
310  events[i].tag_name[j] = QChar::toLower(events[i].tag_name[j]);
311  }
312  log_debug("event[%d]=%d: name='%s' / '%s'\n"
313  "\tdescr_orig='%s'\n"
314  "\tdescr='%s'",
315  i, events[i].event, events[i].enum_name, events[i].tag_name,
317  }
318 
319  for (i = 0; i <= event_type_max(); i++) {
320  // Initialise sorted list of all (even possble missing) events.
321  sorted_events[i] = event_type(i);
322  }
323  qsort(sorted_events, event_type_max() + 1, sizeof(*sorted_events),
325 }
326 
331 {
332  int i;
333 
334  for (i = 0; i <= event_type_max(); i++) {
335  if (E_S_XYZZY > events[i].esn) {
336  // We have allocated memory for this event
337  delete[] events[i].full_descr;
338  events[i].full_descr = nullptr;
339  }
340  }
341 }
const char * get_event_message_text(enum event_type event)
Returns the translated description of the given event.
Definition: events.cpp:239
#define GEN_EV(event, section, descr)
Definition: events.cpp:52
event_section_n
Definition: events.cpp:24
@ E_S_D_THEM
Definition: events.cpp:29
@ E_S_D_ME
Definition: events.cpp:28
@ E_S_NATION
Definition: events.cpp:32
@ E_S_TREATY
Definition: events.cpp:33
@ E_S_WONDER
Definition: events.cpp:36
@ E_S_CITY
Definition: events.cpp:27
@ E_S_ADVANCE
Definition: events.cpp:25
@ E_S_XYZZY
Definition: events.cpp:37
@ E_S_VOTE
Definition: events.cpp:35
@ E_S_GLOBAL
Definition: events.cpp:30
@ E_S_HUT
Definition: events.cpp:31
@ E_S_UNIT
Definition: events.cpp:34
@ E_S_BUILD
Definition: events.cpp:26
enum event_type event
Definition: events.cpp:68
static int event_to_index[E_COUNT]
Definition: events.cpp:232
void events_init()
Initialize events.
Definition: events.cpp:283
const char * descr_orig
Definition: events.cpp:66
const char * enum_name
Definition: events.cpp:63
static const char * event_sections[]
Definition: events.cpp:43
static int compar_event_message_texts(const void *i1, const void *i2)
Comparison function for qsort; i1 and i2 are pointers to an event (enum event_type).
Definition: events.cpp:256
const char * full_descr
Definition: events.cpp:67
enum event_section_n esn
Definition: events.cpp:65
const char * get_event_tag(enum event_type event)
Returns a string for the sound to be used for this message type.
Definition: events.cpp:268
void events_free()
Free events.
Definition: events.cpp:330
char * tag_name
Definition: events.cpp:64
static struct @21 events[]
enum event_type sorted_events[E_COUNT]
Definition: events.cpp:234
#define Q_(String)
Definition: fcintl.h:53
#define _(String)
Definition: fcintl.h:50
#define N_(String)
Definition: fcintl.h:52
#define fc_assert_ret_val(condition, val)
Definition: log.h:114
#define log_debug(message,...)
Definition: log.h:65
#define ARRAY_SIZE(x)
Definition: shared.h:79
int fc_snprintf(char *str, size_t n, const char *format,...)
See also fc_utf8_snprintf_trunc(), fc_utf8_snprintf_rep().
Definition: support.cpp:537
int fc_strcasecmp(const char *str0, const char *str1)
Compare strings like strcmp(), but ignoring case.
Definition: support.cpp:89
#define fc_strdup(str)
Definition: support.h:111