(svn r12864) [0.6] -Backport from trunk r12859, r12857, r12855, r12845, r12844: 0.6
authorrubidium
Thu, 24 Apr 2008 11:48:09 +0000
branch0.6
changeset 10323 57d8fd25473e
parent 9357 bafe57f3402a
child 10324 adab4d41a259
(svn r12864) [0.6] -Backport from trunk r12859, r12857, r12855, r12845, r12844:
- Fix: Make the town rating tests use less memory and much quicker (r12859)
- Fix: Usage of AutoPtr made (trying to) build stuff very expensive (r12857, r12855)
- Fix: Use YAPF for fairly old savegames from before YAPF was introduced (r12845)
- Fix: The industry tick trigger should only be triggered once every 256 ticks, not every tick... Also bail out of the triggers a little earlier if you know they are not going to happen anyway (r12844)
projects/openttd_vs80.vcproj
projects/openttd_vs90.vcproj
source.list
src/engine.cpp
src/group_cmd.cpp
src/industry_cmd.cpp
src/misc/autocopyptr.hpp
src/misc/autoptr.hpp
src/newgrf_house.cpp
src/newgrf_industrytiles.cpp
src/newgrf_station.cpp
src/oldpool.h
src/openttd.cpp
src/rail_cmd.cpp
src/road_cmd.cpp
src/ship_cmd.cpp
src/signs.cpp
src/station_cmd.cpp
src/town_cmd.cpp
src/water_cmd.cpp
src/waypoint.cpp
--- a/projects/openttd_vs80.vcproj	Mon Mar 31 22:09:27 2008 +0000
+++ b/projects/openttd_vs80.vcproj	Thu Apr 24 11:48:09 2008 +0000
@@ -2076,14 +2076,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\misc\autocopyptr.hpp"
-				>
-			</File>
-			<File
-				RelativePath=".\..\src\misc\autoptr.hpp"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\misc\binaryheap.hpp"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj	Mon Mar 31 22:09:27 2008 +0000
+++ b/projects/openttd_vs90.vcproj	Thu Apr 24 11:48:09 2008 +0000
@@ -2073,14 +2073,6 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\misc\autocopyptr.hpp"
-				>
-			</File>
-			<File
-				RelativePath=".\..\src\misc\autoptr.hpp"
-				>
-			</File>
-			<File
 				RelativePath=".\..\src\misc\binaryheap.hpp"
 				>
 			</File>
--- a/source.list	Mon Mar 31 22:09:27 2008 +0000
+++ b/source.list	Thu Apr 24 11:48:09 2008 +0000
@@ -439,8 +439,6 @@
 
 # Misc
 misc/array.hpp
-misc/autocopyptr.hpp
-misc/autoptr.hpp
 misc/binaryheap.hpp
 misc/blob.hpp
 misc/countedptr.hpp
--- a/src/engine.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/engine.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -16,7 +16,6 @@
 #include "aircraft.h"
 #include "newgrf_cargo.h"
 #include "group.h"
-#include "misc/autoptr.hpp"
 #include "strings_func.h"
 #include "gfx_func.h"
 #include "functions.h"
@@ -516,19 +515,15 @@
 		return CommandCost();
 	}
 
-	er = new EngineRenew(old_engine, new_engine);
-	if (er == NULL) return CMD_ERROR;
-	AutoPtrT<EngineRenew> er_auto_delete = er;
-
+	if (!EngineRenew::CanAllocateItem()) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
+		er = new EngineRenew(old_engine, new_engine);
 		er->group_id = group;
 
 		/* Insert before the first element */
 		er->next = (EngineRenew *)(*erl);
 		*erl = (EngineRenewList)er;
-
-		er_auto_delete.Detach();
 	}
 
 	return CommandCost();
--- a/src/group_cmd.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/group_cmd.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -12,7 +12,6 @@
 #include "train.h"
 #include "aircraft.h"
 #include "vehicle_gui.h"
-#include "misc/autoptr.hpp"
 #include "strings_func.h"
 #include "functions.h"
 #include "window_func.h"
@@ -92,20 +91,14 @@
 	VehicleType vt = (VehicleType)p1;
 	if (!IsPlayerBuildableVehicleType(vt)) return CMD_ERROR;
 
-	AutoPtrT<Group> g_auto_delete;
-
-	Group *g = new Group(_current_player);
-	if (g == NULL) return CMD_ERROR;
-
-	g_auto_delete = g;
+	if (!Group::CanAllocateItem()) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
+		Group *g = new Group(_current_player);
 		g->replace_protection = false;
 		g->vehicle_type = vt;
 
 		InvalidateWindowData(GetWCForVT(vt), (vt << 11) | VLW_GROUP_LIST | _current_player);
-
-		g_auto_delete.Detach();
 	}
 
 	return CommandCost();
--- a/src/industry_cmd.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/industry_cmd.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -25,7 +25,6 @@
 #include "newgrf_industries.h"
 #include "newgrf_industrytiles.h"
 #include "newgrf_callbacks.h"
