update: Don't double-round money, fixing mil pay and more

The update tallies income and expenses in full dollars.  Each debit or
credit is rounded before it is added to the tally.  Different things
are rounded differently.  Examples:

* Each sector's military pay is rounded down.  In the stock game, 1m
  is paid $4.999998, so n mil cost n*$5 -$1, for all practical n.  10m
  in one sector cost $49, but spread over ten sectors they cost only
  $40.

* Total pay for military in ships and land units is rounded down.

* Each plane's military pay is rounded down (used to be rounded up
  except for broke countries until recent commit 2eb08f4).  In the
  stock game, flight pay is 5 * $4.999998 = $24.99999.  For a plane
  with n mil, that's n * $25 - $1.  Filed under plane maintenance, not
  military payroll.

* Each sector's civilian tax is rounded.  In the stock game, 1c pays
  $0.499998.  10c in one sector pay $5, but spread over ten sectors
  they pay nothing.

* An occupied sector's civilian tax is first rounded, then divided by
  four and rounded down *boggle*.

* Each sector's uw tax is rounded.  In the stock game, 1u pays
  $0.106662.  1-4u in one sector pay nothing.  5-14u pay $1.

This is madness.  Has always been that way.

Drop the rounding and track money in type double throughout the
update.  Round only the final amount, randomly.  This is similar to
how commands accumulate a money delta in player->dolcost.

Likewise, tally the subtotals for budget in type double.  Display them
rounded to full dollars.

Signed-off-by: Markus Armbruster <armbru@pond.sub.org>
This commit is contained in:
Markus Armbruster 2016-07-06 19:36:33 +02:00
parent 10789a0365
commit 25a6cf92b2
14 changed files with 760 additions and 758 deletions

View file

