(svn r2288) - CodeChange: protected the next batch of commands (41 so far, out of 115).
authorDarkvater
Mon, 09 May 2005 22:33:00 +0000
changeset 1784 6eb3ab1bc33c
parent 1783 5ff88ba55601
child 1785 998f4b5eec29
(svn r2288) - CodeChange: protected the next batch of commands (41 so far, out of 115).
- CodeChange: changed the airport gui airport-type checking. Added function GetValidAirports() that returns bitmasked availibility, is also used for checking.
- CodeChange: to check tree-planting, 2 const arrays have been moved to table/tree_land.h (type and count)
- CodeChange: added IsTownIndex() in following of IsStationIndex(), etc.
- Fix (regression): road tunnels did not work anymore, forgot that their type was 0x200 (documented now)
airport.h
airport_gui.c
command.c
misc_gui.c
road_cmd.c
station_cmd.c
table/tree_land.h
town.h
train_cmd.c
tree_cmd.c
tunnelbridge_cmd.c
water_cmd.c
--- a/airport.h	Mon May 09 19:56:08 2005 +0000
+++ b/airport.h	Mon May 09 22:33:00 2005 +0000
@@ -48,4 +48,20 @@
 void UnInitializeAirports(void);
 const AirportFTAClass* GetAirport(const byte airport_type);
 
+/** Get buildable airport bitmask.
+ * @return get all buildable airports at this given time, bitmasked.
+ * Bit 0 means the small airport is buildable, etc.
+ * @todo set availability of airports by year, instead of airplane
+ */
+static inline uint32 GetValidAirports(void)
+{
+	uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
+
+	// 1980-1-1 is --> 21915
+	// 1990-1-1 is --> 25568
+	if (_date >= 21915) {SETBIT(bytemask, 3);}	// metropilitan airport 1980
+	if (_date >= 25568) {SETBIT(bytemask, 4);}	// international airport 1990
+	return bytemask;
+}
+
 #endif /* AIRPORT_H */
