Update copyright notice Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Tidy up comments Don't use ALL CAPS for headings. Reformat them in the style recommended by doc/coding. Drop a few comments that aren't pulling their weight, and fix the odd typo. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Rename fl_move() to drift_capital() Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Move qprint() and NUMTRIES qprint() was carelessly added at the end of the file in Empire 2, where it's under the "Write a script for placing capitals" headline. Move it to a more sensible place. NUMTRIES was added behind the global variables in Empire 2. Move it before them, and reformat its comment. The order of forward declarations of static functions looks random. Reorder them to match the order of definitions. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Fuse capx[], capy[] into cap[] Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Fuse sectx[], secty[] into sect[] Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Simplify how write_sect() iterates over sectors Iterating over IDs is slightly simpler than iterating over coordinates, so do that. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Represent sector ownership more efficiently Replace own[x][y] by own[XYOFFSET(x, y)], and narrow the element type from int to short. Takes a fourth the space. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Tweak rural iron, fert, oil for simplicity The previous commit's interpolation tables reproduce the historical linear functions faithfully. This exact fit requires an awkward data point in each of the tables for iron fertility and oil. Drop them. No double-valued data points remain. Adjust struct resource_point member @res to int. This results in slightly less rural iron (33 elevations down one point), fertility (10 elevations down one point) and oil (14 elevations down one point, 5 down two points). Only resource values less than 100 are affected. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Compute resources by interpolating tables The functions mapping elevation to resources are piecewise linear. Replace them by linear interpolation on data points defined in tables. Tables are easier to tweak for deities than code. The data points are a bit awkward because the functions they replace are. The next commit will tweak them to address that. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Tweak sea oil & mountain gold for simplicity The functions mapping elevation to resources are piecewise linear, except for set_oil(), which randomly adds 1 to sea oil, and set_gold(), which is isn't linear for mountains, but very close. Drop the random oil bit, and replace the non-liner gold function by a linear one. Both resources decrease at most by one point. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Rewrite complicated, buggy & boring elevation code Land elevation is computed by first placing mountains, then elevating land to fit. Mountains placement is a weighted random sampling. A sector's weight is its distance to sea capped at five and squared. Non-mountain, non-capital sectors get assigned equidistant elevations from 1 up to 97 rounded to integer in an order that depends on distance to mountain and distance to sea, both capped at 5. Mountains get equidistant elevations starting at 98 (see recent commit "fairland: Fair mountain resources"). Capitals get 36. Sea elevation is randomly chosen from a range that depends on the sector's distance to land. The range increases from [-27,-1] next to land to [-127,-1] for distance 5 and up. Without mountains, the result is boring: elevation increases pretty much linearly with the distance from the coast, i.e. each islands is a single cone. With mountains, we get one cone per mountain. The sea sea elevations are basically noise. Worse, it's buggy: mountain placement can place fewer mountains than requested. The weighted random sampling assigns weights even to sectors that cannot be picked (capitals and sectors that have been picked already). When the dice land on such a sector, it instead picks the next one (in island growth order) that can be picked. If there is no next one, the mountain is not placed. This is a fairness issue. Impact varies with fairland parameters. For 60 sector islands with 5% mountains, around one in 10000 islands is short one mountain in my testing. For 10 sector islands with 50% mountains, some 760 out of 10000 islands are short one sector, 80 short two, and five short three. The numbers get worse as spikiness increases. Undocumented misfeature: the placement loop is limited to 1000 iterations, supposedly to catch a runaway loop. Since the loop iterates exactly once per mountain, all this accomplishes it limiting mountains to 1000 per island. When too few mountains are placed, the loop assigning elevations to non-mountain, non-capital decrements elevations below 1. Since Chainsaw 3, such elevations then get mapped to 1, plastering over the bug. We get non-mountain sectors with elevation 1 instead of mountains. Rewrite as follows. Use a simple random hill algorithm to assign raw elevations: initialize elevation to zero, then randomly raise circular hills on land / lower circular depressions at sea. Their size and height depends on the distance to the coast, capped at 3. After a sufficient number of iterations, the resulting terrain has a "natural" look. This is elevate_prep(). elevate_land() then sorts non-capital sectors by raw elevation. The highest become mountains. Sectors get assigned the same equidistant elevations as before, just in raw elevation order. elevate_sea() simply normalizes raw elevation to [-127,-1]. Elevations now show a nice undulating pattern independent of mountain percentage. Implementation detail: replace elev[x][y] by elev[XYOFFSET(x, y)], and narrow the element type from int to short. Takes a fourth the space. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Tweak rural elevations for simplicity elevate_land() computes the sequence of elevations 97, 97 - delta, ... in fixed point with a scaling factor of 100. Switch to floating-point, because it's simpler. Elevations (and thus resources) change slightly due to reduced rounding errors. Note that we map elevations less than 1 to 1 both before and after the patch. Odd. Turns out this mitigates a bug: mountain placement can place fewer mountains than it should, and when that happens, elevations go below 1 here. The next commit will fix this. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Drop unused elevation band for coastal mountains Elevations 34 and 35 are reserved for coastal mountains. When an elevation computed for a non-mountain falls in that band, it's adjusted to 36. This is unnecessary since the previous commit; drop. Test output shows the dropped elevation adjustment. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Fair mountain resources For fairness, fairland aims to make islands of the same size consist of the exact same sectors, just individually arranged. It fails to achieve its aim for mountains: their elevation is random, 34 or 35 for coastal mountains, and between 98 and 254 (two dice) for non-coastal ones. Elevation determines resources. Mountains get 89 gold on average (between 80 and 93), except for coastal mountains, which get none. It didn't really matter until Empire 3 made mountains produce gold dust. Since then, it's unfair. Set mountain elevation to 98 + i * delta, where i is the mountain number (starting at zero), delta is (127 - 98) / max_mn, and max_mn is the maximum number of mountains an island could have. This puts the highest mountains on the largest islands. Non-coastal mountains have slightly less gold than before, coastal mountains have much more. Mountains can still be unfair, because fairland can screw up their number. To be fixed soon. Avoid elevations 34 and 35 for non-mountain, non-capital sectors doesn't make sense anymore. The next commit will get rid of it. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Use zero elevation for "not yet elevated" Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Eliminate sectc[][], use adj_land[] instead Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Replace distance_to_land(), distance_to_sea() distance_to_land() searches for closest land sector, and distance_to_sea() for the closest sea sector. We already have a more efficient alternative: the breadth-first search recently added for spheres of influence can precompute these distances. Put it to use, and retire distance_to_land() and distance_to_sea(). distance_to_what() could now be simplified. Don't bother, because it'll soon be deleted entirely. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Eliminate macro ELEV, it's an abomination Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
fairland: Prefer placing islands away from the edge of the sphere When an island gets placed too close to the edge of the sphere of influence, its side facing the edge will likely be formed by the edge. Looks unnatural, and can give a clue on the location of the other continent. Make place_island() prefer sectors away from the edge: instead of picking one of the admissible sectors with equal probability, reduce the probability as we get closer to the edge. Signed-off-by: Markus Armbruster <armbru@pond.sub.org>