Freeciv21
Develop your civilization from humble roots to a global empire
clientutils.cpp
Go to the documentation of this file.
1 /*__ ___ ***************************************
2 / \ / \ Copyright (c) 1996-2020 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 // common
15 #include "extras.h"
16 #include "fc_types.h"
17 #include "game.h" // FIXME it's extra_type_iterate that needs this really
18 #include "tile.h"
19 
20 #include "clientutils.h"
21 
22 /* This module contains functions that would belong to the client,
23  * except that in case of freeciv-web, server does handle these
24  * for the web client. */
25 
26 /* Stores the expected completion time for all activities on a tile.
27  * (If multiple activities can create/remove an extra, they will
28  * proceed in parallel and the first to complete will win, so they
29  * are accounted separately here.) */
30 struct actcalc {
31  int extra_turns[MAX_EXTRA_TYPES][ACTIVITY_LAST];
32  int rmextra_turns[MAX_EXTRA_TYPES][ACTIVITY_LAST];
33  int activity_turns[ACTIVITY_LAST];
34 };
35 
39 static void calc_activity(struct actcalc *calc, const struct tile *ptile)
40 {
41  // This temporary working state is a bit big to allocate on the stack
42  struct tmp_state {
43  int extra_total[MAX_EXTRA_TYPES][ACTIVITY_LAST];
44  int extra_units[MAX_EXTRA_TYPES][ACTIVITY_LAST];
45  int rmextra_total[MAX_EXTRA_TYPES][ACTIVITY_LAST];
46  int rmextra_units[MAX_EXTRA_TYPES][ACTIVITY_LAST];
47  int activity_total[ACTIVITY_LAST];
48  int activity_units[ACTIVITY_LAST];
49  } * t;
50 
51  t = new tmp_state[1]();
52  memset(calc, 0, sizeof(*calc));
53 
54  // Contributions from real units
55  unit_list_iterate(ptile->units, punit)
56  {
57  if (punit == nullptr) {
58  // We'll account for this one later
59  continue;
60  }
61 
62  Activity_type_id act = punit->activity;
63 
64  if (is_build_activity(act, ptile)) {
65  int eidx = extra_index(punit->activity_target);
66 
67  t->extra_total[eidx][act] += punit->activity_count;
68  t->extra_total[eidx][act] += get_activity_rate_this_turn(punit);
69  t->extra_units[eidx][act] += get_activity_rate(punit);
70  } else if (is_clean_activity(act)) {
71  int eidx = extra_index(punit->activity_target);
72 
73  t->rmextra_total[eidx][act] += punit->activity_count;
74  t->rmextra_total[eidx][act] += get_activity_rate_this_turn(punit);
75  t->rmextra_units[eidx][act] += get_activity_rate(punit);
76  } else {
77  t->activity_total[act] += punit->activity_count;
78  t->activity_total[act] += get_activity_rate_this_turn(punit);
79  t->activity_units[act] += get_activity_rate(punit);
80  }
81  }
83 
84  // Turn activity counts into turn estimates
86  {
87  int remains, turns;
88 
90  {
91  int ei = extra_index(ep);
92 
93  {
94  int units_total = t->extra_units[ei][act];
95 
96  if (units_total > 0) {
97  remains =
98  tile_activity_time(act, ptile, ep) - t->extra_total[ei][act];
99  if (remains > 0) {
100  turns = 1 + (remains + units_total - 1) / units_total;
101  } else {
102  // extra will be finished this turn
103  turns = 1;
104  }
105  calc->extra_turns[ei][act] = turns;
106  }
107  }
108  {
109  int units_total = t->rmextra_units[ei][act];
110 
111  if (units_total > 0) {
112  remains =
113  tile_activity_time(act, ptile, ep) - t->rmextra_total[ei][act];
114  if (remains > 0) {
115  turns = 1 + (remains + units_total - 1) / units_total;
116  } else {
117  // extra will be removed this turn
118  turns = 1;
119  }
120  calc->rmextra_turns[ei][act] = turns;
121  }
122  }
123  }
125 
126  int units_total = t->activity_units[act];
127 
128  if (units_total > 0) {
129  remains =
130  tile_activity_time(act, ptile, nullptr) - t->activity_total[act];
131  if (remains > 0) {
132  turns = 1 + (remains + units_total - 1) / units_total;
133  } else {
134  // activity will be finished this turn
135  turns = 1;
136  }
137  calc->activity_turns[act] = turns;
138  }
139  }
141  delete[] t;
142  t = nullptr;
143 }
144 
148 QString concat_tile_activity_text(struct tile *ptile)
149 {
150  auto *calc = new actcalc;
151  int num_activities = 0;
152  QString str;
153 
154  calc_activity(calc, ptile);
155 
157  {
158  if (is_build_activity(i, ptile)) {
160  {
161  int ei = extra_index(ep);
162 
163  if (calc->extra_turns[ei][i] > 0) {
164  if (num_activities > 0) {
165  str += QLatin1String("/");
166  }
167  str += QStringLiteral("%1(%2)").arg(
169  QString::number(calc->extra_turns[ei][i]));
170  num_activities++;
171  }
172  }
174  } else if (is_clean_activity(i)) {
175  enum extra_rmcause rmcause = ERM_NONE;
176 
177  switch (i) {
178  case ACTIVITY_PILLAGE:
179  rmcause = ERM_PILLAGE;
180  break;
181  case ACTIVITY_POLLUTION:
182  rmcause = ERM_CLEANPOLLUTION;
183  break;
184  case ACTIVITY_FALLOUT:
185  rmcause = ERM_CLEANFALLOUT;
186  break;
187  default:
188  fc_assert(rmcause != ERM_NONE);
189  break;
190  };
191 
192  if (rmcause != ERM_NONE) {
193  extra_type_by_rmcause_iterate(rmcause, ep)
194  {
195  int ei = extra_index(ep);
196 
197  if (calc->rmextra_turns[ei][i] > 0) {
198  if (num_activities > 0) {
199  str += QLatin1String("/");
200  }
201  str += QString(rmcause == ERM_PILLAGE ? _("Pillage %1(%2)")
202  : _("Clean %1(%2)"))
203  .arg(extra_name_translation(ep),
204  QString::number(calc->rmextra_turns[ei][i]));
205  num_activities++;
206  }
207  }
209  }
210  } else if (is_tile_activity(i)) {
211  if (calc->activity_turns[i] > 0) {
212  if (num_activities > 0) {
213  str += QLatin1String("/");
214  }
215  str += QStringLiteral("%1(%2)").arg(
216  get_activity_text(i), QString::number(calc->activity_turns[i]));
217  num_activities++;
218  }
219  }
220  }
222 
223  delete calc;
224  calc = nullptr;
225  return qUtf8Printable(str);
226 }
static void calc_activity(struct actcalc *calc, const struct tile *ptile)
Calculate completion time for all unit activities on tile.
Definition: clientutils.cpp:39
QString concat_tile_activity_text(struct tile *ptile)
Creates the activity progress text for the given tile.
const char * extra_name_translation(const struct extra_type *pextra)
Return the (translated) name of the extra type.
Definition: extras.cpp:165
#define extra_type_iterate(_p)
Definition: extras.h:279
#define extra_type_iterate_end
Definition: extras.h:285
#define extra_type_by_rmcause_iterate_end
Definition: extras.h:330
#define extra_index(_e_)
Definition: extras.h:163
#define extra_type_by_rmcause_iterate(_rmcause, _extra)
Definition: extras.h:324
enum unit_activity Activity_type_id
Definition: fc_types.h:296
#define MAX_EXTRA_TYPES
Definition: fc_types.h:42
#define ERM_NONE
Definition: fc_types.h:958
#define _(String)
Definition: fcintl.h:50
#define fc_assert(condition)
Definition: log.h:89
int rmextra_turns[MAX_EXTRA_TYPES][ACTIVITY_LAST]
Definition: clientutils.cpp:32
int activity_turns[ACTIVITY_LAST]
Definition: clientutils.cpp:33
int extra_turns[MAX_EXTRA_TYPES][ACTIVITY_LAST]
Definition: clientutils.cpp:31
Definition: tile.h:42
struct unit_list * units
Definition: tile.h:50
int tile_activity_time(enum unit_activity activity, const struct tile *ptile, const struct extra_type *tgt)
Time to complete the given activity on the given tile.
Definition: tile.cpp:427
bool is_tile_activity(enum unit_activity activity)
Returns true if given activity affects tile.
Definition: unit.cpp:1480
int get_activity_rate_this_turn(const struct unit *punit)
Returns the amount of work a unit does (will do) on an activity this turn.
Definition: unit.cpp:470
int get_activity_rate(const struct unit *punit)
Returns the speed of a unit doing an activity.
Definition: unit.cpp:443
bool is_build_activity(enum unit_activity activity, const struct tile *ptile)
Returns true if given activity is some kind of building.
Definition: unit.cpp:1434
bool is_clean_activity(enum unit_activity activity)
Returns true if given activity is some kind of cleaning.
Definition: unit.cpp:1450
const char * get_activity_text(enum unit_activity activity)
Return the name of the activity in a static buffer.
Definition: unit.cpp:586
#define activity_type_iterate(_act_)
Definition: unit.h:282
#define activity_type_iterate_end
Definition: unit.h:286
#define unit_list_iterate(unitlist, punit)
Definition: unitlist.h:25
#define unit_list_iterate_end
Definition: unitlist.h:27