Added translator comment about government overthrown message.
[freeciv.git] / server / maphand.c
blobc63ed9df25d94110d866f9dc5a0f60df12ab7e6c
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 /* utility */
19 #include "bitvector.h"
20 #include "fcintl.h"
21 #include "log.h"
22 #include "mem.h"
23 #include "rand.h"
24 #include "support.h"
26 /* common */
27 #include "base.h"
28 #include "borders.h"
29 #include "events.h"
30 #include "game.h"
31 #include "map.h"
32 #include "movement.h"
33 #include "nation.h"
34 #include "packets.h"
35 #include "player.h"
36 #include "road.h"
37 #include "unit.h"
38 #include "unitlist.h"
39 #include "vision.h"
41 /* generator */
42 #include "utilities.h"
44 /* server */
45 #include "citytools.h"
46 #include "cityturn.h"
47 #include "notify.h"
48 #include "plrhand.h"
49 #include "sanitycheck.h"
50 #include "sernet.h"
51 #include "srv_main.h"
52 #include "unithand.h"
53 #include "unittools.h"
55 #include "maphand.h"
57 #define MAXIMUM_CLAIMED_OCEAN_SIZE (20)
59 /* Suppress send_tile_info() during game_load() */
60 static bool send_tile_suppressed = FALSE;
62 static void player_tile_init(struct tile *ptile, struct player *pplayer);
63 static void player_tile_free(struct tile *ptile, struct player *pplayer);
64 static void give_tile_info_from_player_to_player(struct player *pfrom,
65 struct player *pdest,
66 struct tile *ptile);
67 static void shared_vision_change_seen(struct player *pplayer,
68 struct tile *ptile,
69 const v_radius_t change,
70 bool can_reveal_tiles);
71 static void map_change_seen(struct player *pplayer,
72 struct tile *ptile,
73 const v_radius_t change,
74 bool can_reveal_tiles);
75 static void map_change_own_seen(struct player *pplayer,
76 struct tile *ptile,
77 const v_radius_t change);
78 static inline int map_get_seen(const struct player *pplayer,
79 const struct tile *ptile,
80 enum vision_layer vlayer);
81 static inline int map_get_own_seen(const struct player *pplayer,
82 const struct tile *ptile,
83 enum vision_layer vlayer);
85 static bool is_claimable_ocean(struct tile *ptile, struct tile *source,
86 struct player *pplayer);
88 /**************************************************************************
89 Used only in global_warming() and nuclear_winter() below.
90 **************************************************************************/
91 static bool is_terrain_ecologically_wet(struct tile *ptile)
93 return (is_terrain_class_near_tile(ptile, TC_OCEAN)
94 || tile_has_river(ptile)
95 || count_river_near_tile(ptile, NULL) > 0);
98 /**************************************************************************
99 Wrapper for climate_change().
100 **************************************************************************/
101 void global_warming(int effect)
103 climate_change(TRUE, effect);
104 notify_player(NULL, NULL, E_GLOBAL_ECO, ftc_server,
105 _("Global warming has occurred!"));
106 notify_player(NULL, NULL, E_GLOBAL_ECO, ftc_server,
107 _("Coastlines have been flooded and vast "
108 "ranges of grassland have become deserts."));
111 /**************************************************************************
112 Wrapper for climate_change().
113 **************************************************************************/
114 void nuclear_winter(int effect)
116 climate_change(FALSE, effect);
117 notify_player(NULL, NULL, E_GLOBAL_ECO, ftc_server,
118 _("Nuclear winter has occurred!"));
119 notify_player(NULL, NULL, E_GLOBAL_ECO, ftc_server,
120 _("Wetlands have dried up and vast "
121 "ranges of grassland have become tundra."));
124 /*****************************************************************************
125 Do a climate change. Global warming occurred if 'warming' is TRUE, else
126 there is a nuclear winter.
127 *****************************************************************************/
128 void climate_change(bool warming, int effect)
130 int k = map_num_tiles();
131 bool used[k];
132 memset(used, 0, sizeof(used));
134 log_verbose("Climate change: %s (%d)",
135 warming ? "Global warming" : "Nuclear winter", effect);
137 while (effect > 0 && (k--) > 0) {
138 struct terrain *old, *candidates[2], *new;
139 struct tile *ptile;
140 int i;
142 do {
143 /* We want to transform a tile at most once due to a climate change. */
144 ptile = rand_map_pos();
145 } while (used[tile_index(ptile)]);
146 used[tile_index(ptile)] = TRUE;
148 old = tile_terrain(ptile);
149 /* Prefer the transformation that's appropriate to the ambient moisture,
150 * but be prepared to fall back in exceptional circumstances */
152 struct terrain *wetter, *drier;
153 wetter = warming ? old->warmer_wetter_result : old->cooler_wetter_result;
154 drier = warming ? old->warmer_drier_result : old->cooler_drier_result;
155 if (is_terrain_ecologically_wet(ptile)) {
156 candidates[0] = wetter;
157 candidates[1] = drier;
158 } else {
159 candidates[0] = drier;
160 candidates[1] = wetter;
164 /* If the preferred transformation is ruled out for some exceptional reason
165 * specific to this tile, fall back to the other, rather than letting this
166 * tile be immune to change. */
167 for (i=0; i<2; i++) {
168 new = candidates[i];
170 /* If the preferred transformation simply hasn't been specified
171 * for this terrain at all, don't fall back to the other. */
172 if (new == T_NONE) {
173 break;
176 if (tile_city(ptile) != NULL && terrain_has_flag(new, TER_NO_CITIES)) {
177 /* do not change to a terrain with the flag TER_NO_CITIES if the tile
178 * has a city */
179 continue;
182 /* Only change between water and land at coastlines, and between
183 * frozen and unfrozen at ice margin */
184 if (!terrain_surroundings_allow_change(ptile, new)) {
185 continue;
188 /* OK! */
189 break;
191 if (i == 2) {
192 /* Neither transformation was permitted. Give up. */
193 continue;
196 if (new != T_NONE && old != new) {
197 effect--;
199 /* Really change the terrain. */
200 tile_change_terrain(ptile, new);
201 check_terrain_change(ptile, old);
202 update_tile_knowledge(ptile);
204 /* Check the unit activities. */
205 unit_list_iterate(ptile->units, punit) {
206 if (!can_unit_continue_current_activity(punit)) {
207 unit_activity_handling(punit, ACTIVITY_IDLE);
209 } unit_list_iterate_end;
210 } else if (old == new) {
211 /* This counts toward a climate change although nothing is changed. */
212 effect--;
217 /***************************************************************
218 Check city for extra upgrade. Returns whether anything was
219 done.
220 *gained will be set if there's exactly one kind of extra added.
221 ***************************************************************/
222 bool upgrade_city_extras(struct city *pcity, struct extra_type **gained)
224 struct tile *ptile = pcity->tile;
225 struct player *pplayer = city_owner(pcity);
226 bool upgradet = FALSE;
228 extra_type_iterate(pextra) {
229 if (!tile_has_extra(ptile, pextra)) {
230 if (extra_has_flag(pextra, EF_ALWAYS_ON_CITY_CENTER)
231 || (extra_has_flag(pextra, EF_AUTO_ON_CITY_CENTER)
232 && player_can_build_extra(pextra, pplayer, ptile)
233 && !tile_has_conflicting_extra(ptile, pextra))) {
234 tile_add_extra(pcity->tile, pextra);
235 if (gained != NULL) {
236 if (upgradet) {
237 *gained = NULL;
238 } else {
239 *gained = pextra;
242 upgradet = TRUE;
245 } extra_type_iterate_end;
247 return upgradet;
250 /***************************************************************
251 To be called when a player gains some better extra building tech
252 for the first time. Sends a message, and upgrades all city
253 squares to new extras. "discovery" just affects the message: set to
254 1 if the tech is a "discovery",
255 0 if otherwise acquired (conquer/trade/GLib). --dwp
256 ***************************************************************/
257 void upgrade_all_city_extras(struct player *pplayer, bool discovery)
259 int cities_upgradet = 0;
260 struct extra_type *upgradet = NULL;
261 bool multiple_types = FALSE;
262 int cities_total = city_list_size(pplayer->cities);
263 int percent;
265 conn_list_do_buffer(pplayer->connections);
267 city_list_iterate(pplayer->cities, pcity) {
268 struct extra_type *new_upgrade;
270 if (upgrade_city_extras(pcity, &new_upgrade)) {
271 update_tile_knowledge(pcity->tile);
272 cities_upgradet++;
273 if (new_upgrade == NULL) {
274 /* This single city alone had multiple types */
275 multiple_types = TRUE;
276 } else if (upgradet == NULL) {
277 /* First gained */
278 upgradet = new_upgrade;
279 } else if (upgradet != new_upgrade) {
280 /* Different type from what another city got. */
281 multiple_types = TRUE;
284 } city_list_iterate_end;
286 if (cities_total > 0) {
287 percent = cities_upgradet * 100 / cities_total;
288 } else {
289 percent = 0;
292 if (cities_upgradet > 0) {
293 if (discovery) {
294 if (percent >= 75) {
295 notify_player(pplayer, NULL, E_TECH_GAIN, ftc_server,
296 _("New hope sweeps like fire through the country as "
297 "the discovery of new infrastructure building technology "
298 "is announced."));
300 } else {
301 if (percent >= 75) {
302 notify_player(pplayer, NULL, E_TECH_GAIN, ftc_server,
303 _("The people are pleased to hear that your "
304 "scientists finally know about new infrastructure building "
305 "technology."));
309 if (multiple_types) {
310 notify_player(pplayer, NULL, E_TECH_GAIN, ftc_server,
311 _("Workers spontaneously gather and upgrade all "
312 "possible cities with better infrastructure."));
313 } else {
314 notify_player(pplayer, NULL, E_TECH_GAIN, ftc_server,
315 _("Workers spontaneously gather and upgrade all "
316 "possible cities with %s."), extra_name_translation(upgradet));
320 conn_list_do_unbuffer(pplayer->connections);
323 /**************************************************************************
324 Return TRUE iff the player me really gives shared vision to player them.
325 **************************************************************************/
326 bool really_gives_vision(struct player *me, struct player *them)
328 return BV_ISSET(me->server.really_gives_vision, player_index(them));
331 /**************************************************************************
332 Start buffering shared vision
333 **************************************************************************/
334 static void buffer_shared_vision(struct player *pplayer)
336 players_iterate(pplayer2) {
337 if (really_gives_vision(pplayer, pplayer2)) {
338 conn_list_compression_freeze(pplayer2->connections);
339 conn_list_do_buffer(pplayer2->connections);
341 } players_iterate_end;
342 conn_list_compression_freeze(pplayer->connections);
343 conn_list_do_buffer(pplayer->connections);
346 /**************************************************************************
347 Stop buffering shared vision
348 **************************************************************************/
349 static void unbuffer_shared_vision(struct player *pplayer)
351 players_iterate(pplayer2) {
352 if (really_gives_vision(pplayer, pplayer2)) {
353 conn_list_do_unbuffer(pplayer2->connections);
354 conn_list_compression_thaw(pplayer2->connections);
356 } players_iterate_end;
357 conn_list_do_unbuffer(pplayer->connections);
358 conn_list_compression_thaw(pplayer->connections);
361 /**************************************************************************
362 Give information about whole map (all tiles) from player to player.
363 **************************************************************************/
364 void give_map_from_player_to_player(struct player *pfrom, struct player *pdest)
366 buffer_shared_vision(pdest);
368 whole_map_iterate(ptile) {
369 give_tile_info_from_player_to_player(pfrom, pdest, ptile);
370 } whole_map_iterate_end;
372 unbuffer_shared_vision(pdest);
373 city_thaw_workers_queue();
374 sync_cities();
377 /**************************************************************************
378 Give information about all oceanic tiles from player to player
379 **************************************************************************/
380 void give_seamap_from_player_to_player(struct player *pfrom, struct player *pdest)
382 buffer_shared_vision(pdest);
384 whole_map_iterate(ptile) {
385 if (is_ocean_tile(ptile)) {
386 give_tile_info_from_player_to_player(pfrom, pdest, ptile);
388 } whole_map_iterate_end;
390 unbuffer_shared_vision(pdest);
391 city_thaw_workers_queue();
392 sync_cities();
395 /**************************************************************************
396 Give information about tiles within city radius from player to player
397 **************************************************************************/
398 void give_citymap_from_player_to_player(struct city *pcity,
399 struct player *pfrom, struct player *pdest)
401 struct tile *pcenter = city_tile(pcity);
403 buffer_shared_vision(pdest);
405 city_tile_iterate(city_map_radius_sq_get(pcity), pcenter, ptile) {
406 give_tile_info_from_player_to_player(pfrom, pdest, ptile);
407 } city_tile_iterate_end;
409 unbuffer_shared_vision(pdest);
410 city_thaw_workers_queue();
411 sync_cities();
414 /**************************************************************************
415 Send all tiles known to specified clients.
416 If dest is NULL means game.est_connections.
418 Note for multiple connections this may change "sent" multiple times
419 for single player. This is ok, because "sent" data is just optimised
420 calculations, so it will be correct before this, for each connection
421 during this, and at end.
422 **************************************************************************/
423 void send_all_known_tiles(struct conn_list *dest)
425 int tiles_sent;
427 if (!dest) {
428 dest = game.est_connections;
431 /* send whole map piece by piece to each player to balance the load
432 of the send buffers better */
433 tiles_sent = 0;
434 conn_list_do_buffer(dest);
436 whole_map_iterate(ptile) {
437 tiles_sent++;
438 if ((tiles_sent % game.map.xsize) == 0) {
439 conn_list_do_unbuffer(dest);
440 flush_packets();
441 conn_list_do_buffer(dest);
444 send_tile_info(dest, ptile, FALSE);
445 } whole_map_iterate_end;
447 conn_list_do_unbuffer(dest);
448 flush_packets();
451 /**************************************************************************
452 Suppress send_tile_info() during game_load()
453 **************************************************************************/
454 bool send_tile_suppression(bool now)
456 bool formerly = send_tile_suppressed;
458 send_tile_suppressed = now;
459 return formerly;
462 /**************************************************************************
463 Send tile information to all the clients in dest which know and see
464 the tile. If dest is NULL, sends to all clients (game.est_connections)
465 which know and see tile.
467 Note that this function does not update the playermap. For that call
468 update_tile_knowledge().
469 **************************************************************************/
470 void send_tile_info(struct conn_list *dest, struct tile *ptile,
471 bool send_unknown)
473 struct packet_tile_info info;
474 const struct player *owner;
475 const struct player *eowner;
477 if (send_tile_suppressed) {
478 return;
481 if (!dest) {
482 dest = game.est_connections;
485 info.tile = tile_index(ptile);
487 if (ptile->spec_sprite) {
488 sz_strlcpy(info.spec_sprite, ptile->spec_sprite);
489 } else {
490 info.spec_sprite[0] = '\0';
493 conn_list_iterate(dest, pconn) {
494 struct player *pplayer = pconn->playing;
496 if (NULL == pplayer && !pconn->observer) {
497 continue;
500 if (!pplayer || map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
501 info.known = TILE_KNOWN_SEEN;
502 info.continent = tile_continent(ptile);
503 owner = tile_owner(ptile);
504 eowner = extra_owner(ptile);
505 info.owner = (owner ? player_number(owner) : MAP_TILE_OWNER_NULL);
506 info.extras_owner = (eowner ? player_number(eowner) : MAP_TILE_OWNER_NULL);
507 info.worked = (NULL != tile_worked(ptile))
508 ? tile_worked(ptile)->id
509 : IDENTITY_NUMBER_ZERO;
511 info.terrain = (NULL != tile_terrain(ptile))
512 ? terrain_number(tile_terrain(ptile))
513 : terrain_count();
514 info.resource = (NULL != tile_resource(ptile))
515 ? resource_number(tile_resource(ptile))
516 : resource_count();
518 info.extras = ptile->extras;
520 if (ptile->label != NULL) {
521 strncpy(info.label, ptile->label, sizeof(info.label));
522 } else {
523 info.label[0] = '\0';
526 send_packet_tile_info(pconn, &info);
527 } else if (pplayer && map_is_known(ptile, pplayer)) {
528 struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
529 struct vision_site *psite = map_get_player_site(ptile, pplayer);
531 info.known = TILE_KNOWN_UNSEEN;
532 info.continent = tile_continent(ptile);
533 owner = (game.server.foggedborders
534 ? plrtile->owner
535 : tile_owner(ptile));
536 eowner = plrtile->extras_owner;
537 info.owner = (owner ? player_number(owner) : MAP_TILE_OWNER_NULL);
538 info.extras_owner = (eowner ? player_number(eowner) : MAP_TILE_OWNER_NULL);
539 info.worked = (NULL != psite)
540 ? psite->identity
541 : IDENTITY_NUMBER_ZERO;
543 info.terrain = (NULL != plrtile->terrain)
544 ? terrain_number(plrtile->terrain)
545 : terrain_count();
546 info.resource = (NULL != plrtile->resource)
547 ? resource_number(plrtile->resource)
548 : resource_count();
550 info.extras = plrtile->extras;
552 /* Labels never change, so they are not subject to fog of war */
553 if (ptile->label != NULL) {
554 strncpy(info.label, ptile->label, sizeof(info.label));
555 } else {
556 info.label[0] = '\0';
559 send_packet_tile_info(pconn, &info);
560 } else if (send_unknown) {
561 info.known = TILE_UNKNOWN;
562 info.continent = 0;
563 info.owner = MAP_TILE_OWNER_NULL;
564 info.extras_owner = MAP_TILE_OWNER_NULL;
565 info.worked = IDENTITY_NUMBER_ZERO;
567 info.terrain = terrain_count();
568 info.resource = resource_count();
570 BV_CLR_ALL(info.extras);
572 info.label[0] = '\0';
574 send_packet_tile_info(pconn, &info);
577 conn_list_iterate_end;
580 /****************************************************************************
581 Assumption: Each unit type is visible on only one layer.
582 ****************************************************************************/
583 static bool unit_is_visible_on_layer(const struct unit *punit,
584 enum vision_layer vlayer)
586 return XOR(vlayer == V_MAIN, is_hiding_unit(punit));
589 /**************************************************************************
590 Send basic map information: map size, topology, and is_earth.
591 **************************************************************************/
592 void send_map_info(struct conn_list *dest)
594 struct packet_map_info minfo;
596 minfo.xsize = game.map.xsize;
597 minfo.ysize = game.map.ysize;
598 minfo.topology_id = game.map.topology_id;
600 lsend_packet_map_info(dest, &minfo);
603 /****************************************************************************
604 Change the seen count of a tile for a pplayer. It will automatically
605 handle the shared visions.
606 ****************************************************************************/
607 static void shared_vision_change_seen(struct player *pplayer,
608 struct tile *ptile,
609 const v_radius_t change,
610 bool can_reveal_tiles)
612 map_change_own_seen(pplayer, ptile, change);
613 map_change_seen(pplayer, ptile, change, can_reveal_tiles);
615 players_iterate(pplayer2) {
616 if (really_gives_vision(pplayer, pplayer2)) {
617 map_change_seen(pplayer2, ptile, change, can_reveal_tiles);
619 } players_iterate_end;
622 /**************************************************************************
623 There doesn't have to be a city.
624 **************************************************************************/
625 void map_vision_update(struct player *pplayer, struct tile *ptile,
626 const v_radius_t old_radius_sq,
627 const v_radius_t new_radius_sq,
628 bool can_reveal_tiles)
630 v_radius_t change;
631 int max_radius;
633 if (old_radius_sq[V_MAIN] == new_radius_sq[V_MAIN]
634 && old_radius_sq[V_INVIS] == new_radius_sq[V_INVIS]) {
635 return;
638 /* Determines 'max_radius' value. */
639 max_radius = 0;
640 vision_layer_iterate(v) {
641 if (max_radius < old_radius_sq[v]) {
642 max_radius = old_radius_sq[v];
644 if (max_radius < new_radius_sq[v]) {
645 max_radius = new_radius_sq[v];
647 } vision_layer_iterate_end;
649 #ifdef DEBUG
650 log_debug("Updating vision at (%d, %d) in a radius of %d.",
651 TILE_XY(ptile), max_radius);
652 vision_layer_iterate(v) {
653 log_debug(" vision layer %d is changing from %d to %d.",
654 v, old_radius_sq[v], new_radius_sq[v]);
655 } vision_layer_iterate_end;
656 #endif /* DEBUG */
658 buffer_shared_vision(pplayer);
659 circle_dxyr_iterate(ptile, max_radius, tile1, dx, dy, dr) {
660 vision_layer_iterate(v) {
661 if (dr > old_radius_sq[v] && dr <= new_radius_sq[v]) {
662 change[v] = 1;
663 } else if (dr > new_radius_sq[v] && dr <= old_radius_sq[v]) {
664 change[v] = -1;
665 } else {
666 change[v] = 0;
668 } vision_layer_iterate_end;
669 shared_vision_change_seen(pplayer, tile1, change, can_reveal_tiles);
670 } circle_dxyr_iterate_end;
671 unbuffer_shared_vision(pplayer);
674 /****************************************************************************
675 Shows the area to the player. Unless the tile is "seen", it will remain
676 fogged and units will be hidden.
678 Callers may wish to buffer_shared_vision before calling this function.
679 ****************************************************************************/
680 void map_show_tile(struct player *src_player, struct tile *ptile)
682 static int recurse = 0;
684 log_debug("Showing %i,%i to %s", TILE_XY(ptile), player_name(src_player));
686 fc_assert(recurse == 0);
687 recurse++;
689 players_iterate(pplayer) {
690 if (pplayer == src_player || really_gives_vision(src_player, pplayer)) {
691 struct city *pcity;
693 if (!map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
694 map_set_known(ptile, pplayer);
696 /* as the tile may be fogged send_tile_info won't always do this for us */
697 update_player_tile_knowledge(pplayer, ptile);
698 update_player_tile_last_seen(pplayer, ptile);
700 send_tile_info(pplayer->connections, ptile, FALSE);
702 /* remove old cities that exist no more */
703 reality_check_city(pplayer, ptile);
705 if ((pcity = tile_city(ptile))) {
706 /* as the tile may be fogged send_city_info won't do this for us */
707 update_dumb_city(pplayer, pcity);
708 send_city_info(pplayer, pcity);
711 vision_layer_iterate(v) {
712 if (0 < map_get_seen(pplayer, ptile, v)) {
713 unit_list_iterate(ptile->units, punit) {
714 if (unit_is_visible_on_layer(punit, v)) {
715 send_unit_info(pplayer->connections, punit);
717 } unit_list_iterate_end;
719 } vision_layer_iterate_end;
722 } players_iterate_end;
724 recurse--;
727 /****************************************************************************
728 Hides the area to the player.
730 Callers may wish to buffer_shared_vision before calling this function.
731 ****************************************************************************/
732 void map_hide_tile(struct player *src_player, struct tile *ptile)
734 static int recurse = 0;
736 log_debug("Hiding %d,%d to %s", TILE_XY(ptile), player_name(src_player));
738 fc_assert(recurse == 0);
739 recurse++;
741 players_iterate(pplayer) {
742 if (pplayer == src_player || really_gives_vision(src_player, pplayer)) {
743 if (map_is_known(ptile, pplayer)) {
744 if (0 < map_get_seen(pplayer, ptile, V_MAIN)) {
745 update_player_tile_last_seen(pplayer, ptile);
748 /* Remove city. */
749 remove_dumb_city(pplayer, ptile);
751 /* Remove units. */
752 vision_layer_iterate(v) {
753 if (0 < map_get_seen(pplayer, ptile, v)) {
754 unit_list_iterate(ptile->units, punit) {
755 if (unit_is_visible_on_layer(punit, v)) {
756 unit_goes_out_of_sight(pplayer, punit);
758 } unit_list_iterate_end;
760 } vision_layer_iterate_end;
763 map_clear_known(ptile, pplayer);
765 send_tile_info(pplayer->connections, ptile, TRUE);
767 } players_iterate_end;
769 recurse--;
772 /****************************************************************************
773 Shows the area to the player. Unless the tile is "seen", it will remain
774 fogged and units will be hidden.
775 ****************************************************************************/
776 void map_show_circle(struct player *pplayer, struct tile *ptile, int radius_sq)
778 buffer_shared_vision(pplayer);
780 circle_iterate(ptile, radius_sq, tile1) {
781 map_show_tile(pplayer, tile1);
782 } circle_iterate_end;
784 unbuffer_shared_vision(pplayer);
787 /****************************************************************************
788 Shows the area to the player. Unless the tile is "seen", it will remain
789 fogged and units will be hidden.
790 ****************************************************************************/
791 void map_show_all(struct player *pplayer)
793 buffer_shared_vision(pplayer);
795 whole_map_iterate(ptile) {
796 map_show_tile(pplayer, ptile);
797 } whole_map_iterate_end;
799 unbuffer_shared_vision(pplayer);
802 /****************************************************************************
803 Return whether the player knows the tile. Knowing a tile means you've
804 seen it once (as opposed to seeing a tile which means you can see it now).
805 ****************************************************************************/
806 bool map_is_known(const struct tile *ptile, const struct player *pplayer)
808 return dbv_isset(&pplayer->tile_known, tile_index(ptile));
811 /****************************************************************************
812 Returns whether the layer 'vlayer' of the tile 'ptile' is known and seen
813 by the player 'pplayer'.
814 ****************************************************************************/
815 bool map_is_known_and_seen(const struct tile *ptile,
816 const struct player *pplayer,
817 enum vision_layer vlayer)
819 return (map_is_known(ptile, pplayer)
820 && 0 < map_get_seen(pplayer, ptile, vlayer));
823 /****************************************************************************
824 Return whether the player can see the tile. Seeing a tile means you have
825 vision of it now (as opposed to knowing a tile which means you've seen it
826 before). Note that a tile can be seen but not known (currently this only
827 happens when a city is founded with some unknown tiles in its radius); in
828 this case the tile is unknown (but map_get_seen will still return TRUE).
829 ****************************************************************************/
830 static inline int map_get_seen(const struct player *pplayer,
831 const struct tile *ptile,
832 enum vision_layer vlayer)
834 return map_get_player_tile(ptile, pplayer)->seen_count[vlayer];
837 /****************************************************************************
838 This function changes the seen state of one player for all vision layers
839 of a tile. It reveals the tiles if needed and controls the fog of war.
841 See also map_change_own_seen(), shared_vision_change_seen().
842 ****************************************************************************/
843 void map_change_seen(struct player *pplayer,
844 struct tile *ptile,
845 const v_radius_t change,
846 bool can_reveal_tiles)
848 struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
849 bool revealing_tile = FALSE;
851 #ifdef DEBUG
852 log_debug("%s() for player %s (nb %d) at (%d, %d).",
853 __FUNCTION__, player_name(pplayer), player_number(pplayer),
854 TILE_XY(ptile));
855 vision_layer_iterate(v) {
856 log_debug(" vision layer %d is changing from %d to %d.",
857 v, plrtile->seen_count[v], plrtile->seen_count[v] + change[v]);
858 } vision_layer_iterate_end;
859 #endif /* DEBUG */
861 /* Removes units out of vision. First, check V_INVIS layer because
862 * we must remove all units before fog of war because clients expect
863 * the tile is empty when it is fogged. */
864 if (0 > change[V_INVIS]
865 && plrtile->seen_count[V_INVIS] == -change[V_INVIS]) {
866 log_debug("(%d, %d): hiding invisible units to player %s (nb %d).",
867 TILE_XY(ptile), player_name(pplayer), player_number(pplayer));
869 unit_list_iterate(ptile->units, punit) {
870 if (unit_is_visible_on_layer(punit, V_INVIS)
871 && can_player_see_unit(pplayer, punit)) {
872 unit_goes_out_of_sight(pplayer, punit);
874 } unit_list_iterate_end;
877 if (0 > change[V_MAIN]
878 && plrtile->seen_count[V_MAIN] == -change[V_MAIN]) {
879 log_debug("(%d, %d): hiding visible units to player %s (nb %d).",
880 TILE_XY(ptile), player_name(pplayer), player_number(pplayer));
882 unit_list_iterate(ptile->units, punit) {
883 if (unit_is_visible_on_layer(punit, V_MAIN)
884 && can_player_see_unit(pplayer, punit)) {
885 unit_goes_out_of_sight(pplayer, punit);
887 } unit_list_iterate_end;
890 vision_layer_iterate(v) {
891 /* Avoid underflow. */
892 fc_assert(0 <= change[v] || -change[v] <= plrtile->seen_count[v]);
893 plrtile->seen_count[v] += change[v];
894 } vision_layer_iterate_end;
896 /* V_MAIN vision ranges must always be more than V_INVIS ranges
897 * (see comment in common/vision.h), so we assume that the V_MAIN
898 * seen count cannot be inferior to V_INVIS seen count.
899 * Moreover, when the fog of war is disabled, V_MAIN has an extra
900 * seen count point. */
901 fc_assert(plrtile->seen_count[V_INVIS] + !game.info.fogofwar
902 <= plrtile->seen_count[V_MAIN]);
904 if (!map_is_known(ptile, pplayer)) {
905 if (0 < plrtile->seen_count[V_MAIN] && can_reveal_tiles) {
906 log_debug("(%d, %d): revealing tile to player %s (nb %d).",
907 TILE_XY(ptile), player_name(pplayer),
908 player_number(pplayer));
910 map_set_known(ptile, pplayer);
911 revealing_tile = TRUE;
912 } else {
913 return;
917 /* Fog the tile. */
918 if (0 > change[V_MAIN] && 0 == plrtile->seen_count[V_MAIN]) {
919 log_debug("(%d, %d): fogging tile for player %s (nb %d).",
920 TILE_XY(ptile), player_name(pplayer), player_number(pplayer));
922 update_player_tile_last_seen(pplayer, ptile);
923 if (game.server.foggedborders) {
924 plrtile->owner = tile_owner(ptile);
926 plrtile->extras_owner = extra_owner(ptile);
927 send_tile_info(pplayer->connections, ptile, FALSE);
930 if ((revealing_tile && 0 < plrtile->seen_count[V_MAIN])
931 || (0 < change[V_MAIN]
932 /* plrtile->seen_count[V_MAIN] Always set to 1
933 * when the fog of war is disabled. */
934 && (change[V_MAIN] + !game.info.fogofwar
935 == (plrtile->seen_count[V_MAIN])))) {
936 struct city *pcity;
938 log_debug("(%d, %d): unfogging tile for player %s (nb %d).",
939 TILE_XY(ptile), player_name(pplayer), player_number(pplayer));
941 /* Send info about the tile itself.
942 * It has to be sent first because the client needs correct
943 * continent number before it can handle following packets
945 update_player_tile_knowledge(pplayer, ptile);
946 send_tile_info(pplayer->connections, ptile, FALSE);
948 /* Discover units. */
949 unit_list_iterate(ptile->units, punit) {
950 if (unit_is_visible_on_layer(punit, V_MAIN)) {
951 send_unit_info(pplayer->connections, punit);
953 } unit_list_iterate_end;
955 /* Discover cities. */
956 reality_check_city(pplayer, ptile);
958 if (NULL != (pcity = tile_city(ptile))) {
959 send_city_info(pplayer, pcity);
963 if ((revealing_tile && 0 < plrtile->seen_count[V_INVIS])
964 || (0 < change[V_INVIS]
965 && change[V_INVIS] == plrtile->seen_count[V_INVIS])) {
966 log_debug("(%d, %d): revealing invisible units to player %s (nb %d).",
967 TILE_XY(ptile), player_name(pplayer),
968 player_number(pplayer));
969 /* Discover units. */
970 unit_list_iterate(ptile->units, punit) {
971 if (unit_is_visible_on_layer(punit, V_INVIS)) {
972 send_unit_info(pplayer->connections, punit);
974 } unit_list_iterate_end;
978 /****************************************************************************
979 Returns the own seen count of a tile for a player. It doesn't count the
980 shared vision.
982 See also map_get_seen().
983 ****************************************************************************/
984 static inline int map_get_own_seen(const struct player *pplayer,
985 const struct tile *ptile,
986 enum vision_layer vlayer)
988 return map_get_player_tile(ptile, pplayer)->own_seen[vlayer];
991 /***************************************************************
992 Changes the own seen count of a tile for a player.
993 ***************************************************************/
994 static void map_change_own_seen(struct player *pplayer,
995 struct tile *ptile,
996 const v_radius_t change)
998 struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1000 vision_layer_iterate(v) {
1001 plrtile->own_seen[v] += change[v];
1002 } vision_layer_iterate_end;
1005 /***************************************************************
1006 Changes site information for player tile.
1007 ***************************************************************/
1008 void change_playertile_site(struct player_tile *ptile,
1009 struct vision_site *new_site)
1011 if (ptile->site == new_site) {
1012 /* Do nothing. */
1013 return;
1016 if (ptile->site != NULL) {
1017 /* Releasing old site from tile */
1018 vision_site_destroy(ptile->site);
1021 ptile->site = new_site;
1024 /***************************************************************
1025 Set known status of the tile.
1026 ***************************************************************/
1027 void map_set_known(struct tile *ptile, struct player *pplayer)
1029 dbv_set(&pplayer->tile_known, tile_index(ptile));
1032 /***************************************************************
1033 Clear known status of the tile.
1034 ***************************************************************/
1035 void map_clear_known(struct tile *ptile, struct player *pplayer)
1037 dbv_clr(&pplayer->tile_known, tile_index(ptile));
1040 /****************************************************************************
1041 Call this function to unfog all tiles. This should only be called when
1042 a player dies or at the end of the game as it will result in permanent
1043 vision of the whole map.
1044 ****************************************************************************/
1045 void map_know_and_see_all(struct player *pplayer)
1047 const v_radius_t radius_sq = V_RADIUS(1, 1);
1049 buffer_shared_vision(pplayer);
1050 whole_map_iterate(ptile) {
1051 map_change_seen(pplayer, ptile, radius_sq, TRUE);
1052 } whole_map_iterate_end;
1053 unbuffer_shared_vision(pplayer);
1056 /**************************************************************************
1057 Unfogs all tiles for all players. See map_know_and_see_all.
1058 **************************************************************************/
1059 void show_map_to_all(void)
1061 players_iterate(pplayer) {
1062 map_know_and_see_all(pplayer);
1063 } players_iterate_end;
1066 /***************************************************************
1067 Allocate space for map, and initialise the tiles.
1068 Uses current map.xsize and map.ysize.
1069 ****************************************************************/
1070 void player_map_init(struct player *pplayer)
1072 pplayer->server.private_map
1073 = fc_realloc(pplayer->server.private_map,
1074 MAP_INDEX_SIZE * sizeof(*pplayer->server.private_map));
1076 whole_map_iterate(ptile) {
1077 player_tile_init(ptile, pplayer);
1078 } whole_map_iterate_end;
1080 dbv_init(&pplayer->tile_known, MAP_INDEX_SIZE);
1083 /**************************************************************************
1084 Free a player's private map.
1085 **************************************************************************/
1086 void player_map_free(struct player *pplayer)
1088 if (!pplayer->server.private_map) {
1089 return;
1092 whole_map_iterate(ptile) {
1093 player_tile_free(ptile, pplayer);
1094 } whole_map_iterate_end;
1096 free(pplayer->server.private_map);
1097 pplayer->server.private_map = NULL;
1099 dbv_free(&pplayer->tile_known);
1102 /**************************************************************************
1103 Remove all knowledge of a player from main map and other players'
1104 private maps, and send updates to connected clients.
1105 Frees all vision_sites associated with that player.
1106 **************************************************************************/
1107 void remove_player_from_maps(struct player *pplayer)
1109 /* only after removing borders! */
1110 conn_list_do_buffer(game.est_connections);
1111 whole_map_iterate(ptile) {
1112 /* Clear all players' knowledge about the removed player, and free
1113 * data structures (including those in removed player's player map). */
1114 bool reality_changed = FALSE;
1116 players_iterate(aplayer) {
1117 struct player_tile *aplrtile;
1118 bool changed = FALSE;
1120 if (!aplayer->server.private_map) {
1121 continue;
1123 aplrtile = map_get_player_tile(ptile, aplayer);
1125 /* Free vision sites (cities) for removed and other players */
1126 if (aplrtile && aplrtile->site &&
1127 vision_site_owner(aplrtile->site) == pplayer) {
1128 change_playertile_site(aplrtile, NULL);
1129 changed = TRUE;
1132 /* Remove references to player from others' maps */
1133 if (aplrtile->owner == pplayer) {
1134 aplrtile->owner = NULL;
1135 changed = TRUE;
1137 if (aplrtile->extras_owner == pplayer) {
1138 aplrtile->extras_owner = NULL;
1139 changed = TRUE;
1142 /* Must ensure references to dying player are gone from clients
1143 * before player is destroyed */
1144 if (changed) {
1145 /* This will use player tile if fogged */
1146 send_tile_info(pplayer->connections, ptile, FALSE);
1148 } players_iterate_end;
1150 /* Clear removed player's knowledge */
1151 if (pplayer->tile_known.vec) {
1152 map_clear_known(ptile, pplayer);
1155 /* Free all claimed tiles. */
1156 if (tile_owner(ptile) == pplayer) {
1157 tile_set_owner(ptile, NULL, NULL);
1158 reality_changed = TRUE;
1160 if (extra_owner(ptile) == pplayer) {
1161 ptile->extras_owner = NULL;
1162 reality_changed = TRUE;
1165 if (reality_changed) {
1166 /* Update anyone who can see the tile (e.g. global observers) */
1167 send_tile_info(NULL, ptile, FALSE);
1169 } whole_map_iterate_end;
1170 conn_list_do_unbuffer(game.est_connections);
1173 /***************************************************************
1174 We need to use fogofwar_old here, so the player's tiles get
1175 in the same state as the other players' tiles.
1176 ***************************************************************/
1177 static void player_tile_init(struct tile *ptile, struct player *pplayer)
1179 struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1181 plrtile->terrain = T_UNKNOWN;
1182 plrtile->resource = NULL;
1183 plrtile->owner = NULL;
1184 plrtile->extras_owner = NULL;
1185 plrtile->site = NULL;
1186 BV_CLR_ALL(plrtile->extras);
1187 if (!game.server.last_updated_year) {
1188 plrtile->last_updated = game.info.turn;
1189 } else {
1190 plrtile->last_updated = game.info.year;
1193 plrtile->seen_count[V_MAIN] = !game.server.fogofwar_old;
1194 plrtile->seen_count[V_INVIS] = 0;
1195 memcpy(plrtile->own_seen, plrtile->seen_count, sizeof(v_radius_t));
1198 /****************************************************************************
1199 Free the memory stored into the player tile.
1200 ****************************************************************************/
1201 static void player_tile_free(struct tile *ptile, struct player *pplayer)
1203 struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1205 if (plrtile->site != NULL) {
1206 vision_site_destroy(plrtile->site);
1210 /****************************************************************************
1211 Returns city located at given tile from player map.
1212 ****************************************************************************/
1213 struct vision_site *map_get_player_city(const struct tile *ptile,
1214 const struct player *pplayer)
1216 struct vision_site *psite = map_get_player_site(ptile, pplayer);
1218 fc_assert_ret_val(psite == NULL || psite->location == ptile, NULL);
1220 return psite;
1223 /****************************************************************************
1224 Returns site located at given tile from player map.
1225 ****************************************************************************/
1226 struct vision_site *map_get_player_site(const struct tile *ptile,
1227 const struct player *pplayer)
1229 return map_get_player_tile(ptile, pplayer)->site;
1232 /****************************************************************************
1233 Players' information of tiles is tracked so that fogged area can be kept
1234 consistent even when the client disconnects. This function returns the
1235 player tile information for the given tile and player.
1236 ****************************************************************************/
1237 struct player_tile *map_get_player_tile(const struct tile *ptile,
1238 const struct player *pplayer)
1240 fc_assert_ret_val(pplayer->server.private_map, NULL);
1242 return pplayer->server.private_map + tile_index(ptile);
1245 /****************************************************************************
1246 Give pplayer the correct knowledge about tile; return TRUE iff
1247 knowledge changed.
1249 Note that unlike update_tile_knowledge, this function will not send any
1250 packets to the client. Callers may want to call send_tile_info() if this
1251 function returns TRUE.
1252 ****************************************************************************/
1253 bool update_player_tile_knowledge(struct player *pplayer, struct tile *ptile)
1255 struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
1256 bool plrtile_owner_valid = game.server.foggedborders
1257 && !map_is_known_and_seen(ptile, pplayer, V_MAIN);
1258 struct player *owner = plrtile_owner_valid
1259 ? plrtile->owner
1260 : tile_owner(ptile);
1262 if (plrtile->terrain != ptile->terrain
1263 || !BV_ARE_EQUAL(plrtile->extras, ptile->extras)
1264 || plrtile->resource != ptile->resource
1265 || owner != tile_owner(ptile)
1266 || plrtile->extras_owner != extra_owner(ptile)) {
1267 plrtile->terrain = ptile->terrain;
1268 plrtile->extras = ptile->extras;
1269 plrtile->resource = ptile->resource;
1270 if (plrtile_owner_valid) {
1271 plrtile->owner = tile_owner(ptile);
1273 plrtile->extras_owner = extra_owner(ptile);
1275 return TRUE;
1278 return FALSE;
1281 /****************************************************************************
1282 Update playermap knowledge for everybody who sees the tile, and send a
1283 packet to everyone whose info is changed.
1285 Note this only checks for changing of the terrain, special, or resource
1286 for the tile, since these are the only values held in the playermap.
1288 A tile's owner always can see terrain changes in his or her territory.
1289 ****************************************************************************/
1290 void update_tile_knowledge(struct tile *ptile)
1292 /* Players */
1293 players_iterate(pplayer) {
1294 if (map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
1295 if (update_player_tile_knowledge(pplayer, ptile)) {
1296 send_tile_info(pplayer->connections, ptile, FALSE);
1299 } players_iterate_end;
1301 /* Global observers */
1302 conn_list_iterate(game.est_connections, pconn) {
1303 struct player *pplayer = pconn->playing;
1305 if (NULL == pplayer && pconn->observer) {
1306 send_tile_info(pconn->self, ptile, FALSE);
1308 } conn_list_iterate_end;
1311 /***************************************************************
1312 Remember that tile was last seen this year.
1313 ***************************************************************/
1314 void update_player_tile_last_seen(struct player *pplayer,
1315 struct tile *ptile)
1317 if (!game.server.last_updated_year) {
1318 map_get_player_tile(ptile, pplayer)->last_updated = game.info.turn;
1319 } else {
1320 map_get_player_tile(ptile, pplayer)->last_updated = game.info.year;
1324 /***************************************************************
1325 Give tile information from one player to one player.
1326 ***************************************************************/
1327 static void really_give_tile_info_from_player_to_player(struct player *pfrom,
1328 struct player *pdest,
1329 struct tile *ptile)
1331 struct player_tile *from_tile, *dest_tile;
1332 if (!map_is_known_and_seen(ptile, pdest, V_MAIN)) {
1333 /* I can just hear people scream as they try to comprehend this if :).
1334 * Let me try in words:
1335 * 1) if the tile is seen by pfrom the info is sent to pdest
1336 * OR
1337 * 2) if the tile is known by pfrom AND (he has more recent info
1338 * OR it is not known by pdest)
1340 if (map_is_known_and_seen(ptile, pfrom, V_MAIN)
1341 || (map_is_known(ptile, pfrom)
1342 && (((map_get_player_tile(ptile, pfrom)->last_updated
1343 > map_get_player_tile(ptile, pdest)->last_updated))
1344 || !map_is_known(ptile, pdest)))) {
1345 from_tile = map_get_player_tile(ptile, pfrom);
1346 dest_tile = map_get_player_tile(ptile, pdest);
1347 /* Update and send tile knowledge */
1348 map_set_known(ptile, pdest);
1349 dest_tile->terrain = from_tile->terrain;
1350 dest_tile->extras = from_tile->extras;
1351 dest_tile->resource = from_tile->resource;
1352 dest_tile->owner = from_tile->owner;
1353 dest_tile->extras_owner = from_tile->extras_owner;
1354 dest_tile->last_updated = from_tile->last_updated;
1355 send_tile_info(pdest->connections, ptile, FALSE);
1357 /* update and send city knowledge */
1358 /* remove outdated cities */
1359 if (dest_tile->site) {
1360 if (!from_tile->site) {
1361 /* As the city was gone on the newer from_tile
1362 it will be removed by this function */
1363 reality_check_city(pdest, ptile);
1364 } else /* We have a dest_city. update */
1365 if (from_tile->site->identity
1366 != dest_tile->site->identity) {
1367 /* As the city was gone on the newer from_tile
1368 it will be removed by this function */
1369 reality_check_city(pdest, ptile);
1373 /* Set and send new city info */
1374 if (from_tile->site) {
1375 if (!dest_tile->site) {
1376 /* We cannot assign new vision site with change_playertile_site(),
1377 * since location is not yet set up for new site */
1378 dest_tile->site = vision_site_new(0, ptile, NULL);
1379 *dest_tile->site = *from_tile->site;
1381 /* Note that we don't care if receiver knows vision source city
1382 * or not. */
1383 send_city_info_at_tile(pdest, pdest->connections, NULL, ptile);
1386 city_map_update_tile_frozen(ptile);
1391 /***************************************************************
1392 Give tile information from player to player. Handles chains of
1393 shared vision so that receiver may give information forward.
1394 ***************************************************************/
1395 static void give_tile_info_from_player_to_player(struct player *pfrom,
1396 struct player *pdest,
1397 struct tile *ptile)
1399 really_give_tile_info_from_player_to_player(pfrom, pdest, ptile);
1401 players_iterate(pplayer2) {
1402 if (really_gives_vision(pdest, pplayer2)) {
1403 really_give_tile_info_from_player_to_player(pfrom, pplayer2, ptile);
1405 } players_iterate_end;
1408 /***************************************************************
1409 This updates all players' really_gives_vision field.
1410 If p1 gives p2 shared vision and p2 gives p3 shared vision p1
1411 should also give p3 shared vision.
1412 ***************************************************************/
1413 static void create_vision_dependencies(void)
1415 int added;
1417 players_iterate(pplayer) {
1418 pplayer->server.really_gives_vision = pplayer->gives_shared_vision;
1419 } players_iterate_end;
1421 /* In words: This terminates when it has run a round without adding
1422 a dependency. One loop only propagates dependencies one level deep,
1423 which is why we keep doing it as long as changes occur. */
1424 do {
1425 added = 0;
1426 players_iterate(pplayer) {
1427 players_iterate(pplayer2) {
1428 if (really_gives_vision(pplayer, pplayer2)
1429 && pplayer != pplayer2) {
1430 players_iterate(pplayer3) {
1431 if (really_gives_vision(pplayer2, pplayer3)
1432 && !really_gives_vision(pplayer, pplayer3)
1433 && pplayer != pplayer3) {
1434 BV_SET(pplayer->server.really_gives_vision, player_index(pplayer3));
1435 added++;
1437 } players_iterate_end;
1439 } players_iterate_end;
1440 } players_iterate_end;
1441 } while (added > 0);
1444 /***************************************************************
1445 Starts shared vision between two players.
1446 ***************************************************************/
1447 void give_shared_vision(struct player *pfrom, struct player *pto)
1449 bv_player save_vision[player_slot_count()];
1450 if (pfrom == pto) return;
1451 if (gives_shared_vision(pfrom, pto)) {
1452 log_error("Trying to give shared vision from %s to %s, "
1453 "but that vision is already given!",
1454 player_name(pfrom), player_name(pto));
1455 return;
1458 players_iterate(pplayer) {
1459 save_vision[player_index(pplayer)] = pplayer->server.really_gives_vision;
1460 } players_iterate_end;
1462 BV_SET(pfrom->gives_shared_vision, player_index(pto));
1463 create_vision_dependencies();
1464 log_debug("giving shared vision from %s to %s",
1465 player_name(pfrom), player_name(pto));
1467 players_iterate(pplayer) {
1468 buffer_shared_vision(pplayer);
1469 players_iterate(pplayer2) {
1470 if (really_gives_vision(pplayer, pplayer2)
1471 && !BV_ISSET(save_vision[player_index(pplayer)],
1472 player_index(pplayer2))) {
1473 log_debug("really giving shared vision from %s to %s",
1474 player_name(pplayer), player_name(pplayer2));
1475 whole_map_iterate(ptile) {
1476 const v_radius_t change =
1477 V_RADIUS(map_get_own_seen(pplayer, ptile, V_MAIN),
1478 map_get_own_seen(pplayer, ptile, V_INVIS));
1480 if (0 < change[V_MAIN] || 0 < change[V_INVIS]) {
1481 map_change_seen(pplayer2, ptile, change,
1482 map_is_known(ptile, pplayer));
1484 } whole_map_iterate_end;
1486 /* squares that are not seen, but which pfrom may have more recent
1487 knowledge of */
1488 give_map_from_player_to_player(pplayer, pplayer2);
1490 } players_iterate_end;
1491 unbuffer_shared_vision(pplayer);
1492 } players_iterate_end;
1494 if (S_S_RUNNING == server_state()) {
1495 send_player_info_c(pfrom, NULL);
1499 /***************************************************************
1500 Removes shared vision from between two players.
1501 ***************************************************************/
1502 void remove_shared_vision(struct player *pfrom, struct player *pto)
1504 bv_player save_vision[player_slot_count()];
1506 fc_assert_ret(pfrom != pto);
1507 if (!gives_shared_vision(pfrom, pto)) {
1508 log_error("Tried removing the shared vision from %s to %s, "
1509 "but it did not exist in the first place!",
1510 player_name(pfrom), player_name(pto));
1511 return;
1514 players_iterate(pplayer) {
1515 save_vision[player_index(pplayer)] = pplayer->server.really_gives_vision;
1516 } players_iterate_end;
1518 log_debug("removing shared vision from %s to %s",
1519 player_name(pfrom), player_name(pto));
1521 BV_CLR(pfrom->gives_shared_vision, player_index(pto));
1522 create_vision_dependencies();
1524 players_iterate(pplayer) {
1525 buffer_shared_vision(pplayer);
1526 players_iterate(pplayer2) {
1527 if (!really_gives_vision(pplayer, pplayer2)
1528 && BV_ISSET(save_vision[player_index(pplayer)],
1529 player_index(pplayer2))) {
1530 log_debug("really removing shared vision from %s to %s",
1531 player_name(pplayer), player_name(pplayer2));
1532 whole_map_iterate(ptile) {
1533 const v_radius_t change =
1534 V_RADIUS(-map_get_own_seen(pplayer, ptile, V_MAIN),
1535 -map_get_own_seen(pplayer, ptile, V_INVIS));
1537 if (0 > change[V_MAIN] || 0 > change[V_INVIS]) {
1538 map_change_seen(pplayer2, ptile, change, FALSE);
1540 } whole_map_iterate_end;
1542 } players_iterate_end;
1543 unbuffer_shared_vision(pplayer);
1544 } players_iterate_end;
1546 if (S_S_RUNNING == server_state()) {
1547 send_player_info_c(pfrom, NULL);
1551 /*************************************************************************
1552 Turns FoW on for player
1553 *************************************************************************/
1554 void enable_fog_of_war_player(struct player *pplayer)
1556 const v_radius_t radius_sq = V_RADIUS(-1, 0);
1558 buffer_shared_vision(pplayer);
1559 whole_map_iterate(ptile) {
1560 map_change_seen(pplayer, ptile, radius_sq, FALSE);
1561 } whole_map_iterate_end;
1562 unbuffer_shared_vision(pplayer);
1565 /*************************************************************************
1566 Turns FoW on for everyone.
1567 *************************************************************************/
1568 void enable_fog_of_war(void)
1570 players_iterate(pplayer) {
1571 enable_fog_of_war_player(pplayer);
1572 } players_iterate_end;
1575 /*************************************************************************
1576 Turns FoW off for player
1577 *************************************************************************/
1578 void disable_fog_of_war_player(struct player *pplayer)
1580 const v_radius_t radius_sq = V_RADIUS(1, 0);
1582 buffer_shared_vision(pplayer);
1583 whole_map_iterate(ptile) {
1584 map_change_seen(pplayer, ptile, radius_sq, FALSE);
1585 } whole_map_iterate_end;
1586 unbuffer_shared_vision(pplayer);
1589 /*************************************************************************
1590 Turns FoW off for everyone
1591 *************************************************************************/
1592 void disable_fog_of_war(void)
1594 players_iterate(pplayer) {
1595 disable_fog_of_war_player(pplayer);
1596 } players_iterate_end;
1599 /**************************************************************************
1600 Set the tile to be a river if required.
1601 It's required if one of the tiles nearby would otherwise be part of a
1602 river to nowhere.
1603 (Note that rivers-to-nowhere can still occur if a single-tile lake is
1604 transformed away, but this is relatively unlikely.)
1605 For simplicity, I'm assuming that this is the only exit of the river,
1606 so I don't need to trace it across the continent. --CJM
1607 **************************************************************************/
1608 static void ocean_to_land_fix_rivers(struct tile *ptile)
1610 cardinal_adjc_iterate(ptile, tile1) {
1611 bool ocean_near = FALSE;
1613 cardinal_adjc_iterate(tile1, tile2) {
1614 if (is_ocean_tile(tile2))
1615 ocean_near = TRUE;
1616 } cardinal_adjc_iterate_end;
1618 if (!ocean_near) {
1619 /* If ruleset has several river types defined, this
1620 * may cause same tile to contain more than one river. */
1621 extra_type_by_cause_iterate(EC_ROAD, priver) {
1622 if (tile_has_extra(tile1, priver)
1623 && road_has_flag(extra_road_get(priver), RF_RIVER)) {
1624 tile_add_extra(ptile, priver);
1626 } extra_type_by_cause_iterate_end;
1628 } cardinal_adjc_iterate_end;
1631 /****************************************************************************
1632 Helper function for bounce_units_on_terrain_change() that checks units
1633 on a single tile.
1634 ****************************************************************************/
1635 static void check_units_single_tile(struct tile *ptile)
1637 unit_list_iterate_safe(ptile->units, punit) {
1638 bool unit_alive = TRUE;
1640 if (unit_tile(punit) == ptile
1641 && !unit_transported(punit)
1642 && !can_unit_exist_at_tile(punit, ptile)) {
1643 /* look for a nearby safe tile */
1644 adjc_iterate(ptile, ptile2) {
1645 if (can_unit_exist_at_tile(punit, ptile2)
1646 && !is_non_allied_unit_tile(ptile2, unit_owner(punit))
1647 && !is_non_allied_city_tile(ptile2, unit_owner(punit))) {
1648 log_verbose("Moved %s %s due to changing terrain at (%d,%d).",
1649 nation_rule_name(nation_of_unit(punit)),
1650 unit_rule_name(punit), TILE_XY(unit_tile(punit)));
1651 notify_player(unit_owner(punit), unit_tile(punit),
1652 E_UNIT_RELOCATED, ftc_server,
1653 _("Moved your %s due to changing terrain."),
1654 unit_link(punit));
1655 unit_alive = unit_move(punit, ptile2, 0, NULL);
1656 if (unit_alive && punit->activity == ACTIVITY_SENTRY) {
1657 unit_activity_handling(punit, ACTIVITY_IDLE);
1659 break;
1661 } adjc_iterate_end;
1662 if (unit_alive && unit_tile(punit) == ptile) {
1663 /* If we get here we could not move punit. */
1664 log_verbose("Disbanded %s %s due to changing land "
1665 " to sea at (%d, %d).",
1666 nation_rule_name(nation_of_unit(punit)),
1667 unit_rule_name(punit), TILE_XY(unit_tile(punit)));
1668 notify_player(unit_owner(punit), unit_tile(punit),
1669 E_UNIT_LOST_MISC, ftc_server,
1670 _("Disbanded your %s due to changing terrain."),
1671 unit_tile_link(punit));
1672 wipe_unit(punit, ULR_NONNATIVE_TERR, NULL);
1675 } unit_list_iterate_safe_end;
1678 /****************************************************************************
1679 Check ptile and nearby tiles to see if all units can remain at their
1680 current locations, and move or disband any that cannot. Call this after
1681 terrain or specials change on ptile.
1682 ****************************************************************************/
1683 void bounce_units_on_terrain_change(struct tile *ptile)
1685 /* Check this tile for direct effect on its units */
1686 check_units_single_tile(ptile);
1687 /* We have to check adjacent tiles too, in case units in cities are now
1688 * illegal (e.g., boat in a city that has become landlocked). */
1689 adjc_iterate(ptile, ptile2) {
1690 check_units_single_tile(ptile2);
1691 } adjc_iterate_end;
1694 /****************************************************************************
1695 Returns TRUE if the terrain change from 'oldter' to 'newter' may require
1696 expensive reassignment of continents.
1697 ****************************************************************************/
1698 bool need_to_reassign_continents(const struct terrain *oldter,
1699 const struct terrain *newter)
1701 bool old_is_ocean, new_is_ocean;
1703 if (!oldter || !newter) {
1704 return FALSE;
1707 old_is_ocean = is_ocean(oldter);
1708 new_is_ocean = is_ocean(newter);
1710 return (old_is_ocean && !new_is_ocean)
1711 || (!old_is_ocean && new_is_ocean);
1714 /****************************************************************************
1715 Handle local side effects for a terrain change.
1716 ****************************************************************************/
1717 void terrain_changed(struct tile *ptile)
1719 struct city *pcity = tile_city(ptile);
1721 if (pcity != NULL) {
1722 /* Tile is city center and new terrain may support better extras. */
1723 upgrade_city_extras(pcity, NULL);
1726 bounce_units_on_terrain_change(ptile);
1729 /****************************************************************************
1730 Handles local side effects for a terrain change (tile and its
1731 surroundings). Does *not* handle global side effects (such as reassigning
1732 continents).
1733 For in-game terrain changes 'extend_rivers' should be TRUE; for edits it
1734 should be FALSE.
1735 ****************************************************************************/
1736 void fix_tile_on_terrain_change(struct tile *ptile,
1737 struct terrain *oldter,
1738 bool extend_rivers)
1740 if (is_ocean(oldter) && !is_ocean_tile(ptile)) {
1741 if (extend_rivers) {
1742 ocean_to_land_fix_rivers(ptile);
1744 city_landlocked_sell_coastal_improvements(ptile);
1747 terrain_changed(ptile);
1750 /****************************************************************************
1751 Handles local and global side effects for a terrain change for a single
1752 tile.
1753 Call this in the server immediately after calling tile_change_terrain.
1754 Assumes an in-game terrain change (e.g., by workers/engineers).
1755 ****************************************************************************/
1756 void check_terrain_change(struct tile *ptile, struct terrain *oldter)
1758 struct terrain *newter = tile_terrain(ptile);
1759 struct tile *claimer;
1761 /* Check if new terrain is a freshwater terrain next to non-freshwater.
1762 * In that case, the new terrain is *changed*. */
1763 if (is_ocean(newter) && terrain_has_flag(newter, TER_FRESHWATER)) {
1764 bool nonfresh = FALSE;
1765 adjc_iterate(ptile, atile) {
1766 if (is_ocean(tile_terrain(atile))
1767 && !terrain_has_flag(tile_terrain(atile), TER_FRESHWATER)) {
1768 nonfresh = TRUE;
1769 break;
1771 } adjc_iterate_end;
1772 if (nonfresh) {
1773 /* Need to pick a new, non-freshwater ocean type for this tile.
1774 * We don't want e.g. Deep Ocean to be propagated to this tile
1775 * and then to a whole lake by the flooding below, so we pick
1776 * the shallowest non-fresh oceanic type.
1777 * Prefer terrain that matches the frozenness of the target. */
1778 newter = most_shallow_ocean(terrain_has_flag(newter, TER_FROZEN));
1779 tile_change_terrain(ptile, newter);
1783 fix_tile_on_terrain_change(ptile, oldter, TRUE);
1785 /* Check for saltwater filling freshwater lake */
1786 if (game.scenario.lake_flooding
1787 && is_ocean(newter) && !terrain_has_flag(newter, TER_FRESHWATER)) {
1788 adjc_iterate(ptile, atile) {
1789 if (terrain_has_flag(tile_terrain(atile), TER_FRESHWATER)) {
1790 struct terrain *aold = tile_terrain(atile);
1792 tile_change_terrain(atile,
1793 most_shallow_ocean(terrain_has_flag(aold,
1794 TER_FROZEN)));
1796 /* Recursive, but as lakes are of limited size, this
1797 * won't recurse so much as to cause stack problems. */
1798 check_terrain_change(atile, aold);
1799 update_tile_knowledge(atile);
1801 } adjc_iterate_end;
1804 if (need_to_reassign_continents(oldter, newter)) {
1805 assign_continent_numbers();
1806 send_all_known_tiles(NULL);
1809 claimer = tile_claimer(ptile);
1810 if (claimer != NULL && is_ocean_tile(ptile)) {
1811 if (!is_claimable_ocean(ptile, claimer, tile_owner(ptile))) {
1812 map_clear_border(ptile);
1816 sanity_check_tile(ptile);
1819 /*************************************************************************
1820 Ocean tile can be claimed iff one of the following conditions stands:
1821 a) it is an inland lake not larger than MAXIMUM_OCEAN_SIZE
1822 b) it is adjacent to only one continent and not more than two ocean tiles
1823 c) It is one tile away from a border source
1824 d) Player knows tech with Claim_Ocean flag
1825 e) Source itself is Oceanic tile and player knows tech with Claim_Ocean_Limited flag
1826 The source which claims the ocean has to be placed on the correct continent.
1827 in case a) The continent which surrounds the inland lake
1828 in case b) The only continent which is adjacent to the tile
1829 *************************************************************************/
1830 static bool is_claimable_ocean(struct tile *ptile, struct tile *source,
1831 struct player *pplayer)
1833 Continent_id cont = tile_continent(ptile);
1834 Continent_id cont1 = tile_continent(source);
1835 Continent_id cont2;
1836 int ocean_tiles;
1837 bool other_continent;
1839 if (get_ocean_size(-cont) <= MAXIMUM_CLAIMED_OCEAN_SIZE
1840 && get_lake_surrounders(cont) == cont1) {
1841 return TRUE;
1844 if (ptile == source) {
1845 /* Source itself is always claimable. */
1846 return TRUE;
1849 if (num_known_tech_with_flag(pplayer, TF_CLAIM_OCEAN) > 0
1850 || (cont1 < 0 && num_known_tech_with_flag(pplayer, TF_CLAIM_OCEAN_LIMITED) > 0)) {
1851 return TRUE;
1854 ocean_tiles = 0;
1855 other_continent = FALSE;
1856 adjc_iterate(ptile, tile2) {
1857 cont2 = tile_continent(tile2);
1858 if (tile2 == source) {
1859 /* Water next to border source is always claimable */
1860 return TRUE;
1862 if (cont2 == cont) {
1863 ocean_tiles++;
1864 } else if (cont1 <= 0) {
1865 /* First adjacent land (only if border source is not on land) */
1866 cont1 = cont2;
1867 } else if (cont2 != cont1) {
1868 /* This water has two land continents adjacent, or land adjacent
1869 * that is of a different continent from the border source */
1870 other_continent = TRUE;
1872 } adjc_iterate_end;
1873 if (!other_continent && ocean_tiles <= 2) {
1874 return TRUE;
1875 } else {
1876 return FALSE;
1880 /*************************************************************************
1881 For each unit at the tile, queue any unique home city.
1882 *************************************************************************/
1883 static void map_unit_homecity_enqueue(struct tile *ptile)
1885 unit_list_iterate(ptile->units, punit) {
1886 struct city *phome = game_city_by_number(punit->homecity);
1888 if (NULL == phome) {
1889 continue;
1892 city_refresh_queue_add(phome);
1893 } unit_list_iterate_end;
1896 /*************************************************************************
1897 Claim ownership of a single tile.
1898 *************************************************************************/
1899 static void map_claim_border_ownership(struct tile *ptile,
1900 struct player *powner,
1901 struct tile *psource)
1903 struct player *ploser = tile_owner(ptile);
1905 if (BORDERS_SEE_INSIDE == game.info.borders
1906 || BORDERS_EXPAND == game.info.borders) {
1907 if (ploser != powner) {
1908 if (ploser) {
1909 const v_radius_t radius_sq = V_RADIUS(-1, 0);
1911 shared_vision_change_seen(ploser, ptile, radius_sq, FALSE);
1913 if (powner) {
1914 const v_radius_t radius_sq = V_RADIUS(1, 0);
1916 shared_vision_change_seen(powner, ptile, radius_sq, TRUE);
1921 tile_set_owner(ptile, powner, psource);
1923 /* Needed only when foggedborders enabled, but we do it unconditionally
1924 * in case foggedborders ever gets enabled later. Better to have correct
1925 * information in player map just in case. */
1926 update_tile_knowledge(ptile);
1928 if (ploser != powner) {
1929 if (S_S_RUNNING == server_state() && game.info.happyborders != HB_DISABLED) {
1930 map_unit_homecity_enqueue(ptile);
1933 if (!city_map_update_tile_frozen(ptile)) {
1934 send_tile_info(NULL, ptile, FALSE);
1939 /*************************************************************************
1940 Claim ownership of a single tile.
1941 *************************************************************************/
1942 void map_claim_ownership(struct tile *ptile, struct player *powner,
1943 struct tile *psource, bool claim_bases)
1945 map_claim_border_ownership(ptile, powner, psource);
1947 if (claim_bases) {
1948 tile_claim_bases(ptile, powner);
1952 /*************************************************************************
1953 Claim ownership of bases on single tile.
1954 *************************************************************************/
1955 void tile_claim_bases(struct tile *ptile, struct player *powner)
1957 struct player *base_loser = extra_owner(ptile);
1959 /* This MUST be before potentially recursive call to map_claim_base(),
1960 * so that the recursive call will get new owner == base_loser and
1961 * abort recursion. */
1962 ptile->extras_owner = powner;
1964 extra_type_by_cause_iterate(EC_BASE, pextra) {
1965 map_claim_base(ptile, pextra, powner, base_loser);
1966 } extra_type_by_cause_iterate_end;
1969 /*************************************************************************
1970 Remove border for this source.
1971 *************************************************************************/
1972 void map_clear_border(struct tile *ptile)
1974 int radius_sq = tile_border_source_radius_sq(ptile);
1976 circle_dxyr_iterate(ptile, radius_sq, dtile, dx, dy, dr) {
1977 struct tile *claimer = tile_claimer(dtile);
1979 if (claimer == ptile) {
1980 map_claim_ownership(dtile, NULL, NULL, FALSE);
1982 } circle_dxyr_iterate_end;
1985 /*************************************************************************
1986 Update borders for this source. Changes the radius without temporary
1987 clearing.
1988 *************************************************************************/
1989 void map_update_border(struct tile *ptile, struct player *owner,
1990 int old_radius_sq, int new_radius_sq)
1992 if (old_radius_sq == new_radius_sq) {
1993 /* No change */
1994 return;
1997 if (BORDERS_DISABLED == game.info.borders) {
1998 return;
2001 if (old_radius_sq < new_radius_sq) {
2002 map_claim_border(ptile, owner, new_radius_sq);
2003 } else {
2004 circle_dxyr_iterate(ptile, old_radius_sq, dtile, dx, dy, dr) {
2005 if (dr > new_radius_sq) {
2006 struct tile *claimer = tile_claimer(dtile);
2008 if (claimer == ptile) {
2009 map_claim_ownership(dtile, NULL, NULL, FALSE);
2012 } circle_dxyr_iterate_end;
2016 /*************************************************************************
2017 Update borders for this source. Call this for each new source.
2019 If radius_sq is -1, get value from the border source on tile.
2020 *************************************************************************/
2021 void map_claim_border(struct tile *ptile, struct player *owner,
2022 int radius_sq)
2024 if (BORDERS_DISABLED == game.info.borders) {
2025 return;
2028 if (owner == NULL) {
2029 /* Clear the border instead of claiming. Code below this block
2030 * cannot handle NULL owner. */
2031 map_clear_border(ptile);
2033 return;
2036 if (radius_sq < 0) {
2037 radius_sq = tile_border_source_radius_sq(ptile);
2040 circle_dxyr_iterate(ptile, radius_sq, dtile, dx, dy, dr) {
2041 struct tile *dclaimer = tile_claimer(dtile);
2043 if (dclaimer == ptile) {
2044 /* Already claimed by the ptile */
2045 continue;
2048 if (dr != 0 && is_border_source(dtile)) {
2049 /* Do not claim border sources other than self */
2050 /* Note that this is extremely important at the moment for
2051 * base claiming to work correctly in case there's two
2052 * fortresses near each other. There could be infinite
2053 * recursion in them claiming each other. */
2054 continue;
2057 if (!map_is_known(dtile, owner) && game.info.borders < BORDERS_EXPAND) {
2058 continue;
2061 /* Always claim source itself (distance, dr, to it 0) */
2062 if (dr != 0 && NULL != dclaimer && dclaimer != ptile) {
2063 struct city *ccity = tile_city(dclaimer);
2064 int strength_old, strength_new;
2066 if (ccity != NULL) {
2067 /* Previously claimed by city */
2068 int city_x, city_y;
2070 map_distance_vector(&city_x, &city_y, ccity->tile, dtile);
2072 if (map_vector_to_sq_distance(city_x, city_y)
2073 <= city_map_radius_sq_get(ccity)
2074 + game.info.border_city_permanent_radius_sq) {
2075 /* Tile is within region permanently claimed by city */
2076 continue;
2080 strength_old = tile_border_strength(dtile, dclaimer);
2081 strength_new = tile_border_strength(dtile, ptile);
2083 if (strength_new <= strength_old) {
2084 /* Stronger shall prevail,
2085 * in case of equal strength older shall prevail */
2086 continue;
2090 if (is_ocean_tile(dtile)) {
2091 /* Only certain water tiles are claimable */
2092 if (is_claimable_ocean(dtile, ptile, owner)) {
2093 map_claim_ownership(dtile, owner, ptile, dr == 0);
2095 } else {
2096 /* Only land tiles on the same island as the border source
2097 * are claimable */
2098 if (tile_continent(dtile) == tile_continent(ptile)) {
2099 map_claim_ownership(dtile, owner, ptile, dr == 0);
2102 } circle_dxyr_iterate_end;
2105 /*************************************************************************
2106 Update borders for all sources. Call this on turn end.
2107 *************************************************************************/
2108 void map_calculate_borders(void)
2110 if (BORDERS_DISABLED == game.info.borders) {
2111 return;
2114 if (game.map.tiles == NULL) {
2115 /* Map not yet initialized */
2116 return;
2119 log_verbose("map_calculate_borders()");
2121 whole_map_iterate(ptile) {
2122 if (is_border_source(ptile)) {
2123 map_claim_border(ptile, ptile->owner, -1);
2125 } whole_map_iterate_end;
2127 log_verbose("map_calculate_borders() workers");
2128 city_thaw_workers_queue();
2129 city_refresh_queue_processing();
2132 /****************************************************************************
2133 Claim base to player's ownership.
2134 ****************************************************************************/
2135 void map_claim_base(struct tile *ptile, struct extra_type *pextra,
2136 struct player *powner, struct player *ploser)
2138 struct base_type *pbase;
2140 if (!tile_has_extra(ptile, pextra)) {
2141 return;
2144 pbase = extra_base_get(pextra);
2146 fc_assert_ret(pbase != NULL);
2148 /* Transfer base provided vision to new owner */
2149 if (powner != NULL) {
2150 const v_radius_t old_radius_sq = V_RADIUS(-1, -1);
2151 const v_radius_t new_radius_sq = V_RADIUS(pbase->vision_main_sq,
2152 pbase->vision_invis_sq);
2154 map_vision_update(powner, ptile, old_radius_sq, new_radius_sq,
2155 game.server.vision_reveal_tiles);
2158 if (ploser != NULL) {
2159 const v_radius_t old_radius_sq = V_RADIUS(pbase->vision_main_sq,
2160 pbase->vision_invis_sq);
2161 const v_radius_t new_radius_sq = V_RADIUS(-1, -1);
2163 map_vision_update(ploser, ptile, old_radius_sq, new_radius_sq,
2164 game.server.vision_reveal_tiles);
2167 if (BORDERS_DISABLED != game.info.borders
2168 && territory_claiming_base(pbase) && powner != ploser) {
2169 /* Clear borders from old owner. New owner may not know all those
2170 * tiles and thus does not claim them when borders mode is less
2171 * than EXPAND. */
2172 if (ploser != NULL) {
2173 /* Set this particular tile owner by NULL so in recursion
2174 * both loser and owner will be NULL. */
2175 map_claim_border_ownership(ptile, NULL, ptile);
2176 map_clear_border(ptile);
2179 /* We here first claim this tile ownership -> now on extra_owner()
2180 * will return new owner. Then we claim border, which will recursively
2181 * lead to this tile and base being claimed. But at that point
2182 * ploser == powner and above check will abort the recursion. */
2183 if (powner != NULL) {
2184 map_claim_border_ownership(ptile, powner, ptile);
2185 map_claim_border(ptile, powner, -1);
2187 city_thaw_workers_queue();
2188 city_refresh_queue_processing();
2192 /****************************************************************************
2193 Change the sight points for the vision source, fogging or unfogging tiles
2194 as needed.
2196 See documentation in vision.h.
2197 ****************************************************************************/
2198 void vision_change_sight(struct vision *vision, const v_radius_t radius_sq)
2200 map_vision_update(vision->player, vision->tile, vision->radius_sq,
2201 radius_sq, vision->can_reveal_tiles);
2202 memcpy(vision->radius_sq, radius_sq, sizeof(v_radius_t));
2205 /****************************************************************************
2206 Clear all sight points from this vision source.
2208 See documentation in vision.h.
2209 ****************************************************************************/
2210 void vision_clear_sight(struct vision *vision)
2212 const v_radius_t vision_radius_sq = V_RADIUS(-1, -1);
2214 vision_change_sight(vision, vision_radius_sq);
2217 /****************************************************************************
2218 Create extra to tile.
2219 ****************************************************************************/
2220 void create_extra(struct tile *ptile, struct extra_type *pextra,
2221 struct player *pplayer)
2223 bool extras_removed = FALSE;
2225 extra_type_iterate(old_extra) {
2226 if (tile_has_extra(ptile, old_extra)
2227 && !can_extras_coexist(old_extra, pextra)) {
2228 destroy_extra(ptile, old_extra);
2229 extras_removed = TRUE;
2231 } extra_type_iterate_end;
2233 tile_add_extra(ptile, pextra);
2235 /* Watchtower might become effective. */
2236 unit_list_refresh_vision(ptile->units);
2238 if (pextra->data.base != NULL) {
2239 /* Claim bases on tile */
2240 if (pplayer) {
2241 struct player *old_owner = extra_owner(ptile);
2243 /* Created base from NULL -> pplayer */
2244 map_claim_base(ptile, pextra, pplayer, NULL);
2246 if (old_owner != pplayer) {
2247 /* Existing bases from old_owner -> pplayer */
2248 extra_type_by_cause_iterate(EC_BASE, oldbase) {
2249 if (oldbase != pextra) {
2250 map_claim_base(ptile, oldbase, pplayer, old_owner);
2252 } extra_type_by_cause_iterate_end;
2254 ptile->extras_owner = pplayer;
2256 } else {
2257 /* Player who already owns bases on tile claims new base */
2258 map_claim_base(ptile, pextra, extra_owner(ptile), NULL);
2262 if (extras_removed) {
2263 /* Maybe conflicting extra that was removed was the only thing
2264 * making tile native to some unit. */
2265 bounce_units_on_terrain_change(ptile);
2269 /****************************************************************************
2270 Remove extra from tile.
2271 ****************************************************************************/
2272 void destroy_extra(struct tile *ptile, struct extra_type *pextra)
2274 bv_player base_seen;
2275 bool virtual = tile_virtual_check(ptile);
2277 /* Remember what players were able to see the base. */
2278 if (!virtual) {
2279 BV_CLR_ALL(base_seen);
2280 players_iterate(pplayer) {
2281 if (map_is_known_and_seen(ptile, pplayer, V_MAIN)) {
2282 BV_SET(base_seen, player_index(pplayer));
2284 } players_iterate_end;
2287 if (is_extra_caused_by(pextra, EC_BASE)) {
2288 struct base_type *pbase = extra_base_get(pextra);
2289 struct player *owner = extra_owner(ptile);
2291 if (territory_claiming_base(pbase)) {
2292 map_clear_border(ptile);
2295 if (NULL != owner
2296 && (0 <= pbase->vision_main_sq || 0 <= pbase->vision_invis_sq)) {
2297 /* Base provides vision, but no borders. */
2298 const v_radius_t old_radius_sq =
2299 V_RADIUS(0 <= pbase->vision_main_sq ? pbase->vision_main_sq : -1,
2300 0 <= pbase->vision_invis_sq ? pbase->vision_invis_sq : -1);
2301 const v_radius_t new_radius_sq = V_RADIUS(-1, -1);
2303 map_vision_update(owner, ptile, old_radius_sq, new_radius_sq,
2304 game.server.vision_reveal_tiles);
2308 tile_remove_extra(ptile, pextra);
2310 if (!virtual) {
2311 /* Remove base from vision of players which were able to see the base. */
2312 players_iterate(pplayer) {
2313 if (BV_ISSET(base_seen, player_index(pplayer))
2314 && update_player_tile_knowledge(pplayer, ptile)) {
2315 send_tile_info(pplayer->connections, ptile, FALSE);
2317 } players_iterate_end;
2321 /****************************************************************************
2322 Give player pto the map of pfrom, but do some random damage; good to bad
2323 is the ratio of tiles revealed to tiles not revealed, e.g., calling
2324 give_distorted_map(pfrom, pto, 1, 1) reveals half the map on average.
2325 If reveal_cities is TRUE tiles with cities are always revealed.
2326 ****************************************************************************/
2327 void give_distorted_map(struct player *pfrom, struct player *pto,
2328 int good, int bad, bool reveal_cities)
2330 int all = good + bad;
2332 buffer_shared_vision(pto);
2334 whole_map_iterate(ptile) {
2335 if (fc_rand(all) >= bad) {
2336 give_tile_info_from_player_to_player(pfrom, pto, ptile);
2337 } else if (reveal_cities && NULL != tile_city(ptile)) {
2338 give_tile_info_from_player_to_player(pfrom, pto, ptile);
2340 } whole_map_iterate_end;
2342 unbuffer_shared_vision(pto);