--- a/airport_gui.c	Mon May 09 19:56:08 2005 +0000
+++ b/airport_gui.c	Mon May 09 22:33:00 2005 +0000
@@ -135,24 +135,25 @@
 
 static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
 {
-	switch(e->event) {
+	switch (e->event) {
 	case WE_PAINT: {
 		int sel;
 		int rad = 4; // default catchment radious
+		uint32 avail_airports;
 
-		if (WP(w,def_d).close)
-			return;
-		w->disabled_state = 0;
+		if (WP(w,def_d).close) return;
 
 		sel = _selected_airport_type;
-		// FIXME -- BuildAirportPickerWndProc - set availability of airports by year, instead of airplane
-		if (!(_avail_aircraft & 1)) { w->disabled_state |= (1<<3); if (sel == AT_SMALL) sel = AT_LARGE; }
-		if (!(_avail_aircraft & 2)) {	w->disabled_state |= (1<<4); if (sel == AT_LARGE) sel = AT_SMALL; }
-		if (!(_avail_aircraft & 4)) {	w->disabled_state |= (1<<5); }	// heliport
-		// 1980-1-1 is --> 21915
-		// 1990-1-1 is --> 25568
-		if (_date < 21915) {w->disabled_state |= (1<<6);}	// metropilitan airport 1980
-		if (_date < 25568) {w->disabled_state |= (1<<7);}	// international airport 1990
+		avail_airports = GetValidAirports();
+
+		if (!HASBIT(avail_airports, 0) && sel == AT_SMALL) sel = AT_LARGE;
+		if (!HASBIT(avail_airports, 1) && sel == AT_LARGE) sel = AT_SMALL;
+
+		/* 'Country Airport' starts at widget 3, and if its bit is set, it is available,
+		 * so take its opposite value to set the disabled_state. There are only 5 available
+		 * airports, so XOr with 0x1F (1 1111) */
+		w->disabled_state = (avail_airports ^ 0x1F) << 3;
+
 		_selected_airport_type = sel;
 		// select default the coverage area to 'Off' (8)
 		w->click_state = ((1<<3) << sel) | ((1<<8) << _station_show_coverage);
--- a/command.c	Mon May 09 19:56:08 2005 +0000
+++ b/command.c	Mon May 09 22:33:00 2005 +0000
@@ -189,7 +189,6 @@
 	NULL,													/* 20 */
 	CmdBuildRoadStop,							/* 21 */
 	NULL,													/* 22 */
-	/***************************************************/
 	CmdBuildLongRoad,							/* 23 */
 	CmdRemoveLongRoad,						/* 24 */
 	CmdBuildRoad,									/* 25 */
@@ -209,6 +208,7 @@
 	CmdTrainGotoDepot,						/* 39 */
 	CmdForceTrainProceed,					/* 40 */
 	CmdReverseTrainDirection,			/* 41 */
+	/***************************************************/
 
 	CmdModifyOrder,								/* 42 */
 	CmdSkipOrder,									/* 43 */
--- a/misc_gui.c	Mon May 09 19:56:08 2005 +0000
+++ b/misc_gui.c	Mon May 09 22:33:00 2005 +0000
@@ -5,6 +5,7 @@
 #include "strings.h"
 #include "table/sprites.h"
 #include "table/strings.h"
+#include "table/tree_land.h"
 #include "map.h"
 #include "window.h"
 #include "gui.h"
@@ -271,8 +272,6 @@
 
 static int _tree_to_plant;
 
-static const byte _tree_base_by_landscape[4] = {0, 12, 20, 32};
-static const byte _tree_count_by_landscape[4] = {12, 8, 12, 9};
 static const uint32 _tree_sprites[] = {
 	0x655,0x663,0x678,0x62B,0x647,0x639,0x64E,0x632,0x67F,0x68D,0x69B,0x6A9,
 	0x6AF,0x6D2,0x6D9,0x6C4,0x6CB,0x6B6,0x6BD,0x6E0,
--- a/road_cmd.c	Mon May 09 19:56:08 2005 +0000
+++ b/road_cmd.c	Mon May 09 22:33:00 2005 +0000
@@ -124,8 +124,10 @@
 	return (byte)(r | (r >> 8));
 }
 
-/* Delete a piece of road
- * p1 = piece type
+/** Delete a piece of road.
+ * @param x,y tile coordinates for road construction
+ * @param p1 road piece flags
+ * @param p2 unused
  */
 int32 CmdRemoveRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
@@ -137,13 +139,16 @@
 	TileIndex tile;
 	byte owner;
 	Town *t;
-	/*	true if the roadpiece was always removeable,
-			false if it was a center piece. Affects town ratings drop
-	*/
+	/* true if the roadpiece was always removeable,
+	 * false if it was a center piece. Affects town ratings drop */
 	bool edge_road;
+	byte pieces = (byte)p1;
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
+	/* Road pieces are max 4 bitset values (NE, NW, SE, SW) */
+	if (pieces >> 4) return CMD_ERROR;
+
 	FindLandscapeHeight(&ti, x, y);
 	tile = ti.tile;
 
@@ -169,10 +174,9 @@
 	{
 		bool b;
 		_road_special_gettrackstatus = true;
-		b = CheckAllowRemoveRoad(tile, p1, &edge_road);
+		b = CheckAllowRemoveRoad(tile, pieces, &edge_road);
 		_road_special_gettrackstatus = false;
-		if (!b)
-			return CMD_ERROR;
+		if (!b) return CMD_ERROR;
 	}
 
 	if (ti.type == MP_TUNNELBRIDGE) {
@@ -180,9 +184,9 @@
 			return CMD_ERROR;
 
 		if ((ti.map5 & 0xE9) == 0xE8) {
-			if (p1 & 10) goto return_error;
+			if (pieces & 10) goto return_error;
 		} else if ((ti.map5 & 0xE9) == 0xE9) {
-			if (p1 & 5) goto return_error;
+			if (pieces & 5) goto return_error;
 		} else
 			goto return_error;
 
@@ -202,7 +206,7 @@
 
 		// XXX - change cascading ifs to switch when doing rewrite
 		if ((ti.map5 & 0xF0) == 0) { // normal road
-			uint c = p1, t2;
+			byte c = pieces, t2;
 
 			if (ti.tileh != 0  && (ti.map5 == 5 || ti.map5 == 10)) {
 				c |= (c & 0xC) >> 2;
@@ -235,10 +239,10 @@
 
 			if (!(ti.map5 & 8)) {
 				c = 2;
-				if (p1 & 5) goto return_error;
+				if (pieces & 5) goto return_error;
 			} else {
 				c = 1;
-				if (p1 & 10) goto return_error;
+				if (pieces & 10) goto return_error;
 			}
 
 			cost = _price.remove_road * 2;
@@ -340,30 +344,33 @@
 	return CMD_ERROR;
 }
 
-/* Build a piece of road
- * p1 = piece flags
- * p2 = town which is building the road
+/** Build a piece of road.
+ * @param x,y tile coordinates for road construction
+ * @param p1 road piece flags
+ * @param p2 the town that is building the road (0 if not applicable)
  */
-
 int32 CmdBuildRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	TileInfo ti;
 	int32 cost;
 	byte pieces = (byte)p1, existing = 0;
-	uint tile;
+	TileIndex tile;
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
+	/* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
+	 * if a non-player is building the road */
+	if ((pieces >> 4) || (_current_player < MAX_PLAYERS && p2 != 0) || !IsTownIndex(p2)) return CMD_ERROR;
+
 	FindLandscapeHeight(&ti, x, y);
 	tile = ti.tile;
 
 	// allow building road under bridge
-	if (ti.type != MP_TUNNELBRIDGE && !EnsureNoVehicle(tile))
-		return CMD_ERROR;
+	if (ti.type != MP_TUNNELBRIDGE && !EnsureNoVehicle(tile)) return CMD_ERROR;
 
 	if (ti.type == MP_STREET) {
 		if (!(ti.map5 & 0xF0)) {
-			if ( ((pieces) & (byte)(ti.map5)) == (pieces))
+			if ( (pieces & (byte)(ti.map5)) == (pieces))
 				return_cmd_error(STR_1007_ALREADY_BUILT);
 			existing = ti.map5;
 		} else {
@@ -433,12 +440,12 @@
 		return cost;
 	} else {
 do_clear:;
-		if (DoCommandByTile(tile, 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR) == CMD_ERROR)
+		if (CmdFailed(DoCommandByTile(tile, 0, 0, flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR)))
 			return CMD_ERROR;
 	}
 
 	cost = CheckRoadSlope(ti.tileh, &pieces, existing);
-	if (cost == CMD_ERROR) return_cmd_error(STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION);
+	if (CmdFailed(cost)) return_cmd_error(STR_1800_LAND_SLOPED_IN_WRONG_DIRECTION);
 
 	if (cost && (!_patches.build_on_slopes || (!_patches.ainew_active && _is_ai_player)))
 		return CMD_ERROR;
@@ -494,123 +501,130 @@
 }
 
 
-// Build a long piece of road.
-// x,y = end tile
-// p1 = start tile
-// p2&1 = start tile starts in the 2nd half
-// p2&2 = end tile starts in the 2nd half
-// p2&4 = direction (0 = along x, 1=along y)
+/** Build a long piece of road.
+ * @param x,y end tile of drag
+ * @param p1 start tile of drag
+ * @param p2 various bitstuffed elements
+ * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
+ * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
+ * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
+ */
 int32 CmdBuildLongRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
-	uint start_tile, end_tile, tile;
-	int mode;
-	int32 cost,ret;
+	TileIndex start_tile, end_tile, tile;
+	int32 cost, ret;
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
+	if (p1 > MapSize()) return CMD_ERROR;
+
 	start_tile = p1;
 	end_tile = TILE_FROM_XY(x, y);
 
-	if (start_tile > end_tile || (start_tile == end_tile && (p2&1))) {
-		uint t = start_tile; start_tile = end_tile; end_tile = t;
+	/* Only drag in X or Y direction dictated by the direction variable */
+	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
+	if (HASBIT(p2, 2)  && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
+
+	/* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */
+	if (start_tile > end_tile || (start_tile == end_tile && HASBIT(p2, 0))) {
+		TileIndex t = start_tile;
+		start_tile = end_tile;
+		end_tile = t;
 		p2 ^= IS_INT_INSIDE(p2&3, 1, 3) ? 3 : 0;
 	}
 
 	cost = 0;
 	tile = start_tile;
 	// Start tile is the small number.
-	for(;;) {
-		mode = (p2&4) ? 5 : 10;
-
-		if (tile == start_tile && (p2&1))
-			mode &= (4+2);
-		else if (tile == end_tile && !(p2&2))
-			mode &= (1+8);
+	for (;;) {
+		uint bits = HASBIT(p2, 2) ? ROAD_SE | ROAD_NW : ROAD_SW | ROAD_NE;
+		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
+		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
 
-		ret = DoCommandByTile(tile, mode, 0, flags, CMD_BUILD_ROAD);
-		if (ret == CMD_ERROR) {
-			if (_error_message != STR_1007_ALREADY_BUILT)
-				return CMD_ERROR;
-		} else {
+		ret = DoCommandByTile(tile, bits, 0, flags, CMD_BUILD_ROAD);
+		if (CmdFailed(ret)) {
+			if (_error_message != STR_1007_ALREADY_BUILT) return CMD_ERROR;
+		} else
 			cost += ret;
-		}
 
-		if (tile == end_tile)
-			break;
+		if (tile == end_tile) break;
 
-		tile += (p2&4)?TILE_XY(0,1):TILE_XY(1,0);
+		tile += HASBIT(p2, 2) ? TILE_XY(0, 1) : TILE_XY(1, 0);
 	}
 
-	// already built?
-	if (cost == 0)
-		return CMD_ERROR;
-
-	return cost;
+	return (cost == 0) ? CMD_ERROR : cost;
 }
 
-// Remove a long piece of road.
-// x,y = end tile
-// p1 = start tile
-// p2&1 = start tile starts in the 2nd half
-// p2&2 = end tile starts in the 2nd half
-// p2&4 = direction (0 = along x, 1=along y)
+/** Remove a long piece of road.
+ * @param x,y end tile of drag
+ * @param p1 start tile of drag
+ * @param p2 various bitstuffed elements
+ * - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
+ * - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
+ * - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
+ */
 int32 CmdRemoveLongRoad(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
-	uint start_tile, end_tile, tile;
-	int32 cost,ret;
+	TileIndex start_tile, end_tile, tile;
+	int32 cost, ret;
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
+	if (p1 > MapSize()) return CMD_ERROR;
+
 	start_tile = p1;
 	end_tile = TILE_FROM_XY(x, y);
 
-	if (start_tile > end_tile || (start_tile == end_tile && (p2&1))) {
-		uint t = start_tile; start_tile = end_tile; end_tile = t;
+	/* Only drag in X or Y direction dictated by the direction variable */
+	if (!HASBIT(p2, 2) && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
+	if (HASBIT(p2, 2)  && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
+
+	/* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */
+	if (start_tile > end_tile || (start_tile == end_tile && HASBIT(p2, 0))) {
+		TileIndex t = start_tile;
+		start_tile = end_tile;
+		end_tile = t;
 		p2 ^= IS_INT_INSIDE(p2&3, 1, 3) ? 3 : 0;
 	}
 
 	cost = 0;
 	tile = start_tile;
 	// Start tile is the small number.
-	for(;;) {
-		uint bits = (p2 & 4) ? ROAD_SE | ROAD_NW : ROAD_SW | ROAD_NE;
-		if (tile == end_tile && !(p2&2)) bits &= ROAD_NW | ROAD_NE;
-		if (tile == start_tile && (p2&1)) bits &= ROAD_SE | ROAD_SW;
+	for (;;) {
+		uint bits = HASBIT(p2, 2) ? ROAD_SE | ROAD_NW : ROAD_SW | ROAD_NE;
+		if (tile == end_tile && !HASBIT(p2, 1)) bits &= ROAD_NW | ROAD_NE;
+		if (tile == start_tile && HASBIT(p2, 0)) bits &= ROAD_SE | ROAD_SW;
 
 		// try to remove the halves.
 		if (bits) {
 			ret = DoCommandByTile(tile, bits, 0, flags, CMD_REMOVE_ROAD);
-			if (ret != CMD_ERROR)
-				cost += ret;
+			if (!CmdFailed(ret)) cost += ret;
 		}
 
-		if (tile == end_tile)
-			break;
+		if (tile == end_tile) break;
 
-		tile += (p2&4)?TILE_XY(0,1):TILE_XY(1,0);
+		tile += HASBIT(p2, 2) ? TILE_XY(0, 1) : TILE_XY(1, 0);
 	}
 
-	// already built?
-	if (cost == 0)
-		return CMD_ERROR;
-
-	return cost;
+	return (cost == 0) ? CMD_ERROR : cost;
 }
 
-/* Build a road depot
- * p1 - direction (0-3)
- * p2 - unused
+/** Build a road depot.
+ * @param x,y tile coordinates where the depot will be built
+ * @param p1 depot direction (0 through 3), where 0 is NW, 1 is NE, etc.
+ * @param p2 unused
  */
-
 int32 CmdBuildRoadDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	TileInfo ti;
 	int32 cost;
 	Depot *dep;
-	uint tile;
+	TileIndex tile;
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
+	if (p2 > 3) return CMD_ERROR; // check direction
+
 	FindLandscapeHeight(&ti, x, y);
 
 	tile = ti.tile;
@@ -624,8 +638,7 @@
 	}
 
 	cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
-	if (cost == CMD_ERROR)
-		return CMD_ERROR;
+	if (CmdFailed(cost)) return CMD_ERROR;
 
 	dep = AllocateDepot();
 	if (dep == NULL)
--- a/station_cmd.c	Mon May 09 19:56:08 2005 +0000
+++ b/station_cmd.c	Mon May 09 22:33:00 2005 +0000
@@ -1432,7 +1432,7 @@
 
 /** Build a bus station
  * @param x,y coordinates to build bus station at
- * @param p1 direction the busstop exit is pointing towards
+ * @param p1 busstop entrance direction (0 through 3), where 0 is NW, 1 is NE, etc.
  * @param p2 0 for Bus stops, 1 for truck stops
  */
 int32 CmdBuildRoadStop(int x, int y, uint32 flags, uint32 p1, uint32 p2)
@@ -1655,21 +1655,25 @@
 	_airport_map5_tiles_international,	// International Airport (xlarge)
 };
 
-/* Place an Airport
- * p1 - airport type
- * p2 - unused
+/** Place an Airport.
+ * @param x,y tile coordinates where airport will be built
+ * @param p1 airport type, @see airport.h
+ * @param p2 unused
  */
 int32 CmdBuildAirport(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
-	uint tile;
+	TileIndex tile;
 	Town *t;
 	Station *st;
 	int32 cost;
-	int w,h;
+	int w, h;
 	bool airport_upgrade = true;
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
+	/* Check if a valid, buildable airport was chosen for construction */
+	if (!HASBIT(GetValidAirports(), p1)) return CMD_ERROR;
+
 	tile = TILE_FROM_XY(x,y);
 
 	if (!(flags & DC_NO_TOWN_RATING) && !CheckIfAuthorityAllows(tile))
@@ -1694,17 +1698,15 @@
 	h = _airport_size_y[p1];
 
 	cost = CheckFlatLandBelow(tile, w, h, flags, 0, NULL);
-	if (cost == CMD_ERROR)
-		return CMD_ERROR;
+	if (cost == CMD_ERROR) return CMD_ERROR;
 
 	st = GetStationAround(tile, w, h, -1);
-	if (st == CHECK_STATIONS_ERR)
-		return CMD_ERROR;
+	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
 
 	/* Find a station close to us */
 	if (st == NULL) {
 		st = GetClosestStationFromTile(tile, 8, _current_player);
-		if (st!=NULL && st->facilities) st = NULL;
+		if (st != NULL && st->facilities) st = NULL;
 	}
 
 	if (st != NULL) {
@@ -1720,8 +1722,7 @@
 		airport_upgrade = false;
 
 		st = AllocateStation();
-		if (st == NULL)
-			return CMD_ERROR;
+		if (st == NULL) return CMD_ERROR;
 
 		st->town = t;
 
@@ -1732,7 +1733,7 @@
 
 		// if airport type equals Heliport then generate
 		// type 5 name, which is heliport, otherwise airport names (1)
-		if (!GenerateStationName(st, tile, p1 == AT_HELIPORT ? 5 : 1))
+		if (!GenerateStationName(st, tile, (p1 == AT_HELIPORT) ? 5 : 1))
 			return CMD_ERROR;
 
 		if (flags & DC_EXEC)
@@ -1828,10 +1829,11 @@
 	return cost;
 }
 
-/* Build a buoy
- * p1,p2 unused
+/** Build a buoy.
+ * @param x,y tile coordinates of bouy construction
+ * @param p1 unused
+ * @param p2 unused
  */
-
 int32 CmdBuildBuoy(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	TileInfo ti;
@@ -1845,14 +1847,12 @@
 		return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
 	st = AllocateStation();
-	if (st == NULL)
-		return CMD_ERROR;
+	if (st == NULL) return CMD_ERROR;
 
 	st->town = ClosestTownFromTile(ti.tile, (uint)-1);
 	st->sign.width_1 = 0;
 
-	if (!GenerateStationName(st, ti.tile, 4))
-		return CMD_ERROR;
+	if (!GenerateStationName(st, ti.tile, 4)) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
 		StationInitialize(st, ti.tile);
@@ -1946,12 +1946,17 @@
 static const byte _dock_w_chk[4] = { 2,1,2,1 };
 static const byte _dock_h_chk[4] = { 1,2,1,2 };
 
+/** Build a dock/haven.
+ * @param x,y tile coordinates where dock will be built
+ * @param p1 unused
+ * @param p2 unused
+ */
 int32 CmdBuildDock(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	TileInfo ti;
 	int direction;
 	int32 cost;
-	uint tile, tile_cur;
+	TileIndex tile, tile_cur;
 	Station *st;
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
@@ -1964,25 +1969,20 @@
 			(direction++,ti.tileh) != 6)
 		return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
-	if (!EnsureNoVehicle(ti.tile))
-		return CMD_ERROR;
+	if (!EnsureNoVehicle(ti.tile)) return CMD_ERROR;
 
 	cost = DoCommandByTile(ti.tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
-	if (cost == CMD_ERROR)
-		return CMD_ERROR;
+	if (CmdFailed(cost)) return CMD_ERROR;
 
 	tile_cur = (tile=ti.tile) + TileOffsByDir(direction);
 
-	if (!EnsureNoVehicle(tile_cur))
-		return CMD_ERROR;
+	if (!EnsureNoVehicle(tile_cur)) return CMD_ERROR;
 
 	FindLandscapeHeightByTile(&ti, tile_cur);
-	if (ti.tileh != 0 || ti.type != MP_WATER)
-		return_cmd_error(STR_304B_SITE_UNSUITABLE);
+	if (ti.tileh != 0 || ti.type != MP_WATER) return_cmd_error(STR_304B_SITE_UNSUITABLE);
 
 	cost = DoCommandByTile(tile_cur, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
-	if (cost == CMD_ERROR)
-		return CMD_ERROR;
+	if (CmdFailed(cost)) return CMD_ERROR;
 
 	tile_cur = tile_cur + TileOffsByDir(direction);
 	FindLandscapeHeightByTile(&ti, tile_cur);
@@ -1993,8 +1993,7 @@
 	st = GetStationAround(
 		tile + ToTileIndexDiff(_dock_tileoffs_chkaround[direction]),
 		_dock_w_chk[direction], _dock_h_chk[direction], -1);
-	if (st == CHECK_STATIONS_ERR)
-		return CMD_ERROR;
+	if (st == CHECK_STATIONS_ERR) return CMD_ERROR;
 
 	/* Find a station close to us */
 	if (st == NULL) {
@@ -2006,17 +2005,14 @@
 		if (st->owner != OWNER_NONE && st->owner != _current_player)
 			return_cmd_error(STR_3009_TOO_CLOSE_TO_ANOTHER_STATION);
 
-		if (!CheckStationSpreadOut(st, tile, 1, 1))
-			return CMD_ERROR;
-
-		if (st->dock_tile != 0)
-			return_cmd_error(STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK);
+		if (!CheckStationSpreadOut(st, tile, 1, 1)) return CMD_ERROR;
+
+		if (st->dock_tile != 0) return_cmd_error(STR_304C_TOO_CLOSE_TO_ANOTHER_DOCK);
 	} else {
 		Town *t;
 
 		st = AllocateStation();
-		if (st == NULL)
-			return CMD_ERROR;
+		if (st == NULL) return CMD_ERROR;
 
 		st->town = t = ClosestTownFromTile(tile, (uint)-1);
 
@@ -2025,8 +2021,7 @@
 
 		st->sign.width_1 = 0;
 
-		if (!GenerateStationName(st, tile, 3))
-			return CMD_ERROR;
+		if (!GenerateStationName(st, tile, 3)) return CMD_ERROR;
 
 		if (flags & DC_EXEC)
 			StationInitialize(st, tile);
--- a/table/tree_land.h	Mon May 09 19:56:08 2005 +0000
+++ b/table/tree_land.h	Mon May 09 22:33:00 2005 +0000
@@ -1,3 +1,6 @@
+#ifndef TREE_LAND_H
+#define TREE_LAND_H
+
 static const SpriteID _tree_sprites_1[4] = {
 	0x118D,
 	0x11A0,
@@ -5,6 +8,9 @@
 	0x11C6,
 };
 
+static const byte _tree_base_by_landscape[4] = {0, 12, 20, 32};
+static const byte _tree_count_by_landscape[4] = {12, 8, 12, 9};
+
 static const byte _tree_layout_xy[4][8] = {
 {9, 3, 1, 8, 0, 0, 8, 9},
 {4, 4, 9, 1, 6, 9, 0, 9},
@@ -211,3 +217,6 @@
 	{     0x716,      0x716,      0x6f3,      0x6ec}, /* 30 */
 	{     0x716,      0x701,      0x6fa,      0x716}, /* 31 */
 };
+
+#endif /* TREE_LAND_H */
+
--- a/town.h	Mon May 09 19:56:08 2005 +0000
+++ b/town.h	Mon May 09 22:33:00 2005 +0000
@@ -157,6 +157,11 @@
 	return _town_pool.total_items;
 }
 
+static inline bool IsTownIndex(uint index)
+{
+	return index < GetTownPoolSize();
+}
+
 #define FOR_ALL_TOWNS_FROM(t, start) for (t = GetTown(start); t != NULL; t = (t->index + 1 < GetTownPoolSize()) ? GetTown(t->index + 1) : NULL)
 #define FOR_ALL_TOWNS(t) FOR_ALL_TOWNS_FROM(t, 0)
 
--- a/train_cmd.c	Mon May 09 19:56:08 2005 +0000
+++ b/train_cmd.c	Mon May 09 22:33:00 2005 +0000
@@ -517,10 +517,11 @@
 	VehiclePositionChanged(u);
 }
 
-/* Build a railroad vehicle
- * p1 = vehicle type id
+/** Build a railroad vehicle.
+ * @param x,y tile coordinates (depot) where rail-vehicle is built
+ * @param p1 engine type id
+ * @param p2 unused
  */
-
 int32 CmdBuildRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	const RailVehicleInfo *rvi;
@@ -530,8 +531,11 @@
 	Engine *e;
 	TileIndex tile = TILE_FROM_XY(x,y);
 
+	/* Check if the engine-type is valid (for the player) */
 	if (!IsEngineBuildable(p1, VEH_Train)) return CMD_ERROR;
 
+	/* Check if the train is actually being built in a depot belonging
+	 * to the player. Doesn't matter if only the cost is queried */
 	if (!(flags & DC_QUERY_COST)) {
 		if (!IsTileDepotType(tile, TRANSPORT_RAIL)) return CMD_ERROR;
 		if (_map_owner[tile] != _current_player) return CMD_ERROR;
@@ -543,9 +547,7 @@
 
 	rvi = RailVehInfo(p1);
 
-	if (rvi->flags & RVI_WAGON) {
-		return CmdBuildRailWagon(p1, tile, flags);
-	}
+	if (rvi->flags & RVI_WAGON) return CmdBuildRailWagon(p1, tile, flags);
 
 	value = EstimateTrainCost(rvi);
 
@@ -694,10 +696,12 @@
 	return NULL;
 }
 
-/* p1 & 0xffff = source vehicle index
- * p1 & 0xffff0000 = what wagon to put the wagon AFTER,
- *   0xffff0000 to make a new line
- * p2 & 1 = move all vehicles following the vehicle..
+/** Move a rail vehicle around inside the depot.
+ * @param x,y unused
+ * @param p1 various bitstuffed elements
+ * - p1 (bit  0 - 15) source vehicle index (p1 & 0xFFFF)
+ * - p1 (bit 16 - 31) what wagon to put the source wagon AFTER (p1 & 0xFFFF0000) XXX - 0xFFFF0000 to make a new line
+ * @param p2 (bit 0) move all vehicles following the source vehicle
  */
 int32 CmdMoveRailVehicle(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
@@ -721,8 +725,7 @@
 	}
 
 	// don't move the same vehicle..
-	if (src == dst)
-		return 0;
+	if (src == dst) return 0;
 
 	/* the player must be the owner */
 	if (!CheckOwnership(src->owner) || (dst!=NULL && !CheckOwnership(dst->owner)))
@@ -741,16 +744,14 @@
 		for (u = dst_head; u != NULL; u = u->next) u->first = NULL;
 	}
 
-	/* check if all vehicles in the source train are stopped */
-	if (CheckTrainStoppedInDepot(src_head) < 0)
-		return CMD_ERROR;
+	/* check if all vehicles in the source train are stopped inside a depot */
+	if (CheckTrainStoppedInDepot(src_head) < 0) return CMD_ERROR;
 
 	/* check if all the vehicles in the dest train are stopped,
 	 * and that the length of the dest train is no longer than XXX vehicles */
 	if (dst_head != NULL) {
 		int num = CheckTrainStoppedInDepot(dst_head);
-		if (num < 0)
-			return CMD_ERROR;
+		if (num < 0) return CMD_ERROR;
 
 		if (num > (_patches.mammoth_trains ? 100 : 9) && dst_head->subtype == TS_Front_Engine )
 			return_cmd_error(STR_8819_TRAIN_TOO_LONG);
@@ -768,8 +769,7 @@
 	}
 
 	// when moving all wagons, we can't have the same src_head and dst_head
-	if (p2 & 1 && src_head == dst_head)
-		return 0;
+	if (HASBIT(p2, 0) && src_head == dst_head) return 0;
 
 	// moving a loco to a new line?, then we need to assign a unitnumber.
 	if (dst == NULL && src->subtype != TS_Front_Engine && is_loco) {
@@ -784,7 +784,7 @@
 
 	/* do it? */
 	if (flags & DC_EXEC) {
-		if (p2 & 1) {
+		if (HASBIT(p2, 0)) {
 			// unlink ALL wagons
 			if (src != src_head) {
 				Vehicle *v = src_head;
@@ -859,7 +859,11 @@
 	return 0;
 }
 
-/* p1 = train to start / stop */
+/** Start/Stop a train.
+ * @param x,y unused
+ * @param p1 train to start/stop
+ * @param p2 unused
+ */
 int32 CmdStartStopTrain(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	Vehicle *v;
@@ -868,8 +872,7 @@
 
 	v = GetVehicle(p1);
 
-	if (v->type != VEH_Train || !CheckOwnership(v->owner))
-		return CMD_ERROR;
+	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
 		v->u.rail.days_since_order_progr = 0;
@@ -901,15 +904,15 @@
 	return NULL;
 }
 
-/**
- * Sell a (single) train wagon/engine.
+/** Sell a (single) train wagon/engine.
+ * @param x,y unused
  * @param p1 the wagon/engine index
  * @param p2 the selling mode
- * - 0: only sell the single dragged wagon/engine (and any belonging rear-engines)
- * - 1: sell the vehicle and all vehicles following it in the chain
-        if the wagon is dragged, don't delete the possibly belonging rear-engine to some front
- * - 2: when selling attached locos, rearrange all vehicles after it to separate lines;
- *      all wagons of the same type will go on the same line. Used by the AI currently
+ * - p2 = 0: only sell the single dragged wagon/engine (and any belonging rear-engines)
+ * - p2 = 1: sell the vehicle and all vehicles following it in the chain
+             if the wagon is dragged, don't delete the possibly belonging rear-engine to some front
+ * - p2 = 2: when selling attached locos, rearrange all vehicles after it to separate lines;
+ *           all wagons of the same type will go on the same line. Used by the AI currently
  */
 int32 CmdSellRailWagon(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
@@ -920,16 +923,14 @@
 
 	v = GetVehicle(p1);
 
-	if (v->type != VEH_Train || !CheckOwnership(v->owner))
-		return CMD_ERROR;
+	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
 
 	SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
 
 	first = GetFirstVehicleInChain(v);
 
 	// make sure the vehicle is stopped in the depot
-	if (CheckTrainStoppedInDepot(first) < 0)
-		return CMD_ERROR;
+	if (CheckTrainStoppedInDepot(first) < 0) return CMD_ERROR;
 
 	if ((flags & DC_EXEC) && v == first && first->subtype == TS_Front_Engine) {
 		DeleteWindowById(WC_VEHICLE_VIEW, first->index);
@@ -1226,8 +1227,12 @@
 	CLRBIT(v->u.rail.flags, VRF_REVERSING);
 }
 
-/* p1 = vehicle */
-int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+/** Reverse train.
+ * @param x,y unused
+ * @param p1 train to reverse
+ * @param p2 unused
+ */
+ int32 CmdReverseTrainDirection(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	Vehicle *v;
 
@@ -1235,16 +1240,14 @@
 
 	v = GetVehicle(p1);
 
-	if (v->type != VEH_Train || !CheckOwnership(v->owner))
-		return CMD_ERROR;
+	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
 
 	_error_message = STR_EMPTY;
 
 //	if (v->u.rail.track & 0x80 || IsTileDepotType(v->tile, TRANSPORT_RAIL))
 //		return CMD_ERROR;
 
-	if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0)
-		return CMD_ERROR;
+	if (v->u.rail.crash_anim_pos != 0 || v->breakdown_ctr != 0) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
 		if (_patches.realistic_acceleration && v->cur_speed != 0) {
@@ -1258,6 +1261,11 @@
 	return 0;
 }
 
+/** Force a train through a red signal
+ * @param x,y unused
+ * @param p1 train to ignore the red signal
+ * @param p2 unused
+ */
 int32 CmdForceTrainProceed(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	Vehicle *v;
@@ -1266,8 +1274,7 @@
 
 	v = GetVehicle(p1);
 
-	if (v->type != VEH_Train || !CheckOwnership(v->owner))
-		return CMD_ERROR;
+	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
 
 	if (flags & DC_EXEC)
 		v->u.rail.force_proceed = 0x50;
@@ -1421,6 +1428,11 @@
 	return tfdd;
 }
 
+/** Send a train to a depot
+ * @param x,y unused
+ * @param p1 train to send to the depot
+ * @param p2 unused
+ */
 int32 CmdTrainGotoDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
 	Vehicle *v;
@@ -1430,11 +1442,9 @@
 
 	v = GetVehicle(p1);
 
-	if (v->type != VEH_Train || !CheckOwnership(v->owner))
-		return CMD_ERROR;
-
-	if (v->vehstatus & VS_CRASHED)
-		return CMD_ERROR;
+	if (v->type != VEH_Train || !CheckOwnership(v->owner)) return CMD_ERROR;
+
+	if (v->vehstatus & VS_CRASHED) return CMD_ERROR;
 
 	if (v->current_order.type == OT_GOTO_DEPOT) {
 		if (flags & DC_EXEC) {
--- a/tree_cmd.c	Mon May 09 19:56:08 2005 +0000
+++ b/tree_cmd.c	Mon May 09 22:33:00 2005 +0000
@@ -1,6 +1,7 @@
 #include "stdafx.h"
 #include "ttd.h"
 #include "table/strings.h"
+#include "table/tree_land.h"
 #include "map.h"
 #include "tile.h"
 #include "viewport.h"
@@ -142,11 +143,11 @@
 	} while (--i);
 }
 
-/* Plant a tree
- * p1 = tree type, -1 means random.
- * p2 = end tile
+/** Plant a tree.
+ * @param x,y start tile of area-drag of tree plantation
+ * @param p1 tree type, -1 means random.
+ * @param p2 end tile of area-drag
  */
-
 int32 CmdPlantTree(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
 {
 	int32 cost;
@@ -155,7 +156,9 @@
 	int x;
 	int y;
 
-	if (p2 >= MapSize()) return CMD_ERROR;
+	if (p2 > MapSize()) return CMD_ERROR;
+	/* Check the tree type. It can be random or some valid value within the current climate */
+	if (p1 != (uint)-1 && p1 - _tree_base_by_landscape[_opt.landscape] >= _tree_count_by_landscape[_opt.landscape]) return CMD_ERROR;
 
 	SET_EXPENSES_TYPE(EXPENSES_OTHER);
 
@@ -254,8 +257,7 @@
 		}
 	}
 
-	if (cost == 0) return CMD_ERROR;
-	return cost;
+	return (cost == 0) ? CMD_ERROR : cost;
 }
 
 typedef struct TreeListEnt {
@@ -263,10 +265,6 @@
 	byte x,y;
 } TreeListEnt;
 
-
-#include "table/tree_land.h"
-
-
 static void DrawTile_Trees(TileInfo *ti)
 {
 	uint16 m2;
--- a/tunnelbridge_cmd.c	Mon May 09 19:56:08 2005 +0000
+++ b/tunnelbridge_cmd.c	Mon May 09 22:33:00 2005 +0000
@@ -533,7 +533,7 @@
 
 /** Build Tunnel.
  * @param x,y start tile coord of tunnel
- * @param p1 railtype
+ * @param p1 railtype, 0x200 for road tunnel
  * @param p2 unused (XXX - ptr to uint that recieves end tile; wtf?????)
  */
 int32 CmdBuildTunnel(int x, int y, uint32 flags, uint32 p1, uint32 p2)
@@ -547,7 +547,7 @@
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
-	if (!ValParamRailtype(p1)) return CMD_ERROR;
+	if (p1 != 0x200 && !ValParamRailtype(p1)) return CMD_ERROR;
 
 	_build_tunnel_railtype = (byte)(p1 & 0xFF);
 	_build_tunnel_bh = (byte)(p1 >> 8);
--- a/water_cmd.c	Mon May 09 19:56:08 2005 +0000
+++ b/water_cmd.c	Mon May 09 22:33:00 2005 +0000
@@ -22,42 +22,41 @@
 	return (ti.type == MP_WATER && ti.tileh == 0 && ti.map5 == 0);
 }
 
-/* Build a ship depot
- * p1 - direction
+/** Build a ship depot.
+ * @param x,y tile coordinates where ship depot is built
+ * @param p1 depot direction (0 through 3), where 0 is NW, 1 is NE, etc.
+ * @param p2 unused
  */
-
 int32 CmdBuildShipDepot(int x, int y, uint32 flags, uint32 p1, uint32 p2)
 {
-	uint tile, tile2;
+	TileIndex tile, tile2;
 
 	int32 cost, ret;
 	Depot *depot;
 
 	SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
 
+	if (p1 > 3) return CMD_ERROR;
+
 	tile = TILE_FROM_XY(x,y);
-	if (!EnsureNoVehicle(tile))
-		return CMD_ERROR;
+	if (!EnsureNoVehicle(tile)) return CMD_ERROR;
 
 	tile2 = tile + (p1 ? TILE_XY(0,1) : TILE_XY(1,0));
-	if (!EnsureNoVehicle(tile2))
-		return CMD_ERROR;
+	if (!EnsureNoVehicle(tile2)) return CMD_ERROR;
 
 	if (!IsClearWaterTile(tile) || !IsClearWaterTile(tile2))
 		return_cmd_error(STR_3801_MUST_BE_BUILT_ON_WATER);
 
 	ret = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
-	if (ret == CMD_ERROR) return CMD_ERROR;
+	if (CmdFailed(ret)) return CMD_ERROR;
 	ret = DoCommandByTile(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
-	if (ret == CMD_ERROR)
-		return CMD_ERROR;
+	if (CmdFailed(ret)) return CMD_ERROR;
 
 	// pretend that we're not making land from the water even though we actually are.
 	cost = 0;
 
 	depot = AllocateDepot();
-	if (depot == NULL)
-		return CMD_ERROR;
+	if (depot == NULL) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
 		depot->xy = tile;