diff --git a/client/mapview_common.c b/client/mapview_common.c index d317764f8c..3cb1c353e2 100644 --- a/client/mapview_common.c +++ b/client/mapview_common.c @@ -765,10 +765,10 @@ static void normalize_gui_pos(const struct tileset *t, * we wrap even if the map position is unreal, which normalize_map_pos * doesn't necessarily do. */ MAP_TO_NATIVE_POS(&nat_x, &nat_y, map_x, map_y); - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { nat_x = FC_WRAP(nat_x, wld.map.xsize); } - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_Y)) { nat_y = FC_WRAP(nat_y, wld.map.ysize); } NATIVE_TO_MAP_POS(&map_x, &map_y, nat_x, nat_y); @@ -940,11 +940,11 @@ static bool calc_mapview_origin(float *gui_x0, float *gui_y0) * while clipping is done in scroll (native) positions. */ get_mapview_scroll_window(&xmin, &ymin, &xmax, &ymax, &xsize, &ysize); - if (!current_topo_has_flag(TF_WRAPX)) { + if (!current_wrap_has_flag(WRAP_X)) { *gui_x0 = CLIP(xmin, *gui_x0, xmax - xsize); } - if (!current_topo_has_flag(TF_WRAPY)) { + if (!current_wrap_has_flag(WRAP_Y)) { *gui_y0 = CLIP(ymin, *gui_y0, ymax - ysize); } @@ -1083,13 +1083,13 @@ void get_mapview_scroll_window(float *xmin, float *ymin, * iso-view or a full tile in non-iso view. The above math already has * taken care of some of this so all that's left is to fix the corner * cases. */ - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { *xmax += *xsize; /* We need to be able to scroll a little further to the left. */ *xmin -= tileset_tile_width(tileset) * map_zoom; } - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_Y)) { *ymax += *ysize; /* We need to be able to scroll a little further up. */ @@ -1255,19 +1255,19 @@ bool tile_visible_and_not_on_border_mapcanvas(struct tile *ptile) * border, then it's a border tile. We can only really check the * scrolling when the mapview window lines up with the map. */ if (canvas_x < border_x - && (!same || scroll_x > xmin || current_topo_has_flag(TF_WRAPX))) { + && (!same || scroll_x > xmin || current_wrap_has_flag(WRAP_X))) { return FALSE; } if (canvas_y < border_y - && (!same || scroll_y > ymin || current_topo_has_flag(TF_WRAPY))) { + && (!same || scroll_y > ymin || current_wrap_has_flag(WRAP_Y))) { return FALSE; } if (canvas_x + tileset_tile_width(tileset) * map_zoom > mapview.width - border_x - && (!same || scroll_x + xsize < xmax || current_topo_has_flag(TF_WRAPX))) { + && (!same || scroll_x + xsize < xmax || current_wrap_has_flag(WRAP_X))) { return FALSE; } if (canvas_y + tileset_tile_height(tileset) * map_zoom > mapview.height - border_y - && (!same || scroll_y + ysize < ymax || current_topo_has_flag(TF_WRAPY))) { + && (!same || scroll_y + ysize < ymax || current_wrap_has_flag(WRAP_Y))) { return FALSE; } @@ -3209,7 +3209,7 @@ static bool can_do_cached_drawing(void) * * The logic below is complicated and determined in part by * trial-and-error. */ - if (!current_topo_has_flag(TF_WRAPX) && !current_topo_has_flag(TF_WRAPY)) { + if (!current_wrap_has_flag(WRAP_X) && !current_wrap_has_flag(WRAP_Y)) { /* An unwrapping map: no limitation. On an unwrapping map no tile can * be visible twice so there's no problem. */ return TRUE; @@ -3235,11 +3235,11 @@ static bool can_do_cached_drawing(void) /* Now we can use the full width and height, with the exception of a small * area on each side. */ - if (current_topo_has_flag(TF_WRAPX) + if (current_wrap_has_flag(WRAP_X) && w > (NATURAL_WIDTH - isodiff) * W / isofactor) { return FALSE; } - if (current_topo_has_flag(TF_WRAPY) + if (current_wrap_has_flag(WRAP_Y) && h > (NATURAL_HEIGHT - isodiff) * H / isofactor) { return FALSE; } diff --git a/client/overview_common.c b/client/overview_common.c index f3f78143f6..f872a6d3e0 100644 --- a/client/overview_common.c +++ b/client/overview_common.c @@ -83,8 +83,8 @@ static void gui_to_natural_pos(const struct tileset *t, Translate from gui to overview coordinate systems. ****************************************************************************/ static void gui_to_overview_pos(const struct tileset *t, - int *ovr_x, int *ovr_y, - int gui_x, int gui_y) + int *ovr_x, int *ovr_y, + int gui_x, int gui_y) { double ntl_x, ntl_y; @@ -95,7 +95,7 @@ static void gui_to_overview_pos(const struct tileset *t, *ovr_y = floor((ntl_y - (double)gui_options.overview.map_y0) * OVERVIEW_TILE_SIZE); /* Now do additional adjustments. See map_to_overview_pos(). */ - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { *ovr_x = FC_WRAP(*ovr_x, NATURAL_WIDTH * OVERVIEW_TILE_SIZE); } else { if (MAP_IS_ISOMETRIC) { @@ -107,7 +107,8 @@ static void gui_to_overview_pos(const struct tileset *t, *ovr_x -= OVERVIEW_TILE_SIZE; } } - if (current_topo_has_flag(TF_WRAPY)) { + + if (current_wrap_has_flag(WRAP_Y)) { *ovr_y = FC_WRAP(*ovr_y, NATURAL_HEIGHT * OVERVIEW_TILE_SIZE); } } @@ -290,19 +291,19 @@ void center_tile_overviewcanvas(void) int ox, oy; gui_to_natural_pos(tileset, &ntl_x, &ntl_y, - mapview.gui_x0 + mapview.width / 2, - mapview.gui_y0 + mapview.height / 2); + mapview.gui_x0 + mapview.width / 2, + mapview.gui_y0 + mapview.height / 2); /* NOTE: this embeds the map wrapping in the overview code. This is * basically necessary for the overview to be efficiently * updated. */ - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { gui_options.overview.map_x0 = wrap_double(ntl_x - (double)NATURAL_WIDTH / 2.0, NATURAL_WIDTH); } else { gui_options.overview.map_x0 = 0; } - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_Y)) { gui_options.overview.map_y0 = wrap_double(ntl_y - (double)NATURAL_HEIGHT / 2.0, NATURAL_HEIGHT); } else { @@ -330,7 +331,7 @@ void map_to_overview_pos(int *overview_x, int *overview_y, int ovr_x = ntl_x - gui_options.overview.map_x0; int ovr_y = ntl_y - gui_options.overview.map_y0; - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { ovr_x = FC_WRAP(ovr_x, NATURAL_WIDTH); } else { if (MAP_IS_ISOMETRIC) { @@ -342,7 +343,7 @@ void map_to_overview_pos(int *overview_x, int *overview_y, ovr_x--; } } - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_Y)) { ovr_y = FC_WRAP(ovr_y, NATURAL_HEIGHT); } *overview_x = OVERVIEW_TILE_SIZE * ovr_x; @@ -359,7 +360,7 @@ void overview_to_map_pos(int *map_x, int *map_y, int ntl_x = overview_x / OVERVIEW_TILE_SIZE + gui_options.overview.map_x0; int ntl_y = overview_y / OVERVIEW_TILE_SIZE + gui_options.overview.map_y0; - if (MAP_IS_ISOMETRIC && !current_topo_has_flag(TF_WRAPX)) { + if (MAP_IS_ISOMETRIC && !current_wrap_has_flag(WRAP_X)) { /* Clip half tile left and right. See comment in map_to_overview_pos. */ ntl_x++; } @@ -418,7 +419,7 @@ void overview_update_tile(struct tile *ptile) int overview_x = ntl_x * OVERVIEW_TILE_SIZE; if (MAP_IS_ISOMETRIC) { - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { if (overview_x > gui_options.overview.width - OVERVIEW_TILE_WIDTH) { /* This tile is shown half on the left and half on the right * side of the overview. So we have to draw it in two parts. */ @@ -453,7 +454,7 @@ void calculate_overview_dimensions(void) static int recursion = 0; /* Just to be safe. */ /* Clip half tile left and right. See comment in map_to_overview_pos. */ - int shift = (MAP_IS_ISOMETRIC && !current_topo_has_flag(TF_WRAPX)) ? -1 : 0; + int shift = (MAP_IS_ISOMETRIC && !current_wrap_has_flag(WRAP_X)) ? -1 : 0; if (recursion > 0 || wld.map.xsize <= 0 || wld.map.ysize <= 0) { return; diff --git a/client/packhand.c b/client/packhand.c index 37b2df54a4..cf3f421ebb 100644 --- a/client/packhand.c +++ b/client/packhand.c @@ -2152,9 +2152,10 @@ void handle_unit_short_info(const struct packet_unit_short_info *packet) /************************************************************************//** Server requested topology change. ****************************************************************************/ -void handle_set_topology(int topology_id) +void handle_set_topology(int topology_id, int wrap_id) { wld.map.topology_id = topology_id; + wld.map.wrap_id = wrap_id; if (forced_tileset_name[0] == '\0' && (tileset_map_topo_compatible(topology_id, tileset, NULL) @@ -2174,7 +2175,7 @@ void handle_set_topology(int topology_id) Receive information about the map size and topology from the server. We initialize some global variables at the same time. ****************************************************************************/ -void handle_map_info(int xsize, int ysize, int topology_id) +void handle_map_info(int xsize, int ysize, int topology_id, int wrap_id) { int ts_topo; @@ -2192,6 +2193,7 @@ void handle_map_info(int xsize, int ysize, int topology_id) } wld.map.topology_id = topology_id; + wld.map.wrap_id = wrap_id; map_init_topology(); main_map_allocate(); diff --git a/common/fc_types.h b/common/fc_types.h index 8f3285a256..0e333d4303 100644 --- a/common/fc_types.h +++ b/common/fc_types.h @@ -562,9 +562,9 @@ typedef int Unit_Class_id; * Changing the names will break file format compatibility. */ #define SPECENUM_NAME topo_flag #define SPECENUM_BITWISE -#define SPECENUM_VALUE0 TF_WRAPX +#define SPECENUM_VALUE0 TF_OLD_WRAPX #define SPECENUM_VALUE0NAME N_("WrapX") -#define SPECENUM_VALUE1 TF_WRAPY +#define SPECENUM_VALUE1 TF_OLD_WRAPY #define SPECENUM_VALUE1NAME N_("WrapY") #define SPECENUM_VALUE2 TF_ISO #define SPECENUM_VALUE2NAME N_("ISO") @@ -573,6 +573,14 @@ typedef int Unit_Class_id; #define TOPO_FLAG_BITS 4 #include "specenum_gen.h" +#define SPECENUM_NAME wrap_flag +#define SPECENUM_BITWISE +#define SPECENUM_VALUE0 WRAP_X +#define SPECENUM_VALUE0NAME N_("WrapX") +#define SPECENUM_VALUE1 WRAP_Y +#define SPECENUM_VALUE1NAME N_("WrapY") +#include "specenum_gen.h" + /* Used in the network protocol. */ #define SPECENUM_NAME impr_genus_id #define SPECENUM_VALUE0 IG_GREAT_WONDER diff --git a/common/map.c b/common/map.c index ad0ff45331..c4ab2b91d9 100644 --- a/common/map.c +++ b/common/map.c @@ -156,6 +156,7 @@ bool map_is_empty(void) void map_init(struct civ_map *imap, bool server_side) { imap->topology_id = MAP_DEFAULT_TOPO; + imap->wrap_id = MAP_DEFAULT_WRAP; imap->num_continents = 0; imap->num_oceans = 0; imap->tiles = NULL; @@ -238,13 +239,13 @@ static void generate_map_indices(void) * case we're not concerned with going too far and wrapping around, so we * just have to make sure we go far enough if we're at one edge of the * map. */ - nat_min_x = (current_topo_has_flag(TF_WRAPX) ? 0 : (nat_center_x - wld.map.xsize + 1)); - nat_min_y = (current_topo_has_flag(TF_WRAPY) ? 0 : (nat_center_y - wld.map.ysize + 1)); + nat_min_x = (current_wrap_has_flag(WRAP_X) ? 0 : (nat_center_x - wld.map.xsize + 1)); + nat_min_y = (current_wrap_has_flag(WRAP_Y) ? 0 : (nat_center_y - wld.map.ysize + 1)); - nat_max_x = (current_topo_has_flag(TF_WRAPX) + nat_max_x = (current_wrap_has_flag(WRAP_X) ? (wld.map.xsize - 1) : (nat_center_x + wld.map.xsize - 1)); - nat_max_y = (current_topo_has_flag(TF_WRAPY) + nat_max_y = (current_wrap_has_flag(WRAP_Y) ? (wld.map.ysize - 1) : (nat_center_y + wld.map.ysize - 1)); tiles = (nat_max_x - nat_min_x + 1) * (nat_max_y - nat_min_y + 1); @@ -395,12 +396,12 @@ static inline struct tile *base_native_pos_to_tile(const struct civ_map *nmap, /* Wrap in X and Y directions, as needed. */ /* If the position is out of range in a non-wrapping direction, it is * unreal. */ - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { nat_x = FC_WRAP(nat_x, wld.map.xsize); } else if (nat_x < 0 || nat_x >= wld.map.xsize) { return NULL; } - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_Y)) { nat_y = FC_WRAP(nat_y, wld.map.ysize); } else if (nat_y < 0 || nat_y >= wld.map.ysize) { return NULL; @@ -987,10 +988,10 @@ struct tile *nearest_real_tile(const struct civ_map *nmap, int x, int y) int nat_x, nat_y; MAP_TO_NATIVE_POS(&nat_x, &nat_y, x, y); - if (!current_topo_has_flag(TF_WRAPX)) { + if (!current_wrap_has_flag(WRAP_X)) { nat_x = CLIP(0, nat_x, wld.map.xsize - 1); } - if (!current_topo_has_flag(TF_WRAPY)) { + if (!current_wrap_has_flag(WRAP_Y)) { nat_y = CLIP(0, nat_y, wld.map.ysize - 1); } NATIVE_TO_MAP_POS(&x, &y, nat_x, nat_y); @@ -1012,9 +1013,9 @@ int map_num_tiles(void) instead. ***********************************************************************/ void base_map_distance_vector(int *dx, int *dy, - int x0dv, int y0dv, int x1dv, int y1dv) + int x0dv, int y0dv, int x1dv, int y1dv) { - if (current_topo_has_flag(TF_WRAPX) || current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_X) || current_wrap_has_flag(WRAP_Y)) { /* Wrapping is done in native coordinates. */ MAP_TO_NATIVE_POS(&x0dv, &y0dv, x0dv, y0dv); MAP_TO_NATIVE_POS(&x1dv, &y1dv, x1dv, y1dv); @@ -1023,11 +1024,11 @@ void base_map_distance_vector(int *dx, int *dy, * map distance vector but is easier to wrap. */ *dx = x1dv - x0dv; *dy = y1dv - y0dv; - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { /* Wrap dx to be in [-map.xsize/2, map.xsize/2). */ *dx = FC_WRAP(*dx + wld.map.xsize / 2, wld.map.xsize) - wld.map.xsize / 2; } - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_Y)) { /* Wrap dy to be in [-map.ysize/2, map.ysize/2). */ *dy = FC_WRAP(*dy + wld.map.ysize / 2, wld.map.ysize) - wld.map.ysize / 2; } @@ -1417,10 +1418,10 @@ bool is_singular_tile(const struct tile *ptile, int dist) /* Iso-natural coordinates are doubled in scale. */ dist *= MAP_IS_ISOMETRIC ? 2 : 1; - return ((!current_topo_has_flag(TF_WRAPX) - && (ntl_x < dist || ntl_x >= NATURAL_WIDTH - dist)) - || (!current_topo_has_flag(TF_WRAPY) - && (ntl_y < dist || ntl_y >= NATURAL_HEIGHT - dist))); + return ((!current_wrap_has_flag(WRAP_X) + && (ntl_x < dist || ntl_x >= NATURAL_WIDTH - dist)) + || (!current_wrap_has_flag(WRAP_Y) + && (ntl_y < dist || ntl_y >= NATURAL_HEIGHT - dist))); } do_in_natural_pos_end; } diff --git a/common/map.h b/common/map.h index 8f96883f94..3d6fa672bc 100644 --- a/common/map.h +++ b/common/map.h @@ -40,10 +40,14 @@ static const bool C_PERCENT = TRUE; #define MAP_IS_ISOMETRIC (CURRENT_TOPOLOGY & (TF_ISO + TF_HEX)) #define CURRENT_TOPOLOGY (wld.map.topology_id) +#define CURRENT_WRAP (wld.map.wrap_id) #define topo_has_flag(topo, flag) (((topo) & (flag)) != 0) #define current_topo_has_flag(flag) topo_has_flag((CURRENT_TOPOLOGY), (flag)) +#define wrap_has_flag(wrap, flag) (((wrap) & (flag)) != 0) +#define current_wrap_has_flag(flag) wrap_has_flag((CURRENT_WRAP), (flag)) + #define ALL_DIRECTIONS_CARDINAL() topo_has_flag((CURRENT_TOPOLOGY), TF_HEX) bool map_is_empty(void); @@ -612,9 +616,11 @@ moves. Includes MAP_MAX_LINEAR_SIZE because a map can be non wrapping. */ #define MAP_ORIGINAL_TOPO TF_WRAPX #ifdef FREECIV_WEB /* Freeciv-web doesn't support isometric maps yet. */ -#define MAP_DEFAULT_TOPO TF_WRAPX +#define MAP_DEFAULT_TOPO 0 +#define MAP_DEFAULT_WRAP WRAP_X #else /* FREECIV_WEB */ -#define MAP_DEFAULT_TOPO (TF_WRAPX|TF_ISO|TF_HEX) +#define MAP_DEFAULT_TOPO (TF_ISO|TF_HEX) +#define MAP_DEFAULT_WRAP (WRAP_X) #endif /* FREECIV_WEB */ #define MAP_DEFAULT_SEED 0 diff --git a/common/map_types.h b/common/map_types.h index ce81c63ee9..dbaf10c705 100644 --- a/common/map_types.h +++ b/common/map_types.h @@ -70,6 +70,7 @@ enum map_startpos { struct civ_map { int topology_id; + int wrap_id; enum direction8 valid_dirs[8], cardinal_dirs[8]; int num_valid_dirs, num_cardinal_dirs; struct iter_index *iterate_outwards_indices; diff --git a/common/mapimg.c b/common/mapimg.c index 2740cfba36..31abc1ba72 100644 --- a/common/mapimg.c +++ b/common/mapimg.c @@ -389,7 +389,8 @@ struct img { const struct rgbcolor **map; }; -static struct img *img_new(struct mapdef *mapdef, int topo, int xsize, int ysize); +static struct img *img_new(struct mapdef *mapdef, int topo, int wrap, + int xsize, int ysize); static void img_destroy(struct img *pimg); static inline void img_set_pixel(struct img *pimg, const int mindex, const struct rgbcolor *pcolor); @@ -1374,7 +1375,8 @@ bool mapimg_create(struct mapdef *pmapdef, bool force, const char *savename, generate_save_name(savename, mapimgfile, sizeof(mapimgfile), mapimg_generate_name(pmapdef)); - pimg = img_new(pmapdef, CURRENT_TOPOLOGY, wld.map.xsize, wld.map.ysize); + pimg = img_new(pmapdef, CURRENT_TOPOLOGY, CURRENT_WRAP, + wld.map.xsize, wld.map.ysize); img_createmap(pimg); if (!img_save(pimg, mapimgfile, path)) { ret = FALSE; @@ -1397,7 +1399,8 @@ bool mapimg_create(struct mapdef *pmapdef, bool force, const char *savename, generate_save_name(savename, mapimgfile, sizeof(mapimgfile), mapimg_generate_name(pmapdef)); - pimg = img_new(pmapdef, CURRENT_TOPOLOGY, wld.map.xsize, wld.map.ysize); + pimg = img_new(pmapdef, CURRENT_TOPOLOGY, CURRENT_WRAP, + wld.map.xsize, wld.map.ysize); img_createmap(pimg); if (!img_save(pimg, mapimgfile, path)) { ret = FALSE; @@ -1444,7 +1447,7 @@ bool mapimg_colortest(const char *savename, const char *path) #define SIZE_X 16 #define SIZE_Y 5 - pimg = img_new(pmapdef, 0, SIZE_X + 2, + pimg = img_new(pmapdef, 0, 0, SIZE_X + 2, SIZE_Y * (max_playercolor / SIZE_X) + 2); pixel = pimg->pixel_tile(NULL, NULL, FALSE); @@ -1863,7 +1866,8 @@ static const struct toolkit *img_toolkit_get(enum imagetool tool) /************************************************************************//** Create a new image. ****************************************************************************/ -static struct img *img_new(struct mapdef *mapdef, int topo, int xsize, int ysize) +static struct img *img_new(struct mapdef *mapdef, int topo, int wrap, + int xsize, int ysize) { struct img *pimg; @@ -1894,8 +1898,8 @@ static struct img *img_new(struct mapdef *mapdef, int topo, int xsize, int ysize * TILE_SIZE; /* magic for isohexa: change size if wrapping in only one direction */ - if ((topo_has_flag(topo, TF_WRAPX) && !topo_has_flag(topo, TF_WRAPY)) - || (!topo_has_flag(topo, TF_WRAPX) && topo_has_flag(topo, TF_WRAPY))) { + if ((wrap_has_flag(wrap, WRAP_X) && !wrap_has_flag(wrap, WRAP_Y)) + || (!wrap_has_flag(wrap, WRAP_X) && wrap_has_flag(wrap, WRAP_Y))) { pimg->imgsize.y += (pimg->mapsize.x - pimg->mapsize.y / 2) / 2 * TILE_SIZE; } diff --git a/common/networking/packets.def b/common/networking/packets.def index 49569f6e2e..2c2edd1580 100644 --- a/common/networking/packets.def +++ b/common/networking/packets.def @@ -626,6 +626,7 @@ PACKET_MAP_INFO = 17; sc, lsend XYSIZE xsize; XYSIZE ysize; UINT8 topology_id; + UINT8 wrap_id; end PACKET_NUKE_TILE_INFO = 18; sc, dsend,lsend @@ -2044,6 +2045,7 @@ end PACKET_SET_TOPOLOGY = 253; sc UINT8 topology_id; + UINT8 wrap_id; end /************** Effects hash packets **********************/ diff --git a/fc_version b/fc_version index 1f123af4b9..0e07578362 100755 --- a/fc_version +++ b/fc_version @@ -56,7 +56,7 @@ DEFAULT_FOLLOW_TAG=S3_2 # - No new mandatory capabilities can be added to the release branch; doing # so would break network capability of supposedly "compatible" releases. # -NETWORK_CAPSTRING="+Freeciv.Devel-3.2-2022.Feb.03" +NETWORK_CAPSTRING="+Freeciv.Devel-3.2-2022.Feb.05" FREECIV_DISTRIBUTOR="" diff --git a/server/generator/height_map.c b/server/generator/height_map.c index 5624bd09fa..f13567ace9 100644 --- a/server/generator/height_map.c +++ b/server/generator/height_map.c @@ -196,14 +196,14 @@ liklihood of continents butting up to non-wrapped edges. **************************************************************************/ void make_pseudofractal1_hmap(int extra_div) { - const bool xnowrap = !current_topo_has_flag(TF_WRAPX); - const bool ynowrap = !current_topo_has_flag(TF_WRAPY); + const bool xnowrap = !current_wrap_has_flag(WRAP_X); + const bool ynowrap = !current_wrap_has_flag(WRAP_Y); - /* + /* * How many blocks should the x and y directions be divided into - * initially. + * initially. */ - const int xdiv = 5 + extra_div; + const int xdiv = 5 + extra_div; const int ydiv = 5 + extra_div; int xdiv2 = xdiv + (xnowrap ? 1 : 0); @@ -213,9 +213,9 @@ void make_pseudofractal1_hmap(int extra_div) int ymax = wld.map.ysize - (ynowrap ? 1 : 0); int x_current, y_current; /* just need something > log(max(xsize, ysize)) for the recursion */ - int step = wld.map.xsize + wld.map.ysize; + int step = wld.map.xsize + wld.map.ysize; /* edges are avoided more strongly as this increases */ - int avoidedge = (100 - wld.map.server.landpercent) * step / 100 + step / 3; + int avoidedge = (100 - wld.map.server.landpercent) * step / 100 + step / 3; height_map = fc_malloc(sizeof(*height_map) * MAP_INDEX_SIZE); diff --git a/server/generator/mapgen.c b/server/generator/mapgen.c index c9df51262e..6dff89c59b 100644 --- a/server/generator/mapgen.c +++ b/server/generator/mapgen.c @@ -2553,14 +2553,14 @@ fair_map_pos_tile(struct fair_tile *pmap, int x, int y) /* Wrap in X and Y directions, as needed. */ if (nat_x < 0 || nat_x >= wld.map.xsize) { - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { nat_x = FC_WRAP(nat_x, wld.map.xsize); } else { return NULL; } } if (nat_y < 0 || nat_y >= wld.map.ysize) { - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_Y)) { nat_y = FC_WRAP(nat_y, wld.map.ysize); } else { return NULL; @@ -2596,7 +2596,7 @@ fair_map_tile_border(struct fair_tile *pmap, struct fair_tile *ptile, index_to_native_pos(&nat_x, &nat_y, ptile - pmap); - if (!current_topo_has_flag(TF_WRAPX) + if (!current_wrap_has_flag(WRAP_X) && (nat_x < dist || nat_x >= wld.map.xsize - dist)) { return TRUE; } @@ -2605,7 +2605,7 @@ fair_map_tile_border(struct fair_tile *pmap, struct fair_tile *ptile, dist *= 2; } - if (!current_topo_has_flag(TF_WRAPY) + if (!current_wrap_has_flag(WRAP_Y) && (nat_y < dist || nat_y >= wld.map.ysize - dist)) { return TRUE; } @@ -3550,19 +3550,19 @@ static bool map_generate_fair_islands(void) } /* Make start point for teams. */ - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { dx = fc_rand(wld.map.xsize); } - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_Y)) { dy = fc_rand(wld.map.ysize); } for (j = 0; j < teams_num; j++) { start_x[j] = (wld.map.xsize * (2 * j + 1)) / (2 * teams_num) + dx; start_y[j] = (wld.map.ysize * (2 * j + 1)) / (2 * teams_num) + dy; - if (current_topo_has_flag(TF_WRAPX)) { + if (current_wrap_has_flag(WRAP_X)) { start_x[j] = FC_WRAP(start_x[j], wld.map.xsize); } - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_Y)) { start_y[j] = FC_WRAP(start_y[j], wld.map.ysize); } } diff --git a/server/generator/mapgen_topology.c b/server/generator/mapgen_topology.c index a87c1dda95..89d297864c 100644 --- a/server/generator/mapgen_topology.c +++ b/server/generator/mapgen_topology.c @@ -53,12 +53,12 @@ int map_colatitude(const struct tile *ptile) index_to_map_pos(&tile_x, &tile_y, tile_index(ptile)); do_in_natural_pos(ntl_x, ntl_y, tile_x, tile_y) { if (wld.map.server.single_pole) { - if (!current_topo_has_flag(TF_WRAPY)) { + if (!current_wrap_has_flag(WRAP_Y)) { /* Partial planetary map. A polar zone is placed * at the top and the equator is at the bottom. */ return MAX_COLATITUDE * ntl_y / (NATURAL_HEIGHT - 1); } - if (!current_topo_has_flag(TF_WRAPX)) { + if (!current_wrap_has_flag(WRAP_X)) { return MAX_COLATITUDE * ntl_x / (NATURAL_WIDTH -1); } } @@ -96,13 +96,13 @@ int map_colatitude(const struct tile *ptile) / (NATURAL_HEIGHT / 2 - 1)); } do_in_natural_pos_end; - if (!current_topo_has_flag(TF_WRAPY)) { + if (!current_wrap_has_flag(WRAP_Y)) { /* In an Earth-like topology the polar zones are at north and south. * This is equivalent to a Mercator projection. */ return MAX_COLATITUDE * y; } - if (!current_topo_has_flag(TF_WRAPX) && current_topo_has_flag(TF_WRAPY)) { + if (!current_wrap_has_flag(WRAP_X) && current_wrap_has_flag(WRAP_Y)) { /* In a Uranus-like topology the polar zones are at east and west. * This isn't really the way Uranus is; it's the way Earth would look * if you tilted your head sideways. It's still a Mercator @@ -286,8 +286,8 @@ static void set_sizes(double size, int Xratio, int Yratio) ****************************************************************************/ static void get_ratios(int *x_ratio, int *y_ratio) { - if (current_topo_has_flag(TF_WRAPX)) { - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_X)) { + if (current_wrap_has_flag(WRAP_Y)) { /* Ratios for torus map. */ *x_ratio = 1; *y_ratio = 1; @@ -297,7 +297,7 @@ static void get_ratios(int *x_ratio, int *y_ratio) *y_ratio = 2; } } else { - if (current_topo_has_flag(TF_WRAPY)) { + if (current_wrap_has_flag(WRAP_Y)) { /* Ratios for uranus map. */ *x_ratio = 2; *y_ratio = 3; @@ -399,7 +399,7 @@ void generator_init_topology(bool autosize) /* correction for single pole (Flat Earth) */ if (wld.map.server.single_pole) { - if (!current_topo_has_flag(TF_WRAPY) || !current_topo_has_flag(TF_WRAPX)) { + if (!current_wrap_has_flag(WRAP_Y) || !current_wrap_has_flag(WRAP_X)) { ice_base_colatitude /= 2; } } diff --git a/server/maphand.c b/server/maphand.c index d883838276..579e6710ad 100644 --- a/server/maphand.c +++ b/server/maphand.c @@ -633,6 +633,7 @@ void send_map_info(struct conn_list *dest) minfo.xsize = wld.map.xsize; minfo.ysize = wld.map.ysize; minfo.topology_id = wld.map.topology_id; + minfo.wrap_id = wld.map.wrap_id; lsend_packet_map_info(dest, &minfo); } diff --git a/server/settings.c b/server/settings.c index b0a0f290a6..316e0080e8 100644 --- a/server/settings.c +++ b/server/settings.c @@ -251,11 +251,23 @@ static const struct sset_val_name *mapsize_name(int mapsize) static const struct sset_val_name *topology_name(int topology_bit) { switch (1 << topology_bit) { - NAME_CASE(TF_WRAPX, "WRAPX", N_("Wrap East-West")); - NAME_CASE(TF_WRAPY, "WRAPY", N_("Wrap North-South")); NAME_CASE(TF_ISO, "ISO", N_("Isometric")); NAME_CASE(TF_HEX, "HEX", N_("Hexagonal")); } + + return NULL; +} + +/************************************************************************//** + Map wrap setting names accessor. +****************************************************************************/ +static const struct sset_val_name *wrap_name(int wrap_bit) +{ + switch (1 << wrap_bit) { + NAME_CASE(WRAP_X, "WRAPX", N_("Wrap East-West")); + NAME_CASE(WRAP_Y, "WRAPY", N_("Wrap North-South")); + } + return NULL; } @@ -780,6 +792,22 @@ static void topology_action(const struct setting *pset) struct packet_set_topology packet; packet.topology_id = *pset->integer.pvalue; + packet.wrap_id = wld.map.wrap_id; + + conn_list_iterate(game.est_connections, pconn) { + send_packet_set_topology(pconn, &packet); + } conn_list_iterate_end; +} + +/************************************************************************//** + Map wrap setting changed. +****************************************************************************/ +static void wrap_action(const struct setting *pset) +{ + struct packet_set_topology packet; + + packet.topology_id = wld.map.topology_id; + packet.wrap_id = *pset->integer.pvalue; conn_list_iterate(game.est_connections, pconn) { send_packet_set_topology(pconn, &packet); @@ -1256,11 +1284,11 @@ static bool topology_callback(unsigned value, struct connection *caller, #ifdef FREECIV_WEB /* Remember to update the help text too if Freeciv-web gets the ability * to display other map topologies. */ - if ((value & (TF_WRAPY)) != 0 - /* Are you removing this because Freeciv-web gained the ability to - * display isometric maps? Why don't you remove the Freeciv-web - * specific MAP_DEFAULT_TOPO too? */ - || (value & (TF_ISO)) != 0 + + /* Are you removing this because Freeciv-web gained the ability to + * display isometric maps? Why don't you remove the Freeciv-web + * specific MAP_DEFAULT_TOPO too? */ + if ((value & (TF_ISO)) != 0 || (value & (TF_HEX)) != 0) { /* The Freeciv-web client can't display these topologies yet. */ settings_snprintf(reject_msg, reject_msg_len, @@ -1272,6 +1300,26 @@ static bool topology_callback(unsigned value, struct connection *caller, return TRUE; } +/************************************************************************//** + Map wrap setting validation callback. +****************************************************************************/ +static bool wrap_callback(unsigned value, struct connection *caller, + char *reject_msg, size_t reject_msg_len) +{ +#ifdef FREECIV_WEB + /* Remember to update the help text too if Freeciv-web gets the ability + * to display other map wraps. */ + if ((value & (WRAP_Y)) != 0) { + /* The Freeciv-web client can't display wraps mapped this way. */ + settings_snprintf(reject_msg, reject_msg_len, + _("Freeciv-web doesn't support this map wrap.")); + return FALSE; + } +#endif /* FREECIV_WEB */ + + return TRUE; +} + /************************************************************************//** Validate that the player color mode can be used. ****************************************************************************/ @@ -1435,14 +1483,11 @@ static struct setting settings[] = { N_("Map topology"), #ifdef FREECIV_WEB /* TRANS: Freeciv-web version of the help text. */ - N_("Freeciv-web maps are always two-dimensional. They may wrap " - "at the east-west directions to form a flat map or a " - "cylinder.\n"), + N_("Freeciv-web maps are always two-dimensional.\n"), #else /* FREECIV_WEB */ /* TRANS: do not edit the ugly ASCII art */ - N_("Freeciv maps are always two-dimensional. They may wrap at " - "the north-south and east-west directions to form a flat " - "map, a cylinder, or a torus (donut). Individual tiles may " + N_("Freeciv maps are always two-dimensional. " + "Individual tiles may " "be rectangular or hexagonal, with either an overhead " "(\"classic\") or isometric alignment.\n" "To play with a particular topology, clients will need a " @@ -1464,6 +1509,22 @@ static struct setting settings[] = { #endif /* FREECIV_WEB */ topology_callback, topology_action, topology_name, MAP_DEFAULT_TOPO) + GEN_BITWISE("wrap", wld.map.wrap_id, SSET_MAP_SIZE, + SSET_GEOLOGY, SSET_VITAL, ALLOW_NONE, ALLOW_BASIC, + N_("Map wrap"), +#ifdef FREECIV_WEB + /* TRANS: Freeciv-web version of the help text. */ + N_("Freeciv-web maps may wrap " + "at the east-west directions to form a flat map or a " + "cylinder.\n"), +#else /* FREECIV_WEB */ + /* TRANS: do not edit the ugly ASCII art */ + N_("Freeciv maps may wrap at " + "the north-south and east-west directions to form a flat " + "map, a cylinder, or a torus (donut)."), +#endif /* FREECIV_WEB */ + wrap_callback, wrap_action, wrap_name, MAP_DEFAULT_WRAP) + GEN_ENUM("generator", wld.map.server.generator, SSET_MAP_GEN, SSET_GEOLOGY, SSET_VITAL, ALLOW_NONE, ALLOW_BASIC, N_("Method used to generate map"),