src/economy_new.cpp
author celestar
Sun, 01 Apr 2007 09:38:43 +0000
branchgamebalance
changeset 9905 91eca6fdee8d
parent 9903 dc85aaa556ae
permissions -rw-r--r--
(svn r9539) [gamebalance] -Add: Don't take real estate costs into account on the lowest difficulty level
/* $Id$ */

/** @file */

#include "economy_new.h"
#include "town.h"

/** The global economy */
CEconomy *_eco;

/** Base prices used at game startup, reference year 1800 */
static const int32 price_base[CEconomy::MAX_PRICE] = {
	    100, ///< station_value
	    100, ///< build_rail
	     95, ///< build_road
	     65, ///< build_signals
	    275, ///< build_bridge
	    600, ///< build_train_depot
	    500, ///< build_road_depot
	    700, ///< build_ship_depot
	    450, ///< build_tunnel
	    200, ///< train_station_track
	    180, ///< train_station_length
	    600, ///< build_airport
	    200, ///< build_bus_station
	    200, ///< build_truck_station
	    350, ///< build_dock
	 400000, ///< build_railvehicle
	   2000, ///< build_railwagon
	 700000, ///< aircraft_base
	  14000, ///< roadveh_base
	  65000, ///< ship_base
	     20, ///< build_trees
	    250, ///< terraform
	     20, ///< clear_1
	     40, ///< purchase_land
	    200, ///< clear_2
	    500, ///< clear_3
	     20, ///< remove_trees
	    -70, ///< remove_rail
	     10, ///< remove_signals
	     50, ///< clear_bridge
	     80, ///< remove_train_depot
	     80, ///< remove_road_depot
	     90, ///< remove_ship_depot
	     30, ///< clear_tunnel
	  10000, ///< clear_water
	     50, ///< remove_rail_station
	     30, ///< remove_airport
	     50, ///< remove_bus_station
	     50, ///< remove_truck_station
	     55, ///< remove_dock
	   1600, ///< remove_house
	     40, ///< remove_road
	   5600, ///< running_rail[0] railroad
	   5200, ///< running_rail[1] monorail
	   4800, ///< running_rail[2] maglev
	   9600, ///< aircraft_running
	   1600, ///< roadveh_running
	   5600, ///< ship_running
	1000000, ///< build_industry
};

/**
 * Starts the economy. This sets the basic growth by the difficulty level and adjust the current
 * EAL by the year of the game. We also set the economic cycles and initialize the prices here
 * @warning This should be run once per game only
 */
CEconomy::CEconomy()
{
	/* Set basic growth */
	FixedT<int32, 16> growth(_opt.diff.economic_growth, 2);
	m_basic_growth = (growth + 1) / 100 + 1;
	DEBUG(eco, 3, "Starting a new economy with a basic growth factor of %.3f in the year %d", (double)m_basic_growth, _cur_year);

	/* Set up the economic cycles */
	m_long_term_cycle   = RandomRange(15) + 45;
	m_short_term_cycle  = RandomRange( 4) +  6;
	m_long_term_ampl    = RandomRange( 5) + 10;
	m_short_term_ampl   = RandomRange(10) + 15;
	m_long_term_ampl   /= 1000;
	m_short_term_ampl  /= 1000;
	DEBUG(eco, 4, "Adjusting economic cycles to %d and %d years", m_long_term_cycle, m_short_term_cycle);
	DEBUG(eco, 4, "Adjusting economic cycles to %f and %f (amplitude)", (double)m_long_term_ampl, (double)m_short_term_ampl);

	m_activity_level = 1;
	m_activity_level = pow(m_basic_growth, _cur_year - 1820);
	DEBUG(eco, 4, "Adjusting basic EAL for current year (offset %d) to %.3f", _cur_year - 1820, (double)m_activity_level);

	/* Initalize prices */
	for (int i = 0; i < MAX_PRICE; i++) m_prices[i] = price_base[i];
}
/**
 * Adjust the global activity level by the cumulative activity level of all towns.
 * This is to iron out the difference between the sum of all economic activites of
 * all towns and the the product of the economic activity per capita times the
 * population of the map.
 */
void CEconomy::AdjustActivityByTowns()
{
	Town *t;
	FixedT<int64, 16> total_activity = 0;
	FixedT<int64, 16> old_activity = m_activity_level;

	FOR_ALL_TOWNS(t) {
		total_activity += (t->GetActivity() * t->population * m_activity_level);
		DEBUG(eco, 6, "Obtained EAL of %f", (double)t->GetActivity());
	}

	DEBUG(eco, 5, "Global EAL is             %f", (double)m_activity_level * GetWorldPopulation());
	DEBUG(eco, 5, "Total EAL of all towns is %f", (double)total_activity);

	m_activity_level = total_activity / GetWorldPopulation();
	DEBUG(eco, 4, "Adjusting global EAL to %f (ratio %f)", (double)m_activity_level, (double)(m_activity_level/old_activity));

	FOR_ALL_TOWNS(t) t->SetActivity(t->GetActivity() * old_activity / m_activity_level);
}

/**
 * Obtains the costs that a certain user operation at a tile would generate.
 * This function takes into account that cost that arise from obtaining ownership
 * of the tile in question. Note that these costs are not accounted for in the
 * very simple difficulty levels.
 * @warning         This function needs to be called BEFORE the tile actions
 *                  are performed. Otherwise you'll get an assertion on the command
 *                  because the computed prices for the test and the exec run are
 *                  different
 * @todo            Implement inflation
 * @todo            Make this work with "overbuilding" owned land
 * @todo            Implement multipliers (for newgrf)
 * @param operation The operation that is to be performed on the tile
 * @param tile      The tile on which we want to operate, if omitted
 *                  no change of ownership is assumed.
 * @param release   Set to true when the owner releases ownership of tile
 * @return          The cost (positive) or income (negative) for the operation
 */
int32 CEconomy::GetPrice(Price operation, TileIndex tile, bool release) const
{
	int32 cost = m_prices[operation];

	if (tile == INVALID_TILE || _opt.diff.economic_model == 0) return cost;
	if (release) cost -= Town::GetTilePrice(tile);
	else if (_current_player < MAX_PLAYERS && _current_player != GetTileOwner(tile)) cost += Town::GetTilePrice(tile);

	return cost;
}

/**
 * Descriptor for the new economy within the savegame
 */
/* static */
const SaveLoad CEconomy::eco_desc[] = {
	SLE_VAR(CEconomy, m_activity_level,   SLE_INT64),
	SLE_VAR(CEconomy, m_basic_growth,     SLE_INT32),
	SLE_VAR(CEconomy, m_long_term_cycle,  SLE_INT8),
	SLE_VAR(CEconomy, m_short_term_cycle, SLE_INT8),
	SLE_VAR(CEconomy, m_long_term_ampl,   SLE_INT32),
	SLE_VAR(CEconomy, m_short_term_ampl,  SLE_INT32),
	SLE_ARR(CEconomy, m_prices,           SLE_INT32, MAX_PRICE),
	SLE_END()
};

/**
 * Starts a new economy. As there can always be only one economy in place,
 * deletes the one that is currently active
 */
void InitializeEconomy()
{
	delete _eco;
	_eco = new CEconomy;
	assert(_eco != NULL);
}