[Freeciv-Dev] (PR#11126) unify map_get_known
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
<URL: http://rt.freeciv.org/Ticket/Display.html?id=11126 >
This patch unifies map_get_known and the ptile->known data in server and
client.
ptile->known is changed into two fields:
player_bv tile_known, tile_seen;
where
BV_DEFINE(player_bv, MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS)
Thus map_get_known looks into both known and seen fields.
On the server end, tile_seen is kept in sync with plrtile->seen_count.
Whenever seen_count != 0 the tile is seen. This is all done in maphand.c.
To avoid mistakes and force upgrading of old code, plrtile->seen is
renamed as seen_count, and known is renamed as tile_known/tile_seen.
There is one ugly place: savegame code. To make this work with BV
values requires some trickery. Eventually we will need a good way to
serialize BV values.
jason
? vgcore.pid14719
? vgcore.pid22960
Index: client/climap.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/climap.c,v
retrieving revision 1.5
diff -u -r1.5 climap.c
--- client/climap.c 29 Sep 2004 02:24:19 -0000 1.5
+++ client/climap.c 21 Nov 2004 08:42:14 -0000
@@ -34,7 +34,7 @@
*************************************************************************/
enum known_type tile_get_known(const struct tile *ptile)
{
- return (enum known_type) ptile->known;
+ return map_get_known(ptile, game.player_ptr);
}
/**************************************************************************
Index: client/climisc.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/climisc.c,v
retrieving revision 1.143
diff -u -r1.143 climisc.c
--- client/climisc.c 20 Oct 2004 04:34:27 -0000 1.143
+++ client/climisc.c 21 Nov 2004 08:42:14 -0000
@@ -955,16 +955,6 @@
output_window_force_thaw();
}
-/*************************************************************************
-...
-*************************************************************************/
-enum known_type map_get_known(const struct tile *ptile,
- struct player *pplayer)
-{
- assert(pplayer == game.player_ptr);
- return tile_get_known(ptile);
-}
-
/**************************************************************************
Find city nearest to given unit and optionally return squared city
distance Parameter sq_dist may be NULL. Returns NULL only if no city is
Index: client/mapview_common.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/mapview_common.c,v
retrieving revision 1.160
diff -u -r1.160 mapview_common.c
--- client/mapview_common.c 15 Nov 2004 17:20:55 -0000 1.160
+++ client/mapview_common.c 21 Nov 2004 08:42:15 -0000
@@ -1462,7 +1462,7 @@
int count = fill_sprite_array(tile_sprs, ptile,
get_drawable_unit(ptile, citymode),
ptile->city, citymode);
- bool fog = ptile->known == TILE_KNOWN_FOGGED && draw_fog_of_war;
+ bool fog = tile_get_known(ptile) == TILE_KNOWN_FOGGED && draw_fog_of_war;
/*** Draw terrain and specials ***/
put_drawn_sprites(pcanvas, canvas_x, canvas_y, count, tile_sprs, fog);
Index: client/packhand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/client/packhand.c,v
retrieving revision 1.421
diff -u -r1.421 packhand.c
--- client/packhand.c 20 Nov 2004 17:27:43 -0000 1.421
+++ client/packhand.c 21 Nov 2004 08:42:16 -0000
@@ -1933,7 +1933,7 @@
void handle_tile_info(struct packet_tile_info *packet)
{
struct tile *ptile = map_pos_to_tile(packet->x, packet->y);
- enum known_type old_known = ptile->known;
+ enum known_type old_known = tile_get_known(ptile);
bool tile_changed = FALSE;
bool known_changed = FALSE;
@@ -1958,10 +1958,25 @@
tile_changed = TRUE;
}
}
- if (ptile->known != packet->known) {
+ if (old_known != packet->known) {
known_changed = TRUE;
}
- ptile->known = packet->known;
+ BV_CLR(ptile->tile_known, game.player_idx);
+ BV_CLR(ptile->tile_seen, game.player_idx);
+ switch (packet->known) {
+ case TILE_KNOWN:
+ BV_SET(ptile->tile_known, game.player_idx);
+ BV_SET(ptile->tile_seen, game.player_idx);
+ break;
+ case TILE_KNOWN_FOGGED:
+ BV_SET(ptile->tile_known, game.player_idx);
+ break;
+ case TILE_UNKNOWN:
+ break;
+ default:
+ freelog(LOG_NORMAL, "Unknown tile value %d.", packet->known);
+ break;
+ }
if (packet->spec_sprite[0] != '\0') {
if (!ptile->spec_sprite
@@ -1982,7 +1997,8 @@
reset_move_costs(ptile);
- if (ptile->known <= TILE_KNOWN_FOGGED && old_known == TILE_KNOWN) {
+ if (tile_get_known(ptile) <= TILE_KNOWN_FOGGED
+ && old_known == TILE_KNOWN) {
/* This is an error. So first we log the error, then make an assertion.
* But for NDEBUG clients we fix the error. */
unit_list_iterate(ptile->units, punit) {
@@ -2015,9 +2031,9 @@
* A tile can only change if it was known before and is still
* known. In the other cases the tile is new or removed.
*/
- if (known_changed && ptile->known == TILE_KNOWN) {
+ if (known_changed && tile_get_known(ptile) == TILE_KNOWN) {
agents_tile_new(ptile);
- } else if (known_changed && ptile->known == TILE_KNOWN_FOGGED) {
+ } else if (known_changed && tile_get_known(ptile) == TILE_KNOWN_FOGGED) {
agents_tile_remove(ptile);
} else {
agents_tile_changed(ptile);
@@ -2027,7 +2043,7 @@
/* refresh tiles */
if (can_client_change_view()) {
/* the tile itself */
- if (tile_changed || old_known!=ptile->known)
+ if (tile_changed || old_known != tile_get_known(ptile))
refresh_tile_mapcanvas(ptile, FALSE);
/* if the terrain or the specials of the tile
Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.203
diff -u -r1.203 map.c
--- common/map.c 13 Nov 2004 08:34:17 -0000 1.203
+++ common/map.c 21 Nov 2004 08:42:17 -0000
@@ -355,7 +355,8 @@
{
ptile->terrain = T_UNKNOWN;
ptile->special = S_NO_SPECIAL;
- ptile->known = 0;
+ BV_CLR_ALL(ptile->tile_known);
+ BV_CLR_ALL(ptile->tile_seen);
ptile->continent = 0;
ptile->city = NULL;
unit_list_init(&ptile->units);
@@ -1309,6 +1310,23 @@
ptile->terrain = ter;
}
+/*************************************************************************
+ Return a known_type enumeration value for the tile.
+
+ Note that the client only knows known data about game.player_ptr.
+*************************************************************************/
+enum known_type map_get_known(const struct tile *ptile,
+ const struct player *pplayer)
+{
+ if (!BV_ISSET(ptile->tile_known, pplayer->player_no)) {
+ return TILE_UNKNOWN;
+ } else if (!BV_ISSET(ptile->tile_seen, pplayer->player_no)) {
+ return TILE_KNOWN_FOGGED;
+ } else {
+ return TILE_KNOWN;
+ }
+}
+
/***************************************************************
...
***************************************************************/
Index: common/map.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.h,v
retrieving revision 1.225
diff -u -r1.225 map.h
--- common/map.h 13 Nov 2004 08:34:17 -0000 1.225
+++ common/map.h 21 Nov 2004 08:42:17 -0000
@@ -49,9 +49,7 @@
enum tile_special_type special;
struct city *city;
struct unit_list units;
- unsigned int known; /* A bitvector on the server side, an
- enum known_type on the client side.
- Player_no is index */
+ player_bv tile_known, tile_seen;
int assigned; /* these can save a lot of CPU usage -- Syela */
struct city *worked; /* city working tile, or NULL if none */
Continent_id continent;
@@ -359,9 +357,8 @@
bool is_real_map_pos(int x, int y);
bool is_normal_map_pos(int x, int y);
-/* implemented in server/maphand.c and client/climisc.c */
enum known_type map_get_known(const struct tile *ptile,
- struct player *pplayer);
+ const struct player *pplayer);
/* special testing */
bool map_has_special(const struct tile *ptile,
Index: common/player.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/player.h,v
retrieving revision 1.132
diff -u -r1.132 player.h
--- common/player.h 17 Nov 2004 16:59:07 -0000 1.132
+++ common/player.h 21 Nov 2004 08:42:17 -0000
@@ -57,6 +57,8 @@
H_DIPLOMACY = 2048 /* Not very good at diplomacy */
};
+BV_DEFINE(player_bv, MAX_NUM_PLAYERS + MAX_NUM_BARBARIANS);
+
struct player_economic {
int gold;
int tax;
Index: server/maphand.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.c,v
retrieving revision 1.150
diff -u -r1.150 maphand.c
--- server/maphand.c 15 Oct 2004 09:39:05 -0000 1.150
+++ server/maphand.c 21 Nov 2004 08:42:19 -0000
@@ -912,7 +912,7 @@
***************************************************************/
bool map_is_known(const struct tile *ptile, struct player *pplayer)
{
- return TEST_BIT(ptile->known, pplayer->player_no);
+ return BV_ISSET(ptile->tile_known, pplayer->player_no);
}
/***************************************************************
@@ -920,8 +920,10 @@
***************************************************************/
bool map_is_known_and_seen(const struct tile *ptile, struct player *pplayer)
{
- return TEST_BIT(ptile->known, pplayer->player_no)
- && ((pplayer->private_map + ptile->index)->seen != 0);
+ assert(BV_ISSET(ptile->tile_seen, pplayer->player_no)
+ == (map_get_player_tile(ptile, pplayer)->seen_count > 0));
+ return (BV_ISSET(ptile->tile_known, pplayer->player_no)
+ && BV_ISSET(ptile->tile_seen, pplayer->player_no));
}
/***************************************************************
@@ -929,7 +931,9 @@
***************************************************************/
static int map_get_seen(const struct tile *ptile, struct player *pplayer)
{
- return map_get_player_tile(ptile, pplayer)->seen;
+ assert(BV_ISSET(ptile->tile_seen, pplayer->player_no)
+ == (map_get_player_tile(ptile, pplayer)->seen_count > 0));
+ return map_get_player_tile(ptile, pplayer)->seen_count;
}
/***************************************************************
@@ -937,10 +941,16 @@
***************************************************************/
void map_change_seen(struct tile *ptile, struct player *pplayer, int change)
{
- map_get_player_tile(ptile, pplayer)->seen += change;
+ struct player_tile *plrtile = map_get_player_tile(ptile, pplayer);
+
+ plrtile->seen_count += change;
+ if (plrtile->seen_count != 0) {
+ BV_SET(ptile->tile_seen, pplayer->player_no);
+ } else {
+ BV_CLR(ptile->tile_seen, pplayer->player_no);
+ }
freelog(LOG_DEBUG, "%d,%d, p: %d, change %d, result %d\n", TILE_XY(ptile),
- pplayer->player_no, change, map_get_player_tile(ptile,
- pplayer)->seen);
+ pplayer->player_no, change, plrtile->seen_count);
}
/***************************************************************
@@ -969,7 +979,7 @@
***************************************************************/
void map_set_known(struct tile *ptile, struct player *pplayer)
{
- ptile->known |= (1u<<pplayer->player_no);
+ BV_SET(ptile->tile_known, pplayer->player_no);
}
/***************************************************************
@@ -977,7 +987,7 @@
***************************************************************/
void map_clear_known(struct tile *ptile, struct player *pplayer)
{
- ptile->known &= ~(1u<<pplayer->player_no);
+ BV_CLR(ptile->tile_known, pplayer->player_no);
}
/***************************************************************
@@ -1057,18 +1067,20 @@
plrtile->special = S_NO_SPECIAL;
plrtile->city = NULL;
- plrtile->seen = 0;
+ plrtile->seen_count = 0;
plrtile->pending_seen = 0;
+ BV_CLR(ptile->tile_seen, pplayer->player_no);
if (!game.fogofwar_old) {
if (map_is_known(ptile, pplayer)) {
- plrtile->seen = 1;
+ plrtile->seen_count = 1;
+ BV_SET(ptile->tile_seen, pplayer->player_no);
} else {
plrtile->pending_seen = 1;
}
}
plrtile->last_updated = GAME_START_YEAR;
- plrtile->own_seen = plrtile->seen;
+ plrtile->own_seen = plrtile->seen_count;
}
/***************************************************************
@@ -1358,23 +1370,6 @@
/*************************************************************************
...
*************************************************************************/
-enum known_type map_get_known(const struct tile *ptile,
- struct player *pplayer)
-{
- if (map_is_known(ptile, pplayer)) {
- if (map_get_seen(ptile, pplayer) > 0) {
- return TILE_KNOWN;
- } else {
- return TILE_KNOWN_FOGGED;
- }
- } else {
- return TILE_UNKNOWN;
- }
-}
-
-/*************************************************************************
-...
-*************************************************************************/
static void enable_fog_of_war_player(struct player *pplayer)
{
whole_map_iterate(ptile) {
Index: server/maphand.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/maphand.h,v
retrieving revision 1.50
diff -u -r1.50 maphand.h
--- server/maphand.h 11 Nov 2004 16:50:54 -0000 1.50
+++ server/maphand.h 21 Nov 2004 08:42:19 -0000
@@ -38,7 +38,7 @@
struct player_tile {
Terrain_type_id terrain;
enum tile_special_type special;
- unsigned short seen;
+ unsigned short seen_count;
unsigned short own_seen;
/* If you build a city with an unknown square within city radius
the square stays unknown. However, we still have to keep count
Index: server/sanitycheck.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/sanitycheck.c,v
retrieving revision 1.54
diff -u -r1.54 sanitycheck.c
--- server/sanitycheck.c 30 Oct 2004 11:46:11 -0000 1.54
+++ server/sanitycheck.c 21 Nov 2004 08:42:19 -0000
@@ -66,11 +66,17 @@
players_iterate(pplayer) {
struct player_tile *plr_tile = map_get_player_tile(ptile, pplayer);
/* underflow of unsigned int */
- assert(plr_tile->seen < 60000);
+ assert(plr_tile->seen_count < 60000);
assert(plr_tile->own_seen < 60000);
assert(plr_tile->pending_seen < 60000);
- assert(plr_tile->own_seen <= plr_tile->seen);
+ if (plr_tile->seen_count > 0) {
+ assert(BV_ISSET(ptile->tile_seen, pplayer->player_no));
+ } else {
+ assert(!BV_ISSET(ptile->tile_seen, pplayer->player_no));
+ }
+
+ assert(plr_tile->own_seen <= plr_tile->seen_count);
if (map_is_known(ptile, pplayer)) {
assert(plr_tile->pending_seen == 0);
}
Index: server/savegame.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/savegame.c,v
retrieving revision 1.207
diff -u -r1.207 savegame.c
--- server/savegame.c 20 Nov 2004 18:08:42 -0000 1.207
+++ server/savegame.c 21 Nov 2004 08:42:19 -0000
@@ -617,36 +617,48 @@
ptile->special |= ascii_hex2bin(ch, 3));
if (secfile_lookup_bool_default(file, TRUE, "game.save_known")) {
+ int known[MAX_MAP_INDEX];
/* get 4-bit segments of the first half of the 32-bit "known" field */
LOAD_MAP_DATA(ch, nat_y, ptile,
secfile_lookup_str(file, "map.a%03d", nat_y),
- ptile->known = ascii_hex2bin(ch, 0));
+ known[ptile->index] = ascii_hex2bin(ch, 0));
LOAD_MAP_DATA(ch, nat_y, ptile,
secfile_lookup_str(file, "map.b%03d", nat_y),
- ptile->known |= ascii_hex2bin(ch, 1));
+ known[ptile->index] |= ascii_hex2bin(ch, 1));
LOAD_MAP_DATA(ch, nat_y, ptile,
secfile_lookup_str(file, "map.c%03d", nat_y),
- ptile->known |= ascii_hex2bin(ch, 2));
+ known[ptile->index] |= ascii_hex2bin(ch, 2));
LOAD_MAP_DATA(ch, nat_y, ptile,
secfile_lookup_str(file, "map.d%03d", nat_y),
- ptile->known |= ascii_hex2bin(ch, 3));
+ known[ptile->index] |= ascii_hex2bin(ch, 3));
if (has_capability("known32fix", savefile_options)) {
/* get 4-bit segments of the second half of the 32-bit "known" field */
LOAD_MAP_DATA(ch, nat_y, ptile,
secfile_lookup_str(file, "map.e%03d", nat_y),
- ptile->known |= ascii_hex2bin(ch, 4));
+ known[ptile->index] |= ascii_hex2bin(ch, 4));
LOAD_MAP_DATA(ch, nat_y, ptile,
secfile_lookup_str(file, "map.g%03d", nat_y),
- ptile->known |= ascii_hex2bin(ch, 5));
+ known[ptile->index] |= ascii_hex2bin(ch, 5));
LOAD_MAP_DATA(ch, nat_y, ptile,
secfile_lookup_str(file, "map.h%03d", nat_y),
- ptile->known |= ascii_hex2bin(ch, 6));
+ known[ptile->index] |= ascii_hex2bin(ch, 6));
LOAD_MAP_DATA(ch, nat_y, ptile,
secfile_lookup_str(file, "map.i%03d", nat_y),
- ptile->known |= ascii_hex2bin(ch, 7));
+ known[ptile->index] |= ascii_hex2bin(ch, 7));
}
+
+ /* HACK: we read the known data from hex into a 32-bit integer, and
+ * now we convert it to player_bv. */
+ whole_map_iterate(ptile) {
+ BV_CLR_ALL(ptile->tile_known);
+ players_iterate(pplayer) {
+ if (known[ptile->index] & (1u << pplayer->player_no)) {
+ BV_SET(ptile->tile_known, pplayer->player_no);
+ }
+ } players_iterate_end;
+ } whole_map_iterate_end;
}
@@ -712,27 +724,40 @@
secfile_insert_bool(file, game.save_options.save_known, "game.save_known");
if (game.save_options.save_known) {
+ int known[MAX_MAP_INDEX];
+
/* put the top 4 bits (bits 12-15) of special flags */
SAVE_NORMAL_MAP_DATA(ptile, file, "map.f%03d",
bin2ascii_hex(ptile->special, 3));
+ /* HACK: we convert the data into a 32-bit integer, and then save it as
+ * hex. */
+ memset(known, 0, sizeof(known));
+ whole_map_iterate(ptile) {
+ players_iterate(pplayer) {
+ if (map_is_known(ptile, pplayer)) {
+ known[ptile->index] |= (1u << pplayer->player_no);
+ }
+ } players_iterate_end;
+ } whole_map_iterate_end;
+
/* put 4-bit segments of the 32-bit "known" field */
SAVE_NORMAL_MAP_DATA(ptile, file, "map.a%03d",
- bin2ascii_hex(ptile->known, 0));
+ bin2ascii_hex(known[ptile->index], 0));
SAVE_NORMAL_MAP_DATA(ptile, file, "map.b%03d",
- bin2ascii_hex(ptile->known, 1));
+ bin2ascii_hex(known[ptile->index], 1));
SAVE_NORMAL_MAP_DATA(ptile, file, "map.c%03d",
- bin2ascii_hex(ptile->known, 2));
+ bin2ascii_hex(known[ptile->index], 2));
SAVE_NORMAL_MAP_DATA(ptile, file, "map.d%03d",
- bin2ascii_hex(ptile->known, 3));
+ bin2ascii_hex(known[ptile->index], 3));
SAVE_NORMAL_MAP_DATA(ptile, file, "map.e%03d",
- bin2ascii_hex(ptile->known, 4));
+ bin2ascii_hex(known[ptile->index], 4));
SAVE_NORMAL_MAP_DATA(ptile, file, "map.g%03d",
- bin2ascii_hex(ptile->known, 5));
+ bin2ascii_hex(known[ptile->index], 5));
SAVE_NORMAL_MAP_DATA(ptile, file, "map.h%03d",
- bin2ascii_hex(ptile->known, 6));
+ bin2ascii_hex(known[ptile->index], 6));
SAVE_NORMAL_MAP_DATA(ptile, file, "map.i%03d",
- bin2ascii_hex(ptile->known, 7));
+ bin2ascii_hex(known[ptile->index], 7));
}
whole_map_iterate(ptile) {
Index: server/score.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/server/score.c,v
retrieving revision 1.8
diff -u -r1.8 score.c
--- server/score.c 29 Sep 2004 02:24:24 -0000 1.8
+++ server/score.c 21 Nov 2004 08:42:20 -0000
@@ -36,7 +36,7 @@
struct claim_cell {
int when;
int whom;
- int know;
+ player_bv know;
int cities;
};
@@ -199,7 +199,7 @@
nextedge++;
pcmap->player_landarea[owner]++;
pcmap->player_owndarea[owner]++;
- pclaim->know = ptile->known;
+ BV_COPY(pclaim->know, ptile->tile_known);
} else if (ptile->worked) {
owner = ptile->worked->owner;
pclaim->when = turn + 1;
@@ -208,7 +208,7 @@
nextedge++;
pcmap->player_landarea[owner]++;
pcmap->player_owndarea[owner]++;
- pclaim->know = ptile->known;
+ BV_COPY(pclaim->know, ptile->tile_known);
} else if (unit_list_size(&ptile->units) > 0) {
owner = (unit_list_get(&ptile->units, 0))->owner;
pclaim->when = turn + 1;
@@ -219,11 +219,11 @@
if (TEST_BIT(pclaim->cities, owner)) {
pcmap->player_owndarea[owner]++;
}
- pclaim->know = ptile->known;
+ BV_COPY(pclaim->know, ptile->tile_known);
} else {
/* pclaim->when = 0; */
pclaim->whom = no_owner;
- pclaim->know = ptile->known;
+ BV_COPY(pclaim->know, ptile->tile_known);
}
} whole_map_iterate_end;
@@ -260,7 +260,7 @@
int j = tile1->index;
struct claim_cell *pclaim = &pcmap->claims[j];
- if (TEST_BIT(pclaim->know, owner)) {
+ if (BV_ISSET(pclaim->know, owner)) {
if (pclaim->when == 0) {
pclaim->when = turn + 1;
pclaim->whom = owner;
Index: utility/shared.h
===================================================================
RCS file: /home/freeciv/CVS/freeciv/utility/shared.h,v
retrieving revision 1.137
diff -u -r1.137 shared.h
--- utility/shared.h 21 Oct 2004 20:27:29 -0000 1.137
+++ utility/shared.h 21 Nov 2004 08:42:20 -0000
@@ -185,6 +185,10 @@
#define BV_ARE_EQUAL(vec1, vec2) \
bv_are_equal((vec1).vec, (vec2).vec, sizeof((vec1).vec), sizeof((vec2).vec))
+#define BV_COPY(dst, src) \
+ (assert(sizeof((src).vec) == sizeof((dst).vec)), \
+ memcpy((dst).vec, (src).vec, sizeof((dst).vec)))
+
#define BV_DEFINE(name, bits) \
typedef struct { unsigned char vec[_BV_BYTES(bits)]; } name
- [Freeciv-Dev] (PR#11126) unify map_get_known,
Jason Short <=
|
|