-#include "misc/autoptr.hpp"
 #include "autoslope.h"
 #include "transparency.h"
 #include "water.h"
@@ -1025,6 +1024,9 @@
 
 			if (cut) ChopLumberMillTrees(i);
 		}
+
+		TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK);
+		StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
 	}
 }
 
@@ -1046,8 +1048,6 @@
 	if (_game_mode == GM_EDITOR) return;
 
 	FOR_ALL_INDUSTRIES(i) {
-		TriggerIndustry(i, INDUSTRY_TRIGGER_INDUSTRY_TICK);
-		StartStopIndustryTileAnimation(i, IAT_INDUSTRY_TICK);
 		ProduceIndustryGoods(i);
 	}
 }
@@ -1583,17 +1583,19 @@
 	if (!CheckIfIndustryIsAllowed(tile, type, t)) return NULL;
 	if (!CheckSuitableIndustryPos(tile)) return NULL;
 
-	Industry *i = new Industry(tile);
-	if (i == NULL) return NULL;
-	AutoPtrT<Industry> i_auto_delete = i;
+	if (!Industry::CanAllocateItem()) return NULL;
 
 	if (flags & DC_EXEC) {
+		Industry *i = new Industry(tile);
 		if (!custom_shape_check) CheckIfCanLevelIndustryPlatform(tile, DC_EXEC, it, type);
 		DoCreateNewIndustry(i, tile, type, it, itspec_index, t, OWNER_NONE);
-		i_auto_delete.Detach();
+
+		return i;
 	}
 
