src/ai/api/ai_road.cpp
author truebrain
Fri, 22 Feb 2008 12:30:17 +0000
branchnoai
changeset 9737 ee408edf3851
parent 9723 eee46cb39750
child 9801 03a3eebd7fb7
permissions -rw-r--r--
(svn r12216) [NoAI] -Codechange: made most functions 'static', which removes the need to create an instance to get, for example, engine information, and therefor heavily simplifying AI creation (Morloth)
/* $Id$ */

/** @file ai_road.cpp handles the functions of the AIRoad class */

#include "ai_road.hpp"
#include "../../road_map.h"
#include "../../station_map.h"

/* static */ bool AIRoad::IsRoadTile(TileIndex tile)
{
	/* Outside of the map */
	if (tile >= ::MapSize()) return false;

	return (::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) != ROAD_TILE_DEPOT) ||
			IsDriveThroughRoadStationTile(tile);
}

/* static */ bool AIRoad::IsRoadDepotTile(TileIndex tile)
{
	/* Outside of the map */
	if (tile >= ::MapSize()) return false;

	return ::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) == ROAD_TILE_DEPOT;
}

/* static */ bool AIRoad::IsRoadStationTile(TileIndex tile)
{
	/* Outside of the map */
	if (tile >= ::MapSize()) return false;

	return ::IsRoadStopTile(tile);
}

/* static */ bool AIRoad::IsDriveThroughRoadStationTile(TileIndex tile)
{
	/* Outside of the map */
	if (tile >= ::MapSize()) return false;

	return ::IsDriveThroughStopTile(tile);
}

/* static */ bool AIRoad::AreRoadTilesConnected(TileIndex t1, TileIndex t2)
{
	/* Outside of the map */
	if (t1 >= ::MapSize() || t2 >= ::MapSize()) return false;

	/* Tiles not neighbouring */
	if ((abs((int)::TileX(t1) - (int)::TileX(t2)) + abs((int)::TileY(t1) - (int)::TileY(t2))) != 1) return false;

	RoadBits r1 = ::GetAnyRoadBits(t1, ROADTYPE_ROAD);
	RoadBits r2 = ::GetAnyRoadBits(t2, ROADTYPE_ROAD);

	DiagDirection dir_1 = (DiagDirection)((::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3));
	DiagDirection dir_2 = ::ReverseDiagDir(dir_1);

	return HasBit(r1, dir_1) && HasBit(r2, dir_2);
}

/* static */ int32 AIRoad::GetNeighbourRoadCount(TileIndex tile)
{
	/* Outside of the map */
	if (tile >= ::MapSize()) return false;

	int32 neighbour = 0;

	if (::IsTileType(tile + ::TileDiffXY(-1, 0), MP_ROAD) && ::GetRoadTileType(tile + ::TileDiffXY(-1, 0)) != ROAD_TILE_DEPOT) neighbour++;
	if (::IsTileType(tile + ::TileDiffXY( 1, 0), MP_ROAD) && ::GetRoadTileType(tile + ::TileDiffXY( 1, 0)) != ROAD_TILE_DEPOT) neighbour++;
	if (::IsTileType(tile + ::TileDiffXY( 0,-1), MP_ROAD) && ::GetRoadTileType(tile + ::TileDiffXY( 0,-1)) != ROAD_TILE_DEPOT) neighbour++;
	if (::IsTileType(tile + ::TileDiffXY( 0, 1), MP_ROAD) && ::GetRoadTileType(tile + ::TileDiffXY( 0, 1)) != ROAD_TILE_DEPOT) neighbour++;

	return neighbour;
}

/* static */ TileIndex AIRoad::GetRoadDepotFrontTile(TileIndex depot)
{
	if (!IsRoadDepotTile(depot)) return INVALID_TILE;

	return depot + ::TileOffsByDiagDir(::GetRoadDepotDirection(depot));
}

/* static */ TileIndex AIRoad::GetRoadStationFrontTile(TileIndex station)
{
	if (!IsRoadStationTile(station)) return INVALID_TILE;

	return station + ::TileOffsByDiagDir(::GetRoadStopDir(station));
}

