Complete.Org: Mailing Lists: Archives: freeciv-dev: December 1999:
[Freeciv-Dev] Re: Using tax rates
Home

[Freeciv-Dev] Re: Using tax rates

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: jjm@xxxxxxxxxxxx
Cc: freeciv-dev@xxxxxxxxxxx
Subject: [Freeciv-Dev] Re: Using tax rates
From: Stan Shebs <shebs@xxxxxxxxxx>
Date: Mon, 20 Dec 1999 17:08:26 -0800

   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




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