-	return i;
+	/* We need to return a non-NULL pointer to tell we have created an industry.
+	 * However, we haven't created a real one (no DC_EXEC), so return a fake one. */
+	return GetIndustry(0);
 }
 
 /** Build/Fund an industry
--- a/src/misc/autocopyptr.hpp	Mon Mar 31 22:09:27 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/* $Id$ */
-
-/** @file autocopyptr.hpp */
-
-#ifndef  AUTOCOPYPTR_HPP
-#define  AUTOCOPYPTR_HPP
-
-#if 0 // reenable when needed
-/** CAutoCopyPtrT - kind of CoW (Copy on Write) pointer.
- *  It is non-invasive smart pointer (reference counter is held outside
- *  of Tdata).
- *  When copied, its new copy shares the same underlaying structure Tdata.
- *  When dereferenced, its behaviour depends on 2 factors:
- *     - whether the data is shared (used by more than one pointer)
- *     - type of access (read/write)
- *    When shared pointer is dereferenced for write, new clone of Tdata
- *  is made first.
- *  Can't be used for polymorphic data types (interfaces).
- */
-template <class Tdata_>
-class CAutoCopyPtrT {
-protected:
-	typedef Tdata_ Tdata;
-
-	struct CItem {
-		int     m_ref_cnt;  ///< reference counter
-		Tdata   m_data;     ///< custom data itself
-
-		FORCEINLINE CItem()                  : m_ref_cnt(1)                     {};
-		FORCEINLINE CItem(const Tdata& data) : m_ref_cnt(1), m_data(data)       {};
-		FORCEINLINE CItem(const CItem& src)  : m_ref_cnt(1), m_data(src.m_data) {};
-	};
-
-	mutable CItem* m_pI; ///< points to the ref-counted data
-
-public:
-	FORCEINLINE CAutoCopyPtrT() : m_pI(NULL) {};
-	FORCEINLINE CAutoCopyPtrT(const Tdata& data) : m_pI(new CItem(data)) {};
-	FORCEINLINE CAutoCopyPtrT(const CAutoCopyPtrT& src) : m_pI(src.m_pI) {if (m_pI != NULL) m_pI->m_ref_cnt++;}
-	FORCEINLINE ~CAutoCopyPtrT() {if (m_pI == NULL || (--m_pI->m_ref_cnt) > 0) return; delete m_pI; m_pI = NULL;}
-
-	/** data accessor (read only) */
-	FORCEINLINE const Tdata& GetDataRO() const {if (m_pI == NULL) m_pI = new CItem(); return m_pI->m_data;}
-	/** data accessor (read / write) */
-	FORCEINLINE Tdata& GetDataRW() {CloneIfShared(); if (m_pI == NULL) m_pI = new CItem(); return m_pI->m_data;}
-
-	/** clone data if it is shared */
-	FORCEINLINE void CloneIfShared()
-	{
-		if (m_pI != NULL && m_pI->m_ref_cnt > 1) {
-			// we share data item with somebody, clone it to become an exclusive owner
-			CItem* pNewI = new CItem(*m_pI);
-			m_pI->m_ref_cnt--;
-			m_pI = pNewI;
-		}
-	}
-
-	/** assign pointer from the other one (maintaining ref counts) */
-	FORCEINLINE void Assign(const CAutoCopyPtrT& src)
-	{
-		if (m_pI == src.m_pI) return;
-		if (m_pI != NULL && (--m_pI->m_ref_cnt) <= 0) delete m_pI;
-		m_pI = src.m_pI;
-		if (m_pI != NULL) m_pI->m_ref_cnt++;
-	}
-
-	/** dereference operator (read only) */
-	FORCEINLINE const Tdata* operator -> () const {return &GetDataRO();}
-	/** dereference operator (read / write) */
-	FORCEINLINE Tdata* operator -> () {return &GetDataRW();}
-
-	/** assignment operator */
-	FORCEINLINE CAutoCopyPtrT& operator = (const CAutoCopyPtrT& src) {Assign(src); return *this;}
-
-	/** forwarding 'lower then' operator to the underlaying items */
-	FORCEINLINE bool operator < (const CAutoCopyPtrT& other) const
-	{
-		assert(m_pI != NULL);
-		assert(other.m_pI != NULL);
-		return (m_pI->m_data) < (other.m_pI->m_data);
-	}
-};
-
-#endif /* 0 */
-#endif /* AUTOCOPYPTR_HPP */
--- a/src/misc/autoptr.hpp	Mon Mar 31 22:09:27 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/* $Id$ */
-
-/** @file autoptr.hpp */
-
-#ifndef AUTOPTR_HPP
-#define AUTOPTR_HPP
-
-/** AutoPtrT - kind of smart pointer that ensures the owned object gets
- *  deleted when its pointer goes out of scope.
- *  It is non-invasive smart pointer (no reference counter).
- *  When copied, the copy takes ownership of underlying object
- *  and original becomes NULL!
- *  Can be used also for polymorphic data types (interfaces).
- */
-template <class T>
-class AutoPtrT {
-public:
-	typedef T obj_t;
-
-protected:
-	mutable T* m_p; ///< points to the data
-
-public:
-	FORCEINLINE AutoPtrT()
-	 : m_p(NULL)
-	{};
-
-	FORCEINLINE AutoPtrT(const AutoPtrT<T>& src)
-	 : m_p(src.m_p)
-	{
-		if (m_p != NULL) src.m_p = NULL;
-	};
-
-	FORCEINLINE AutoPtrT(T *p)
-	 : m_p(p)
-	{}
-
-	FORCEINLINE ~AutoPtrT()
-	{
-		if (m_p != NULL) {
-			T *p = m_p;
-			m_p = NULL;
-			delete p;
-		}
-	}
-
-	/** give-up ownership and NULLify the raw pointer */
-	FORCEINLINE T* Detach()
-	{
-		T* p = m_p;
-		m_p = NULL;
-		return p;
-	}
-
-	/** raw-pointer cast operator (read only) */
-	FORCEINLINE operator const T* () const
-	{
-		return m_p;
-	}
-
-	/** raw-pointer cast operator */
-	FORCEINLINE operator T* ()
-	{
-		return m_p;
-	}
-
-	/** dereference operator (read only) */
-	FORCEINLINE const T* operator -> () const
-	{
-		assert(m_p != NULL);
-		return m_p;
-	}
-
-	/** dereference operator (read / write) */
-	FORCEINLINE T* operator -> ()
-	{
-		assert(m_p != NULL);
-		return m_p;
-	}
-
-	/** assignment operator */
-	FORCEINLINE AutoPtrT& operator = (const AutoPtrT& src)
-	{
-		/* Save original pointer and replace it with the given one to avoid recursive calls. */
-		T* p = m_p;
-		m_p = src.m_p;
-
-		if (m_p != NULL) src.m_p = NULL;
-
-		if (p != NULL) {
-			/* Now we can safely delete the old one. */
-			delete p;
-		}
-		return *this;
-	}
-
-	/** forwarding 'lower than' operator to the underlaying items */
-	FORCEINLINE bool operator < (const AutoPtrT& other) const
-	{
-		assert(m_p != NULL);
-		assert(other.m_p != NULL);
-		return (*m_p) < (*other.m_p);
-	}
-};
-
-#endif /* AUTOPTR_HPP */
--- a/src/newgrf_house.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/newgrf_house.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -541,6 +541,8 @@
 	HouseID hid = GetHouseType(tile);
 	HouseSpec *hs = GetHouseSpecs(hid);
 
+	if (hs->spritegroup == NULL) return;
+
 	NewHouseResolver(&object, hid, tile, GetTownByTile(tile));
 
 	object.callback = CBID_RANDOM_TRIGGER;
--- a/src/newgrf_industrytiles.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/newgrf_industrytiles.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -403,6 +403,8 @@
 	IndustryGfx gfx = GetIndustryGfx(tile);
 	const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx);
 
+	if (itspec->grf_prop.spritegroup == NULL) return;
+
 	NewIndustryTileResolver(&object, gfx, tile, ind);
 
 	object.callback = CBID_RANDOM_TRIGGER;
