Complete.Org: Mailing Lists: Archives: freeciv-dev: July 2004:
[Freeciv-Dev] (PR#9328) improvements to set_ratio
Home

[Freeciv-Dev] (PR#9328) improvements to set_ratio

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: undisclosed-recipients: ;
Subject: [Freeciv-Dev] (PR#9328) improvements to set_ratio
From: "Jason Short" <jdorje@xxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 10 Jul 2004 01:39:01 -0700
Reply-to: rt@xxxxxxxxxxx

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

There are two problems with set_ratio:

- It enforces even sizes (xsize/ysize).  This is unnecessary for current 
topologies, and it's easy to avoid it by adding a new internal variable 
"factor".

- It has big rounding errors.  For instance if you set size==1 with 
topology==1 you get a 32x20 = 640-tile map.  This is quite bad since we 
should obviously have a 40x25 map.  This is fixed by making isize a 
float (actually a double just like base_size), and making sure we round 
it back to an integer at the right time later on.

I also made some other cleanups:

- There's some ugly code to fix cases where the size is too big or too 
small.  This isn't needed since it never happens...I replaced it with 
some assertions.  In fact if it ever does happen we should either 
increase the linear size range or decrease the range of possible sizes. 
  Changing the size after the user has set it is not a good user 
interface.  (I think with size==30 we would run into this problem.  As 
it is we are right on the border with some topologies.)

- Improved the logging.

Also attached is a table of the final sizes created by this algorithm. 
It's pretty good; both size and ratio are quite accurate.

jason

Index: common/map.c
===================================================================
RCS file: /home/freeciv/CVS/freeciv/common/map.c,v
retrieving revision 1.176
diff -u -r1.176 map.c
--- common/map.c        9 Jul 2004 19:30:58 -0000       1.176
+++ common/map.c        10 Jul 2004 08:34:38 -0000
@@ -218,65 +218,51 @@
 /****************************************************************************
   Set the map xsize and ysize based on a base size and ratio (in natural
   coordinates).
-
-  xsize and ysize are even numbers.  For iso-maps ysize%4 == 0.  This avoids
-  problems in current and future topologies.
 ****************************************************************************/
-static void set_ratio(double base_size, int Xratio, int Yratio)
+static void set_ratio(int size, int Xratio, int Yratio)
 {
+  const int factor = 1; /* Future topologies may require even dimensions. */
+
   /* In TF_ISO we need to double the map.ysize factor, since xsize is
    * in native coordinates which are compressed 2x in the X direction. */ 
   const int iso = topo_has_flag(TF_ISO) ? 2 : 1;
 
   /* We have:
    *
-   *   size = xsize * ysize
+   *   1000 * size = xsize * ysize
    *
    * And to satisfy the ratios and other constraints we set
    *
-   *   xsize = 2 * isize * xratio
-   *   ysize = 2 * isize * yratio * iso
+   *   xsize = factor * isize * xratio
+   *   ysize = factor * isize * yratio * iso
    *
-   * For any value of "isize".  The factor of 2 is to ensure even dimensions
+   * For any value of "isize".  The "factor" is to ensure even dimensions
    * (which are important for some topologies).  So with some substitution
    *
-   *   size = 4 * isize * xratio * isize * yratio * iso
-   *   isize = sqrt(size / (4 * xratio * yratio * iso))
-   *
-   * Remember that size = base_size * 1000.  So this gives us
-   *
-   *   isize = sqrt(base_size * 250 / (xratio * yratio * iso))
+   *   1000 * size = factor * factor * isize * xratio * isize * yratio * iso
+   *   isize = sqrt(1000 * size / (factor * factor * xratio * yratio * iso))
    */
-  int i_size = sqrt(250.0 * base_size / (Xratio * Yratio * iso)) + 0.49;
-
-  /* Make sure the linear size is large enough. */
-  while (MIN(Xratio, iso * Yratio) * 2 * i_size < MAP_MIN_LINEAR_SIZE) {
-    i_size++;
-  }
-
-  /* Now build xsize and ysize value as described above.  This gives and
-   * even xsize and ysize.  For iso maps ysize % 4 == 0. */
-  map.xsize =       2 * Xratio * i_size;
-  map.ysize = iso * 2 * Yratio * i_size;
-
-  /* Now make sure the linear size isn't too large.  If it is, the best thing
-   * we can do is decrease the base_size and try again. */
-  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 + 0.9) {
-    /* Warning when size is set uselessly big */ 
-    freelog(LOG_NORMAL,
-           _("Requested size of %d is too big for this topology."),
-           map.size);
-  }
-  freelog(LOG_VERBOSE, "Creating a map of size of %2.1fk tiles.", base_size);
-  freelog(LOG_VERBOSE, "xsize and ysize are set to %d and %d.",
-         map.xsize, map.ysize);
+  const float i_size
+    = sqrt((float)(1000 * size)
+          / (float)(Xratio * Yratio * iso * factor * factor));
+
+  /* Now build xsize and ysize value as described above.  Make sure to
+   * round off _before_ multiplying by factor and iso so that we can end up
+   * with even values if needed. */
+  map.xsize = (int)(Xratio * i_size + 0.5) * factor;
+  map.ysize = (int)(Yratio * i_size + 0.5) * factor * iso;
+
+  /* The size and ratio must satisfy the minimum and maximum *linear*
+   * restrictions on width.  If not then either these restrictions should
+   * be lifted or the size should be more limited. */
+  assert(MAP_WIDTH >= MAP_MIN_LINEAR_SIZE);
+  assert(MAP_HEIGHT >= MAP_MIN_LINEAR_SIZE);
+  assert(MAP_WIDTH <= MAP_MAX_LINEAR_SIZE);
+  assert(MAP_HEIGHT <= MAP_MAX_LINEAR_SIZE);
+
+  freelog(LOG_VERBOSE,
+         "Creating a map of size %d x %d = %d tiles (%d requested).",
+         map.xsize, map.ysize, map.xsize * map.ysize, size * 1000);
 }
 
 /*
This diagram shows the X and Y sizes created for maps.  Topologies go from 0-7,
sizes from 1-29.

    |     0   |     1   |     2   |     3   |     4   |     5   |     6   |     
7
 1  |  32x 32 |  40x 25 |  25x 40 |  32x 32 |  22x 44 |  28x 36 |  18x 56 |  
22x 44
 2  |  45x 45 |  57x 35 |  35x 57 |  45x 45 |  32x 64 |  40x 50 |  25x 80 |  
32x 64
 3  |  55x 55 |  69x 43 |  43x 69 |  55x 55 |  39x 78 |  49x 62 |  31x 98 |  
39x 78
 4  |  63x 63 |  80x 50 |  50x 80 |  63x 63 |  45x 90 |  57x 70 |  35x114 |  
45x 90
 5  |  71x 71 |  89x 56 |  56x 89 |  71x 71 |  50x100 |  63x 80 |  40x126 |  
50x100
 6  |  77x 77 |  98x 61 |  61x 98 |  77x 77 |  55x110 |  69x 86 |  43x138 |  
55x110
 7  |  84x 84 | 106x 66 |  66x106 |  84x 84 |  59x118 |  75x 94 |  47x150 |  
59x118
 8  |  89x 89 | 113x 71 |  71x113 |  89x 89 |  63x126 |  80x100 |  50x160 |  
63x126
 9  |  95x 95 | 120x 75 |  75x120 |  95x 95 |  67x134 |  85x106 |  53x170 |  
67x134
10  | 100x100 | 126x 79 |  79x126 | 100x100 |  71x142 |  89x112 |  56x178 |  
71x142
11  | 105x105 | 133x 83 |  83x133 | 105x105 |  74x148 |  94x118 |  59x188 |  
74x148
12  | 110x110 | 139x 87 |  87x139 | 110x110 |  77x154 |  98x122 |  61x196 |  
77x154
13  | 114x114 | 144x 90 |  90x144 | 114x114 |  81x162 | 102x128 |  64x204 |  
81x162
14  | 118x118 | 150x 94 |  94x150 | 118x118 |  84x168 | 106x132 |  66x212 |  
84x168
15  | 122x122 | 155x 97 |  97x155 | 122x122 |  87x174 | 110x136 |  68x220 |  
87x174
16  | 126x126 | 160x100 | 100x160 | 126x126 |  89x178 | 113x142 |  71x226 |  
89x178
17  | 130x130 | 165x103 | 103x165 | 130x130 |  92x184 | 117x146 |  73x234 |  
92x184
18  | 134x134 | 170x106 | 106x170 | 134x134 |  95x190 | 120x150 |  75x240 |  
95x190
19  | 138x138 | 174x109 | 109x174 | 138x138 |  97x194 | 123x154 |  77x246 |  
97x194
20  | 141x141 | 179x112 | 112x179 | 141x141 | 100x200 | 126x158 |  79x252 | 
100x200
21  | 145x145 | 183x115 | 115x183 | 145x145 | 102x204 | 130x162 |  81x260 | 
102x204
22  | 148x148 | 188x117 | 117x188 | 148x148 | 105x210 | 133x166 |  83x266 | 
105x210
23  | 152x152 | 192x120 | 120x192 | 152x152 | 107x214 | 136x170 |  85x272 | 
107x214
24  | 155x155 | 196x122 | 122x196 | 155x155 | 110x220 | 139x174 |  87x278 | 
110x220
25  | 158x158 | 200x125 | 125x200 | 158x158 | 112x224 | 141x176 |  88x282 | 
112x224
26  | 161x161 | 204x127 | 127x204 | 161x161 | 114x228 | 144x180 |  90x288 | 
114x228
27  | 164x164 | 208x130 | 130x208 | 164x164 | 116x232 | 147x184 |  92x294 | 
116x232
28  | 167x167 | 212x132 | 132x212 | 167x167 | 118x236 | 150x188 |  94x300 | 
118x236
29  | 170x170 | 215x135 | 135x215 | 170x170 | 120x240 | 152x190 |  95x304 | 
120x240

[Prev in Thread] Current Thread [Next in Thread]
  • [Freeciv-Dev] (PR#9328) improvements to set_ratio, Jason Short <=