@ -87,7 +87,7 @@ budg(void)
pchr[dchr[i].d_prd].p_sname);
else
pr("\t\t");
pr("\t\t%8d\n", -budget->prod[i].money);
pr("\t\t%8.0f\n", -budget->prod[i].money);
expenses -= budget->prod[i].money;
}
@ -97,7 +97,7 @@ budg(void)
snprintf(buf, sizeof(buf), "%d %s%s",
budget->bm[i].count, bm_name[i].object,
splur(budget->bm[i].count));
pr("%-20s\t\t%-16s\t\t%8d\n",
pr("%-20s\t\t%-16s\t\t%8.0f\n",
bm_name[i].activity, buf, -budget->bm[i].money);
expenses -= budget->bm[i].money;
}
@ -105,7 +105,7 @@ budg(void)
if (budget->mil.money) {
snprintf(buf, sizeof(buf), "%d mil, %d res",
budget->mil.count, np->nat_reserve);
pr("Military payroll\t\t%-32s%8d\n",
pr("Military payroll\t\t%-32s%8.0f\n",
buf, -budget->mil.money);
expenses -= budget->mil.money;
}
@ -122,7 +122,7 @@ budg(void)
if (budget->bars.money) {
snprintf(buf, sizeof(buf), "%d bar%s",
budget->bars.count, splur(budget->bars.count));
pr("Income from bars\t\t%-32s%+8d\n",
pr("Income from bars\t\t%-32s%+8.0f\n",
buf, budget->bars.money);
income += budget->bars.money;
}

View file

@ -89,7 +89,8 @@ upd_land(struct lndstr *lp, int etus, struct bp *bp, int build)
struct natstr *np = getnatp(lp->lnd_own);
int pstage, ptime;
int min = morale_base - (int)np->nat_level[NAT_HLEV];
int n, mult, cost, eff_lost;
int n, mult, eff_lost;
double cost;
if (!player->simulation)
if (lp->lnd_retreat < min)
@ -107,7 +108,7 @@ upd_land(struct lndstr *lp, int etus, struct bp *bp, int build)
if (lcp->l_flags & L_ENGINEER)
mult *= 3;
budget->bm[BUDG_LND_MAINT].count++;
cost = -(mult * etus * MIN(0.0, money_land * lcp->l_cost));
cost = mult * etus * -money_land * lcp->l_cost;
if (budget->money < cost && !player->simulation) {
eff_lost = etus / 5;
if (lp->lnd_effic - eff_lost < LAND_MINEFF)
@ -196,7 +197,7 @@ landrepair(struct lndstr *land, struct natstr *np, struct bp *bp, int etus,
int build;
int avail;
int mult;
int cost;
double cost;
if (land->lnd_effic == 100)
return;
@ -239,7 +240,7 @@ landrepair(struct lndstr *land, struct natstr *np, struct bp *bp, int etus,
sp->sct_avail = avail;
bp_set_from_sect(bp, sp);
cost = roundavg(mult * lp->l_cost * build / 100.0);
cost = mult * lp->l_cost * build / 100.0;
budget->bm[BUDG_LND_BUILD].count += !!build;
budget->bm[BUDG_LND_BUILD].money -= cost;
budget->money -= cost;

View file

@ -35,6 +35,7 @@
#include <config.h>
#include <math.h>
#include "chance.h"
#include "file.h"
#include "game.h"
#include "item.h"
@ -217,9 +218,9 @@ prod_nat(int etu)
lnd_money, sea_money, air_money);
if (CANT_HAPPEN(np->nat_money != nat_budget[n].start_money))
nat_budget[n].money += np->nat_money - nat_budget[n].start_money;
np->nat_money = roundavg(nat_budget[n].money);
wu(0, n, "money delta was $%d for this update\n",
nat_budget[n].money - nat_budget[n].start_money);
np->nat_money = nat_budget[n].money;
np->nat_money - nat_budget[n].start_money);
if (opt_LOSE_CONTACT) {
for (cn = 1; cn < MAXNOC; cn++) {

View file

@ -85,7 +85,8 @@ upd_plane(struct plnstr *pp, int etus, struct bp *bp, int build)
struct budget *budget = &nat_budget[pp->pln_own];
struct plchrstr *pcp = &plchr[pp->pln_type];
struct natstr *np = getnatp(pp->pln_own);
int mult, cost, eff_lost;
int mult, eff_lost;
double cost;
if (build == 1) {
if (!pp->pln_off && budget->money >= 0)
@ -97,7 +98,7 @@ upd_plane(struct plnstr *pp, int etus, struct bp *bp, int build)
if (np->nat_level[NAT_TLEV] < pp->pln_tech * 0.85)
mult = 2;
budget->bm[BUDG_PLN_MAINT].count++;
cost = -(mult * etus * MIN(0.0, pcp->pl_cost * money_plane));
cost = mult * etus * -money_plane * pcp->pl_cost;
if (budget->money < cost && !player->simulation) {
eff_lost = etus / 5;
if (pp->pln_effic - eff_lost < PLANE_MINEFF)
@ -130,7 +131,7 @@ planerepair(struct plnstr *pp, struct natstr *np, struct bp *bp, int etus,
int mult;
int avail;
int used;
int cost;
double cost;
if (pp->pln_effic == 100)
return;
@ -196,7 +197,7 @@ planerepair(struct plnstr *pp, struct natstr *np, struct bp *bp, int etus,
}
bp_set_from_sect(bp, sp);
cost = roundavg(mult * build * pcp->pl_cost / 100.0);
cost = mult * pcp->pl_cost * build / 100.0;
budget->bm[BUDG_PLN_BUILD].count += !!build;
budget->bm[BUDG_PLN_BUILD].money -= cost;
budget->money -= cost;

View file

@ -108,10 +108,9 @@ void
tax(struct sctstr *sp, int etu, int *pop)
{
struct budget *budget = &nat_budget[sp->sct_own];
int civ_tax, uw_tax, mil_pay;
double civ_tax, uw_tax, mil_pay;
civ_tax = (int)(0.5 + sp->sct_item[I_CIVIL] * sp->sct_effic *
etu * money_civ / 100);
civ_tax = sp->sct_item[I_CIVIL] * etu * money_civ * sp->sct_effic / 100;
/*
* captured civs only pay 1/4 taxes
*/
@ -121,8 +120,7 @@ tax(struct sctstr *sp, int etu, int *pop)
budget->civ.money += civ_tax;
budget->money += civ_tax;
uw_tax = (int)(0.5 + sp->sct_item[I_UW] * sp->sct_effic *
etu * money_uw / 100);
uw_tax = sp->sct_item[I_UW] * etu * money_uw * sp->sct_effic / 100;
budget->uw.count += sp->sct_item[I_UW];
budget->uw.money += uw_tax;
budget->money += uw_tax;
@ -144,7 +142,8 @@ upd_slmilcosts(int etu, natid n)
{
struct shpstr *sp;
struct lndstr *lp;
int mil, i, mil_pay;
int mil, i;
double mil_pay;
mil = 0;
@ -169,18 +168,18 @@ upd_slmilcosts(int etu, natid n)
void
bank_income(struct sctstr *sp, int etu)
{
int inc;
double income;
inc = (int)(sp->sct_item[I_BAR] * etu * bankint * sp->sct_effic / 100);
income = sp->sct_item[I_BAR] * etu * bankint * sp->sct_effic / 100;
nat_budget[sp->sct_own].bars.count += sp->sct_item[I_BAR];
nat_budget[sp->sct_own].bars.money += inc;
nat_budget[sp->sct_own].money += inc;
nat_budget[sp->sct_own].bars.money += income;
nat_budget[sp->sct_own].money += income;
}
void
pay_reserve(struct natstr *np, int etu)
{
int pay = (int)(np->nat_reserve * money_res * etu);
double pay = np->nat_reserve * money_res * etu;
nat_budget[np->nat_cnum].mil.money += pay;
nat_budget[np->nat_cnum].money += pay;

View file

@ -62,7 +62,7 @@ produce(struct natstr *np, struct sctstr *sp)
int material_limit, res_limit;
int material_consume;
int val;
int cost;
double cost;
if (dchr[sp->sct_type].d_prd < 0)
return;

View file

@ -229,8 +229,8 @@ produce_sect(struct natstr *np, int etu, struct bp *bp)
{
struct budget *budget = &nat_budget[np->nat_cnum];
struct sctstr *sp, scratch_sect;
int cost;
int n;
double cost;
for (n = 0; NULL != (sp = getsectid(n)); n++) {
if (sp->sct_type == SCT_WATER)
@ -272,7 +272,7 @@ produce_sect(struct natstr *np, int etu, struct bp *bp)
if ((sp->sct_effic < 100 || sp->sct_type != sp->sct_newtype) &&
budget->money >= 0) {
cost = roundavg(buildeff(sp));
cost = buildeff(sp);
budget->bm[BUDG_SCT_BUILD].count++;
budget->bm[BUDG_SCT_BUILD].money -= cost;
budget->money -= cost;

View file

@ -93,7 +93,8 @@ upd_ship(struct shpstr *sp, int etus, struct bp *bp, int build)
struct pchrstr *product;
unsigned char *resource;
int dep;
int n, mult, cost, eff_lost;
int n, mult, eff_lost;
double cost;
if (build == 1) {
if (!sp->shp_off && budget->money >= 0)
@ -105,7 +106,7 @@ upd_ship(struct shpstr *sp, int etus, struct bp *bp, int build)
if (np->nat_level[NAT_TLEV] < sp->shp_tech * 0.85)
mult = 2;
budget->bm[BUDG_SHP_MAINT].count++;
cost = -(mult * etus * MIN(0.0, money_ship * mp->m_cost));
cost = mult * etus * -money_ship * mp->m_cost;
if (budget->money < cost && !player->simulation) {
eff_lost = etus / 5;
if (sp->shp_effic - eff_lost < SHIP_MINEFF)
@ -244,7 +245,7 @@ shiprepair(struct shpstr *ship, struct natstr *np, struct bp *bp, int etus,
int wf;
int avail;
int mult;
int cost;
double cost;
if (ship->shp_effic == 100)
return;
@ -307,7 +308,7 @@ shiprepair(struct shpstr *ship, struct natstr *np, struct bp *bp, int etus,
}
bp_set_from_sect(bp, sp);
cost = roundavg(mult * mp->m_cost * build / 100.0);
cost = mult * mp->m_cost * build / 100.0;
budget->bm[BUDG_SHP_BUILD].count += !!build;
budget->bm[BUDG_SHP_BUILD].money -= cost;
budget->money -= cost;