--- a/src/newgrf_station.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/newgrf_station.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -665,7 +665,7 @@
 {
 	uint i;
 
-	if (statspec == NULL) return 0;
+	if (statspec == NULL || st == NULL) return 0;
 
 	/* Check if this spec has already been allocated */
 	for (i = 1; i < st->num_specs && i < MAX_SPECLIST; i++) {
--- a/src/oldpool.h	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/oldpool.h	Thu Apr 24 11:48:09 2008 +0000
@@ -317,6 +317,28 @@
 	{
 		return Tpool->CleaningPool();
 	}
+
+public:
+	/**
+	 * Check whether we can allocate an item in this pool. This to prevent the
+	 * need to actually construct the object and then destructing it again,
+	 * which could be *very* costly.
+	 * @return true if and only if at least ONE item can be allocated.
+	 */
+	static inline bool CanAllocateItem()
+	{
+		uint last_minus_one = Tpool->GetSize() - 1;
+
+		for (T *t = Tpool->Get(Tpool->first_free_index); t != NULL; t = (t->index < last_minus_one) ? Tpool->Get(t->index + 1U) : NULL) {
+			if (!t->IsValid()) return true;
+			Tpool->first_free_index = t->index;
+		}
+
+		/* Check if we can add a block to the pool */
+		if (Tpool->AddBlockToPool()) return CanAllocateItem();
+
+		return false;
+	}
 };
 
 
--- a/src/openttd.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/openttd.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -2402,13 +2402,13 @@
 		}
 
 		/* Convert old PF settings to new */
-		if (_patches.yapf.rail_use_yapf) {
+		if (_patches.yapf.rail_use_yapf || CheckSavegameVersion(28)) {
 			_patches.pathfinder_for_trains = VPF_YAPF;
 		} else {
 			_patches.pathfinder_for_trains = (_patches.new_pathfinding_all ? VPF_NPF : VPF_NTP);
 		}
 
-		if (_patches.yapf.road_use_yapf) {
+		if (_patches.yapf.road_use_yapf || CheckSavegameVersion(28)) {
 			_patches.pathfinder_for_roadvehs = VPF_YAPF;
 		} else {
 			_patches.pathfinder_for_roadvehs = (_patches.new_pathfinding_all ? VPF_NPF : VPF_OPF);
--- a/src/rail_cmd.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/rail_cmd.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -30,7 +30,6 @@
 #include "newgrf_callbacks.h"
 #include "newgrf_station.h"
 #include "train.h"
-#include "misc/autoptr.hpp"
 #include "variables.h"
 #include "autoslope.h"
 #include "transparency.h"
@@ -763,12 +762,10 @@
 
 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 
-	Depot *d = new Depot(tile);
-
-	if (d == NULL) return CMD_ERROR;
-	AutoPtrT<Depot> d_auto_delete = d;
+	if (!Depot::CanAllocateItem()) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
+		Depot *d = new Depot(tile);
 		MakeRailDepot(tile, _current_player, dir, (RailType)p1);
 		MarkTileDirtyByTile(tile);
 
@@ -776,7 +773,6 @@
 
 		AddSideToSignalBuffer(tile, INVALID_DIAGDIR, _current_player);
 		YapfNotifyTrackLayoutChange(tile, TrackdirToTrack(DiagdirToDiagTrackdir(dir)));
-		d_auto_delete.Detach();
 	}
 
 	return cost.AddCost(_price.build_train_depot);
--- a/src/road_cmd.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/road_cmd.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -22,7 +22,6 @@
 #include "newgrf.h"
 #include "station_map.h"
 #include "tunnel_map.h"
-#include "misc/autoptr.hpp"
 #include "variables.h"
 #include "autoslope.h"
 #include "transparency.h"
@@ -805,16 +804,14 @@
 
 	if (MayHaveBridgeAbove(tile) && IsBridgeAbove(tile)) return_cmd_error(STR_5007_MUST_DEMOLISH_BRIDGE_FIRST);
 
-	Depot *dep = new Depot(tile);
-	if (dep == NULL) return CMD_ERROR;
-	AutoPtrT<Depot> d_auto_delete = dep;
+	if (!Depot::CanAllocateItem()) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
+		Depot *dep = new Depot(tile);
 		dep->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
 
 		MakeRoadDepot(tile, _current_player, dir, rt);
 		MarkTileDirtyByTile(tile);
-		d_auto_delete.Detach();
 	}
 	return cost.AddCost(_price.build_road_depot);
 }
--- a/src/ship_cmd.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/ship_cmd.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -27,7 +27,6 @@
 #include "newgrf_text.h"
 #include "newgrf_sound.h"
 #include "spritecache.h"
-#include "misc/autoptr.hpp"
 #include "strings_func.h"
 #include "functions.h"
 #include "window_func.h"
--- a/src/signs.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/signs.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -10,7 +10,6 @@
 #include "saveload.h"
 #include "command_func.h"
 #include "variables.h"
-#include "misc/autoptr.hpp"
 #include "strings_func.h"
 #include "viewport_func.h"
 #include "zoom_func.h"
