Complete.Org: Mailing Lists: Archives: freeciv-dev: May 2004:
[Freeciv-Dev] Re: (PR#8632) Easy way to set map size with auto ratios (s
Home

[Freeciv-Dev] Re: (PR#8632) Easy way to set map size with auto ratios (s

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: mburda@xxxxxxxxx
Subject: [Freeciv-Dev] Re: (PR#8632) Easy way to set map size with auto ratios (seteables if desired)
From: "rwetmore@xxxxxxxxxxxx" <rwetmore@xxxxxxxxxxxx>
Date: Mon, 31 May 2004 05:53:11 -0700
Reply-to: rt@xxxxxxxxxxx

<URL: http://rt.freeciv.org/Ticket/Display.html?id=8632 >


The ratio form is still an unnecessarily complex and unneeded way to handle 
things and should be dropped from the patch. It should never be exposed to
the advanced end user that accesses the lowest level parameters, let along 
the naive end user that should work through a simple interface layer that 
consolidates coordinated options into common scenarios.

The issues with this have not been addressed and it has not received 
sufficient discussion or sanction to be included in CVS.

Incidentally, maps with singularities are also not yet at a stage for 
inclusion in CVS. The associated playability and other robustness problems 
resulting from duplicate tiles need to be dealt with first. Duplicate tiles 
in user visible displays are strictly forbidden - a standards rule that 
still stands and has not been done away with (nor should it be in a casual 
manner without strong considerations).

Cheers,
RossW
=====

Marcelo Burda wrote:

> <URL: http://rt.freeciv.org/Ticket/Display.html?id=8632 >
> 
> Le jeu 27/05/2004 à 07:28, Jason Short a écrit :
> 
>><URL: http://rt.freeciv.org/Ticket/Display.html?id=8632 >
>>
>>Your mcd (maximum common denominator?) function isn't good.
>>
>>- I've always seen it called gcf, greatest common factor. 
>>http://www.math.com/school/subject1/lessons/S1U3L2GL.html.  But gcd
>>would also be okay.
>>
>>- According to Euclid's Algorithm (Euclidean algorithm):
>>
>>gcf(a, b) = gfc(b, a-b)
>>gcf(a, 0) = a.
>>
>>which gives:
>>
>>int gcf(int a, int b)
>>{
>>  int min = MIN(a, b), max = MAX(a, b);
>>
>>  if (min == 0) return max;
>>  return gcf(min, max - min);
>>}
>>
> 
> done
> 
>>Also...
>>
>>INIT_TOPOLOGY_CASE shouldn't be a macro.  In fact you don't need a
>>switch statement here at all.  Make the list of default values an array
>>and just give something like
>>
> 
> done too, but this choice as a side effet if we change enum topo_flag, i
> was avoided it with a no side effet cast. but code are more clear with a
> array and i ave comment the side effet then there is no problem
> 
>>  if (map.ratio == 100) {
>>    set_ratio(default_ratio[map.topology_id]);
>>  } else {
>>    set_ratio(map.ratio);
>>  }
>>
>>Which brings me to my next point that auto_ratio and user_ratio should
>>be merged.
>>
>>I haven't delved too deep into set_mapratio yet though.
>>
>>jason
> 
> other changes 
> -fixed MAP_HEIGHT, there are right now?
> -i am a litle change LOG message, now we send a warning message when
> size was to big.
> 
> 
> ------------------------------------------------------------------------
> 
> diff -ruN -Xfreeciv/diff_ignore freeciv/client/packhand.c 
> freeciv_/client/packhand.c
> --- freeciv/client/packhand.c 2004-05-23 15:20:35.000000000 +0200
> +++ freeciv_/client/packhand.c        2004-05-27 12:58:35.000000000 +0200
> @@ -1305,9 +1305,13 @@
>  ****************************************************************************/
>  void handle_map_info(int xsize, int ysize, int topology_id)
>  {
> +  map.size = 0; /* use server sended sizes */
> +  map.ratio = 100;
> +  map.topology_id = topology_id;
> +  map_init_topology();
> +
>    map.xsize = xsize;
>    map.ysize = ysize;
> -  map.topology_id = topology_id;
>  
>    map_allocate();
>    init_client_goto();
> diff -ruN -Xfreeciv/diff_ignore freeciv/common/map.c freeciv_/common/map.c
> --- freeciv/common/map.c      2004-05-27 12:55:38.000000000 +0200
> +++ freeciv_/common/map.c     2004-05-27 18:18:31.000000000 +0200
> @@ -176,9 +176,18 @@
>  ***************************************************************/
>  void map_init(void)
>  {
> -  map.topology_id = MAP_DEFAULT_TOPO;
> -  map.xsize                 = MAP_DEFAULT_WIDTH;
> -  map.ysize                 = MAP_DEFAULT_HEIGHT;
> +  map.topology_id           = MAP_DEFAULT_TOPO;
> +  map.size                  = MAP_DEFAULT_SIZE;
> +  map.ratio                 = MAP_DEFAULT_RATIO;
> +  /*
> +    begin comment
> +    To be set by map_init_topology(), begin with 0 teorical is ok but
> +    I set it to some not zero value to fix a bug where
> +    client execute advance_unit_focus befor server send sizes of the map!
> +  */
> +  map.xsize                 = MAP_MIN_LINEAR_SIZE;  
> +  map.ysize                 = MAP_MIN_LINEAR_SIZE;
> +  /*end comment                                               [mburda]*/
>    map.seed                  = MAP_DEFAULT_SEED;
>    map.riches                = MAP_DEFAULT_RICHES;
>    map.huts                  = MAP_DEFAULT_HUTS;
> @@ -200,6 +209,109 @@
>    map.have_huts             = FALSE;
>  }
>  
> +/* ***************************************************************
> +   return the maximum common denominator or greatest common factor
> +   *************************************************************** */
> +static int gcf(int a, int b) {
> +  int min = MIN(a, b), max = MAX(a, b);
> +
> +  if (min == 0) return max;
> +  return gcf(min, max - min);
> +}
> +
> +/*
> + * This is the core of calculate size of the maps 
> + * final value are calculate to get defined ratios size in natural
> + * coordinated
> + * xsize and ysize are even numbers
> + * if iso-map ysize%4 == 0 to avoid any type of problems in
> + * extended topologies and iso-maps
> + */   
> +static void set_ratio(double base_size, int Xratio, int Yratio)
> +{
> +  int i_size, iso, mcd = gcf(Xratio, Yratio);
> +  /* if map.xsize and map.ysize are set from server  do nothing*/
> +  if (base_size == 0) 
> +    return;
> +  /*
> +   * Simplify the common divisor in ratios 
> +   * ratios as 9:9 8:8 7:7 are converted to 1:1
> +   */
> +  Xratio /= mcd;
> +  Yratio /= mcd;
> +  /*
> +   Correct exesives ratios
> +  */
> +  if( Xratio / Yratio >= 3) {
> +    Xratio = 3;
> +    Yratio = 1;
> +    mcd = 0; /* != 1 force to correct map.ratio if this is not a auto ratio 
> */
> +  }
> +  if( Yratio / Xratio >= 3) {
> +    Xratio = 1;
> +    Yratio = 3 ;
> +    mcd = 0; /* != 1 force to correct map.ratio if this is not a auto ratio 
> */
> +  }
> +  /* set corrected ratio in map.ratio if these values are set by user */
> +  if( map.ratio != 100 && mcd != 1) {
> +    map.ratio = 10 * Xratio + Yratio;
> +    freelog(LOG_NORMAL,
> +       "map.c: The user defined ratios was corrected to %d \n", map.ratio);
> +  }
> +  /* in TF_ISO we need double map.ysize/map.ysize factor */ 
> +  iso = topo_has_flag(TF_ISO)? 2 : 1;
> +  /* Get a integer for the internal i_size var,
> +     this alow to make easly even numbers */
> +  i_size = floor(0.49 + sqrt(250.0 * base_size / (Xratio * Yratio * iso)));
> +  /* verify for map.xsize and map.ysize minimum value*/ 
> +  while (MIN(Xratio, iso * Yratio)* 2 * i_size < MAP_MIN_LINEAR_SIZE)
> +  { i_size++; };
> +  /* set map.[xy]size as even numbers (and ysize %4 == 0 for TF_ISO)*/
> +  map.xsize =       2 * Xratio * i_size;
> +  map.ysize = iso * 2 * Yratio * i_size;
> +  /* Verify up limit for map coordinates and correct it if needed */
> +  if (MAX(MAP_WIDTH,MAP_HEIGHT) - 1 > MAP_MAX_LINEAR_SIZE ) {
> +      /* make a more litle map if possible */
> +    assert(base_size > 0.1);
> +    set_ratio(base_size - 0.1, Xratio, Yratio);
> +    return;
> +  }
> +  if( map.size > base_size ) {
> +      freelog(LOG_NORMAL,
> +      "map.c: size of %d is too big using %f ",
> +       map.size, base_size - 0.1);
> +  }
> +  freelog(LOG_NORMAL,
> +      "map.c: map.xsize and map.ysize are seted to %d and %d ",
> +       map.xsize, map.ysize);
> +}
> +
> +/*************************************************************************** 
> + map_init_topology() need to be called after changes on
> + map.topology_id, map.size and map.ratio was donned.
> + this calculate map.xsize and map.ysize
> +
> + in client or when loading savegames map.size can be set to zero to
> + alow code to set direcly xsize and ysize 
> +                                                                [mburda]
> +*************************************************************************/
> +void map_init_topology( void)
> +{
> +  /* Comment: This is harded related to enum topo_flag */
> +  const int default_ratios[4] =
> +      { AUTO_RATIO_FLAT, AUTO_RATIO_CLASSIC,
> +     AUTO_RATIO_URANUS, AUTO_RATIO_TORUS};
> +  const int id = 0x3 & map.topology_id;
> +  /* End Comment */
> +
> + if (map.ratio == 100) {
> +    set_ratio(map.size, default_ratios[id] / 10, default_ratios[id] % 10);
> +  } else {
> +    set_ratio(map.size, map.ratio / 10, map.ratio % 10);
> +  }
> + 
> +}
> +
>  /***************************************************************
>  ...
>  ***************************************************************/
> diff -ruN -Xfreeciv/diff_ignore freeciv/common/map.h freeciv_/common/map.h
> --- freeciv/common/map.h      2004-05-27 12:55:38.000000000 +0200
> +++ freeciv_/common/map.h     2004-05-27 18:21:35.000000000 +0200
> @@ -117,6 +117,7 @@
>  
>  struct civ_map { 
>    int topology_id;
> +  int size, ratio; /* used to calculate [xy]size */
>    int xsize, ysize; /* native dimensions */
>    int seed;
>    int riches;
> @@ -147,8 +148,8 @@
>  
>  enum topo_flag {
>    /* Bit-values. */
> -  TF_WRAPX = 1,
> -  TF_WRAPY = 2,
> +  TF_WRAPX = 1, /* correct map_init_topology if changed */
> +  TF_WRAPY = 2, /* correct map_init_topology if changed */
>    TF_ISO = 4
>  };
>  
> @@ -156,6 +157,8 @@
>  
>  #define topo_has_flag(flag) ((CURRENT_TOPOLOGY & (flag)) != 0)
>  
> +void map_init_topology(void );
> +
>  bool map_is_empty(void);
>  void map_init(void);
>  void map_allocate(void);
> @@ -272,6 +275,14 @@
>  (    (dest_x) = DIR_DX[(dir)],       \
>       (dest_y) = DIR_DY[(dir)])
>  
> +#define MAP_WIDTH \
> +   (topo_has_flag(TF_ISO) \
> +    ? (map.xsize + map.ysize / 2) \
> +    : map.xsize)
> +#define MAP_HEIGHT \
> +   (topo_has_flag(TF_ISO) \
> +    ? (map.ysize + map.xsize / 2) \
> +    : map.ysize)
>  /*
>   * Returns true if the step yields a new valid map position. If yes
>   * (dest_x, dest_y) is set to the new map position.
> @@ -636,13 +647,47 @@
>  #define MAP_MIN_HUTS             0
>  #define MAP_MAX_HUTS             500
>  
> -#define MAP_DEFAULT_WIDTH        80
> -#define MAP_MIN_WIDTH            40
> -#define MAP_MAX_WIDTH            200
> -
> -#define MAP_DEFAULT_HEIGHT       50
> -#define MAP_MIN_HEIGHT           25
> -#define MAP_MAX_HEIGHT           100
> +/* size of the map in thusand of tiles */
> +#define MAP_DEFAULT_SIZE         4
> +#define MAP_MIN_SIZE             1
> +#define MAP_MAX_SIZE             26
> +
> +/*
> + * This define the max linear size in map or native coordinates
> + * this must be liter than 255, this value is reserved for net usage
> + */
> +#define MAP_MAX_LINEAR_SIZE      254
> +#define MAP_MIN_LINEAR_SIZE      8
> +
> +/*
> + * This value determine the x:y ration of the map in NATURAL coordinated
> + * This ratio need to be corrected for NATIVE coordinated in
> + * iso-map by a factor sqrt(2) as (x / sqrt(2)) : (y * sqrt (2))
> + * the spetial values 100 is the AUTO RATIO (this is the prefered value)
> + */
> +#define MAP_DEFAULT_RATIO         100
> +#define MAP_MIN_RATIO             11
> +#define MAP_MAX_RATIO             100
> +
> +/*
> + * The auto ratios for knowns topologies
> + * Best for litles map sizes if (but not needed)
> + * get RATIO factor = Xratio*Yratio as litle as posible  
> + * In biger map this is best if Xratio is biger than Yratio
> + * when using iso topologies. in iso Y coordinates are
> + * internaly expanded and X contracted. this convert the ratio
> + * to extreme ones and that limit the maximal size of the map
> + * get DEFAULT RATIO <= 2:1 or 1:2                              
> + */
> +#define AUTO_RATIO_FLAT           11
> +#define AUTO_RATIO_CLASSIC        85 
> +#define AUTO_RATIO_URANUS         58 
> +#define AUTO_RATIO_TORUS          11
> +
> +#define MAP_MIN_WIDTH            MAP_MIN_LINEAR_SIZE
> +#define MAP_MAX_WIDTH            MAP_MAX_LINEAR_SIZE
> +#define MAP_MIN_HEIGHT           MAP_MIN_LINEAR_SIZE
> +#define MAP_MAX_HEIGHT           MAP_MAX_LINEAR_SIZE
>  
>  #define MAP_ORIGINAL_TOPO        TF_WRAPX
>  #define MAP_DEFAULT_TOPO         TF_WRAPX
> diff -ruN -Xfreeciv/diff_ignore freeciv/server/mapgen.c 
> freeciv_/server/mapgen.c
> --- freeciv/server/mapgen.c   2004-05-21 10:54:02.000000000 +0200
> +++ freeciv_/server/mapgen.c  2004-05-27 12:58:35.000000000 +0200
> @@ -1288,7 +1288,7 @@
>  {
>    /* save the current random state: */
>    RANDOM_STATE rstate = get_myrand_state();
> - 
> +  
>    if (map.seed==0)
>      map.seed = (myrand(MAX_UINT32) ^ time(NULL)) & (MAX_UINT32 >> 1);
>  
> @@ -1303,7 +1303,8 @@
>  
>    /* don't generate tiles with mapgen==0 as we've loaded them from file */
>    /* also, don't delete (the handcrafted!) tiny islands in a scenario */
> -  if (map.generator != 0) {
> +  if (map.generator != 0) { 
> +    map_init_topology();/* initialize map.xsize and map.ysize, etc */
>      map_allocate();
>      adjust_terrain_param();
>      /* if one mapgenerator fails, it will choose another mapgenerator */
> diff -ruN -Xfreeciv/diff_ignore freeciv/server/savegame.c 
> freeciv_/server/savegame.c
> --- freeciv/server/savegame.c 2004-05-27 12:55:39.000000000 +0200
> +++ freeciv_/server/savegame.c        2004-05-27 12:58:35.000000000 +0200
> @@ -341,8 +341,11 @@
>  ***************************************************************/
>  static void map_tiles_load(struct section_file *file)
>  {
> +  map.size = 0; /* use xize/ysize from load */
> +  map.ratio= 100;
>    map.topology_id = secfile_lookup_int_default(file, MAP_ORIGINAL_TOPO,
>                                              "map.topology_id");
> +  map_init_topology(); /* this call never change [xy]size */
>  
>    /* In some cases we read these before, but not always, and
>     * its safe to read them again:
> diff -ruN -Xfreeciv/diff_ignore freeciv/server/stdinhand.c 
> freeciv_/server/stdinhand.c
> --- freeciv/server/stdinhand.c        2004-05-27 12:55:39.000000000 +0200
> +++ freeciv_/server/stdinhand.c       2004-05-27 12:58:36.000000000 +0200
> @@ -254,28 +254,42 @@
>    /* These should be grouped by sclass */
>    
>  /* Map size parameters: adjustable if we don't yet have a map */  
> -  GEN_INT("xsize", map.xsize, SSET_MAP_SIZE, SSET_GEOLOGY, SSET_TO_CLIENT,
> -       N_("Map width in squares"), "", NULL,
> -       MAP_MIN_WIDTH, MAP_MAX_WIDTH, MAP_DEFAULT_WIDTH)
> -    
> -  GEN_INT("ysize", map.ysize, SSET_MAP_SIZE, SSET_GEOLOGY, SSET_TO_CLIENT,
> -       N_("Map height in squares"), "", NULL,
> -       MAP_MIN_HEIGHT, MAP_MAX_HEIGHT, MAP_DEFAULT_HEIGHT)
> -
> +  GEN_INT("size", map.size, SSET_MAP_SIZE, SSET_GEOLOGY, SSET_TO_CLIENT,
> +          N_("Map size in 1,000 tiles units"),
> +          N_("This value is used to determine xsize and ysize\n"
> +             " size = 4 is a litle map of  4,000 tiles (default)\n"
> +             " size = 20 is a Huge map of 20,000 tiles \n"
> +          "The maximal size is limited by topology and ratio\n"
> +          "See the topologie help. the real size auto reised\n"
> +          "to these maximals"), NULL,
> +          MAP_MIN_SIZE,MAP_MAX_SIZE , MAP_DEFAULT_SIZE)
> +
> +   GEN_INT("ratio", map.ratio, SSET_MAP_SIZE, SSET_INTERNAL, SSET_TO_CLIENT,
> +          N_("Map ratio, keep it default value of 100 (auto)\n"),
> +          N_("This value is used to determine xsize and ysize \n"
> +          " 100 is the default ratio determined by the topology_id\n"
> +          "Otherwise first digit is the x factor \n"
> +          "and second digit the y factor of the x:y ratio \n"
> +             " 11 is 1:1 ratio, 85 is a 8:5 ratio. \n"
> +          "Extreme ratio (more than 3/1) are auto raised to these limit \n"
> +          "Change it at your own risk, bad ratios limit size of map!"
> +             ), NULL,
> +          MAP_MIN_RATIO, MAP_MAX_RATIO , MAP_DEFAULT_RATIO)
>    GEN_INT("topology", map.topology_id, SSET_MAP_SIZE, SSET_GEOLOGY, 
>            SSET_TO_CLIENT,
>         N_("The map topology index"),
>         N_("Two-dimensional maps can wrap at the north-south or \n"
>            "east-west edges, and use a cartesian or isometric \n"
>            "rectangular grid.  See the manual for further explanation.\n"
> -             "  0 Flat Earth (unwrapped)\n"
> -             "  1 Earth (wraps E-W)\n"
> -             "  2 Uranus (wraps N-S)\n"
> -             "  3 Donut World (wraps N-S, E-W)\n"
> -          "  4 Flat Earth (isometric)\n"
> -          "  5 Earth (isometric)\n"
> -          "  6 Uranus (isometric)\n"
> -          "  7 Donut World (isometric)"
> +             "  0 Flat Earth (unwrapped)      [64]\n"
> +             "  1 Earth (wraps E-W)           [40]\n"
> +             "  2 Uranus (wraps N-S)          [36]\n"
> +             "  3 Donut World (wraps N-S, E-W)[64]\n"
> +          "  4 Flat Earth (isometric)      [14]\n"
> +          "  5 Earth (isometric)           [26]\n"
> +          "  6 Uranus (isometric)          [11]\n"
> +          "  7 Donut World (isometric)     [14]\n"
> +          " [] the maximal size are calculated for auto ratio"
>            ), NULL, 
>         MAP_MIN_TOPO, MAP_MAX_TOPO, MAP_DEFAULT_TOPO)
>  




[Prev in Thread] Current Thread [Next in Thread]