src/town.cpp
author celestar
Wed, 13 Jun 2007 11:45:14 +0000
branchgamebalance
changeset 9911 0b8b245a2391
parent 9903 dc85aaa556ae
permissions -rw-r--r--
(svn r10135) [gamebalance] -Sync: r9700:9900 from trunk
/* $Id */

/** @file */

#include "stdafx.h"
#include "openttd.h"
#include "road_map.h"
#include "town.h"
#include "town_map.h"

/* static */
int64 Town::GetTilePrice(TileIndex tile)
{
	uint rad;
	const Town *t = GetRadiusGroupForTile(tile, rad);
	FixedT<int64, 16> price = t->GetActivity();
	DEBUG(eco, 6, "Getting price for tile 0x%x at %f (authority at 0x%x)", tile, (double)price, t->xy);
	price *=  _eco->GetPrice(CEconomy::PURCHASE_LAND) * rad * rad * 10;

	return price;
}

/* static */
const Town *Town::GetRadiusGroupForTile(TileIndex tile, uint &group)
{
	const Town *t;
	group = 0;
	const Town *best_town = NULL;

	DEBUG(eco, 7, "Obtaining highest town radius for tile 0x%x", tile);

	/* We do have a tile that directly belongs to a town */
	if (IsTileType(tile, MP_HOUSE) ||
			(IsTileType(tile, MP_STREET) &&
			(GetTileOwner(tile)) == OWNER_TOWN)) { /** @todo check this for level crossings, trams, etc */
		t = GetTownByTile(tile);
		group = t->GetRadiusGroup(tile, true) + 1;
		DEBUG(eco, 6, "Tile 0x%x belongs to town at 0x%x, level %d", tile, t->xy, group);
		return t;
	}

	uint best_dist = UINT_MAX;
	FOR_ALL_TOWNS(t) {
		if (1 + t->GetRadiusGroup(tile, true) > group) {
			group = t->GetRadiusGroup(tile, true) + 1;
			DEBUG(eco, 7, "Higher group (%d) found for town at 0x%x", group, t->xy);
			best_town = t;
			if (best_dist > DistanceSquare(tile, t->xy)) best_dist = DistanceSquare(tile, t->xy);
		} else if (1 + t->GetRadiusGroup(tile, true) == group) {
			DEBUG(eco, 7, "Same group found town at 0x%x is closer", t->xy);
			if (best_dist > DistanceSquare(tile, t->xy)) {
				best_dist = DistanceSquare(tile, t->xy);
				best_town = t;
			}
		}
	}

	assert(best_town != NULL);

	return best_town;
}

uint Town::GetRadiusGroup(TileIndex tile, bool ignore_funding) const
{
	uint dist = DistanceSquare(tile, xy);
	uint smallest = 0;

	if (!ignore_funding && fund_buildings_months > 0 && dist < 25) return 4;

	for (uint i = 0; i != lengthof(radius); i++) if (dist < radius[i]) smallest = i;

	return smallest;
}

void Town::UpdateActivity()
{
	if (new_act_pass == 0 && act_pass == 0) {
		DEBUG(eco, 7, "Town is not connected, bailing out");
		return;
	}

	static const FixedT<int, 12> max_activity_change   (1, 400);
	static const FixedT<int, 12> min_activity_change = -max_activity_change;
	FixedT<int, 12>              activity_change       (1, 200);

	activity_change *= act_pass;
	activity_change /= max_pass;
	activity_change -= max_activity_change;
	DEBUG(eco, 6, "Raw EAL change for town at 0x%x is %f", xy, (double)activity_change);

	if (activity_change > max_activity_change) activity_change = max_activity_change;
	if (activity_change < min_activity_change) activity_change = min_activity_change;

	this->SetActivity(this->GetActivity() + activity_change);

	DEBUG(eco, 5, "Modifying EAL for town at 0x%x by %f to %f", xy, (double)activity_change, (double)this->GetActivity());
}