@@ -97,12 +96,11 @@
 CommandCost CmdPlaceSign(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
 	/* Try to locate a new sign */
-	Sign *si = new Sign(_current_player);
-	if (si == NULL) return_cmd_error(STR_2808_TOO_MANY_SIGNS);
-	AutoPtrT<Sign> s_auto_delete = si;
+	if (!Sign::CanAllocateItem()) return_cmd_error(STR_2808_TOO_MANY_SIGNS);
 
 	/* When we execute, really make the sign */
 	if (flags & DC_EXEC) {
+		Sign *si = new Sign(_current_player);
 		int x = TileX(tile) * TILE_SIZE;
 		int y = TileY(tile) * TILE_SIZE;
 
@@ -115,7 +113,6 @@
 		_sign_sort_dirty = true;
 		_new_sign_id = si->index;
 		_total_signs++;
-		s_auto_delete.Detach();
 	}
 
 	return CommandCost();
--- a/src/station_cmd.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/station_cmd.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -27,7 +27,6 @@
 #include "newgrf_callbacks.h"
 #include "newgrf_station.h"
 #include "yapf/yapf.h"
-#include "misc/autoptr.hpp"
 #include "road_type.h"
 #include "road_internal.h" /* For drawing catenary/checking road removal */
 #include "cargotype.h"
@@ -239,7 +238,7 @@
 	STATIONNAMING_HELIPORT,
 };
 
-static bool GenerateStationName(Station *st, TileIndex tile, int flag)
+static void GenerateStationName(Station *st, TileIndex tile, int flag)
 {
 	static const uint32 _gen_station_name_bits[] = {
 		0,                                      /* 0 */
@@ -344,7 +343,6 @@
 
 done:
 	st->string_id = found + STR_SV_STNAME;
-	return true;
 }
 #undef M
 
@@ -966,10 +964,6 @@
 	/* See if there is a deleted station close to us. */
 	if (st == NULL) st = GetClosestStationFromTile(tile_org);
 
-	/* In case of new station if DC_EXEC is NOT set we still need to create the station
-	 * to test if everything is OK. In this case we need to delete it before return. */
-	AutoPtrT<Station> st_auto_delete;
-
 	if (st != NULL) {
 		/* Reuse an existing station. */
 		if (st->owner != _current_player)
@@ -987,17 +981,17 @@
 		if (!st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TEST)) return CMD_ERROR;
 	} else {
 		/* allocate and initialize new station */
-		st = new Station(tile_org);
-		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
-
-		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
-		st_auto_delete = st;
-
-		st->town = ClosestTownFromTile(tile_org, (uint)-1);
-		if (!GenerateStationName(st, tile_org, STATIONNAMING_RAIL)) return CMD_ERROR;
-
-		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
-			SetBit(st->town->have_ratings, _current_player);
+		if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
+
+		if (flags & DC_EXEC) {
+			st = new Station();
+
+			st->town = ClosestTownFromTile(tile_org, (uint)-1);
+			GenerateStationName(st, tile_org, STATIONNAMING_RAIL);
+
+			if (IsValidPlayer(_current_player)) {
+				SetBit(st->town->have_ratings, _current_player);
+			}
 		}
 	}
 
@@ -1082,8 +1076,6 @@
 		RebuildStationLists();
 		InvalidateWindow(WC_STATION_LIST, st->owner);
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS);
-		/* success, so don't delete the new station */
-		st_auto_delete.Detach();
 	}
 
 	return cost;
@@ -1388,23 +1380,13 @@
 	if (st == NULL) st = GetClosestStationFromTile(tile);
 
 	/* give us a road stop in the list, and check if something went wrong */
-	RoadStop *road_stop = new RoadStop(tile);
-	if (road_stop == NULL) {
-		return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS);
-	}
-
-	/* ensure that in case of error (or no DC_EXEC) the new road stop gets deleted upon return */
-	AutoPtrT<RoadStop> rs_auto_delete(road_stop);
+	if (!RoadStop::CanAllocateItem()) return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS);
 
 	if (st != NULL &&
 			GetNumRoadStopsInStation(st, RoadStop::BUS) + GetNumRoadStopsInStation(st, RoadStop::TRUCK) >= RoadStop::LIMIT) {
 		return_cmd_error(type ? STR_TOO_MANY_TRUCK_STOPS : STR_TOO_MANY_BUS_STOPS);
 	}
 