/* static */ TileIndex AIRoad::GetDriveThroughBackTile(TileIndex station)
{
	if (!IsDriveThroughRoadStationTile(station)) return INVALID_TILE;

	return station + ::TileOffsByDiagDir(::ReverseDiagDir(::GetRoadStopDir(station)));
}

/* static */ bool AIRoad::BuildRoad(TileIndex start, TileIndex end)
{
	/* Outside of the map */
	if (start >= ::MapSize() || end >= ::MapSize() || start == end) return false;
	/* Not on one line */
	if (TileX(start) != TileX(end) &&
			TileY(start) != TileY(end)) return false;

	return AIObject::DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (ROADTYPE_ROAD << 3), CMD_BUILD_LONG_ROAD);
}

/* static */ bool AIRoad::BuildRoadFull(TileIndex start, TileIndex end)
{
	/* Outside of the map */
	if (start >= ::MapSize() || end >= ::MapSize() || start == end) return false;
	/* Not on one line */
	if (TileX(start) != TileX(end) &&
			TileY(start) != TileY(end)) return false;

	return AIObject::DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 2 : 1), CMD_BUILD_LONG_ROAD);
}

/* static */ bool AIRoad::BuildRoadDepot(TileIndex tile, TileIndex front)
{
	/* Outside of the map */
	if (tile >= ::MapSize() || tile == front) return false;

	uint entrance_dir = (TileX(tile) == TileX(front)) ? (TileY(tile) < TileY(front) ? 1 : 3) : (TileX(tile) < TileX(front) ? 2 : 0);

	return AIObject::DoCommand(tile, entrance_dir, ROADTYPE_ROAD << 2, CMD_BUILD_ROAD_DEPOT);
}

/* static */ bool AIRoad::BuildRoadStation(TileIndex tile, TileIndex front, bool truck, bool drive_through)
{
	/* Outside of the map */
	if (tile >= ::MapSize() || tile == front) return false;

	uint entrance_dir;
	if (drive_through) {
		entrance_dir = TileY(tile) != TileY(front);
	} else {
		entrance_dir = (TileX(tile) == TileX(front)) ? (TileY(tile) < TileY(front) ? 1 : 3) : (TileX(tile) < TileX(front) ? 2 : 0);
	}

	return AIObject::DoCommand(tile, entrance_dir, (drive_through ? 2 : 0) | (truck ? 1 : 0) | (ROADTYPES_ROAD << 2), CMD_BUILD_ROAD_STOP);
}

/* static */ bool AIRoad::RemoveRoad(TileIndex start, TileIndex end)
{
	/* Outside of the map */
	if (start >= ::MapSize() || end >= ::MapSize()) return false;
	/* Not on one line */
	if (TileX(start) != TileX(end) &&
			TileY(start) != TileY(end)) return false;

	return AIObject::DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (ROADTYPE_ROAD << 3), CMD_REMOVE_LONG_ROAD);
}

/* static */ bool AIRoad::RemoveRoadFull(TileIndex start, TileIndex end)
{
	/* Outside of the map */
	if (start >= ::MapSize() || end >= ::MapSize()) return false;
	/* Not on one line */
	if (TileX(start) != TileX(end) &&
			TileY(start) != TileY(end)) return false;

	return AIObject::DoCommand(end, start, (TileY(start) != TileY(end) ? 4 : 0) | (start < end ? 2 : 1), CMD_REMOVE_LONG_ROAD);
}

/* static */ bool AIRoad::RemoveRoadDepot(TileIndex tile)
{
	/* Outside of the map */
	if (tile >= ::MapSize()) return false;

	/* Not a road depot tile */
	if (!IsTileType(tile, MP_ROAD) || GetRoadTileType(tile) != ROAD_TILE_DEPOT) return false;

	return AIObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
}

/* static */ bool AIRoad::RemoveRoadStation(TileIndex tile)
{
	/* Outside of the map */
	if (tile >= ::MapSize()) return false;

	/* Not a road station tile */
	if (!IsTileType(tile, MP_STATION) || !IsRoadStop(tile)) return false;

	return AIObject::DoCommand(tile, 0, GetRoadStopType(tile), CMD_REMOVE_ROAD_STOP);
}