Freeciv21
Develop your civilization from humble roots to a global empire
texaiplayer.c
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 #include <fc_config.h>
15 
16 /* utility */
17 #include "log.h"
18 
19 /* common */
20 #include "ai.h"
21 #include "city.h"
22 #include "game.h"
23 #include "map.h"
24 #include "unit.h"
25 
26 /* server/advisors */
27 #include "advchoice.h"
28 #include "infracache.h"
29 
30 /* ai/default */
31 #include "aiplayer.h"
32 #include "daimilitary.h"
33 
34 /* ai/tex */
35 #include "texaicity.h"
36 #include "texaiworld.h"
37 
38 #include "texaiplayer.h"
39 
40 /* What level of operation we should abort because
41  * of received messages. Lower is more critical;
42  * TEXAI_ABORT_EXIT means that whole thread should exit,
43  * TEXAI_ABORT_NONE means that we can continue what we were doing */
48 };
49 
50 static enum texai_abort_msg_class texai_check_messages(struct ai_type *ait);
51 
52 struct texai_thr {
54  struct texai_msgs msgs_to;
55  struct texai_reqs reqs_from;
59 
61  int city_id;
62  struct adv_choice choice;
63 };
64 
65 /**********************************************************************/
69 {
70  exthrai.thread_running = false;
71 
72  exthrai.num_players = 0;
73 }
74 
75 /**********************************************************************/
78 static void texai_thread_start(void *arg)
79 {
80  bool finished = false;
81  struct ai_type *texai = arg;
82 
83  log_debug("New AI thread launched");
84 
86  if (!map_is_empty()) {
88  }
89 
90  /* Just wait until we are signaled to shutdown */
91  fc_allocate_mutex(&exthrai.msgs_to.mutex);
92  while (!finished) {
93  fc_thread_cond_wait(&exthrai.msgs_to.thr_cond, &exthrai.msgs_to.mutex);
94 
95  if (texai_check_messages(texai) <= TEXAI_ABORT_EXIT) {
96  finished = true;
97  }
98  }
99  fc_release_mutex(&exthrai.msgs_to.mutex);
100 
102 
103  log_debug("AI thread exiting");
104 }
105 
106 /**********************************************************************/
109 void texai_map_alloc(void)
110 {
111  texai_send_msg(TEXAI_MSG_MAP_ALLOC, NULL, NULL);
112 }
113 
114 /**********************************************************************/
118 {
119  whole_map_iterate(&(wld.map), ptile) { texai_tile_info(ptile); }
121 }
122 
123 /**********************************************************************/
126 static void texai_map_alloc_recv(void) { texai_map_init(); }
127 
128 /**********************************************************************/
131 void texai_map_free(void) { texai_send_msg(TEXAI_MSG_MAP_FREE, NULL, NULL); }
132 
133 /**********************************************************************/
136 static void texai_map_free_recv(void) { texai_map_close(); }
137 
138 /**********************************************************************/
141 struct unit_list *texai_player_units(struct player *pplayer)
142 {
143  struct texai_plr *plr_data = player_ai_data(pplayer, texai_get_self());
144 
145  return plr_data->units;
146 }
147 
148 /**********************************************************************/
151 static enum texai_abort_msg_class texai_check_messages(struct ai_type *ait)
152 {
153  enum texai_abort_msg_class ret_abort = TEXAI_ABORT_NONE;
154 
155  texaimsg_list_allocate_mutex(exthrai.msgs_to.msglist);
156  while (texaimsg_list_size(exthrai.msgs_to.msglist) > 0) {
157  struct texai_msg *msg;
158  enum texai_abort_msg_class new_abort = TEXAI_ABORT_NONE;
159 
160  msg = texaimsg_list_get(exthrai.msgs_to.msglist, 0);
161  texaimsg_list_remove(exthrai.msgs_to.msglist, msg);
162  texaimsg_list_release_mutex(exthrai.msgs_to.msglist);
163 
164  log_debug("Plr thr got %s", texaimsgtype_name(msg->type));
165 
166  switch (msg->type) {
167  case TEXAI_MSG_FIRST_ACTIVITIES:
168  fc_allocate_mutex(&game.server.mutexes.city_list);
169 
171 
172  /* Use _safe iterate in case the main thread
173  * destroyes cities while we are iterating through these. */
174  city_list_iterate_safe(msg->plr->cities, pcity)
175  {
176  struct adv_choice *choice;
177  struct texai_build_choice_req *choice_req =
178  fc_malloc(sizeof(struct texai_build_choice_req));
179  struct city *tex_city = texai_map_city(pcity->id);
180 
181  texai_city_worker_requests_create(ait, msg->plr, pcity);
182  texai_city_worker_wants(ait, msg->plr, pcity);
183 
184  if (tex_city != NULL) {
186  ait, msg->plr, tex_city, texai_map_get(), texai_player_units);
187  choice_req->city_id = tex_city->id;
188  adv_choice_copy(&(choice_req->choice), choice);
189  adv_free_choice(choice);
190  texai_send_req(TEXAI_BUILD_CHOICE, msg->plr, choice_req);
191  }
192 
193  /* Release mutex for a second in case main thread
194  * wants to do something to city list. */
195  fc_release_mutex(&game.server.mutexes.city_list);
196 
197  /* Recursive message check in case phase is finished. */
198  new_abort = texai_check_messages(ait);
199  fc_allocate_mutex(&game.server.mutexes.city_list);
200  if (new_abort < TEXAI_ABORT_NONE) {
201  break;
202  }
203  }
205  fc_release_mutex(&game.server.mutexes.city_list);
206 
207  texai_send_req(TEXAI_REQ_TURN_DONE, msg->plr, NULL);
208 
209  break;
210  case TEXAI_MSG_TILE_INFO:
212  break;
213  case TEXAI_MSG_UNIT_MOVED:
215  break;
216  case TEXAI_MSG_UNIT_CREATED:
217  case TEXAI_MSG_UNIT_CHANGED:
218  texai_unit_info_recv(msg->data, msg->type);
219  break;
220  case TEXAI_MSG_UNIT_DESTROYED:
222  break;
223  case TEXAI_MSG_CITY_CREATED:
224  case TEXAI_MSG_CITY_CHANGED:
225  texai_city_info_recv(msg->data, msg->type);
226  break;
227  case TEXAI_MSG_CITY_DESTROYED:
229  break;
230  case TEXAI_MSG_PHASE_FINISHED:
231  new_abort = TEXAI_ABORT_PHASE_END;
232  break;
233  case TEXAI_MSG_THR_EXIT:
234  new_abort = TEXAI_ABORT_EXIT;
235  break;
236  case TEXAI_MSG_MAP_ALLOC:
238  break;
239  case TEXAI_MSG_MAP_FREE:
241  break;
242  default:
243  qCritical("Illegal message type %s (%d) for threaded ai!",
244  texaimsgtype_name(msg->type), msg->type);
245  break;
246  }
247 
248  if (new_abort < ret_abort) {
249  ret_abort = new_abort;
250  }
251 
252  delete msg;
253  msg = nullptr;
254 
255  texaimsg_list_allocate_mutex(exthrai.msgs_to.msglist);
256  }
257  texaimsg_list_release_mutex(exthrai.msgs_to.msglist);
258 
259  return ret_abort;
260 }
261 
262 /**********************************************************************/
265 void texai_player_alloc(struct ai_type *ait, struct player *pplayer)
266 {
267  struct texai_plr *player_data = new texai_plr{};
268 
269  player_set_ai_data(pplayer, ait, player_data);
270 
271  /* Default AI */
272  dai_data_init(ait, pplayer);
273 
274  player_data->units = unit_list_new();
275 }
276 
277 /**********************************************************************/
280 void texai_player_free(struct ai_type *ait, struct player *pplayer)
281 {
282  struct texai_plr *player_data = player_ai_data(pplayer, ait);
283 
284  /* Default AI */
285  dai_data_close(ait, pplayer);
286 
287  if (player_data != NULL) {
288  player_set_ai_data(pplayer, ait, NULL);
289  unit_list_destroy(player_data->units);
290  delete player_data;
291  player_data = nullptr;
292  }
293 }
294 
295 /**********************************************************************/
298 void texai_control_gained(struct ai_type *ait, struct player *pplayer)
299 {
301 
302  log_debug("%s now under tex AI (%d)", pplayer->name, exthrai.num_players);
303 
304  if (!exthrai.thread_running) {
305  exthrai.msgs_to.msglist = texaimsg_list_new();
306  exthrai.reqs_from.reqlist = texaireq_list_new();
307 
308  exthrai.thread_running = true;
309 
310  fc_thread_cond_init(&exthrai.msgs_to.thr_cond);
311  fc_init_mutex(&exthrai.msgs_to.mutex);
313  exthrai.ait.start(QThread::LowestPriority);
314 
315  players_iterate(oplayer)
316  {
317  city_list_iterate(oplayer->cities, pcity)
318  {
319  texai_city_created(pcity);
320  }
322  unit_list_iterate(oplayer->units, punit) { texai_unit_created(punit); }
324  }
326  }
327 }
328 
329 /**********************************************************************/
332 void texai_control_lost(struct ai_type *ait, struct player *pplayer)
333 {
335 
336  log_debug("%s no longer under threaded AI (%d)", pplayer->name,
338 
339  if (exthrai.num_players <= 0) {
340  texai_send_msg(TEXAI_MSG_THR_EXIT, pplayer, NULL);
341 
342  fc_thread_wait(&exthrai.ait);
343  exthrai.thread_running = false;
344 
345  fc_thread_cond_destroy(&exthrai.msgs_to.thr_cond);
346  fc_destroy_mutex(&exthrai.msgs_to.mutex);
347  texaimsg_list_destroy(exthrai.msgs_to.msglist);
348  texaireq_list_destroy(exthrai.reqs_from.reqlist);
349  }
350 }
351 
352 /**********************************************************************/
355 void texai_refresh(struct ai_type *ait, struct player *pplayer)
356 {
357  if (exthrai.thread_running) {
358  texaireq_list_allocate_mutex(exthrai.reqs_from.reqlist);
359  while (texaireq_list_size(exthrai.reqs_from.reqlist) > 0) {
360  struct texai_req *req;
361 
362  req = texaireq_list_get(exthrai.reqs_from.reqlist, 0);
363  texaireq_list_remove(exthrai.reqs_from.reqlist, req);
364 
365  texaireq_list_release_mutex(exthrai.reqs_from.reqlist);
366 
367  log_debug("Plr thr sent %s", texaireqtype_name(req->type));
368 
369  switch (req->type) {
370  case TEXAI_REQ_WORKER_TASK:
372  break;
373  case TEXAI_BUILD_CHOICE: {
374  struct texai_build_choice_req *choice_req =
375  (struct texai_build_choice_req *) (req->data);
376  struct city *pcity = game_city_by_number(choice_req->city_id);
377 
378  if (pcity != NULL && city_owner(pcity) == req->plr) {
379  adv_choice_copy(&(def_ai_city_data(pcity, ait)->choice),
380  &(choice_req->choice));
381  delete choice_req;
382  choice_req = nullptr;
383  }
384  } break;
385  case TEXAI_REQ_TURN_DONE:
386  req->plr->ai_phase_done = true;
387  break;
388  }
389 
390  delete req;
391  req = nullptr;
392 
393  texaireq_list_allocate_mutex(exthrai.reqs_from.reqlist);
394  }
395  texaireq_list_release_mutex(exthrai.reqs_from.reqlist);
396  }
397 }
398 
399 /**********************************************************************/
403 void texai_msg_to_thr(struct texai_msg *msg)
404 {
405  fc_allocate_mutex(&exthrai.msgs_to.mutex);
406  texaimsg_list_append(exthrai.msgs_to.msglist, msg);
407  fc_thread_cond_signal(&exthrai.msgs_to.thr_cond);
408  fc_release_mutex(&exthrai.msgs_to.mutex);
409 }
410 
411 /**********************************************************************/
414 void texai_req_from_thr(struct texai_req *req)
415 {
416  texaireq_list_allocate_mutex(exthrai.reqs_from.reqlist);
417  texaireq_list_append(exthrai.reqs_from.reqlist, req);
418  texaireq_list_release_mutex(exthrai.reqs_from.reqlist);
419 }
420 
421 /**********************************************************************/
void adv_free_choice(struct adv_choice *choice)
Free dynamically allocated choice.
Definition: advchoice.cpp:67
static void adv_choice_copy(struct adv_choice *dest, struct adv_choice *src)
Definition: advchoice.h:62
void dai_data_init(struct ai_type *ait, struct player *pplayer)
Initialize ai data structure.
Definition: aidata.cpp:50
void dai_data_close(struct ai_type *ait, struct player *pplayer)
Deinitialize ai data structure.
Definition: aidata.cpp:98
static struct ai_city * def_ai_city_data(const struct city *pcity, struct ai_type *deftype)
Definition: aiplayer.h:35
struct player * city_owner(const struct city *pcity)
Return the owner of the city.
Definition: city.cpp:1083
#define city_list_iterate_safe(citylist, _city)
Definition: city.h:500
#define city_list_iterate(citylist, pcity)
Definition: city.h:482
#define city_list_iterate_end
Definition: city.h:484
#define city_list_iterate_safe_end
Definition: city.h:521
void set_func(void(tfunc)(void *), void *tdata)
Definition: fcthread.cpp:20
struct adv_choice * military_advisor_choose_build(struct ai_type *ait, struct player *pplayer, struct city *pcity, const struct civ_map *mamap, player_unit_list_getter ul_cb)
This function selects either a defender or an attacker to be built.
struct civ_game game
Definition: game.cpp:47
struct world wld
Definition: game.cpp:48
struct city * game_city_by_number(int id)
Often used function to get a city pointer from a city ID.
Definition: game.cpp:103
void initialize_infrastructure_cache(struct player *pplayer)
Do all tile improvement calculations and cache them for later.
Definition: infracache.cpp:245
#define log_debug(message,...)
Definition: log.h:65
bool map_is_empty()
Returns TRUE if we are at a stage of the game where the map has not yet been generated/loaded.
Definition: map.cpp:124
#define whole_map_iterate(_map, _tile)
Definition: map.h:473
#define whole_map_iterate_end
Definition: map.h:480
void * player_ai_data(const struct player *pplayer, const struct ai_type *ai)
Return pointer to ai data of given player and ai type.
Definition: player.cpp:1838
void player_set_ai_data(struct player *pplayer, const struct ai_type *ai, void *data)
Attach ai data to player.
Definition: player.cpp:1846
#define players_iterate_end
Definition: player.h:520
#define players_iterate(_pplayer)
Definition: player.h:514
Definition: ai.h:42
Definition: city.h:291
int id
Definition: city.h:296
struct civ_game::@28::@32 server
Definition: player.h:231
struct city_list * cities
Definition: player.h:263
char name[MAX_LEN_NAME]
Definition: player.h:233
bool ai_phase_done
Definition: player.h:246
struct adv_choice choice
Definition: texaiplayer.c:62
struct player * plr
Definition: texaimsg.h:55
enum texaimsgtype type
Definition: texaimsg.h:54
void * data
Definition: texaimsg.h:56
QWaitCondition thr_cond
Definition: texaiplayer.h:32
QMutex mutex
Definition: texaiplayer.h:33
struct texaimsg_list * msglist
Definition: texaiplayer.h:34
struct unit_list * units
Definition: texaiplayer.h:43
void * data
Definition: texaimsg.h:62
enum texaireqtype type
Definition: texaimsg.h:60
struct player * plr
Definition: texaimsg.h:61
struct texaireq_list * reqlist
Definition: texaiplayer.h:38
bool thread_running
Definition: texaiplayer.c:56
fcThread ait
Definition: texaiplayer.c:57
struct texai_reqs reqs_from
Definition: texaiplayer.c:55
int num_players
Definition: texaiplayer.c:53
struct texai_msgs msgs_to
Definition: texaiplayer.c:54
struct civ_map map
Definition: world_object.h:21
#define fc_malloc(sz)
Definition: support.h:58
struct ai_type * texai_get_self(void)
Get pointer to ai type of the tex ai.
Definition: texai.c:58
void texai_city_worker_requests_create(struct ai_type *ait, struct player *pplayer, struct city *pcity)
Create worker request for the city.
Definition: texaicity.c:68
void texai_city_worker_wants(struct ai_type *ait, struct player *pplayer, struct city *pcity)
Set wants for worker-type units.
Definition: texaicity.c:91
void texai_req_worker_task_rcv(struct texai_req *req)
Receive message from thread to main thread.
Definition: texaicity.c:549
void texai_send_msg(enum texaimsgtype type, struct player *pplayer, void *data)
Construct and send message to player thread.
Definition: texaimsg.c:24
void texai_send_req(enum texaireqtype type, struct player *pplayer, void *data)
Construct and send request from player thread.
Definition: texaimsg.c:46
void texai_player_alloc(struct ai_type *ait, struct player *pplayer)
Initialize player for use with tex AI.
Definition: texaiplayer.c:265
struct unit_list * texai_player_units(struct player *pplayer)
Callback that returns unit list from player tex ai data.
Definition: texaiplayer.c:141
struct texai_thr exthrai
void texai_control_gained(struct ai_type *ait, struct player *pplayer)
We actually control the player.
Definition: texaiplayer.c:298
void texai_player_free(struct ai_type *ait, struct player *pplayer)
Free player from use with tex AI.
Definition: texaiplayer.c:280
bool texai_thread_running(void)
Return whether player thread is running.
Definition: texaiplayer.c:424
void texai_control_lost(struct ai_type *ait, struct player *pplayer)
We no longer control the player.
Definition: texaiplayer.c:332
void texai_req_from_thr(struct texai_req *req)
Thread sends message.
Definition: texaiplayer.c:414
static void texai_thread_start(void *arg)
This is main function of ai thread.
Definition: texaiplayer.c:78
static void texai_map_free_recv(void)
Map free message received.
Definition: texaiplayer.c:136
texai_abort_msg_class
Definition: texaiplayer.c:44
@ TEXAI_ABORT_NONE
Definition: texaiplayer.c:47
@ TEXAI_ABORT_PHASE_END
Definition: texaiplayer.c:46
@ TEXAI_ABORT_EXIT
Definition: texaiplayer.c:45
static enum texai_abort_msg_class texai_check_messages(struct ai_type *ait)
Handle messages from message queue.
Definition: texaiplayer.c:151
void texai_refresh(struct ai_type *ait, struct player *pplayer)
Check for messages sent by player thread.
Definition: texaiplayer.c:355
void texai_init_threading(void)
Initialize ai thread.
Definition: texaiplayer.c:68
void texai_msg_to_thr(struct texai_msg *msg)
Send message to thread.
Definition: texaiplayer.c:403
void texai_map_alloc(void)
Main map has been allocated.
Definition: texaiplayer.c:109
void texai_whole_map_copy(void)
Send all tiles to tex thread.
Definition: texaiplayer.c:117
static void texai_map_alloc_recv(void)
Map allocation message received.
Definition: texaiplayer.c:126
void texai_map_free(void)
Main map has been freed.
Definition: texaiplayer.c:131
void texai_city_info_recv(void *data, enum texaimsgtype msgtype)
Receive city update to the thread.
Definition: texaiworld.c:159
void texai_city_created(struct city *pcity)
New city has been added to the main map.
Definition: texaiworld.c:143
void texai_city_destruction_recv(void *data)
Receive city destruction to the thread.
Definition: texaiworld.c:211
struct civ_map * texai_map_get(void)
Return tex worldmap.
Definition: texaiworld.c:81
void texai_tile_info_recv(void *data)
Receive tile update to the thread.
Definition: texaiworld.c:108
void texai_map_close(void)
Free resources allocated for texai world map.
Definition: texaiworld.c:86
void texai_world_init(void)
Initialize world object for texai.
Definition: texaiworld.c:62
void texai_tile_info(struct tile *ptile)
Tile info updated on main map.
Definition: texaiworld.c:91
void texai_unit_info_recv(void *data, enum texaimsgtype msgtype)
Receive unit update to the thread.
Definition: texaiworld.c:264
void texai_unit_created(struct unit *punit)
New unit has been added to the main map.
Definition: texaiworld.c:248
void texai_unit_moved_recv(void *data)
Receive unit move to the thread.
Definition: texaiworld.c:357
void texai_map_init(void)
Initialize world map for texai.
Definition: texaiworld.c:72
void texai_world_close(void)
Free resources allocated for texai world object.
Definition: texaiworld.c:67
void texai_unit_destruction_recv(void *data)
Receive unit destruction to the thread.
Definition: texaiworld.c:319
struct city * texai_map_city(int city_id)
Get city from the tex map.
Definition: texaiworld.c:189
#define unit_list_iterate(unitlist, punit)
Definition: unitlist.h:25
#define unit_list_iterate_end
Definition: unitlist.h:27