-	/* In case of new station if DC_EXEC is NOT set we still need to create the station
-	 * to test if everything is OK. In this case we need to delete it before return. */
-	AutoPtrT<Station> st_auto_delete;
-
 	if (st != NULL) {
 		if (st->owner != _current_player) {
 			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
@@ -1413,26 +1395,25 @@
 		if (!st->rect.BeforeAddTile(tile, StationRect::ADD_TEST)) return CMD_ERROR;
 	} else {
 		/* allocate and initialize new station */
-		st = new Station(tile);
-		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
-
-		/* ensure that in case of error (or no DC_EXEC) the new station gets deleted upon return */
-		st_auto_delete = st;
-
-
-		Town *t = st->town = ClosestTownFromTile(tile, (uint)-1);
-		if (!GenerateStationName(st, tile, STATIONNAMING_ROAD)) return CMD_ERROR;
-
-		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
-			SetBit(t->have_ratings, _current_player);
+		if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
+
+		if (flags & DC_EXEC) {
+			st = new Station();
+
+			st->town = ClosestTownFromTile(tile, (uint)-1);
+			GenerateStationName(st, tile, STATIONNAMING_ROAD);
+
+			if (IsValidPlayer(_current_player)) {
+				SetBit(st->town->have_ratings, _current_player);
+			}
+			st->sign.width_1 = 0;
 		}
-
-		st->sign.width_1 = 0;
 	}
 
 	cost.AddCost((type) ? _price.build_truck_station : _price.build_bus_station);
 
 	if (flags & DC_EXEC) {
+		RoadStop *road_stop = new RoadStop(tile);
 		/* Insert into linked list of RoadStops */
 		RoadStop **currstop = FindRoadStopSpot(type, st);
 		*currstop = road_stop;
@@ -1454,9 +1435,6 @@
 		RebuildStationLists();
 		InvalidateWindow(WC_STATION_LIST, st->owner);
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_ROADVEHS);
-		/* success, so don't delete the new station and the new road stop */
-		st_auto_delete.Detach();
-		rs_auto_delete.Detach();
 	}
 	return cost;
 }
@@ -1711,10 +1689,6 @@
 		return CMD_ERROR;
 	}
 
-	/* In case of new station if DC_EXEC is NOT set we still need to create the station
-	 * to test if everything is OK. In this case we need to delete it before return. */
-	AutoPtrT<Station> st_auto_delete;
-
 	if (st != NULL) {
 		if (st->owner != _current_player)
 			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
@@ -1727,24 +1701,18 @@
 		airport_upgrade = false;
 
 		/* allocate and initialize new station */
-		st = new Station(tile);
-		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
-
-		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
-		st_auto_delete = st;
-
-		st->town = t;
-
-		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
-			SetBit(t->have_ratings, _current_player);
-		}
-
-		st->sign.width_1 = 0;
-
-		/* If only helicopters may use the airport generate a helicopter related (5)
-		 * station name, otherwise generate a normal airport name (1) */
-		if (!GenerateStationName(st, tile, !(afc->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_HELIPORT : STATIONNAMING_AIRPORT)) {
-			return CMD_ERROR;
+		if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
+
+		if (flags & DC_EXEC) {
+			st = new Station();
+
+			st->town = ClosestTownFromTile(tile, (uint)-1);
+			GenerateStationName(st, tile, !(afc->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_HELIPORT : STATIONNAMING_AIRPORT);
+
+			if (IsValidPlayer(_current_player)) {
+				SetBit(st->town->have_ratings, _current_player);
+			}
+			st->sign.width_1 = 0;
 		}
 	}
 
@@ -1781,8 +1749,6 @@
 		RebuildStationLists();
 		InvalidateWindow(WC_STATION_LIST, st->owner);
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_PLANES);
-		/* success, so don't delete the new station */
-		st_auto_delete.Detach();
 	}
 
 	return cost;
@@ -1851,18 +1817,18 @@
 	if (GetTileSlope(tile, NULL) != SLOPE_FLAT) return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
 	/* allocate and initialize new station */
-	Station *st = new Station(tile);
-	if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
-
-	/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
-	AutoPtrT<Station> st_auto_delete(st);
-
-	st->town = ClosestTownFromTile(tile, (uint)-1);
-	st->sign.width_1 = 0;
-
-	if (!GenerateStationName(st, tile, STATIONNAMING_BUOY)) return CMD_ERROR;
+	if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
 
 	if (flags & DC_EXEC) {
+		Station *st = new Station();
+
+		st->town = ClosestTownFromTile(tile, (uint)-1);
+		GenerateStationName(st, tile, STATIONNAMING_BUOY);
+
+		if (IsValidPlayer(_current_player)) {
+			SetBit(st->town->have_ratings, _current_player);
+		}
+		st->sign.width_1 = 0;
 		st->dock_tile = tile;
 		st->facilities |= FACIL_DOCK;
 		/* Buoys are marked in the Station struct by this flag. Yes, it is this
@@ -1879,8 +1845,6 @@
 		RebuildStationLists();
 		InvalidateWindow(WC_STATION_LIST, st->owner);
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
-		/* success, so don't delete the new station */
-		st_auto_delete.Detach();
 	}
 
 	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_dock);
@@ -2006,10 +1970,6 @@
 	/* Find a station close to us */
 	if (st == NULL) st = GetClosestStationFromTile(tile);
 
