[Freeciv-Dev] Re: Using tax rates
[Top] [All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
Date: Tue, 14 Dec 1999 10:32:14 -0500
From: Jeff Mallatt <jjm@xxxxxxxxxxxx>
At 1999/12/13 10:17 , you wrote:
>I've been working on extending Xconq to handle Civ-type games, and
>have some good luck building on work by Hans Ronne from a while ago.
>One of things I've had to do was work out the trade -> tax/lux/science
>conversion, the problem being how to "fairly" divide up small amounts
>by percentage. My first attempt at this didn't work very well, so I
>cheated :-) and looked at freeciv sources, and found a really
>interesting algorithm in cityturn.c:set_tax_income. It seems to work,
>but there is no explanation of how/why, and I must confess that it has
>me stumped.
>
>Is there some kind soul out there who understands freeciv's trade
>conversion algorithm and can explain it? Thanks!
I'll try...
Below is a slightly modified and commented version.
Thanks for the info, although I was actually looking for more of a
"why" than a walkthrough of the algorithm. In particular, one can
usually do a subdivision without any iteration at all, just by doing
simple division and handling the remainders intelligently. The
iteration could get expensive, if for instance you wanted to do a
CivCTP game with its larger production values. Peter Schaefer
mentioned privately that the algorithm is a Bresenham algorithm, which
is an interesting way to look at it. It does make me wonder if it's
really necessary, because Bresenham is useful when you want
intermediate values (for instance, the points on a line), but in this
case the intermediate values are effectively discarded.
On the other hand, things aren't broke, so this is not a call to
fix anything... :-)
Stan
The algorithm of interest is the while loop. We want two things: 1. the
sum of the three tax/sci/lux totals to equal the available trade
production; 2. the allocations to the tax/sci/lux totals to be in the same
ratio as their "percentages", as set by the player.
The first is accomplished simply by decrementing trade_to_dist once for
each increment of any tax/sci/lux total, and stopping when there is nothing
more to distribute. (The while loop just keeps going until there is no
more trade to be distributed (trade_to_dist == 0). The three if's at the
end of the loop also check to make sure that there is remaining trade to
distribute, before doing so.)
The second is done by using the three tax/sci/lux accumulators. Each time
through the loop, each accumulator is incremented by its "percentage", as
set by the player. Whenever an accumulator gets to or beyond 100%, a point
is added to the corresponding total, and the amount of trade to be
distributed is decremented. (Note that any number (from zero through all
three) of the totals may be incremented in a single pass through the while
loop.) Also, when an accumulator reaches 100%, we subtract 100 from it to
"reset" it (subtracting 100, rather than setting it to 0, retains any
remainder above 100).
I put some printf's in the code to generate the following. The first
column is the trade to distribute, the next three are the accumulators and
the last three are the totals.
Tax=40% Sci=50% Lux=10%
---------------------------------------
TTD=12 Ta=0 Sa=0 La=0 Tt=0 St=0 Lt=0
TTD=12 Ta=40 Sa=50 La=10 Tt=0 St=0 Lt=0
TTD=11 Ta=80 Sa=0 La=20 Tt=0 St=1 Lt=0
TTD=10 Ta=20 Sa=50 La=30 Tt=1 St=1 Lt=0
TTD=9 Ta=60 Sa=0 La=40 Tt=1 St=2 Lt=0
TTD=8 Ta=0 Sa=50 La=50 Tt=2 St=2 Lt=0
TTD=7 Ta=40 Sa=0 La=60 Tt=2 St=3 Lt=0
TTD=7 Ta=80 Sa=50 La=70 Tt=2 St=3 Lt=0
TTD=5 Ta=20 Sa=0 La=80 Tt=3 St=4 Lt=0
TTD=5 Ta=60 Sa=50 La=90 Tt=3 St=4 Lt=0
TTD=2 Ta=0 Sa=0 La=0 Tt=4 St=5 Lt=1
TTD=2 Ta=40 Sa=50 La=10 Tt=4 St=5 Lt=1
TTD=1 Ta=80 Sa=0 La=20 Tt=4 St=6 Lt=1
TTD=0 Ta=20 Sa=50 La=30 Tt=5 St=6 Lt=1
Well, I hope this makes things more clear (or, at least not *less* clear :).
static void set_tax_income(struct city *pcity)
{
int sci, tax, lux;
int trade_to_dist;
/* init totals to zero */
pcity->science_total = 0;
pcity->luxury_total = 0;
pcity->tax_total = 0;
/* set accumulators to zero */
sci = tax = lux = 0;
/* loop, distributing available trade production until no more... */
trade_to_dist = pcity->trade_prod;
while (trade_to_dist) {
/* add to each accumulator its percentage (if anarchy, only lux) */
if( get_gov_pcity(pcity)->index != game.government_when_anarchy ) {
tax += (100 -
game.players[pcity->owner].economic.science -
game.players[pcity->owner].economic.luxury);
sci += game.players[pcity->owner].economic.science;
lux += game.players[pcity->owner].economic.luxury;
} else {/* ANARCHY */
lux+= 100;
}
/* for each accumulator: if it has reached 100%, reset the
accumulator (by '-= 100', because it may be greater than 100),
add one to the corresponding total, and subtract one from the
available trade production. */
if (tax >= 100 && trade_to_dist) {
tax -= 100;
pcity->tax_total++;
trade_to_dist--;
}
if (sci >= 100 && trade_to_dist) {
sci -= 100;
pcity->science_total++;
trade_to_dist--;
}
if (lux >= 100 && trade_to_dist) {
lux -= 100;
pcity->luxury_total++;
trade_to_dist--;
}
}
/* add the effects of specialists */
pcity->luxury_total+=(pcity->ppl_elvis*2);
pcity->science_total+=(pcity->ppl_scientist*3);
pcity->tax_total+=(pcity->ppl_taxman*3);
}
jjm
|
|