-	/* In case of new station if DC_EXEC is NOT set we still need to create the station
-	 * to test if everything is OK. In this case we need to delete it before return. */
-	AutoPtrT<Station> st_auto_delete;
-
 	if (st != NULL) {
 		if (st->owner != _current_player)
 			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
@@ -2019,21 +1979,19 @@
 		if (st->dock_tile != 0) return_cmd_error(STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK);
 	} else {
 		/* allocate and initialize new station */
-		st = new Station(tile);
-		if (st == NULL) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
-
-		/* ensure that in case of error (or no DC_EXEC) the station gets deleted upon return */
-		st_auto_delete = st;
-
-		Town *t = st->town = ClosestTownFromTile(tile, (uint)-1);
-
-		if (IsValidPlayer(_current_player) && (flags & DC_EXEC) != 0) {
-			SetBit(t->have_ratings, _current_player);
+		/* allocate and initialize new station */
+		if (!Station::CanAllocateItem()) return_cmd_error(STR_3008_TOO_MANY_STATIONS_LOADING);
+
+		if (flags & DC_EXEC) {
+			st = new Station();
+
+			st->town = ClosestTownFromTile(tile, (uint)-1);
+			GenerateStationName(st, tile, STATIONNAMING_DOCK);
+
+			if (IsValidPlayer(_current_player)) {
+				SetBit(st->town->have_ratings, _current_player);
+			}
 		}
-
-		st->sign.width_1 = 0;
-
-		if (!GenerateStationName(st, tile, STATIONNAMING_DOCK)) return CMD_ERROR;
 	}
 
 	if (flags & DC_EXEC) {
@@ -2049,8 +2007,6 @@
 		RebuildStationLists();
 		InvalidateWindow(WC_STATION_LIST, st->owner);
 		InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
-		/* success, so don't delete the new station */
-		st_auto_delete.Detach();
 	}
 	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_dock);
 }
@@ -2848,11 +2804,7 @@
 	st->town = ClosestTownFromTile(tile, (uint)-1);
 	st->sign.width_1 = 0;
 
-	if (!GenerateStationName(st, tile, STATIONNAMING_OILRIG)) {
-		DEBUG(misc, 0, "Can't allocate station-name for oilrig at 0x%X, reverting to oilrig only", tile);
-		delete st;
-		return;
-	}
+	GenerateStationName(st, tile, STATIONNAMING_OILRIG);
 
 	MakeOilrig(tile, st->index);
 
--- a/src/town_cmd.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/town_cmd.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -31,7 +31,6 @@
 #include "newgrf_house.h"
 #include "newgrf_commons.h"
 #include "newgrf_townname.h"
-#include "misc/autoptr.hpp"
 #include "autoslope.h"
 #include "waypoint.h"
 #include "transparency.h"
@@ -44,6 +43,8 @@
 #include "table/sprites.h"
 #include "table/town_land.h"
 
+#include <map>
+
 uint _total_towns;
 HouseSpec _house_specs[HOUSE_MAX];
 
@@ -1508,16 +1509,14 @@
 		return_cmd_error(STR_023A_TOO_MANY_TOWNS);
 
 	/* Allocate town struct */
-	Town *t = new Town(tile);
-	if (t == NULL) return_cmd_error(STR_023A_TOO_MANY_TOWNS);
-	AutoPtrT<Town> t_auto_delete = t;
+	if (!Town::CanAllocateItem()) return_cmd_error(STR_023A_TOO_MANY_TOWNS);
 
 	/* Create the town */
 	if (flags & DC_EXEC) {
+		Town *t = new Town(tile);
 		_generating_world = true;
 		DoCreateTown(t, tile, townnameparts, (TownSizeMode)p2, p1);
 		_generating_world = false;
-		t_auto_delete.Detach();
 	}
 	return CommandCost();
 }
@@ -2410,14 +2409,14 @@
 }
 
 static bool _town_rating_test = false;
+std::map<const Town *, int> _town_test_ratings;
 
 void SetTownRatingTestMode(bool mode)
 {
 	static int ref_count = 0;
 	if (mode) {
 		if (ref_count == 0) {
-			Town *t;
-			FOR_ALL_TOWNS(t) t->test_rating = t->ratings[_current_player];
+			_town_test_ratings.empty();
 		}
 		ref_count++;
 	} else {
@@ -2427,10 +2426,19 @@
 	_town_rating_test = !(ref_count == 0);
 }
 
+static int GetRating(const Town *t)
+{
+	if (_town_rating_test) {
+		std::map<const Town *, int>::iterator it = _town_test_ratings.find(t);
+		if (it != _town_test_ratings.end()) {
+			return (*it).second;
+		}
+	}
+	return t->ratings[_current_player];
+}
+
 void ChangeTownRating(Town *t, int add, int max)
 {
-	int rating;
-
 	/* if magic_bulldozer cheat is active, town doesn't penaltize for removing stuff */
 	if (t == NULL ||
 			!IsValidPlayer(_current_player) ||
@@ -2440,8 +2448,7 @@
 
 	SetBit(t->have_ratings, _current_player);
 
-	rating = _town_rating_test ? t->test_rating : t->ratings[_current_player];
-
+	int rating = GetRating(t);
 	if (add < 0) {
 		if (rating > max) {
 			rating += add;
@@ -2454,7 +2461,7 @@
 		}
 	}
 	if (_town_rating_test) {
-		t->test_rating = rating;
+		_town_test_ratings[t] = rating;
 	} else {
 		t->ratings[_current_player] = rating;
 	}
@@ -2482,7 +2489,7 @@
 	 */
 	modemod = _default_rating_settings[_opt.diff.town_council_tolerance][type];
 
-	if ((_town_rating_test ? t->test_rating : t->ratings[_current_player]) < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) {
+	if (GetRating(t) < 16 + modemod && !(flags & DC_NO_TOWN_RATING)) {
 		SetDParam(0, t->index);
 		_error_message = STR_2009_LOCAL_AUTHORITY_REFUSES;
 		return false;
--- a/src/water_cmd.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/water_cmd.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -23,7 +23,6 @@
 #include "industry_map.h"
 #include "newgrf.h"
 #include "newgrf_canal.h"
-#include "misc/autoptr.hpp"
 #include "transparency.h"
 #include "strings_func.h"
 #include "functions.h"
@@ -196,18 +195,16 @@
 	ret = DoCommand(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
 	if (CmdFailed(ret)) return CMD_ERROR;
 
-	Depot *depot = new Depot(tile);
-	if (depot == NULL) return CMD_ERROR;
-	AutoPtrT<Depot> d_auto_delete = depot;
+	if (!Depot::CanAllocateItem()) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
+		Depot *depot = new Depot(tile);
 		depot->town_index = ClosestTownFromTile(tile, (uint)-1)->index;
 
 		MakeShipDepot(tile,  _current_player, DEPOT_NORTH, axis, wc1);
 		MakeShipDepot(tile2, _current_player, DEPOT_SOUTH, axis, wc2);
 		MarkTileDirtyByTile(tile);
 		MarkTileDirtyByTile(tile2);
-		d_auto_delete.Detach();
 	}
 
 	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_ship_depot);
--- a/src/waypoint.cpp	Mon Mar 31 22:09:27 2008 +0000
+++ b/src/waypoint.cpp	Thu Apr 24 11:48:09 2008 +0000
@@ -18,7 +18,6 @@
 #include "variables.h"
 #include "yapf/yapf.h"
 #include "newgrf.h"
-#include "misc/autoptr.hpp"
 #include "strings_func.h"
 #include "gfx_func.h"
 #include "functions.h"
@@ -189,7 +188,6 @@
 CommandCost CmdBuildTrainWaypoint(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
 {
 	Waypoint *wp;
-	AutoPtrT<Waypoint> wp_auto_delete;
 	Slope tileh;
 	Axis axis;
 
@@ -217,35 +215,34 @@
 
 	/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
 	wp = FindDeletedWaypointCloseTo(tile);
-	if (wp == NULL) {
-		wp = new Waypoint(tile);
-		if (wp == NULL) return CMD_ERROR;
-
-		wp_auto_delete = wp;
+	if (wp == NULL && !Waypoint::CanAllocateItem()) return CMD_ERROR;
 
-		wp->town_index = INVALID_TOWN;
-		wp->name = NULL;
-		wp->town_cn = 0;
-	} else if (flags & DC_EXEC) {
-		/* Move existing (recently deleted) waypoint to the new location */
+	if (flags & DC_EXEC) {
+		if (wp == NULL) {
+			wp = new Waypoint(tile);
 
-		/* First we update the destination for all vehicles that
-		 * have the old waypoint in their orders. */
-		Vehicle *v;
-		FOR_ALL_VEHICLES(v) {
-			if (v->type == VEH_TRAIN &&
-					v->First() == v &&
-					v->current_order.type == OT_GOTO_WAYPOINT &&
-					v->dest_tile == wp->xy) {
-				v->dest_tile = tile;
+			wp->town_index = INVALID_TOWN;
+			wp->name = NULL;
+			wp->town_cn = 0;
+		} else {
+			/* Move existing (recently deleted) waypoint to the new location */
+
+			/* First we update the destination for all vehicles that
+			* have the old waypoint in their orders. */
+			Vehicle *v;
+			FOR_ALL_VEHICLES(v) {
+				if (v->type == VEH_TRAIN &&
+						v->First() == v &&
+						v->current_order.type == OT_GOTO_WAYPOINT &&
+						v->dest_tile == wp->xy) {
+					v->dest_tile = tile;
+				}
 			}
+
+			RedrawWaypointSign(wp);
+			wp->xy = tile;
 		}
 
-		RedrawWaypointSign(wp);
-		wp->xy = tile;
-	}
-
-	if (flags & DC_EXEC) {
 		const StationSpec* statspec;
 
 		MakeRailWaypoint(tile, GetTileOwner(tile), axis, GetRailType(tile), wp->index);
@@ -272,7 +269,6 @@
 		UpdateWaypointSign(wp);
 		RedrawWaypointSign(wp);
 		YapfNotifyTrackLayoutChange(tile, AxisToTrack(axis));
-		wp_auto_delete.Detach();
 	}
 
 	return CommandCost(EXPENSES_CONSTRUCTION, _price.build_train_depot);