(svn r111) -Fix: converted all linebreaks to UNIX-linebreak (\n)
This commit is contained in:
		
							
								
								
									
										486
									
								
								ai.h
									
									
									
									
									
								
							
							
						
						
									
										486
									
								
								ai.h
									
									
									
									
									
								
							@@ -1,243 +1,243 @@
 | 
				
			|||||||
#ifndef AI_H
 | 
					#ifndef AI_H
 | 
				
			||||||
#define AI_H
 | 
					#define AI_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "aystar.h"
 | 
					#include "aystar.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * These defines can be altered to change the behavoir of the AI
 | 
					 * These defines can be altered to change the behavoir of the AI
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * WARNING:
 | 
					 * WARNING:
 | 
				
			||||||
 *   This can also alter the AI in a negative way. I will never claim these settings
 | 
					 *   This can also alter the AI in a negative way. I will never claim these settings
 | 
				
			||||||
 *   are perfect, but don't change them if you don't know what the effect is.
 | 
					 *   are perfect, but don't change them if you don't know what the effect is.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
// How many times it the H multiplied. The higher, the more it will go straight to the
 | 
					// How many times it the H multiplied. The higher, the more it will go straight to the
 | 
				
			||||||
//   end point. The lower, how more it will find the route with the lowest cost.
 | 
					//   end point. The lower, how more it will find the route with the lowest cost.
 | 
				
			||||||
//   also: the lower, the longer it takes before route is calculated..
 | 
					//   also: the lower, the longer it takes before route is calculated..
 | 
				
			||||||
#define AI_PATHFINDER_H_MULTIPLER 100
 | 
					#define AI_PATHFINDER_H_MULTIPLER 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// How many loops may AyStar do before it stops
 | 
					// How many loops may AyStar do before it stops
 | 
				
			||||||
//   0 = infinite
 | 
					//   0 = infinite
 | 
				
			||||||
#define AI_PATHFINDER_LOOPS_PER_TICK 5
 | 
					#define AI_PATHFINDER_LOOPS_PER_TICK 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// How long may the AI search for one route?
 | 
					// How long may the AI search for one route?
 | 
				
			||||||
//   0 = infinite
 | 
					//   0 = infinite
 | 
				
			||||||
// This number is the number of tiles tested.
 | 
					// This number is the number of tiles tested.
 | 
				
			||||||
//  It takes (AI_PATHFINDER_MAX_SEARCH_NODES / AI_PATHFINDER_LOOPS_PER_TICK) ticks
 | 
					//  It takes (AI_PATHFINDER_MAX_SEARCH_NODES / AI_PATHFINDER_LOOPS_PER_TICK) ticks
 | 
				
			||||||
//  to get here.. with 5000 / 10 = 500. 500 / 74 (one day) = 8 days till it aborts
 | 
					//  to get here.. with 5000 / 10 = 500. 500 / 74 (one day) = 8 days till it aborts
 | 
				
			||||||
//   (that is: if the AI is on VERY FAST! :p
 | 
					//   (that is: if the AI is on VERY FAST! :p
 | 
				
			||||||
#define AI_PATHFINDER_MAX_SEARCH_NODES 5000
 | 
					#define AI_PATHFINDER_MAX_SEARCH_NODES 5000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// If you enable this, the AI is not allowed to make 90degree turns
 | 
					// If you enable this, the AI is not allowed to make 90degree turns
 | 
				
			||||||
#define AI_PATHFINDER_NO_90DEGREES_TURN
 | 
					#define AI_PATHFINDER_NO_90DEGREES_TURN
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Below are defines for the g-calculation
 | 
					// Below are defines for the g-calculation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Standard penalty given to a tile
 | 
					// Standard penalty given to a tile
 | 
				
			||||||
#define AI_PATHFINDER_PENALTY 150
 | 
					#define AI_PATHFINDER_PENALTY 150
 | 
				
			||||||
// The penalty given to a tile that is going up
 | 
					// The penalty given to a tile that is going up
 | 
				
			||||||
#define AI_PATHFINDER_TILE_GOES_UP_PENALTY 450
 | 
					#define AI_PATHFINDER_TILE_GOES_UP_PENALTY 450
 | 
				
			||||||
// Changing direction is a penalty, to prevent curved ways (with that: slow ways)
 | 
					// Changing direction is a penalty, to prevent curved ways (with that: slow ways)
 | 
				
			||||||
#define AI_PATHFINDER_DIRECTION_CHANGE_PENALTY 200
 | 
					#define AI_PATHFINDER_DIRECTION_CHANGE_PENALTY 200
 | 
				
			||||||
// Same penalty, only for when road already exists
 | 
					// Same penalty, only for when road already exists
 | 
				
			||||||
#define AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY 50
 | 
					#define AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY 50
 | 
				
			||||||
// A diagonal track cost the same as a straigh, but a diagonal is faster... so give
 | 
					// A diagonal track cost the same as a straigh, but a diagonal is faster... so give
 | 
				
			||||||
//  a bonus for using diagonal track
 | 
					//  a bonus for using diagonal track
 | 
				
			||||||
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
 | 
					#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
 | 
				
			||||||
#define AI_PATHFINDER_DIAGONAL_BONUS 95
 | 
					#define AI_PATHFINDER_DIAGONAL_BONUS 95
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#define AI_PATHFINDER_DIAGONAL_BONUS 75
 | 
					#define AI_PATHFINDER_DIAGONAL_BONUS 75
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
// If a roadblock already exists, it gets a bonus
 | 
					// If a roadblock already exists, it gets a bonus
 | 
				
			||||||
#define AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS 140
 | 
					#define AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS 140
 | 
				
			||||||
// To prevent 3 direction changes in 3 tiles, this penalty is given in such situation
 | 
					// To prevent 3 direction changes in 3 tiles, this penalty is given in such situation
 | 
				
			||||||
#define AI_PATHFINDER_CURVE_PENALTY 200
 | 
					#define AI_PATHFINDER_CURVE_PENALTY 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Penalty a bridge gets per length
 | 
					// Penalty a bridge gets per length
 | 
				
			||||||
#define AI_PATHFINDER_BRIDGE_PENALTY 180
 | 
					#define AI_PATHFINDER_BRIDGE_PENALTY 180
 | 
				
			||||||
// The penalty for a bridge going up
 | 
					// The penalty for a bridge going up
 | 
				
			||||||
#define AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY 1000
 | 
					#define AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY 1000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Tunnels are expensive...
 | 
					// Tunnels are expensive...
 | 
				
			||||||
//  Because of that, every tile the cost is increased with 1/8th of his value
 | 
					//  Because of that, every tile the cost is increased with 1/8th of his value
 | 
				
			||||||
//  This is also true if you are building a tunnel yourself
 | 
					//  This is also true if you are building a tunnel yourself
 | 
				
			||||||
#define AI_PATHFINDER_TUNNEL_PENALTY 350
 | 
					#define AI_PATHFINDER_TUNNEL_PENALTY 350
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Ai_New defines
 | 
					 * Ai_New defines
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// How long may we search cities and industry for a new route?
 | 
					// How long may we search cities and industry for a new route?
 | 
				
			||||||
#define AI_LOCATE_ROUTE_MAX_COUNTER 200
 | 
					#define AI_LOCATE_ROUTE_MAX_COUNTER 200
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// How many days must there be between building the first station and the second station
 | 
					// How many days must there be between building the first station and the second station
 | 
				
			||||||
//  within one city. This number is in days and should be more then 4 months.
 | 
					//  within one city. This number is in days and should be more then 4 months.
 | 
				
			||||||
#define AI_CHECKCITY_DATE_BETWEEN 180
 | 
					#define AI_CHECKCITY_DATE_BETWEEN 180
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// How many cargo is needed for one station in a city?
 | 
					// How many cargo is needed for one station in a city?
 | 
				
			||||||
#define AI_CHECKCITY_CARGO_PER_STATION 60
 | 
					#define AI_CHECKCITY_CARGO_PER_STATION 60
 | 
				
			||||||
// How much cargo must there not be used in a city before we can build a new station?
 | 
					// How much cargo must there not be used in a city before we can build a new station?
 | 
				
			||||||
#define AI_CHECKCITY_NEEDED_CARGO 50
 | 
					#define AI_CHECKCITY_NEEDED_CARGO 50
 | 
				
			||||||
// When there is already a station which takes the same good and the rating of that
 | 
					// When there is already a station which takes the same good and the rating of that
 | 
				
			||||||
//  city is higher then this numer, we are not going to attempt to build anything
 | 
					//  city is higher then this numer, we are not going to attempt to build anything
 | 
				
			||||||
//  there
 | 
					//  there
 | 
				
			||||||
#define AI_CHECKCITY_CARGO_RATING 50
 | 
					#define AI_CHECKCITY_CARGO_RATING 50
 | 
				
			||||||
// But, there is a chance of 1 out of this number, that we do ;)
 | 
					// But, there is a chance of 1 out of this number, that we do ;)
 | 
				
			||||||
#define AI_CHECKCITY_CARGO_RATING_CHANCE 5
 | 
					#define AI_CHECKCITY_CARGO_RATING_CHANCE 5
 | 
				
			||||||
// If a city is too small to contain a station, there is a small chance
 | 
					// If a city is too small to contain a station, there is a small chance
 | 
				
			||||||
//  that we still do so.. just to make the city bigger!
 | 
					//  that we still do so.. just to make the city bigger!
 | 
				
			||||||
#define AI_CHECKCITY_CITY_CHANCE 5
 | 
					#define AI_CHECKCITY_CITY_CHANCE 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This number indicates for every unit of cargo, how many tiles two stations maybe be away
 | 
					// This number indicates for every unit of cargo, how many tiles two stations maybe be away
 | 
				
			||||||
//  from eachother. In other words: if we have 120 units of cargo in one station, and 120 units
 | 
					//  from eachother. In other words: if we have 120 units of cargo in one station, and 120 units
 | 
				
			||||||
//  of the cargo in the other station, both stations can be 96 units away from eachother, if the
 | 
					//  of the cargo in the other station, both stations can be 96 units away from eachother, if the
 | 
				
			||||||
//  next number is 0.4.
 | 
					//  next number is 0.4.
 | 
				
			||||||
#define AI_LOCATEROUTE_BUS_CARGO_DISTANCE 0.4
 | 
					#define AI_LOCATEROUTE_BUS_CARGO_DISTANCE 0.4
 | 
				
			||||||
#define AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE 0.7
 | 
					#define AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE 0.7
 | 
				
			||||||
// In whole tiles, the minimum distance for a truck route
 | 
					// In whole tiles, the minimum distance for a truck route
 | 
				
			||||||
#define AI_LOCATEROUTE_TRUCK_MIN_DISTANCE 30
 | 
					#define AI_LOCATEROUTE_TRUCK_MIN_DISTANCE 30
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The amount of tiles in a square from -X to +X that is scanned for a station spot
 | 
					// The amount of tiles in a square from -X to +X that is scanned for a station spot
 | 
				
			||||||
//  (so if this number is 10, 20x20 = 400 tiles are scanned for _the_ perfect spot
 | 
					//  (so if this number is 10, 20x20 = 400 tiles are scanned for _the_ perfect spot
 | 
				
			||||||
// Safe values are between 15 and 5
 | 
					// Safe values are between 15 and 5
 | 
				
			||||||
#define AI_FINDSTATION_TILE_RANGE 10
 | 
					#define AI_FINDSTATION_TILE_RANGE 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Building on normal speed goes very fast. Idle this amount of ticks between every
 | 
					// Building on normal speed goes very fast. Idle this amount of ticks between every
 | 
				
			||||||
//  building part. It is calculated like this: (4 - competitor_speed) * num + 1
 | 
					//  building part. It is calculated like this: (4 - competitor_speed) * num + 1
 | 
				
			||||||
//  where competitor_speed is between 0 (very slow) to 4 (very fast)
 | 
					//  where competitor_speed is between 0 (very slow) to 4 (very fast)
 | 
				
			||||||
#define AI_BUILDPATH_PAUSE 10
 | 
					#define AI_BUILDPATH_PAUSE 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Minimum % of reliabilty a vehicle has to have before the AI buys it
 | 
					// Minimum % of reliabilty a vehicle has to have before the AI buys it
 | 
				
			||||||
#define AI_VEHICLE_MIN_RELIABILTY 60
 | 
					#define AI_VEHICLE_MIN_RELIABILTY 60
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The minimum amount of money a player should always have
 | 
					// The minimum amount of money a player should always have
 | 
				
			||||||
#define AI_MINIMUM_MONEY 15000
 | 
					#define AI_MINIMUM_MONEY 15000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// If the most cheap route is build, how much is it going to cost..
 | 
					// If the most cheap route is build, how much is it going to cost..
 | 
				
			||||||
// This is to prevent the AI from trying to build a route which can not be paid for
 | 
					// This is to prevent the AI from trying to build a route which can not be paid for
 | 
				
			||||||
#define AI_MINIMUM_BUS_ROUTE_MONEY 25000
 | 
					#define AI_MINIMUM_BUS_ROUTE_MONEY 25000
 | 
				
			||||||
#define AI_MINIMUM_TRUCK_ROUTE_MONEY 35000
 | 
					#define AI_MINIMUM_TRUCK_ROUTE_MONEY 35000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The minimum amount of money before we are going to repay any money
 | 
					// The minimum amount of money before we are going to repay any money
 | 
				
			||||||
#define AI_MINIMUM_LOAN_REPAY_MONEY 40000
 | 
					#define AI_MINIMUM_LOAN_REPAY_MONEY 40000
 | 
				
			||||||
// How many repays do we do if we have enough money to do so?
 | 
					// How many repays do we do if we have enough money to do so?
 | 
				
			||||||
//  Every repay is 10000
 | 
					//  Every repay is 10000
 | 
				
			||||||
#define AI_LOAN_REPAY 2
 | 
					#define AI_LOAN_REPAY 2
 | 
				
			||||||
// How much income must we have before paying back a loan? Month-based (and looked at the last month)
 | 
					// How much income must we have before paying back a loan? Month-based (and looked at the last month)
 | 
				
			||||||
#define AI_MINIMUM_INCOME_FOR_LOAN 7000
 | 
					#define AI_MINIMUM_INCOME_FOR_LOAN 7000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// If there is <num> time as much cargo in the station then the vehicle can handle
 | 
					// If there is <num> time as much cargo in the station then the vehicle can handle
 | 
				
			||||||
//  reuse the station instead of building a new one!
 | 
					//  reuse the station instead of building a new one!
 | 
				
			||||||
#define AI_STATION_REUSE_MULTIPLER 2
 | 
					#define AI_STATION_REUSE_MULTIPLER 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// No more then this amount of vehicles per station..
 | 
					// No more then this amount of vehicles per station..
 | 
				
			||||||
#define AI_CHECK_MAX_VEHICLE_PER_STATION 10
 | 
					#define AI_CHECK_MAX_VEHICLE_PER_STATION 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// How many thick between building 2 vehicles
 | 
					// How many thick between building 2 vehicles
 | 
				
			||||||
#define AI_BUILD_VEHICLE_TIME_BETWEEN 74
 | 
					#define AI_BUILD_VEHICLE_TIME_BETWEEN 74
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * End of defines
 | 
					 * End of defines
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This stops 90degrees curves
 | 
					// This stops 90degrees curves
 | 
				
			||||||
static const byte _illegal_curves[6] = {
 | 
					static const byte _illegal_curves[6] = {
 | 
				
			||||||
    255, 255, // Horz and vert, don't have the effect
 | 
					    255, 255, // Horz and vert, don't have the effect
 | 
				
			||||||
    5, // upleft and upright are not valid
 | 
					    5, // upleft and upright are not valid
 | 
				
			||||||
    4, // downright and downleft are not valid
 | 
					    4, // downright and downleft are not valid
 | 
				
			||||||
    2, // downleft and upleft are not valid
 | 
					    2, // downleft and upleft are not valid
 | 
				
			||||||
    3, // upright and downright are not valid
 | 
					    3, // upright and downright are not valid
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const TileIndexDiff _tiles_around[4] = {
 | 
					static const TileIndexDiff _tiles_around[4] = {
 | 
				
			||||||
    TILE_XY(-1,0),
 | 
					    TILE_XY(-1,0),
 | 
				
			||||||
    TILE_XY(0,1),
 | 
					    TILE_XY(0,1),
 | 
				
			||||||
    TILE_XY(1,0),
 | 
					    TILE_XY(1,0),
 | 
				
			||||||
    TILE_XY(0,-1),
 | 
					    TILE_XY(0,-1),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    AI_STATE_STARTUP = 0,
 | 
					    AI_STATE_STARTUP = 0,
 | 
				
			||||||
    AI_STATE_FIRST_TIME,
 | 
					    AI_STATE_FIRST_TIME,
 | 
				
			||||||
    AI_STATE_NOTHING,
 | 
					    AI_STATE_NOTHING,
 | 
				
			||||||
    AI_STATE_WAKE_UP,
 | 
					    AI_STATE_WAKE_UP,
 | 
				
			||||||
    AI_STATE_LOCATE_ROUTE,
 | 
					    AI_STATE_LOCATE_ROUTE,
 | 
				
			||||||
    AI_STATE_FIND_STATION,
 | 
					    AI_STATE_FIND_STATION,
 | 
				
			||||||
    AI_STATE_FIND_PATH,
 | 
					    AI_STATE_FIND_PATH,
 | 
				
			||||||
    AI_STATE_FIND_DEPOT,
 | 
					    AI_STATE_FIND_DEPOT,
 | 
				
			||||||
    AI_STATE_VERIFY_ROUTE,
 | 
					    AI_STATE_VERIFY_ROUTE,
 | 
				
			||||||
    AI_STATE_BUILD_STATION,
 | 
					    AI_STATE_BUILD_STATION,
 | 
				
			||||||
    AI_STATE_BUILD_PATH,
 | 
					    AI_STATE_BUILD_PATH,
 | 
				
			||||||
    AI_STATE_BUILD_DEPOT,
 | 
					    AI_STATE_BUILD_DEPOT,
 | 
				
			||||||
    AI_STATE_BUILD_VEHICLE,
 | 
					    AI_STATE_BUILD_VEHICLE,
 | 
				
			||||||
    AI_STATE_GIVE_ORDERS,
 | 
					    AI_STATE_GIVE_ORDERS,
 | 
				
			||||||
    AI_STATE_START_VEHICLE,
 | 
					    AI_STATE_START_VEHICLE,
 | 
				
			||||||
    AI_STATE_REPAY_MONEY,
 | 
					    AI_STATE_REPAY_MONEY,
 | 
				
			||||||
    AI_STATE_ACTION_DONE,
 | 
					    AI_STATE_ACTION_DONE,
 | 
				
			||||||
    AI_STATE_STOP, // Temporary function to stop the AI
 | 
					    AI_STATE_STOP, // Temporary function to stop the AI
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Used for tbt (train/bus/truck)
 | 
					// Used for tbt (train/bus/truck)
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	AI_TRAIN = 0,
 | 
						AI_TRAIN = 0,
 | 
				
			||||||
	AI_BUS,
 | 
						AI_BUS,
 | 
				
			||||||
	AI_TRUCK,
 | 
						AI_TRUCK,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	AI_ACTION_NONE = 0,
 | 
						AI_ACTION_NONE = 0,
 | 
				
			||||||
	AI_ACTION_BUS_ROUTE,
 | 
						AI_ACTION_BUS_ROUTE,
 | 
				
			||||||
	AI_ACTION_TRUCK_ROUTE,
 | 
						AI_ACTION_TRUCK_ROUTE,
 | 
				
			||||||
	AI_ACTION_REPAY_LOAN,
 | 
						AI_ACTION_REPAY_LOAN,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Used for from_type/to_type
 | 
					// Used for from_type/to_type
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    AI_NO_TYPE = 0,
 | 
					    AI_NO_TYPE = 0,
 | 
				
			||||||
	AI_CITY,
 | 
						AI_CITY,
 | 
				
			||||||
	AI_INDUSTRY,
 | 
						AI_INDUSTRY,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define AI_NO_CARGO 0xFF // Means that there is no cargo defined yet (used for industry)
 | 
					#define AI_NO_CARGO 0xFF // Means that there is no cargo defined yet (used for industry)
 | 
				
			||||||
#define AI_NEED_CARGO 0xFE // Used when the AI needs to find out a cargo for the route
 | 
					#define AI_NEED_CARGO 0xFE // Used when the AI needs to find out a cargo for the route
 | 
				
			||||||
#define AI_STATION_RANGE TILE_XY(TILE_X_MAX, TILE_Y_MAX)
 | 
					#define AI_STATION_RANGE TILE_XY(TILE_X_MAX, TILE_Y_MAX)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define AI_PATHFINDER_NO_DIRECTION (byte)-1
 | 
					#define AI_PATHFINDER_NO_DIRECTION (byte)-1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Flags used in user_data
 | 
					// Flags used in user_data
 | 
				
			||||||
#define AI_PATHFINDER_FLAG_BRIDGE 1
 | 
					#define AI_PATHFINDER_FLAG_BRIDGE 1
 | 
				
			||||||
#define AI_PATHFINDER_FLAG_TUNNEL 2
 | 
					#define AI_PATHFINDER_FLAG_TUNNEL 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// A macro for mp_street, where 0x20 is depot
 | 
					// A macro for mp_street, where 0x20 is depot
 | 
				
			||||||
//   mp_tunnelbridge, where 0xf0 is a bridge, and 0x4/0x2 means: roadtunnel/bridge
 | 
					//   mp_tunnelbridge, where 0xf0 is a bridge, and 0x4/0x2 means: roadtunnel/bridge
 | 
				
			||||||
#define AI_PATHFINDER_IS_ROAD(tile) ((IS_TILETYPE(tile, MP_STREET) && !(_map5[tile] & 0x20)) || \
 | 
					#define AI_PATHFINDER_IS_ROAD(tile) ((IS_TILETYPE(tile, MP_STREET) && !(_map5[tile] & 0x20)) || \
 | 
				
			||||||
(IS_TILETYPE(tile, MP_TUNNELBRIDGE) && \
 | 
					(IS_TILETYPE(tile, MP_TUNNELBRIDGE) && \
 | 
				
			||||||
	(((_map5[tile] & 0x80) == 0 && (_map5[tile] & 0x4) == 0x4) || \
 | 
						(((_map5[tile] & 0x80) == 0 && (_map5[tile] & 0x4) == 0x4) || \
 | 
				
			||||||
	 ((_map5[tile] & 0x80) != 0 && (_map5[tile] & 0x2) == 0x2))))
 | 
						 ((_map5[tile] & 0x80) != 0 && (_map5[tile] & 0x2) == 0x2))))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef void AiNew_StateFunction(Player *p);
 | 
					typedef void AiNew_StateFunction(Player *p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ai_new.c
 | 
					// ai_new.c
 | 
				
			||||||
void AiNewDoGameLoop(Player *p);
 | 
					void AiNewDoGameLoop(Player *p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ai_pathfinder.c
 | 
					// ai_pathfinder.c
 | 
				
			||||||
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo);
 | 
					AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo);
 | 
				
			||||||
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo);
 | 
					void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ai_shared.c
 | 
					// ai_shared.c
 | 
				
			||||||
int AiNew_GetRailDirection(uint tile_a, uint tile_b, uint tile_c);
 | 
					int AiNew_GetRailDirection(uint tile_a, uint tile_b, uint tile_c);
 | 
				
			||||||
int AiNew_GetRoadDirection(uint tile_a, uint tile_b, uint tile_c);
 | 
					int AiNew_GetRoadDirection(uint tile_a, uint tile_b, uint tile_c);
 | 
				
			||||||
int AiNew_GetDirection(uint tile_a, uint tile_b);
 | 
					int AiNew_GetDirection(uint tile_a, uint tile_b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ai_build.c
 | 
					// ai_build.c
 | 
				
			||||||
bool AiNew_Build_CompanyHQ(Player *p, uint tile);
 | 
					bool AiNew_Build_CompanyHQ(Player *p, uint tile);
 | 
				
			||||||
int AiNew_Build_Station(Player *p, byte type, uint tile, byte length, byte numtracks, byte direction, byte flag);
 | 
					int AiNew_Build_Station(Player *p, byte type, uint tile, byte length, byte numtracks, byte direction, byte flag);
 | 
				
			||||||
int AiNew_Build_Bridge(Player *p, uint tile_a, uint tile_b, byte flag);
 | 
					int AiNew_Build_Bridge(Player *p, uint tile_a, uint tile_b, byte flag);
 | 
				
			||||||
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
 | 
					int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
 | 
				
			||||||
int AiNew_PickVehicle(Player *p);
 | 
					int AiNew_PickVehicle(Player *p);
 | 
				
			||||||
int AiNew_Build_Vehicle(Player *p, uint tile, byte flag);
 | 
					int AiNew_Build_Vehicle(Player *p, uint tile, byte flag);
 | 
				
			||||||
int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag);
 | 
					int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										514
									
								
								ai_build.c
									
									
									
									
									
								
							
							
						
						
									
										514
									
								
								ai_build.c
									
									
									
									
									
								
							@@ -1,257 +1,257 @@
 | 
				
			|||||||
#include "stdafx.h"
 | 
					#include "stdafx.h"
 | 
				
			||||||
#include "ttd.h"
 | 
					#include "ttd.h"
 | 
				
			||||||
#include "command.h"
 | 
					#include "command.h"
 | 
				
			||||||
#include "ai.h"
 | 
					#include "ai.h"
 | 
				
			||||||
#include "engine.h"
 | 
					#include "engine.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Build HQ
 | 
					// Build HQ
 | 
				
			||||||
//  Params:
 | 
					//  Params:
 | 
				
			||||||
//    tile : tile where HQ is going to be build
 | 
					//    tile : tile where HQ is going to be build
 | 
				
			||||||
bool AiNew_Build_CompanyHQ(Player *p, uint tile) {
 | 
					bool AiNew_Build_CompanyHQ(Player *p, uint tile) {
 | 
				
			||||||
	if (DoCommandByTile(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ) == CMD_ERROR)
 | 
						if (DoCommandByTile(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ) == CMD_ERROR)
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
 | 
						DoCommandByTile(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Build station
 | 
					// Build station
 | 
				
			||||||
//  Params:
 | 
					//  Params:
 | 
				
			||||||
//    type : AI_TRAIN/AI_BUS/AI_TRUCK : indicates the type of station
 | 
					//    type : AI_TRAIN/AI_BUS/AI_TRUCK : indicates the type of station
 | 
				
			||||||
//    tile : tile where station is going to be build
 | 
					//    tile : tile where station is going to be build
 | 
				
			||||||
//    length : in case of AI_TRAIN: length of station
 | 
					//    length : in case of AI_TRAIN: length of station
 | 
				
			||||||
//    numtracks : in case of AI_TRAIN: tracks of station
 | 
					//    numtracks : in case of AI_TRAIN: tracks of station
 | 
				
			||||||
//    direction : the direction of the station
 | 
					//    direction : the direction of the station
 | 
				
			||||||
//    flag : flag passed to DoCommand (normally 0 to get the cost or DC_EXEC to build it)
 | 
					//    flag : flag passed to DoCommand (normally 0 to get the cost or DC_EXEC to build it)
 | 
				
			||||||
int AiNew_Build_Station(Player *p, byte type, uint tile, byte length, byte numtracks, byte direction, byte flag) {
 | 
					int AiNew_Build_Station(Player *p, byte type, uint tile, byte length, byte numtracks, byte direction, byte flag) {
 | 
				
			||||||
	if (type == AI_TRAIN)
 | 
						if (type == AI_TRAIN)
 | 
				
			||||||
		return DoCommandByTile(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
 | 
							return DoCommandByTile(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
 | 
				
			||||||
	else if (type == AI_BUS)
 | 
						else if (type == AI_BUS)
 | 
				
			||||||
		return DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_BUS_STATION);
 | 
							return DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_BUS_STATION);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRUCK_STATION);
 | 
							return DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRUCK_STATION);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Builds a brdige. The second best out of the ones available for this player
 | 
					// Builds a brdige. The second best out of the ones available for this player
 | 
				
			||||||
//  Params:
 | 
					//  Params:
 | 
				
			||||||
//   tile_a : starting point
 | 
					//   tile_a : starting point
 | 
				
			||||||
//   tile_b : end point
 | 
					//   tile_b : end point
 | 
				
			||||||
//   flag : flag passed to DoCommand
 | 
					//   flag : flag passed to DoCommand
 | 
				
			||||||
int AiNew_Build_Bridge(Player *p, uint tile_a, uint tile_b, byte flag) {
 | 
					int AiNew_Build_Bridge(Player *p, uint tile_a, uint tile_b, byte flag) {
 | 
				
			||||||
	int bridge_type, bridge_len, type, type2;
 | 
						int bridge_type, bridge_len, type, type2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Find a good bridgetype (the best money can buy)
 | 
						// Find a good bridgetype (the best money can buy)
 | 
				
			||||||
	bridge_len = GetBridgeLength(tile_a, tile_b);
 | 
						bridge_len = GetBridgeLength(tile_a, tile_b);
 | 
				
			||||||
	type = type2 = 0;
 | 
						type = type2 = 0;
 | 
				
			||||||
	for (bridge_type = MAX_BRIDGES-1; bridge_type >= 0; bridge_type--) {
 | 
						for (bridge_type = MAX_BRIDGES-1; bridge_type >= 0; bridge_type--) {
 | 
				
			||||||
		if (CheckBridge_Stuff(bridge_type, bridge_len)) {
 | 
							if (CheckBridge_Stuff(bridge_type, bridge_len)) {
 | 
				
			||||||
			type2 = type;
 | 
								type2 = type;
 | 
				
			||||||
			type = bridge_type;
 | 
								type = bridge_type;
 | 
				
			||||||
			// We found two bridges, exit
 | 
								// We found two bridges, exit
 | 
				
			||||||
			if (type2 != 0)
 | 
								if (type2 != 0)
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// There is only one bridge that can be build..
 | 
						// There is only one bridge that can be build..
 | 
				
			||||||
	if (type2 == 0 && type != 0) type2 = type;
 | 
						if (type2 == 0 && type != 0) type2 = type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Now, simply, build the bridge!
 | 
						// Now, simply, build the bridge!
 | 
				
			||||||
	if (p->ainew.tbt == AI_TRAIN)
 | 
						if (p->ainew.tbt == AI_TRAIN)
 | 
				
			||||||
		return DoCommandByTile(tile_a, tile_b, (0<<8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
 | 
							return DoCommandByTile(tile_a, tile_b, (0<<8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		return DoCommandByTile(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
 | 
							return DoCommandByTile(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Build the route part by part
 | 
					// Build the route part by part
 | 
				
			||||||
// Basicly what this function do, is build that amount of parts of the route
 | 
					// Basicly what this function do, is build that amount of parts of the route
 | 
				
			||||||
//  that go in the same direction. It sets 'part' to the last part of the route builded.
 | 
					//  that go in the same direction. It sets 'part' to the last part of the route builded.
 | 
				
			||||||
//  The return value is the cost for the builded parts
 | 
					//  The return value is the cost for the builded parts
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//  Params:
 | 
					//  Params:
 | 
				
			||||||
//   PathFinderInfo : Pointer to the PathFinderInfo used for AiPathFinder
 | 
					//   PathFinderInfo : Pointer to the PathFinderInfo used for AiPathFinder
 | 
				
			||||||
//   part : Which part we need to build
 | 
					//   part : Which part we need to build
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// TODO: skip already builded road-pieces (e.g.: cityroad)
 | 
					// TODO: skip already builded road-pieces (e.g.: cityroad)
 | 
				
			||||||
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag) {
 | 
					int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag) {
 | 
				
			||||||
    int part = PathFinderInfo->position;
 | 
					    int part = PathFinderInfo->position;
 | 
				
			||||||
	byte *route_extra = PathFinderInfo->route_extra;
 | 
						byte *route_extra = PathFinderInfo->route_extra;
 | 
				
			||||||
	TileIndex *route = PathFinderInfo->route;
 | 
						TileIndex *route = PathFinderInfo->route;
 | 
				
			||||||
	int dir;
 | 
						int dir;
 | 
				
			||||||
	int old_dir = -1;
 | 
						int old_dir = -1;
 | 
				
			||||||
	int cost = 0;
 | 
						int cost = 0;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
	// We need to calculate the direction with the parent of the parent.. so we skip
 | 
						// We need to calculate the direction with the parent of the parent.. so we skip
 | 
				
			||||||
	//  the first pieces and the last piece
 | 
						//  the first pieces and the last piece
 | 
				
			||||||
	if (part < 1) part = 1;
 | 
						if (part < 1) part = 1;
 | 
				
			||||||
	// When we are done, stop it
 | 
						// When we are done, stop it
 | 
				
			||||||
	if (part >= PathFinderInfo->route_length - 1) { PathFinderInfo->position = -2; return 0; }
 | 
						if (part >= PathFinderInfo->route_length - 1) { PathFinderInfo->position = -2; return 0; }
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	if (PathFinderInfo->rail_or_road) {
 | 
						if (PathFinderInfo->rail_or_road) {
 | 
				
			||||||
		// Tunnel code
 | 
							// Tunnel code
 | 
				
			||||||
     	if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
 | 
					     	if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
 | 
				
			||||||
     		cost += DoCommandByTile(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
 | 
					     		cost += DoCommandByTile(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
 | 
				
			||||||
     		PathFinderInfo->position++;
 | 
					     		PathFinderInfo->position++;
 | 
				
			||||||
     		// TODO: problems!
 | 
					     		// TODO: problems!
 | 
				
			||||||
     		if (cost == CMD_ERROR) {
 | 
					     		if (cost == CMD_ERROR) {
 | 
				
			||||||
     			DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
 | 
					     			DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
 | 
				
			||||||
				return 0;
 | 
									return 0;
 | 
				
			||||||
     		}
 | 
					     		}
 | 
				
			||||||
     		return cost;
 | 
					     		return cost;
 | 
				
			||||||
     	}
 | 
					     	}
 | 
				
			||||||
     	// Bridge code
 | 
					     	// Bridge code
 | 
				
			||||||
     	if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
 | 
					     	if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
 | 
				
			||||||
     		cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
 | 
					     		cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
 | 
				
			||||||
     		PathFinderInfo->position++;
 | 
					     		PathFinderInfo->position++;
 | 
				
			||||||
     		// TODO: problems!
 | 
					     		// TODO: problems!
 | 
				
			||||||
     		if (cost == CMD_ERROR) {
 | 
					     		if (cost == CMD_ERROR) {
 | 
				
			||||||
     			DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
 | 
					     			DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
 | 
				
			||||||
				return 0;
 | 
									return 0;
 | 
				
			||||||
     		}
 | 
					     		}
 | 
				
			||||||
     		return cost;
 | 
					     		return cost;
 | 
				
			||||||
     	}
 | 
					     	}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     	// Build normal rail
 | 
					     	// Build normal rail
 | 
				
			||||||
     	// Keep it doing till we go an other way
 | 
					     	// Keep it doing till we go an other way
 | 
				
			||||||
     	if (route_extra[part-1] == 0 && route_extra[part] == 0) {
 | 
					     	if (route_extra[part-1] == 0 && route_extra[part] == 0) {
 | 
				
			||||||
     		while (route_extra[part] == 0) {
 | 
					     		while (route_extra[part] == 0) {
 | 
				
			||||||
	     		// Get the current direction
 | 
						     		// Get the current direction
 | 
				
			||||||
	     		dir = AiNew_GetRailDirection(route[part-1], route[part], route[part+1]);
 | 
						     		dir = AiNew_GetRailDirection(route[part-1], route[part], route[part+1]);
 | 
				
			||||||
	     		// Is it the same as the last one?
 | 
						     		// Is it the same as the last one?
 | 
				
			||||||
	     		if (old_dir != -1 && old_dir != dir) break;
 | 
						     		if (old_dir != -1 && old_dir != dir) break;
 | 
				
			||||||
	     		old_dir = dir;
 | 
						     		old_dir = dir;
 | 
				
			||||||
	     		// Build the tile
 | 
						     		// Build the tile
 | 
				
			||||||
	     		res = DoCommandByTile(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
 | 
						     		res = DoCommandByTile(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
 | 
				
			||||||
	     		if (res == CMD_ERROR) {
 | 
						     		if (res == CMD_ERROR) {
 | 
				
			||||||
	     			// Problem.. let's just abort it all!
 | 
						     			// Problem.. let's just abort it all!
 | 
				
			||||||
	     			p->ainew.state = AI_STATE_NOTHING;
 | 
						     			p->ainew.state = AI_STATE_NOTHING;
 | 
				
			||||||
	     			return 0;
 | 
						     			return 0;
 | 
				
			||||||
	     		}
 | 
						     		}
 | 
				
			||||||
	     		cost += res;
 | 
						     		cost += res;
 | 
				
			||||||
	     		// Go to the next tile
 | 
						     		// Go to the next tile
 | 
				
			||||||
	     		part++;
 | 
						     		part++;
 | 
				
			||||||
	     		// Check if it is still in range..
 | 
						     		// Check if it is still in range..
 | 
				
			||||||
	     		if (part >= PathFinderInfo->route_length - 1) break;
 | 
						     		if (part >= PathFinderInfo->route_length - 1) break;
 | 
				
			||||||
	     	}
 | 
						     	}
 | 
				
			||||||
	     	part--;
 | 
						     	part--;
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
     	// We want to return the last position, so we go back one
 | 
					     	// We want to return the last position, so we go back one
 | 
				
			||||||
     	PathFinderInfo->position = part;
 | 
					     	PathFinderInfo->position = part;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
		// Tunnel code
 | 
							// Tunnel code
 | 
				
			||||||
     	if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
 | 
					     	if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
 | 
				
			||||||
     		cost += DoCommandByTile(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
 | 
					     		cost += DoCommandByTile(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
 | 
				
			||||||
     		PathFinderInfo->position++;
 | 
					     		PathFinderInfo->position++;
 | 
				
			||||||
     		// TODO: problems!
 | 
					     		// TODO: problems!
 | 
				
			||||||
     		if (cost == CMD_ERROR) {
 | 
					     		if (cost == CMD_ERROR) {
 | 
				
			||||||
     			DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
 | 
					     			DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be build!");
 | 
				
			||||||
				return 0;
 | 
									return 0;
 | 
				
			||||||
     		}
 | 
					     		}
 | 
				
			||||||
     		return cost;
 | 
					     		return cost;
 | 
				
			||||||
     	}
 | 
					     	}
 | 
				
			||||||
     	// Bridge code
 | 
					     	// Bridge code
 | 
				
			||||||
     	if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
 | 
					     	if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
 | 
				
			||||||
     		cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
 | 
					     		cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
 | 
				
			||||||
     		PathFinderInfo->position++;
 | 
					     		PathFinderInfo->position++;
 | 
				
			||||||
     		// TODO: problems!
 | 
					     		// TODO: problems!
 | 
				
			||||||
     		if (cost == CMD_ERROR) {
 | 
					     		if (cost == CMD_ERROR) {
 | 
				
			||||||
     			DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
 | 
					     			DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be build!");
 | 
				
			||||||
				return 0;
 | 
									return 0;
 | 
				
			||||||
     		}
 | 
					     		}
 | 
				
			||||||
     		return cost;
 | 
					     		return cost;
 | 
				
			||||||
     	}
 | 
					     	}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
     	// Build normal road
 | 
					     	// Build normal road
 | 
				
			||||||
     	// Keep it doing till we go an other way
 | 
					     	// Keep it doing till we go an other way
 | 
				
			||||||
     	// EnsureNoVehicle makes sure we don't build on a tile where a vehicle is. This way
 | 
					     	// EnsureNoVehicle makes sure we don't build on a tile where a vehicle is. This way
 | 
				
			||||||
     	//  it will wait till the vehicle is gone..
 | 
					     	//  it will wait till the vehicle is gone..
 | 
				
			||||||
     	if (route_extra[part-1] == 0 && route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
 | 
					     	if (route_extra[part-1] == 0 && route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
 | 
				
			||||||
     		while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
 | 
					     		while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
 | 
				
			||||||
	     		// Get the current direction
 | 
						     		// Get the current direction
 | 
				
			||||||
	     		dir = AiNew_GetRoadDirection(route[part-1], route[part], route[part+1]);
 | 
						     		dir = AiNew_GetRoadDirection(route[part-1], route[part], route[part+1]);
 | 
				
			||||||
	     		// Is it the same as the last one?
 | 
						     		// Is it the same as the last one?
 | 
				
			||||||
	     		if (old_dir != -1 && old_dir != dir) break;
 | 
						     		if (old_dir != -1 && old_dir != dir) break;
 | 
				
			||||||
	     		old_dir = dir;
 | 
						     		old_dir = dir;
 | 
				
			||||||
	     		// There is already some road, and it is a bridge.. don't build!!!
 | 
						     		// There is already some road, and it is a bridge.. don't build!!!
 | 
				
			||||||
	     		if (!IS_TILETYPE(route[part], MP_TUNNELBRIDGE)) {
 | 
						     		if (!IS_TILETYPE(route[part], MP_TUNNELBRIDGE)) {
 | 
				
			||||||
	     			// Build the tile
 | 
						     			// Build the tile
 | 
				
			||||||
	     			res = DoCommandByTile(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
 | 
						     			res = DoCommandByTile(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
 | 
				
			||||||
	     			// Currently, we ignore CMD_ERRORs!
 | 
						     			// Currently, we ignore CMD_ERRORs!
 | 
				
			||||||
	     			if (res == CMD_ERROR && !IS_TILETYPE(route[part], MP_STREET) && (flag == DC_EXEC && !EnsureNoVehicle(route[part]))) {
 | 
						     			if (res == CMD_ERROR && !IS_TILETYPE(route[part], MP_STREET) && (flag == DC_EXEC && !EnsureNoVehicle(route[part]))) {
 | 
				
			||||||
     					// Problem.. let's just abort it all!
 | 
					     					// Problem.. let's just abort it all!
 | 
				
			||||||
     					DEBUG(ai,0)("Darn, the route could not be builded.. aborting!");
 | 
					     					DEBUG(ai,0)("Darn, the route could not be builded.. aborting!");
 | 
				
			||||||
    	     			p->ainew.state = AI_STATE_NOTHING;
 | 
					    	     			p->ainew.state = AI_STATE_NOTHING;
 | 
				
			||||||
    	     			return 0;
 | 
					    	     			return 0;
 | 
				
			||||||
    	     		} else {
 | 
					    	     		} else {
 | 
				
			||||||
    	     			if (res != CMD_ERROR)
 | 
					    	     			if (res != CMD_ERROR)
 | 
				
			||||||
    	     				cost += res;
 | 
					    	     				cost += res;
 | 
				
			||||||
    	     		}
 | 
					    	     		}
 | 
				
			||||||
		     	}
 | 
							     	}
 | 
				
			||||||
	     		// Go to the next tile
 | 
						     		// Go to the next tile
 | 
				
			||||||
	     		part++;
 | 
						     		part++;
 | 
				
			||||||
	     		// Check if it is still in range..
 | 
						     		// Check if it is still in range..
 | 
				
			||||||
	     		if (part >= PathFinderInfo->route_length - 1) break;
 | 
						     		if (part >= PathFinderInfo->route_length - 1) break;
 | 
				
			||||||
	     	}
 | 
						     	}
 | 
				
			||||||
	     	part--;
 | 
						     	part--;
 | 
				
			||||||
	     	// We want to return the last position, so we go back one
 | 
						     	// We want to return the last position, so we go back one
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	    if (!EnsureNoVehicle(route[part]) && flag == DC_EXEC) part--;
 | 
						    if (!EnsureNoVehicle(route[part]) && flag == DC_EXEC) part--;
 | 
				
			||||||
     	PathFinderInfo->position = part;
 | 
					     	PathFinderInfo->position = part;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    return cost;
 | 
					    return cost;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This functions tries to find the best vehicle for this type of cargo
 | 
					// This functions tries to find the best vehicle for this type of cargo
 | 
				
			||||||
// It returns vehicle_id or -1 if not found
 | 
					// It returns vehicle_id or -1 if not found
 | 
				
			||||||
int AiNew_PickVehicle(Player *p) {
 | 
					int AiNew_PickVehicle(Player *p) {
 | 
				
			||||||
    if (p->ainew.tbt == AI_TRAIN) {
 | 
					    if (p->ainew.tbt == AI_TRAIN) {
 | 
				
			||||||
        // Not supported yet
 | 
					        // Not supported yet
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        int start, count, i, r = CMD_ERROR;
 | 
					        int start, count, i, r = CMD_ERROR;
 | 
				
			||||||
        start = _cargoc.ai_roadveh_start[p->ainew.cargo];
 | 
					        start = _cargoc.ai_roadveh_start[p->ainew.cargo];
 | 
				
			||||||
        count = _cargoc.ai_roadveh_count[p->ainew.cargo];
 | 
					        count = _cargoc.ai_roadveh_count[p->ainew.cargo];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Let's check it backwards.. we simply want to best engine available..
 | 
					        // Let's check it backwards.. we simply want to best engine available..
 | 
				
			||||||
        for (i=start+count-1;i>=start;i--) {
 | 
					        for (i=start+count-1;i>=start;i--) {
 | 
				
			||||||
        	// Is it availiable?
 | 
					        	// Is it availiable?
 | 
				
			||||||
        	// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
 | 
					        	// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
 | 
				
			||||||
        	if (!HASBIT(_engines[i].player_avail, _current_player) || _engines[i].reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
 | 
					        	if (!HASBIT(_engines[i].player_avail, _current_player) || _engines[i].reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
 | 
				
			||||||
        	// Can we build it?
 | 
					        	// Can we build it?
 | 
				
			||||||
        	r = DoCommandByTile(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
 | 
					        	r = DoCommandByTile(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
 | 
				
			||||||
        	if (r != CMD_ERROR) break;
 | 
					        	if (r != CMD_ERROR) break;
 | 
				
			||||||
       	}
 | 
					       	}
 | 
				
			||||||
       	// We did not find a vehicle :(
 | 
					       	// We did not find a vehicle :(
 | 
				
			||||||
       	if (r == CMD_ERROR) { return -1; }
 | 
					       	if (r == CMD_ERROR) { return -1; }
 | 
				
			||||||
       	return i;
 | 
					       	return i;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Builds the best vehicle possible
 | 
					// Builds the best vehicle possible
 | 
				
			||||||
int AiNew_Build_Vehicle(Player *p, uint tile, byte flag) {
 | 
					int AiNew_Build_Vehicle(Player *p, uint tile, byte flag) {
 | 
				
			||||||
	int i = AiNew_PickVehicle(p);
 | 
						int i = AiNew_PickVehicle(p);
 | 
				
			||||||
	if (i == -1) return CMD_ERROR;
 | 
						if (i == -1) return CMD_ERROR;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	if (p->ainew.tbt == AI_TRAIN) {
 | 
						if (p->ainew.tbt == AI_TRAIN) {
 | 
				
			||||||
		return CMD_ERROR;
 | 
							return CMD_ERROR;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return DoCommandByTile(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
 | 
							return DoCommandByTile(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag) {
 | 
					int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag) {
 | 
				
			||||||
	static const byte _roadbits_by_dir[4] = {2,1,8,4};
 | 
						static const byte _roadbits_by_dir[4] = {2,1,8,4};
 | 
				
			||||||
	int r, r2;
 | 
						int r, r2;
 | 
				
			||||||
    if (p->ainew.tbt == AI_TRAIN) {
 | 
					    if (p->ainew.tbt == AI_TRAIN) {
 | 
				
			||||||
    	return DoCommandByTile(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
 | 
					    	return DoCommandByTile(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
    	r = DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
 | 
					    	r = DoCommandByTile(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
 | 
				
			||||||
    	if (r == CMD_ERROR) return r;
 | 
					    	if (r == CMD_ERROR) return r;
 | 
				
			||||||
    	// Try to build the road from the depot
 | 
					    	// Try to build the road from the depot
 | 
				
			||||||
    	r2 = DoCommandByTile(tile + _tileoffs_by_dir[direction], _roadbits_by_dir[direction], 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
 | 
					    	r2 = DoCommandByTile(tile + _tileoffs_by_dir[direction], _roadbits_by_dir[direction], 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
 | 
				
			||||||
    	// If it fails, ignore it..
 | 
					    	// If it fails, ignore it..
 | 
				
			||||||
    	if (r2 == CMD_ERROR) return r;
 | 
					    	if (r2 == CMD_ERROR) return r;
 | 
				
			||||||
    	return r + r2;
 | 
					    	return r + r2;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										914
									
								
								ai_pathfinder.c
									
									
									
									
									
								
							
							
						
						
									
										914
									
								
								ai_pathfinder.c
									
									
									
									
									
								
							@@ -1,457 +1,457 @@
 | 
				
			|||||||
#include "stdafx.h"
 | 
					#include "stdafx.h"
 | 
				
			||||||
#include "ttd.h"
 | 
					#include "ttd.h"
 | 
				
			||||||
#include "command.h"
 | 
					#include "command.h"
 | 
				
			||||||
#include "ai.h"
 | 
					#include "ai.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TEST_STATION_NO_DIR 0xFF
 | 
					#define TEST_STATION_NO_DIR 0xFF
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Tests if a station can be build on the given spot
 | 
					// Tests if a station can be build on the given spot
 | 
				
			||||||
// TODO: make it train compatible
 | 
					// TODO: make it train compatible
 | 
				
			||||||
bool TestCanBuildStationHere(uint tile, byte dir) {
 | 
					bool TestCanBuildStationHere(uint tile, byte dir) {
 | 
				
			||||||
    Player *p = DEREF_PLAYER(_current_player);
 | 
					    Player *p = DEREF_PLAYER(_current_player);
 | 
				
			||||||
    if (dir == TEST_STATION_NO_DIR) {
 | 
					    if (dir == TEST_STATION_NO_DIR) {
 | 
				
			||||||
        // TODO: currently we only allow spots that can be access from al 4 directions...
 | 
					        // TODO: currently we only allow spots that can be access from al 4 directions...
 | 
				
			||||||
        //  should be fixed!!!
 | 
					        //  should be fixed!!!
 | 
				
			||||||
        for (dir=0;dir<4;dir++) {
 | 
					        for (dir=0;dir<4;dir++) {
 | 
				
			||||||
        	int res = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
 | 
					        	int res = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
 | 
				
			||||||
            if (res != CMD_ERROR)
 | 
					            if (res != CMD_ERROR)
 | 
				
			||||||
            	return true;
 | 
					            	return true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
       	int res = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
 | 
					       	int res = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
 | 
				
			||||||
        if (res == CMD_ERROR)
 | 
					        if (res == CMD_ERROR)
 | 
				
			||||||
        	return false;
 | 
					        	return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return true;
 | 
					    return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Checks if a tile 'a' is between the tiles 'b' and 'c'
 | 
					// Checks if a tile 'a' is between the tiles 'b' and 'c'
 | 
				
			||||||
#define TILES_BETWEEN(a,b,c) (GET_TILE_X(a) >= GET_TILE_X(b) && GET_TILE_X(a) <= GET_TILE_X(c) && GET_TILE_Y(a) >= GET_TILE_Y(b) && GET_TILE_Y(a) <= GET_TILE_Y(c))
 | 
					#define TILES_BETWEEN(a,b,c) (GET_TILE_X(a) >= GET_TILE_X(b) && GET_TILE_X(a) <= GET_TILE_X(c) && GET_TILE_Y(a) >= GET_TILE_Y(b) && GET_TILE_Y(a) <= GET_TILE_Y(c))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Check if the current tile is in our end-area
 | 
					// Check if the current tile is in our end-area
 | 
				
			||||||
int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current) {
 | 
					int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current) {
 | 
				
			||||||
	Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
 | 
						Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
 | 
				
			||||||
	// It is not allowed to have a station on the end of a bridge or tunnel ;)
 | 
						// It is not allowed to have a station on the end of a bridge or tunnel ;)
 | 
				
			||||||
	if (current->path.node.user_data[0] != 0) return AYSTAR_DONE;
 | 
						if (current->path.node.user_data[0] != 0) return AYSTAR_DONE;
 | 
				
			||||||
	if (TILES_BETWEEN(current->path.node.tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br))
 | 
						if (TILES_BETWEEN(current->path.node.tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br))
 | 
				
			||||||
		if (IS_TILETYPE(current->path.node.tile, MP_CLEAR) || IS_TILETYPE(current->path.node.tile, MP_TREES))
 | 
							if (IS_TILETYPE(current->path.node.tile, MP_CLEAR) || IS_TILETYPE(current->path.node.tile, MP_TREES))
 | 
				
			||||||
			if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile,AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
 | 
								if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile,AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
 | 
				
			||||||
    			return AYSTAR_FOUND_END_NODE;
 | 
					    			return AYSTAR_FOUND_END_NODE;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
	return AYSTAR_DONE;
 | 
						return AYSTAR_DONE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Calculates the hash
 | 
					// Calculates the hash
 | 
				
			||||||
//   Currently it is a 10 bit hash, so the hash array has a max depth of 6 bits (so 64)
 | 
					//   Currently it is a 10 bit hash, so the hash array has a max depth of 6 bits (so 64)
 | 
				
			||||||
uint AiPathFinder_Hash(uint key1, uint key2) {
 | 
					uint AiPathFinder_Hash(uint key1, uint key2) {
 | 
				
			||||||
	return (GET_TILE_X(key1) & 0x1F) + ((GET_TILE_Y(key1) & 0x1F) << 5);
 | 
						return (GET_TILE_X(key1) & 0x1F) + ((GET_TILE_Y(key1) & 0x1F) << 5);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Clear the memory of all the things
 | 
					// Clear the memory of all the things
 | 
				
			||||||
void AyStar_AiPathFinder_Free(AyStar *aystar) {
 | 
					void AyStar_AiPathFinder_Free(AyStar *aystar) {
 | 
				
			||||||
	AyStarMain_Free(aystar);
 | 
						AyStarMain_Free(aystar);
 | 
				
			||||||
	free(aystar);
 | 
						free(aystar);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
 | 
					static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
 | 
				
			||||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
 | 
					static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
 | 
				
			||||||
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current);
 | 
					static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current);
 | 
				
			||||||
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
 | 
					static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This creates the AiPathFinder
 | 
					// This creates the AiPathFinder
 | 
				
			||||||
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo) {
 | 
					AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo) {
 | 
				
			||||||
	PathNode start_node;
 | 
						PathNode start_node;
 | 
				
			||||||
	uint x,y;
 | 
						uint x,y;
 | 
				
			||||||
	// Create AyStar
 | 
						// Create AyStar
 | 
				
			||||||
	AyStar *result = malloc(sizeof(AyStar));
 | 
						AyStar *result = malloc(sizeof(AyStar));
 | 
				
			||||||
	init_AyStar(result, AiPathFinder_Hash, 1 << 10);
 | 
						init_AyStar(result, AiPathFinder_Hash, 1 << 10);
 | 
				
			||||||
	// Set the function pointers
 | 
						// Set the function pointers
 | 
				
			||||||
	result->CalculateG = AyStar_AiPathFinder_CalculateG;
 | 
						result->CalculateG = AyStar_AiPathFinder_CalculateG;
 | 
				
			||||||
	result->CalculateH = AyStar_AiPathFinder_CalculateH;
 | 
						result->CalculateH = AyStar_AiPathFinder_CalculateH;
 | 
				
			||||||
	result->EndNodeCheck = AyStar_AiPathFinder_EndNodeCheck;
 | 
						result->EndNodeCheck = AyStar_AiPathFinder_EndNodeCheck;
 | 
				
			||||||
	result->FoundEndNode = AyStar_AiPathFinder_FoundEndNode;
 | 
						result->FoundEndNode = AyStar_AiPathFinder_FoundEndNode;
 | 
				
			||||||
	result->GetNeighbours = AyStar_AiPathFinder_GetNeighbours;
 | 
						result->GetNeighbours = AyStar_AiPathFinder_GetNeighbours;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	result->free = AyStar_AiPathFinder_Free;
 | 
						result->free = AyStar_AiPathFinder_Free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set some information
 | 
						// Set some information
 | 
				
			||||||
	result->loops_per_tick = AI_PATHFINDER_LOOPS_PER_TICK;
 | 
						result->loops_per_tick = AI_PATHFINDER_LOOPS_PER_TICK;
 | 
				
			||||||
	result->max_path_cost = 0;
 | 
						result->max_path_cost = 0;
 | 
				
			||||||
	result->max_search_nodes = AI_PATHFINDER_MAX_SEARCH_NODES;
 | 
						result->max_search_nodes = AI_PATHFINDER_MAX_SEARCH_NODES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set the user_data to the PathFinderInfo
 | 
						// Set the user_data to the PathFinderInfo
 | 
				
			||||||
	result->user_target = PathFinderInfo;
 | 
						result->user_target = PathFinderInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set the start node
 | 
						// Set the start node
 | 
				
			||||||
	start_node.parent = NULL;
 | 
						start_node.parent = NULL;
 | 
				
			||||||
	start_node.node.direction = 0;
 | 
						start_node.node.direction = 0;
 | 
				
			||||||
	start_node.node.user_data[0] = 0;
 | 
						start_node.node.user_data[0] = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Now we add all the starting tiles
 | 
						// Now we add all the starting tiles
 | 
				
			||||||
	for (x=GET_TILE_X(PathFinderInfo->start_tile_tl);x<=GET_TILE_X(PathFinderInfo->start_tile_br);x++) {
 | 
						for (x=GET_TILE_X(PathFinderInfo->start_tile_tl);x<=GET_TILE_X(PathFinderInfo->start_tile_br);x++) {
 | 
				
			||||||
		for (y=GET_TILE_Y(PathFinderInfo->start_tile_tl);y<=GET_TILE_Y(PathFinderInfo->start_tile_br);y++) {
 | 
							for (y=GET_TILE_Y(PathFinderInfo->start_tile_tl);y<=GET_TILE_Y(PathFinderInfo->start_tile_br);y++) {
 | 
				
			||||||
			start_node.node.tile = TILE_XY(x,y);
 | 
								start_node.node.tile = TILE_XY(x,y);
 | 
				
			||||||
			result->addstart(result, &start_node.node);
 | 
								result->addstart(result, &start_node.node);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return result;
 | 
						return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// To reuse AyStar we sometimes have to clean all the memory
 | 
					// To reuse AyStar we sometimes have to clean all the memory
 | 
				
			||||||
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo) {
 | 
					void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo) {
 | 
				
			||||||
	PathNode start_node;
 | 
						PathNode start_node;
 | 
				
			||||||
	uint x,y;
 | 
						uint x,y;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	aystar->clear(aystar);
 | 
						aystar->clear(aystar);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set the user_data to the PathFinderInfo
 | 
						// Set the user_data to the PathFinderInfo
 | 
				
			||||||
	aystar->user_target = PathFinderInfo;
 | 
						aystar->user_target = PathFinderInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set the start node
 | 
						// Set the start node
 | 
				
			||||||
	start_node.parent = NULL;
 | 
						start_node.parent = NULL;
 | 
				
			||||||
	start_node.node.direction = 0;
 | 
						start_node.node.direction = 0;
 | 
				
			||||||
	start_node.node.user_data[0] = 0;
 | 
						start_node.node.user_data[0] = 0;
 | 
				
			||||||
	start_node.node.tile = PathFinderInfo->start_tile_tl;
 | 
						start_node.node.tile = PathFinderInfo->start_tile_tl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Now we add all the starting tiles
 | 
						// Now we add all the starting tiles
 | 
				
			||||||
	for (x=GET_TILE_X(PathFinderInfo->start_tile_tl);x<=GET_TILE_X(PathFinderInfo->start_tile_br);x++) {
 | 
						for (x=GET_TILE_X(PathFinderInfo->start_tile_tl);x<=GET_TILE_X(PathFinderInfo->start_tile_br);x++) {
 | 
				
			||||||
		for (y=GET_TILE_Y(PathFinderInfo->start_tile_tl);y<=GET_TILE_Y(PathFinderInfo->start_tile_br);y++) {
 | 
							for (y=GET_TILE_Y(PathFinderInfo->start_tile_tl);y<=GET_TILE_Y(PathFinderInfo->start_tile_br);y++) {
 | 
				
			||||||
			if (!(IS_TILETYPE(TILE_XY(x,y), MP_CLEAR) || IS_TILETYPE(TILE_XY(x,y), MP_TREES))) continue;
 | 
								if (!(IS_TILETYPE(TILE_XY(x,y), MP_CLEAR) || IS_TILETYPE(TILE_XY(x,y), MP_TREES))) continue;
 | 
				
			||||||
			if (!TestCanBuildStationHere(TILE_XY(x,y),TEST_STATION_NO_DIR)) continue;
 | 
								if (!TestCanBuildStationHere(TILE_XY(x,y),TEST_STATION_NO_DIR)) continue;
 | 
				
			||||||
			start_node.node.tile = TILE_XY(x,y);
 | 
								start_node.node.tile = TILE_XY(x,y);
 | 
				
			||||||
			aystar->addstart(aystar, &start_node.node);
 | 
								aystar->addstart(aystar, &start_node.node);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The h-value, simple calculation
 | 
					// The h-value, simple calculation
 | 
				
			||||||
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
 | 
					static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
 | 
				
			||||||
	Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
 | 
						Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
 | 
				
			||||||
	int r, r2;
 | 
						int r, r2;
 | 
				
			||||||
	if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
 | 
						if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
 | 
				
			||||||
		// The station is pointing to a direction, add a tile towards that direction, so the H-value is more accurate
 | 
							// The station is pointing to a direction, add a tile towards that direction, so the H-value is more accurate
 | 
				
			||||||
		r = GetTileDist(current->tile, PathFinderInfo->end_tile_tl + _tiles_around[PathFinderInfo->end_direction]);
 | 
							r = GetTileDist(current->tile, PathFinderInfo->end_tile_tl + _tiles_around[PathFinderInfo->end_direction]);
 | 
				
			||||||
		r2 = GetTileDist(current->tile, PathFinderInfo->end_tile_br + _tiles_around[PathFinderInfo->end_direction]);
 | 
							r2 = GetTileDist(current->tile, PathFinderInfo->end_tile_br + _tiles_around[PathFinderInfo->end_direction]);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// No direction, so just get the fastest route to the station
 | 
							// No direction, so just get the fastest route to the station
 | 
				
			||||||
		r = GetTileDist(current->tile, PathFinderInfo->end_tile_tl);
 | 
							r = GetTileDist(current->tile, PathFinderInfo->end_tile_tl);
 | 
				
			||||||
		r2 = GetTileDist(current->tile, PathFinderInfo->end_tile_br);
 | 
							r2 = GetTileDist(current->tile, PathFinderInfo->end_tile_br);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// See if the bottomright is faster then the topleft..
 | 
						// See if the bottomright is faster then the topleft..
 | 
				
			||||||
	if (r2 < r) r = r2;
 | 
						if (r2 < r) r = r2;
 | 
				
			||||||
	return r * AI_PATHFINDER_H_MULTIPLER;
 | 
						return r * AI_PATHFINDER_H_MULTIPLER;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// We found the end.. let's get the route back and put it in an array
 | 
					// We found the end.. let's get the route back and put it in an array
 | 
				
			||||||
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current) {
 | 
					static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current) {
 | 
				
			||||||
	Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
 | 
						Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
 | 
				
			||||||
	int i = 0;
 | 
						int i = 0;
 | 
				
			||||||
	PathNode *parent = ¤t->path;
 | 
						PathNode *parent = ¤t->path;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	do {
 | 
						do {
 | 
				
			||||||
     	PathFinderInfo->route_extra[i] = parent->node.user_data[0];
 | 
					     	PathFinderInfo->route_extra[i] = parent->node.user_data[0];
 | 
				
			||||||
		PathFinderInfo->route[i++] = parent->node.tile;
 | 
							PathFinderInfo->route[i++] = parent->node.tile;
 | 
				
			||||||
		if (i > lengthof(PathFinderInfo->route)) {
 | 
							if (i > lengthof(PathFinderInfo->route)) {
 | 
				
			||||||
			// We ran out of space for the PathFinder
 | 
								// We ran out of space for the PathFinder
 | 
				
			||||||
			DEBUG(ai,0)("[AiPathFinder] Ran out of spacein the route[] array!!!");
 | 
								DEBUG(ai,0)("[AiPathFinder] Ran out of spacein the route[] array!!!");
 | 
				
			||||||
			PathFinderInfo->route_length = -1; // -1 indicates out of space
 | 
								PathFinderInfo->route_length = -1; // -1 indicates out of space
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		parent = parent->parent;
 | 
							parent = parent->parent;
 | 
				
			||||||
	} while (parent != NULL);
 | 
						} while (parent != NULL);
 | 
				
			||||||
	PathFinderInfo->route_length = i;
 | 
						PathFinderInfo->route_length = i;
 | 
				
			||||||
	DEBUG(ai,1)("[Ai-PathFinding] Found route of %d nodes long in %d nodes of searching",i,Hash_Size(&aystar->ClosedListHash));
 | 
						DEBUG(ai,1)("[Ai-PathFinding] Found route of %d nodes long in %d nodes of searching",i,Hash_Size(&aystar->ClosedListHash));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// What tiles are around us.
 | 
					// What tiles are around us.
 | 
				
			||||||
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current) {
 | 
					static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current) {
 | 
				
			||||||
    int i, r, dir;
 | 
					    int i, r, dir;
 | 
				
			||||||
   	Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
 | 
					   	Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    aystar->num_neighbours = 0;
 | 
					    aystar->num_neighbours = 0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
  	// Go through all surrounding tiles and check if they are within the limits
 | 
					  	// Go through all surrounding tiles and check if they are within the limits
 | 
				
			||||||
   	for (i=0;i<4;i++) {
 | 
					   	for (i=0;i<4;i++) {
 | 
				
			||||||
   		if (GET_TILE_X(_tiles_around[i] + current->path.node.tile) > 1 && GET_TILE_X(_tiles_around[i] + current->path.node.tile) < TILE_X_MAX - 1 &&
 | 
					   		if (GET_TILE_X(_tiles_around[i] + current->path.node.tile) > 1 && GET_TILE_X(_tiles_around[i] + current->path.node.tile) < TILE_X_MAX - 1 &&
 | 
				
			||||||
       		GET_TILE_Y(_tiles_around[i] + current->path.node.tile) > 1 && GET_TILE_Y(_tiles_around[i] + current->path.node.tile) < TILE_Y_MAX - 1) {
 | 
					       		GET_TILE_Y(_tiles_around[i] + current->path.node.tile) > 1 && GET_TILE_Y(_tiles_around[i] + current->path.node.tile) < TILE_Y_MAX - 1) {
 | 
				
			||||||
       		// We also directly test if the current tile can connect to this tile..
 | 
					       		// We also directly test if the current tile can connect to this tile..
 | 
				
			||||||
       		//  We do this simply by just building the tile!
 | 
					       		//  We do this simply by just building the tile!
 | 
				
			||||||
       		
 | 
					       		
 | 
				
			||||||
       		// If the next step is a bridge, we have to enter it the right way
 | 
					       		// If the next step is a bridge, we have to enter it the right way
 | 
				
			||||||
       		if (!PathFinderInfo->rail_or_road && AI_PATHFINDER_IS_ROAD(current->path.node.tile + _tiles_around[i])) {
 | 
					       		if (!PathFinderInfo->rail_or_road && AI_PATHFINDER_IS_ROAD(current->path.node.tile + _tiles_around[i])) {
 | 
				
			||||||
       			if (IS_TILETYPE(current->path.node.tile + _tiles_around[i], MP_TUNNELBRIDGE)) {
 | 
					       			if (IS_TILETYPE(current->path.node.tile + _tiles_around[i], MP_TUNNELBRIDGE)) {
 | 
				
			||||||
       				// An existing bridge... let's test the direction ;)
 | 
					       				// An existing bridge... let's test the direction ;)
 | 
				
			||||||
       				if ((_map5[current->path.node.tile + _tiles_around[i]] & 1) != (i & 1)) continue;
 | 
					       				if ((_map5[current->path.node.tile + _tiles_around[i]] & 1) != (i & 1)) continue;
 | 
				
			||||||
   					// This problem only is valid for tunnels:
 | 
					   					// This problem only is valid for tunnels:
 | 
				
			||||||
       				// When the last tile was not yet a tunnel, check if we enter from the right side..
 | 
					       				// When the last tile was not yet a tunnel, check if we enter from the right side..
 | 
				
			||||||
       				if (!IS_TILETYPE(current->path.node.tile, MP_TUNNELBRIDGE) && (_map5[current->path.node.tile + _tiles_around[i]] & 0x80) == 0) {
 | 
					       				if (!IS_TILETYPE(current->path.node.tile, MP_TUNNELBRIDGE) && (_map5[current->path.node.tile + _tiles_around[i]] & 0x80) == 0) {
 | 
				
			||||||
       					if ((i^2) != (_map5[current->path.node.tile + _tiles_around[i]] & 3)) continue;
 | 
					       					if ((i^2) != (_map5[current->path.node.tile + _tiles_around[i]] & 3)) continue;
 | 
				
			||||||
       				}
 | 
					       				}
 | 
				
			||||||
       			}
 | 
					       			}
 | 
				
			||||||
       		}
 | 
					       		}
 | 
				
			||||||
       		// But also if we are on a bridge, we can only move a certain direction
 | 
					       		// But also if we are on a bridge, we can only move a certain direction
 | 
				
			||||||
       		if (!PathFinderInfo->rail_or_road && AI_PATHFINDER_IS_ROAD(current->path.node.tile)) {
 | 
					       		if (!PathFinderInfo->rail_or_road && AI_PATHFINDER_IS_ROAD(current->path.node.tile)) {
 | 
				
			||||||
       			if (IS_TILETYPE(current->path.node.tile, MP_TUNNELBRIDGE)) {
 | 
					       			if (IS_TILETYPE(current->path.node.tile, MP_TUNNELBRIDGE)) {
 | 
				
			||||||
       				// An existing bridge/tunnel... let's test the direction ;)
 | 
					       				// An existing bridge/tunnel... let's test the direction ;)
 | 
				
			||||||
       				if ((_map5[current->path.node.tile] & 1) != (i & 1)) continue;
 | 
					       				if ((_map5[current->path.node.tile] & 1) != (i & 1)) continue;
 | 
				
			||||||
       			}
 | 
					       			}
 | 
				
			||||||
       		}
 | 
					       		}
 | 
				
			||||||
       		
 | 
					       		
 | 
				
			||||||
       		if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
 | 
					       		if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
 | 
				
			||||||
       			(AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
 | 
					       			(AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
 | 
				
			||||||
       			// We are a bridge/tunnel, how cool!!
 | 
					       			// We are a bridge/tunnel, how cool!!
 | 
				
			||||||
       			//  This means we can only point forward.. get the direction from the user_data
 | 
					       			//  This means we can only point forward.. get the direction from the user_data
 | 
				
			||||||
       			if (i != (current->path.node.user_data[0] >> 8)) continue;
 | 
					       			if (i != (current->path.node.user_data[0] >> 8)) continue;
 | 
				
			||||||
       		}
 | 
					       		}
 | 
				
			||||||
       		dir = 0;
 | 
					       		dir = 0;
 | 
				
			||||||
       		
 | 
					       		
 | 
				
			||||||
       		// First, check if we have a parent
 | 
					       		// First, check if we have a parent
 | 
				
			||||||
       		if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
 | 
					       		if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
 | 
				
			||||||
       			// If not, this means we are at the starting station
 | 
					       			// If not, this means we are at the starting station
 | 
				
			||||||
       			if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
 | 
					       			if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
 | 
				
			||||||
		       		// We do need a direction?
 | 
							       		// We do need a direction?
 | 
				
			||||||
		       		if (AiNew_GetDirection(current->path.node.tile, current->path.node.tile + _tiles_around[i]) != PathFinderInfo->start_direction)
 | 
							       		if (AiNew_GetDirection(current->path.node.tile, current->path.node.tile + _tiles_around[i]) != PathFinderInfo->start_direction)
 | 
				
			||||||
		       			// We are not pointing the right way, invalid tile
 | 
							       			// We are not pointing the right way, invalid tile
 | 
				
			||||||
		       			continue;
 | 
							       			continue;
 | 
				
			||||||
		       	}
 | 
							       	}
 | 
				
			||||||
       		} else if (current->path.node.user_data[0] == 0) {
 | 
					       		} else if (current->path.node.user_data[0] == 0) {
 | 
				
			||||||
       			if (PathFinderInfo->rail_or_road) {
 | 
					       			if (PathFinderInfo->rail_or_road) {
 | 
				
			||||||
       				// Rail check
 | 
					       				// Rail check
 | 
				
			||||||
       				dir = AiNew_GetRailDirection(current->path.parent->node.tile, current->path.node.tile, current->path.node.tile + _tiles_around[i]);
 | 
					       				dir = AiNew_GetRailDirection(current->path.parent->node.tile, current->path.node.tile, current->path.node.tile + _tiles_around[i]);
 | 
				
			||||||
       				r = DoCommandByTile(current->path.node.tile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
 | 
					       				r = DoCommandByTile(current->path.node.tile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
 | 
				
			||||||
       				if (r == CMD_ERROR) continue;
 | 
					       				if (r == CMD_ERROR) continue;
 | 
				
			||||||
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
 | 
					#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
 | 
				
			||||||
       				if (current->path.parent->parent != NULL) {
 | 
					       				if (current->path.parent->parent != NULL) {
 | 
				
			||||||
       					// Check if we don't make a 90degree curve
 | 
					       					// Check if we don't make a 90degree curve
 | 
				
			||||||
       					int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, current->path.node.tile);
 | 
					       					int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, current->path.node.tile);
 | 
				
			||||||
       					if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
 | 
					       					if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
 | 
				
			||||||
       						continue;
 | 
					       						continue;
 | 
				
			||||||
       					}
 | 
					       					}
 | 
				
			||||||
       				}
 | 
					       				}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
       			} else {
 | 
					       			} else {
 | 
				
			||||||
       				// Road check
 | 
					       				// Road check
 | 
				
			||||||
       				dir = AiNew_GetRoadDirection(current->path.parent->node.tile, current->path.node.tile, current->path.node.tile + _tiles_around[i]);
 | 
					       				dir = AiNew_GetRoadDirection(current->path.parent->node.tile, current->path.node.tile, current->path.node.tile + _tiles_around[i]);
 | 
				
			||||||
       				if (AI_PATHFINDER_IS_ROAD(current->path.node.tile)) {
 | 
					       				if (AI_PATHFINDER_IS_ROAD(current->path.node.tile)) {
 | 
				
			||||||
       					if (IS_TILETYPE(current->path.node.tile, MP_TUNNELBRIDGE)) {
 | 
					       					if (IS_TILETYPE(current->path.node.tile, MP_TUNNELBRIDGE)) {
 | 
				
			||||||
       						// We have a bridge, how nicely! We should mark it...
 | 
					       						// We have a bridge, how nicely! We should mark it...
 | 
				
			||||||
       						dir = 0;
 | 
					       						dir = 0;
 | 
				
			||||||
       					} else {
 | 
					       					} else {
 | 
				
			||||||
	       					// It already has road.. check if we miss any bits!
 | 
						       					// It already has road.. check if we miss any bits!
 | 
				
			||||||
	       					if ((_map5[current->path.node.tile] & dir) != dir) {
 | 
						       					if ((_map5[current->path.node.tile] & dir) != dir) {
 | 
				
			||||||
	       						// We do miss some pieces :(
 | 
						       						// We do miss some pieces :(
 | 
				
			||||||
	       						dir &= ~_map5[current->path.node.tile];
 | 
						       						dir &= ~_map5[current->path.node.tile];
 | 
				
			||||||
	       					} else {
 | 
						       					} else {
 | 
				
			||||||
	       						dir = 0;
 | 
						       						dir = 0;
 | 
				
			||||||
    	   					}
 | 
					    	   					}
 | 
				
			||||||
    	   				}
 | 
					    	   				}
 | 
				
			||||||
       				}
 | 
					       				}
 | 
				
			||||||
       				// Only destruct things if it is MP_CLEAR of MP_TREES
 | 
					       				// Only destruct things if it is MP_CLEAR of MP_TREES
 | 
				
			||||||
       				if (dir != 0) {
 | 
					       				if (dir != 0) {
 | 
				
			||||||
       					r = DoCommandByTile(current->path.node.tile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
 | 
					       					r = DoCommandByTile(current->path.node.tile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
 | 
				
			||||||
       					if (r == CMD_ERROR) continue;
 | 
					       					if (r == CMD_ERROR) continue;
 | 
				
			||||||
       				}
 | 
					       				}
 | 
				
			||||||
       			}
 | 
					       			}
 | 
				
			||||||
       			
 | 
					       			
 | 
				
			||||||
       		}
 | 
					       		}
 | 
				
			||||||
       		
 | 
					       		
 | 
				
			||||||
			// The tile can be connected
 | 
								// The tile can be connected
 | 
				
			||||||
   			aystar->neighbours[aystar->num_neighbours].tile = _tiles_around[i] + current->path.node.tile;
 | 
					   			aystar->neighbours[aystar->num_neighbours].tile = _tiles_around[i] + current->path.node.tile;
 | 
				
			||||||
   			aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
 | 
					   			aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
 | 
				
			||||||
   			aystar->neighbours[aystar->num_neighbours++].direction = 0;
 | 
					   			aystar->neighbours[aystar->num_neighbours++].direction = 0;
 | 
				
			||||||
       	}
 | 
					       	}
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    // Next step, check for bridges and tunnels
 | 
					    // Next step, check for bridges and tunnels
 | 
				
			||||||
    if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
 | 
					    if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        TileInfo ti;
 | 
					        TileInfo ti;
 | 
				
			||||||
        // First we get the dir from this tile and his parent
 | 
					        // First we get the dir from this tile and his parent
 | 
				
			||||||
    	int dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
 | 
					    	int dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
 | 
				
			||||||
    	// It means we can only walk with the track, so the bridge has to be in the same direction
 | 
					    	// It means we can only walk with the track, so the bridge has to be in the same direction
 | 
				
			||||||
    	TileIndex tile = current->path.node.tile;
 | 
					    	TileIndex tile = current->path.node.tile;
 | 
				
			||||||
    	TileIndex new_tile = tile;
 | 
					    	TileIndex new_tile = tile;
 | 
				
			||||||
    	
 | 
					    	
 | 
				
			||||||
    	FindLandscapeHeightByTile(&ti, tile);
 | 
					    	FindLandscapeHeightByTile(&ti, tile);
 | 
				
			||||||
    	
 | 
					    	
 | 
				
			||||||
   		// Bridges can only be build on land that is not flat
 | 
					   		// Bridges can only be build on land that is not flat
 | 
				
			||||||
   		//  And if there is a road or rail blocking
 | 
					   		//  And if there is a road or rail blocking
 | 
				
			||||||
   		if (ti.tileh != 0 ||
 | 
					   		if (ti.tileh != 0 ||
 | 
				
			||||||
     		(PathFinderInfo->rail_or_road && IS_TILETYPE(tile + _tiles_around[dir], MP_STREET)) ||
 | 
					     		(PathFinderInfo->rail_or_road && IS_TILETYPE(tile + _tiles_around[dir], MP_STREET)) ||
 | 
				
			||||||
       		(!PathFinderInfo->rail_or_road && IS_TILETYPE(tile + _tiles_around[dir], MP_RAILWAY))) {
 | 
					       		(!PathFinderInfo->rail_or_road && IS_TILETYPE(tile + _tiles_around[dir], MP_RAILWAY))) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    		for (;;) {
 | 
					    		for (;;) {
 | 
				
			||||||
    			new_tile += _tiles_around[dir];
 | 
					    			new_tile += _tiles_around[dir];
 | 
				
			||||||
    	
 | 
					    	
 | 
				
			||||||
    	    	// Precheck, is the length allowed?
 | 
					    	    	// Precheck, is the length allowed?
 | 
				
			||||||
    	    	if (!CheckBridge_Stuff(0,GetBridgeLength(tile, new_tile))) break;
 | 
					    	    	if (!CheckBridge_Stuff(0,GetBridgeLength(tile, new_tile))) break;
 | 
				
			||||||
    	    	
 | 
					    	    	
 | 
				
			||||||
    	    	// Check if we hit the station-tile.. we don't like that!
 | 
					    	    	// Check if we hit the station-tile.. we don't like that!
 | 
				
			||||||
    	    	if (TILES_BETWEEN(new_tile,PathFinderInfo->end_tile_tl,PathFinderInfo->end_tile_br)) break;
 | 
					    	    	if (TILES_BETWEEN(new_tile,PathFinderInfo->end_tile_tl,PathFinderInfo->end_tile_br)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    	    	// Try building the bridge..
 | 
					    	    	// Try building the bridge..
 | 
				
			||||||
    	    	r = DoCommandByTile(tile, new_tile, (0<<8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
 | 
					    	    	r = DoCommandByTile(tile, new_tile, (0<<8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
 | 
				
			||||||
	    	   	if (r == CMD_ERROR) continue;
 | 
						    	   	if (r == CMD_ERROR) continue;
 | 
				
			||||||
    		   	// We can build a bridge here.. add him to the neighbours
 | 
					    		   	// We can build a bridge here.. add him to the neighbours
 | 
				
			||||||
   				aystar->neighbours[aystar->num_neighbours].tile = new_tile;
 | 
					   				aystar->neighbours[aystar->num_neighbours].tile = new_tile;
 | 
				
			||||||
	   			aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
 | 
						   			aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
 | 
				
			||||||
	   			aystar->neighbours[aystar->num_neighbours++].direction = 0;
 | 
						   			aystar->neighbours[aystar->num_neighbours++].direction = 0;
 | 
				
			||||||
				// We can only have 12 neighbours, and we need 1 left for tunnels
 | 
									// We can only have 12 neighbours, and we need 1 left for tunnels
 | 
				
			||||||
				if (aystar->num_neighbours == 11) break;
 | 
									if (aystar->num_neighbours == 11) break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
    	}
 | 
					    	}
 | 
				
			||||||
    	
 | 
					    	
 | 
				
			||||||
    	// Next, check for tunnels!
 | 
					    	// Next, check for tunnels!
 | 
				
			||||||
    	// Tunnels can only be build with tileh of 3, 6, 9 or 12, depending on the direction
 | 
					    	// Tunnels can only be build with tileh of 3, 6, 9 or 12, depending on the direction
 | 
				
			||||||
    	//  For now, we check both sides for this tile.. terraforming gives fuzzy result
 | 
					    	//  For now, we check both sides for this tile.. terraforming gives fuzzy result
 | 
				
			||||||
    	if ((dir == 0 && ti.tileh == 12) ||
 | 
					    	if ((dir == 0 && ti.tileh == 12) ||
 | 
				
			||||||
    		(dir == 1 && ti.tileh == 6) ||
 | 
					    		(dir == 1 && ti.tileh == 6) ||
 | 
				
			||||||
    		(dir == 2 && ti.tileh == 3) ||
 | 
					    		(dir == 2 && ti.tileh == 3) ||
 | 
				
			||||||
    		(dir == 3 && ti.tileh == 9)) {
 | 
					    		(dir == 3 && ti.tileh == 9)) {
 | 
				
			||||||
    		// Now simply check if a tunnel can be build
 | 
					    		// Now simply check if a tunnel can be build
 | 
				
			||||||
    		r = DoCommandByTile(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
 | 
					    		r = DoCommandByTile(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
 | 
				
			||||||
    		FindLandscapeHeightByTile(&ti, _build_tunnel_endtile);
 | 
					    		FindLandscapeHeightByTile(&ti, _build_tunnel_endtile);
 | 
				
			||||||
    		if (r != CMD_ERROR && (ti.tileh == 3 || ti.tileh == 6 || ti.tileh == 9 || ti.tileh == 12)) {
 | 
					    		if (r != CMD_ERROR && (ti.tileh == 3 || ti.tileh == 6 || ti.tileh == 9 || ti.tileh == 12)) {
 | 
				
			||||||
    			aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
 | 
					    			aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
 | 
				
			||||||
	   			aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
 | 
						   			aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
 | 
				
			||||||
	   			aystar->neighbours[aystar->num_neighbours++].direction = 0;
 | 
						   			aystar->neighbours[aystar->num_neighbours++].direction = 0;
 | 
				
			||||||
    		}
 | 
					    		}
 | 
				
			||||||
    	}
 | 
					    	}
 | 
				
			||||||
  	}
 | 
					  	}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern uint GetRailFoundation(uint tileh, uint bits);
 | 
					extern uint GetRailFoundation(uint tileh, uint bits);
 | 
				
			||||||
extern uint GetRoadFoundation(uint tileh, uint bits);
 | 
					extern uint GetRoadFoundation(uint tileh, uint bits);
 | 
				
			||||||
extern uint GetBridgeFoundation(uint tileh, byte direction);
 | 
					extern uint GetBridgeFoundation(uint tileh, byte direction);
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
    BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12,
 | 
					    BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// The most important function: it calculates the g-value
 | 
					// The most important function: it calculates the g-value
 | 
				
			||||||
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
 | 
					static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
 | 
				
			||||||
	Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
 | 
						Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
 | 
				
			||||||
	int r, res = 0;
 | 
						int r, res = 0;
 | 
				
			||||||
	TileInfo ti, parent_ti;
 | 
						TileInfo ti, parent_ti;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Gather some information about the tile..
 | 
						// Gather some information about the tile..
 | 
				
			||||||
	FindLandscapeHeightByTile(&ti, current->tile);
 | 
						FindLandscapeHeightByTile(&ti, current->tile);
 | 
				
			||||||
	FindLandscapeHeightByTile(&parent_ti, parent->path.node.tile);
 | 
						FindLandscapeHeightByTile(&parent_ti, parent->path.node.tile);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Check if we hit the end-tile
 | 
						// Check if we hit the end-tile
 | 
				
			||||||
	if (TILES_BETWEEN(current->tile,PathFinderInfo->end_tile_tl,PathFinderInfo->end_tile_br)) {
 | 
						if (TILES_BETWEEN(current->tile,PathFinderInfo->end_tile_tl,PathFinderInfo->end_tile_br)) {
 | 
				
			||||||
		// We are at the end-tile, check if we had a direction or something...
 | 
							// We are at the end-tile, check if we had a direction or something...
 | 
				
			||||||
		if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION && AiNew_GetDirection(current->tile, parent->path.node.tile) != PathFinderInfo->end_direction)
 | 
							if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION && AiNew_GetDirection(current->tile, parent->path.node.tile) != PathFinderInfo->end_direction)
 | 
				
			||||||
			// We are not pointing the right way, invalid tile
 | 
								// We are not pointing the right way, invalid tile
 | 
				
			||||||
			return AYSTAR_INVALID_NODE;
 | 
								return AYSTAR_INVALID_NODE;
 | 
				
			||||||
		// If it was valid, drop out.. we don't build on the endtile
 | 
							// If it was valid, drop out.. we don't build on the endtile
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Give everything a small penalty
 | 
						// Give everything a small penalty
 | 
				
			||||||
	res += AI_PATHFINDER_PENALTY;
 | 
						res += AI_PATHFINDER_PENALTY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!PathFinderInfo->rail_or_road) {
 | 
						if (!PathFinderInfo->rail_or_road) {
 | 
				
			||||||
		// Road has the lovely advantage it can use other road... check if
 | 
							// Road has the lovely advantage it can use other road... check if
 | 
				
			||||||
		//  the current tile is road, and if so, give a good bonus
 | 
							//  the current tile is road, and if so, give a good bonus
 | 
				
			||||||
		if (AI_PATHFINDER_IS_ROAD(current->tile)) {
 | 
							if (AI_PATHFINDER_IS_ROAD(current->tile)) {
 | 
				
			||||||
			res -= AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS;
 | 
								res -= AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// We should give a penalty when the tile is going up or down.. this is one way to do so!
 | 
						// We should give a penalty when the tile is going up or down.. this is one way to do so!
 | 
				
			||||||
	//  Too bad we have to count it from the parent.. but that is not so bad
 | 
						//  Too bad we have to count it from the parent.. but that is not so bad
 | 
				
			||||||
	if (parent_ti.tileh != 0 && parent->path.parent != NULL) {
 | 
						if (parent_ti.tileh != 0 && parent->path.parent != NULL) {
 | 
				
			||||||
		// Skip if the tile was from a bridge or tunnel
 | 
							// Skip if the tile was from a bridge or tunnel
 | 
				
			||||||
		if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
 | 
							if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
 | 
				
			||||||
			if (PathFinderInfo->rail_or_road) {
 | 
								if (PathFinderInfo->rail_or_road) {
 | 
				
			||||||
				r = GetRailFoundation(parent_ti.tileh, 1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
 | 
									r = GetRailFoundation(parent_ti.tileh, 1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
 | 
				
			||||||
				// Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information..
 | 
									// Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information..
 | 
				
			||||||
				if (r >= 15 || (r == 0 && (BRIDGE_NO_FOUNDATION & (1 << ti.tileh)))) {
 | 
									if (r >= 15 || (r == 0 && (BRIDGE_NO_FOUNDATION & (1 << ti.tileh)))) {
 | 
				
			||||||
					res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
 | 
										res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				if (!(AI_PATHFINDER_IS_ROAD(parent->path.node.tile) && IS_TILETYPE(parent->path.node.tile, MP_TUNNELBRIDGE))) {
 | 
									if (!(AI_PATHFINDER_IS_ROAD(parent->path.node.tile) && IS_TILETYPE(parent->path.node.tile, MP_TUNNELBRIDGE))) {
 | 
				
			||||||
					r = GetRoadFoundation(parent_ti.tileh, AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
 | 
										r = GetRoadFoundation(parent_ti.tileh, AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
 | 
				
			||||||
					if (r >= 15 || r == 0)
 | 
										if (r >= 15 || r == 0)
 | 
				
			||||||
						res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
 | 
											res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Are we part of a tunnel?
 | 
						// Are we part of a tunnel?
 | 
				
			||||||
	if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
 | 
						if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
 | 
				
			||||||
		// Tunnels are very expensive when build on long routes..
 | 
							// Tunnels are very expensive when build on long routes..
 | 
				
			||||||
		// Ironicly, we are using BridgeCode here ;)
 | 
							// Ironicly, we are using BridgeCode here ;)
 | 
				
			||||||
		r = AI_PATHFINDER_TUNNEL_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
 | 
							r = AI_PATHFINDER_TUNNEL_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
 | 
				
			||||||
		res += r + (r >> 8);
 | 
							res += r + (r >> 8);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Are we part of a bridge?
 | 
						// Are we part of a bridge?
 | 
				
			||||||
	if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) {
 | 
						if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) {
 | 
				
			||||||
		// That means for every length a penalty
 | 
							// That means for every length a penalty
 | 
				
			||||||
		res += AI_PATHFINDER_BRIDGE_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
 | 
							res += AI_PATHFINDER_BRIDGE_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
 | 
				
			||||||
		// Check if we are going up or down, first for the starting point
 | 
							// Check if we are going up or down, first for the starting point
 | 
				
			||||||
		// In user_data[0] is at the 8th bit the direction
 | 
							// In user_data[0] is at the 8th bit the direction
 | 
				
			||||||
		if (!(BRIDGE_NO_FOUNDATION & (1 << parent_ti.tileh))) {
 | 
							if (!(BRIDGE_NO_FOUNDATION & (1 << parent_ti.tileh))) {
 | 
				
			||||||
			if (GetBridgeFoundation(parent_ti.tileh, (current->user_data[0] >> 8) & 1) < 15)
 | 
								if (GetBridgeFoundation(parent_ti.tileh, (current->user_data[0] >> 8) & 1) < 15)
 | 
				
			||||||
				res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
 | 
									res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Second for the end point
 | 
							// Second for the end point
 | 
				
			||||||
		if (!(BRIDGE_NO_FOUNDATION & (1 << ti.tileh))) {
 | 
							if (!(BRIDGE_NO_FOUNDATION & (1 << ti.tileh))) {
 | 
				
			||||||
			if (GetBridgeFoundation(ti.tileh, (current->user_data[0] >> 8) & 1) < 15)
 | 
								if (GetBridgeFoundation(ti.tileh, (current->user_data[0] >> 8) & 1) < 15)
 | 
				
			||||||
				res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
 | 
									res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if (parent_ti.tileh == 0)
 | 
							if (parent_ti.tileh == 0)
 | 
				
			||||||
			res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
 | 
								res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
 | 
				
			||||||
		if (ti.tileh == 0)
 | 
							if (ti.tileh == 0)
 | 
				
			||||||
			res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
 | 
								res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	//  To prevent the AI from taking the fastest way in tiles, but not the fastest way
 | 
						//  To prevent the AI from taking the fastest way in tiles, but not the fastest way
 | 
				
			||||||
	//    in speed, we have to give a good penalty to direction changing
 | 
						//    in speed, we have to give a good penalty to direction changing
 | 
				
			||||||
	//  This way, we get almost the fastest way in tiles, and a very good speed on the track
 | 
						//  This way, we get almost the fastest way in tiles, and a very good speed on the track
 | 
				
			||||||
	if (!PathFinderInfo->rail_or_road) {
 | 
						if (!PathFinderInfo->rail_or_road) {
 | 
				
			||||||
		if (parent->path.parent != NULL &&
 | 
							if (parent->path.parent != NULL &&
 | 
				
			||||||
			AiNew_GetDirection(current->tile, parent->path.node.tile) != AiNew_GetDirection(parent->path.node.tile, parent->path.parent->node.tile)) {
 | 
								AiNew_GetDirection(current->tile, parent->path.node.tile) != AiNew_GetDirection(parent->path.node.tile, parent->path.parent->node.tile)) {
 | 
				
			||||||
			// When road exists, we don't like turning, but its free, so don't be to piggy about it
 | 
								// When road exists, we don't like turning, but its free, so don't be to piggy about it
 | 
				
			||||||
			if (AI_PATHFINDER_IS_ROAD(parent->path.node.tile))
 | 
								if (AI_PATHFINDER_IS_ROAD(parent->path.node.tile))
 | 
				
			||||||
				res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
 | 
									res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
 | 
				
			||||||
			else
 | 
								else
 | 
				
			||||||
				res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
 | 
									res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// For rail we have 1 exeption: diagonal rail..
 | 
							// For rail we have 1 exeption: diagonal rail..
 | 
				
			||||||
		// So we fetch 2 raildirection. That of the current one, and of the one before that
 | 
							// So we fetch 2 raildirection. That of the current one, and of the one before that
 | 
				
			||||||
		if (parent->path.parent != NULL && parent->path.parent->parent != NULL) {
 | 
							if (parent->path.parent != NULL && parent->path.parent->parent != NULL) {
 | 
				
			||||||
			int dir1 = AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile);
 | 
								int dir1 = AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile);
 | 
				
			||||||
			int dir2 = AiNew_GetRailDirection(parent->path.parent->parent->node.tile, parent->path.parent->node.tile, parent->path.node.tile);
 | 
								int dir2 = AiNew_GetRailDirection(parent->path.parent->parent->node.tile, parent->path.parent->node.tile, parent->path.node.tile);
 | 
				
			||||||
			// First, see if we are on diagonal path, that is better then straight path
 | 
								// First, see if we are on diagonal path, that is better then straight path
 | 
				
			||||||
			if (dir1 > 1) { res -= AI_PATHFINDER_DIAGONAL_BONUS; }
 | 
								if (dir1 > 1) { res -= AI_PATHFINDER_DIAGONAL_BONUS; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// First see if they are different
 | 
								// First see if they are different
 | 
				
			||||||
			if (dir1 != dir2) {
 | 
								if (dir1 != dir2) {
 | 
				
			||||||
				// dir 2 and 3 are 1 diagonal track, and 4 and 5.
 | 
									// dir 2 and 3 are 1 diagonal track, and 4 and 5.
 | 
				
			||||||
				if (!(((dir1 == 2 || dir1 == 3) && (dir2 == 2 || dir2 == 3)) || ((dir1 == 4 || dir1 == 5) && (dir2 == 4 || dir2 == 5)))) {
 | 
									if (!(((dir1 == 2 || dir1 == 3) && (dir2 == 2 || dir2 == 3)) || ((dir1 == 4 || dir1 == 5) && (dir2 == 4 || dir2 == 5)))) {
 | 
				
			||||||
					// It is not, so we changed of direction
 | 
										// It is not, so we changed of direction
 | 
				
			||||||
					res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
 | 
										res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if (parent->path.parent->parent->parent != NULL) {
 | 
									if (parent->path.parent->parent->parent != NULL) {
 | 
				
			||||||
					int dir3 = AiNew_GetRailDirection(parent->path.parent->parent->parent->node.tile, parent->path.parent->parent->node.tile, parent->path.parent->node.tile);
 | 
										int dir3 = AiNew_GetRailDirection(parent->path.parent->parent->parent->node.tile, parent->path.parent->parent->node.tile, parent->path.parent->node.tile);
 | 
				
			||||||
					// Check if we changed 3 tiles of direction in 3 tiles.. bad!!!
 | 
										// Check if we changed 3 tiles of direction in 3 tiles.. bad!!!
 | 
				
			||||||
					if ((dir1 == 0 || dir1 == 1) && dir2 > 1 && (dir3 == 0 || dir3 == 1)) {
 | 
										if ((dir1 == 0 || dir1 == 1) && dir2 > 1 && (dir3 == 0 || dir3 == 1)) {
 | 
				
			||||||
						res += AI_PATHFINDER_CURVE_PENALTY;
 | 
											res += AI_PATHFINDER_CURVE_PENALTY;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Res should never be below zero.. if so, make it zero!
 | 
						// Res should never be below zero.. if so, make it zero!
 | 
				
			||||||
	if (res < 0) { res = 0; }
 | 
						if (res < 0) { res = 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Return our value
 | 
						// Return our value
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										164
									
								
								ai_shared.c
									
									
									
									
									
								
							
							
						
						
									
										164
									
								
								ai_shared.c
									
									
									
									
									
								
							@@ -1,82 +1,82 @@
 | 
				
			|||||||
#include "stdafx.h"
 | 
					#include "stdafx.h"
 | 
				
			||||||
#include "ttd.h"
 | 
					#include "ttd.h"
 | 
				
			||||||
#include "player.h"
 | 
					#include "player.h"
 | 
				
			||||||
#include "ai.h"
 | 
					#include "ai.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int AiNew_GetRailDirection(uint tile_a, uint tile_b, uint tile_c) {
 | 
					int AiNew_GetRailDirection(uint tile_a, uint tile_b, uint tile_c) {
 | 
				
			||||||
	// 0 = vert
 | 
						// 0 = vert
 | 
				
			||||||
	// 1 = horz
 | 
						// 1 = horz
 | 
				
			||||||
	// 2 = dig up-left
 | 
						// 2 = dig up-left
 | 
				
			||||||
	// 3 = dig down-right
 | 
						// 3 = dig down-right
 | 
				
			||||||
	// 4 = dig down-left
 | 
						// 4 = dig down-left
 | 
				
			||||||
	// 5 = dig up-right
 | 
						// 5 = dig up-right
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int x1, x2, x3;
 | 
						int x1, x2, x3;
 | 
				
			||||||
	int y1, y2, y3;
 | 
						int y1, y2, y3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	x1 = GET_TILE_X(tile_a);
 | 
						x1 = GET_TILE_X(tile_a);
 | 
				
			||||||
	x2 = GET_TILE_X(tile_b);
 | 
						x2 = GET_TILE_X(tile_b);
 | 
				
			||||||
	x3 = GET_TILE_X(tile_c);
 | 
						x3 = GET_TILE_X(tile_c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	y1 = GET_TILE_Y(tile_a);
 | 
						y1 = GET_TILE_Y(tile_a);
 | 
				
			||||||
	y2 = GET_TILE_Y(tile_b);
 | 
						y2 = GET_TILE_Y(tile_b);
 | 
				
			||||||
	y3 = GET_TILE_Y(tile_c);
 | 
						y3 = GET_TILE_Y(tile_c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (y1 == y2 && y2 == y3) return 0;
 | 
						if (y1 == y2 && y2 == y3) return 0;
 | 
				
			||||||
	if (x1 == x2 && x2 == x3) return 1;
 | 
						if (x1 == x2 && x2 == x3) return 1;
 | 
				
			||||||
	if (y2 > y1) {
 | 
						if (y2 > y1) {
 | 
				
			||||||
		if (x2 > x3) return 2;
 | 
							if (x2 > x3) return 2;
 | 
				
			||||||
		else return 4;
 | 
							else return 4;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (x2 > x1) {
 | 
						if (x2 > x1) {
 | 
				
			||||||
		if (y2 > y3) return 2;
 | 
							if (y2 > y3) return 2;
 | 
				
			||||||
		else return 5;
 | 
							else return 5;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (y1 > y2) {
 | 
						if (y1 > y2) {
 | 
				
			||||||
		if (x2 > x3) return 5;
 | 
							if (x2 > x3) return 5;
 | 
				
			||||||
		else return 3;
 | 
							else return 3;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (x1 > x2) {
 | 
						if (x1 > x2) {
 | 
				
			||||||
		if (y2 > y3) return 4;
 | 
							if (y2 > y3) return 4;
 | 
				
			||||||
		else return 3;
 | 
							else return 3;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int AiNew_GetRoadDirection(uint tile_a, uint tile_b, uint tile_c) {
 | 
					int AiNew_GetRoadDirection(uint tile_a, uint tile_b, uint tile_c) {
 | 
				
			||||||
	int x1, x2, x3;
 | 
						int x1, x2, x3;
 | 
				
			||||||
	int y1, y2, y3;
 | 
						int y1, y2, y3;
 | 
				
			||||||
	int r;
 | 
						int r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	x1 = GET_TILE_X(tile_a);
 | 
						x1 = GET_TILE_X(tile_a);
 | 
				
			||||||
	x2 = GET_TILE_X(tile_b);
 | 
						x2 = GET_TILE_X(tile_b);
 | 
				
			||||||
	x3 = GET_TILE_X(tile_c);
 | 
						x3 = GET_TILE_X(tile_c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	y1 = GET_TILE_Y(tile_a);
 | 
						y1 = GET_TILE_Y(tile_a);
 | 
				
			||||||
	y2 = GET_TILE_Y(tile_b);
 | 
						y2 = GET_TILE_Y(tile_b);
 | 
				
			||||||
	y3 = GET_TILE_Y(tile_c);
 | 
						y3 = GET_TILE_Y(tile_c);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r = 0;
 | 
						r = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (x1 < x2) r += 8;
 | 
						if (x1 < x2) r += 8;
 | 
				
			||||||
	if (y1 < y2) r += 1;
 | 
						if (y1 < y2) r += 1;
 | 
				
			||||||
	if (x1 > x2) r += 2;
 | 
						if (x1 > x2) r += 2;
 | 
				
			||||||
	if (y1 > y2) r += 4;
 | 
						if (y1 > y2) r += 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (x2 < x3) r += 2;
 | 
						if (x2 < x3) r += 2;
 | 
				
			||||||
	if (y2 < y3) r += 4;
 | 
						if (y2 < y3) r += 4;
 | 
				
			||||||
	if (x2 > x3) r += 8;
 | 
						if (x2 > x3) r += 8;
 | 
				
			||||||
	if (y2 > y3) r += 1;
 | 
						if (y2 > y3) r += 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return r;
 | 
						return r;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get's the direction between 2 tiles seen from tile_a
 | 
					// Get's the direction between 2 tiles seen from tile_a
 | 
				
			||||||
int AiNew_GetDirection(uint tile_a, uint tile_b) {
 | 
					int AiNew_GetDirection(uint tile_a, uint tile_b) {
 | 
				
			||||||
	if (GET_TILE_Y(tile_a) < GET_TILE_Y(tile_b)) return 1;
 | 
						if (GET_TILE_Y(tile_a) < GET_TILE_Y(tile_b)) return 1;
 | 
				
			||||||
	if (GET_TILE_Y(tile_a) > GET_TILE_Y(tile_b)) return 3;
 | 
						if (GET_TILE_Y(tile_a) > GET_TILE_Y(tile_b)) return 3;
 | 
				
			||||||
	if (GET_TILE_X(tile_a) < GET_TILE_X(tile_b)) return 2;
 | 
						if (GET_TILE_X(tile_a) < GET_TILE_X(tile_b)) return 2;
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										542
									
								
								aystar.c
									
									
									
									
									
								
							
							
						
						
									
										542
									
								
								aystar.c
									
									
									
									
									
								
							@@ -1,271 +1,271 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * This file has the core function for AyStar
 | 
					 * This file has the core function for AyStar
 | 
				
			||||||
 *  AyStar is a fast pathfinding routine and is used for things like
 | 
					 *  AyStar is a fast pathfinding routine and is used for things like
 | 
				
			||||||
 *  AI_pathfinding and Train_pathfinding.
 | 
					 *  AI_pathfinding and Train_pathfinding.
 | 
				
			||||||
 *  For more information about AyStar (A* Algorithm), you can look at
 | 
					 *  For more information about AyStar (A* Algorithm), you can look at
 | 
				
			||||||
 *    http://en.wikipedia.org/wiki/A-star_search_algorithm
 | 
					 *    http://en.wikipedia.org/wiki/A-star_search_algorithm
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Friendly reminder:
 | 
					 * Friendly reminder:
 | 
				
			||||||
 *  Call (AyStar).free() when you are done with Aystar. It reserves a lot of memory
 | 
					 *  Call (AyStar).free() when you are done with Aystar. It reserves a lot of memory
 | 
				
			||||||
 *  And when not free'd, it can cause system-crashes.
 | 
					 *  And when not free'd, it can cause system-crashes.
 | 
				
			||||||
 * Also remember that when you stop an algorithm before it is finished, your
 | 
					 * Also remember that when you stop an algorithm before it is finished, your
 | 
				
			||||||
 * should call clear() yourself!
 | 
					 * should call clear() yourself!
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "stdafx.h"
 | 
					#include "stdafx.h"
 | 
				
			||||||
#include "ttd.h"
 | 
					#include "ttd.h"
 | 
				
			||||||
#include "aystar.h"
 | 
					#include "aystar.h"
 | 
				
			||||||
// This looks in the Hash if a node exists in ClosedList
 | 
					// This looks in the Hash if a node exists in ClosedList
 | 
				
			||||||
//  If so, it returns the PathNode, else NULL
 | 
					//  If so, it returns the PathNode, else NULL
 | 
				
			||||||
PathNode *AyStarMain_ClosedList_IsInList(AyStar *aystar, AyStarNode *node) {
 | 
					PathNode *AyStarMain_ClosedList_IsInList(AyStar *aystar, AyStarNode *node) {
 | 
				
			||||||
	return (PathNode*)Hash_Get(&aystar->ClosedListHash, node->tile, node->direction);
 | 
						return (PathNode*)Hash_Get(&aystar->ClosedListHash, node->tile, node->direction);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// This adds a node to the ClosedList
 | 
					// This adds a node to the ClosedList
 | 
				
			||||||
//  It makes a copy of the data
 | 
					//  It makes a copy of the data
 | 
				
			||||||
void AyStarMain_ClosedList_Add(AyStar *aystar, PathNode *node) {
 | 
					void AyStarMain_ClosedList_Add(AyStar *aystar, PathNode *node) {
 | 
				
			||||||
	// Add a node to the ClosedList
 | 
						// Add a node to the ClosedList
 | 
				
			||||||
	PathNode *new_node = malloc(sizeof(PathNode));
 | 
						PathNode *new_node = malloc(sizeof(PathNode));
 | 
				
			||||||
	*new_node = *node;
 | 
						*new_node = *node;
 | 
				
			||||||
	Hash_Set(&aystar->ClosedListHash, node->node.tile, node->node.direction, new_node);
 | 
						Hash_Set(&aystar->ClosedListHash, node->node.tile, node->node.direction, new_node);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Checks if a node is in the OpenList
 | 
					// Checks if a node is in the OpenList
 | 
				
			||||||
//   If so, it returns the OpenListNode, else NULL
 | 
					//   If so, it returns the OpenListNode, else NULL
 | 
				
			||||||
OpenListNode *AyStarMain_OpenList_IsInList(AyStar *aystar, AyStarNode *node) {
 | 
					OpenListNode *AyStarMain_OpenList_IsInList(AyStar *aystar, AyStarNode *node) {
 | 
				
			||||||
	return (OpenListNode*)Hash_Get(&aystar->OpenListHash, node->tile, node->direction);
 | 
						return (OpenListNode*)Hash_Get(&aystar->OpenListHash, node->tile, node->direction);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Gets the best node from OpenList
 | 
					// Gets the best node from OpenList
 | 
				
			||||||
//  returns the best node, or NULL of none is found
 | 
					//  returns the best node, or NULL of none is found
 | 
				
			||||||
// Also it deletes the node from the OpenList
 | 
					// Also it deletes the node from the OpenList
 | 
				
			||||||
OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar) {
 | 
					OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar) {
 | 
				
			||||||
	// Return the item the Queue returns.. the best next OpenList item.
 | 
						// Return the item the Queue returns.. the best next OpenList item.
 | 
				
			||||||
	OpenListNode* res = (OpenListNode*)aystar->OpenListQueue.pop(&aystar->OpenListQueue);
 | 
						OpenListNode* res = (OpenListNode*)aystar->OpenListQueue.pop(&aystar->OpenListQueue);
 | 
				
			||||||
	if (res != NULL)
 | 
						if (res != NULL)
 | 
				
			||||||
		Hash_Delete(&aystar->OpenListHash, res->path.node.tile, res->path.node.direction);
 | 
							Hash_Delete(&aystar->OpenListHash, res->path.node.tile, res->path.node.direction);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Adds a node to the OpenList
 | 
					// Adds a node to the OpenList
 | 
				
			||||||
//  It makes a copy of node, and puts the pointer of parent in the struct
 | 
					//  It makes a copy of node, and puts the pointer of parent in the struct
 | 
				
			||||||
void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, AyStarNode *node, int f, int g, int userdata) {
 | 
					void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, AyStarNode *node, int f, int g, int userdata) {
 | 
				
			||||||
	// Add a new Node to the OpenList
 | 
						// Add a new Node to the OpenList
 | 
				
			||||||
	OpenListNode* new_node = malloc(sizeof(OpenListNode));
 | 
						OpenListNode* new_node = malloc(sizeof(OpenListNode));
 | 
				
			||||||
	new_node->g = g;
 | 
						new_node->g = g;
 | 
				
			||||||
	new_node->path.parent = parent;
 | 
						new_node->path.parent = parent;
 | 
				
			||||||
	new_node->path.node = *node;
 | 
						new_node->path.node = *node;
 | 
				
			||||||
	Hash_Set(&aystar->OpenListHash, node->tile, node->direction, new_node);
 | 
						Hash_Set(&aystar->OpenListHash, node->tile, node->direction, new_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Add it to the queue
 | 
						// Add it to the queue
 | 
				
			||||||
	aystar->OpenListQueue.push(&aystar->OpenListQueue, new_node, f);
 | 
						aystar->OpenListQueue.push(&aystar->OpenListQueue, new_node, f);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Checks one tile and calculate his f-value
 | 
					 * Checks one tile and calculate his f-value
 | 
				
			||||||
 *  return values:
 | 
					 *  return values:
 | 
				
			||||||
 *	AYSTAR_DONE : indicates we are done
 | 
					 *	AYSTAR_DONE : indicates we are done
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
 | 
					int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent) {
 | 
				
			||||||
	int new_f, new_g, new_h;
 | 
						int new_f, new_g, new_h;
 | 
				
			||||||
	PathNode *closedlist_parent;
 | 
						PathNode *closedlist_parent;
 | 
				
			||||||
	OpenListNode *check;
 | 
						OpenListNode *check;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Check the new node against the ClosedList
 | 
						// Check the new node against the ClosedList
 | 
				
			||||||
	if (AyStarMain_ClosedList_IsInList(aystar, current) != NULL) return AYSTAR_DONE;
 | 
						if (AyStarMain_ClosedList_IsInList(aystar, current) != NULL) return AYSTAR_DONE;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Calculate the G-value for this node
 | 
						// Calculate the G-value for this node
 | 
				
			||||||
	new_g = aystar->CalculateG(aystar, current, parent);
 | 
						new_g = aystar->CalculateG(aystar, current, parent);
 | 
				
			||||||
	// If the value was INVALID_NODE, we don't do anything with this node
 | 
						// If the value was INVALID_NODE, we don't do anything with this node
 | 
				
			||||||
	if (new_g == AYSTAR_INVALID_NODE) return AYSTAR_DONE;
 | 
						if (new_g == AYSTAR_INVALID_NODE) return AYSTAR_DONE;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// There should not be given any other error-code..
 | 
						// There should not be given any other error-code..
 | 
				
			||||||
	assert(new_g >= 0);
 | 
						assert(new_g >= 0);
 | 
				
			||||||
	// Add the parent g-value to the new g-value
 | 
						// Add the parent g-value to the new g-value
 | 
				
			||||||
	new_g += parent->g;
 | 
						new_g += parent->g;
 | 
				
			||||||
	if (aystar->max_path_cost != 0 && (uint)new_g > aystar->max_path_cost) return AYSTAR_DONE;
 | 
						if (aystar->max_path_cost != 0 && (uint)new_g > aystar->max_path_cost) return AYSTAR_DONE;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Calculate the h-value
 | 
						// Calculate the h-value
 | 
				
			||||||
	new_h = aystar->CalculateH(aystar, current, parent);
 | 
						new_h = aystar->CalculateH(aystar, current, parent);
 | 
				
			||||||
	// There should not be given any error-code..
 | 
						// There should not be given any error-code..
 | 
				
			||||||
	assert(new_h >= 0);
 | 
						assert(new_h >= 0);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// The f-value if g + h
 | 
						// The f-value if g + h
 | 
				
			||||||
	new_f = new_g + new_h;
 | 
						new_f = new_g + new_h;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Get the pointer to the parent in the ClosedList (the currentone is to a copy of the one in the OpenList)
 | 
						// Get the pointer to the parent in the ClosedList (the currentone is to a copy of the one in the OpenList)
 | 
				
			||||||
	closedlist_parent = AyStarMain_ClosedList_IsInList(aystar, &parent->path.node);
 | 
						closedlist_parent = AyStarMain_ClosedList_IsInList(aystar, &parent->path.node);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Check if this item is already in the OpenList
 | 
						// Check if this item is already in the OpenList
 | 
				
			||||||
	if ((check = AyStarMain_OpenList_IsInList(aystar, current)) != NULL) {
 | 
						if ((check = AyStarMain_OpenList_IsInList(aystar, current)) != NULL) {
 | 
				
			||||||
		int i;
 | 
							int i;
 | 
				
			||||||
		// Yes, check if this g value is lower..
 | 
							// Yes, check if this g value is lower..
 | 
				
			||||||
		if (new_g > check->g) return AYSTAR_DONE;
 | 
							if (new_g > check->g) return AYSTAR_DONE;
 | 
				
			||||||
		aystar->OpenListQueue.del(&aystar->OpenListQueue, check, 0);
 | 
							aystar->OpenListQueue.del(&aystar->OpenListQueue, check, 0);
 | 
				
			||||||
		// It is lower, so change it to this item
 | 
							// It is lower, so change it to this item
 | 
				
			||||||
		check->g = new_g;
 | 
							check->g = new_g;
 | 
				
			||||||
		check->path.parent = closedlist_parent;
 | 
							check->path.parent = closedlist_parent;
 | 
				
			||||||
		/* Copy user data, will probably have changed */
 | 
							/* Copy user data, will probably have changed */
 | 
				
			||||||
		for (i=0;i<lengthof(current->user_data);i++)
 | 
							for (i=0;i<lengthof(current->user_data);i++)
 | 
				
			||||||
			check->path.node.user_data[i] = current->user_data[i];
 | 
								check->path.node.user_data[i] = current->user_data[i];
 | 
				
			||||||
		// Readd him in the OpenListQueue
 | 
							// Readd him in the OpenListQueue
 | 
				
			||||||
		aystar->OpenListQueue.push(&aystar->OpenListQueue, check, new_f);
 | 
							aystar->OpenListQueue.push(&aystar->OpenListQueue, check, new_f);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		// A new node, add him to the OpenList
 | 
							// A new node, add him to the OpenList
 | 
				
			||||||
		AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g, 0);
 | 
							AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g, 0);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	return AYSTAR_DONE;
 | 
						return AYSTAR_DONE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This function is the core of AyStar. It handles one item and checks
 | 
					 * This function is the core of AyStar. It handles one item and checks
 | 
				
			||||||
 *  his neighbour items. If they are valid, they are added to be checked too.
 | 
					 *  his neighbour items. If they are valid, they are added to be checked too.
 | 
				
			||||||
 *  return values:
 | 
					 *  return values:
 | 
				
			||||||
 *	AYSTAR_EMPTY_OPENLIST : indicates all items are tested, and no path
 | 
					 *	AYSTAR_EMPTY_OPENLIST : indicates all items are tested, and no path
 | 
				
			||||||
 *	has been found.
 | 
					 *	has been found.
 | 
				
			||||||
 *	AYSTAR_LIMIT_REACHED : Indicates that the max_nodes limit has been
 | 
					 *	AYSTAR_LIMIT_REACHED : Indicates that the max_nodes limit has been
 | 
				
			||||||
 *	reached.
 | 
					 *	reached.
 | 
				
			||||||
 *	AYSTAR_FOUND_END_NODE : indicates we found the end. Path_found now is true, and in path is the path found.
 | 
					 *	AYSTAR_FOUND_END_NODE : indicates we found the end. Path_found now is true, and in path is the path found.
 | 
				
			||||||
 *	AYSTAR_STILL_BUSY : indicates we have done this tile, did not found the path yet, and have items left to try.
 | 
					 *	AYSTAR_STILL_BUSY : indicates we have done this tile, did not found the path yet, and have items left to try.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int AyStarMain_Loop(AyStar *aystar) {
 | 
					int AyStarMain_Loop(AyStar *aystar) {
 | 
				
			||||||
	int i, r;
 | 
						int i, r;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Get the best node from OpenList
 | 
						// Get the best node from OpenList
 | 
				
			||||||
	OpenListNode *current = AyStarMain_OpenList_Pop(aystar);
 | 
						OpenListNode *current = AyStarMain_OpenList_Pop(aystar);
 | 
				
			||||||
	// If empty, drop an error
 | 
						// If empty, drop an error
 | 
				
			||||||
	if (current == NULL) return AYSTAR_EMPTY_OPENLIST;
 | 
						if (current == NULL) return AYSTAR_EMPTY_OPENLIST;
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Check for end node and if found, return that code
 | 
						// Check for end node and if found, return that code
 | 
				
			||||||
	if (aystar->EndNodeCheck(aystar, current) == AYSTAR_FOUND_END_NODE) {
 | 
						if (aystar->EndNodeCheck(aystar, current) == AYSTAR_FOUND_END_NODE) {
 | 
				
			||||||
		if (aystar->FoundEndNode != NULL)
 | 
							if (aystar->FoundEndNode != NULL)
 | 
				
			||||||
			aystar->FoundEndNode(aystar, current);
 | 
								aystar->FoundEndNode(aystar, current);
 | 
				
			||||||
		free(current);
 | 
							free(current);
 | 
				
			||||||
		return AYSTAR_FOUND_END_NODE;
 | 
							return AYSTAR_FOUND_END_NODE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Add the node to the ClosedList
 | 
						// Add the node to the ClosedList
 | 
				
			||||||
	AyStarMain_ClosedList_Add(aystar, ¤t->path);
 | 
						AyStarMain_ClosedList_Add(aystar, ¤t->path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Load the neighbours
 | 
						// Load the neighbours
 | 
				
			||||||
	aystar->GetNeighbours(aystar, current);
 | 
						aystar->GetNeighbours(aystar, current);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Go through all neighbours
 | 
						// Go through all neighbours
 | 
				
			||||||
	for (i=0;i<aystar->num_neighbours;i++) {
 | 
						for (i=0;i<aystar->num_neighbours;i++) {
 | 
				
			||||||
		// Check and add them to the OpenList if needed
 | 
							// Check and add them to the OpenList if needed
 | 
				
			||||||
		r = aystar->checktile(aystar, &aystar->neighbours[i], current);
 | 
							r = aystar->checktile(aystar, &aystar->neighbours[i], current);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	// Free the node
 | 
						// Free the node
 | 
				
			||||||
	free(current);
 | 
						free(current);
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	if (aystar->max_search_nodes != 0 && Hash_Size(&aystar->ClosedListHash) >= aystar->max_search_nodes)
 | 
						if (aystar->max_search_nodes != 0 && Hash_Size(&aystar->ClosedListHash) >= aystar->max_search_nodes)
 | 
				
			||||||
		/* We've expanded enough nodes */
 | 
							/* We've expanded enough nodes */
 | 
				
			||||||
		return AYSTAR_LIMIT_REACHED;
 | 
							return AYSTAR_LIMIT_REACHED;
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		// Return that we are still busy
 | 
							// Return that we are still busy
 | 
				
			||||||
		return AYSTAR_STILL_BUSY;
 | 
							return AYSTAR_STILL_BUSY;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This function frees the memory it allocated
 | 
					 * This function frees the memory it allocated
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void AyStarMain_Free(AyStar *aystar) {
 | 
					void AyStarMain_Free(AyStar *aystar) {
 | 
				
			||||||
	aystar->OpenListQueue.free(&aystar->OpenListQueue, false);
 | 
						aystar->OpenListQueue.free(&aystar->OpenListQueue, false);
 | 
				
			||||||
	/* 2nd argument above is false, below is true, to free the values only
 | 
						/* 2nd argument above is false, below is true, to free the values only
 | 
				
			||||||
	 * once */
 | 
						 * once */
 | 
				
			||||||
	delete_Hash(&aystar->OpenListHash, true);
 | 
						delete_Hash(&aystar->OpenListHash, true);
 | 
				
			||||||
	delete_Hash(&aystar->ClosedListHash, true);
 | 
						delete_Hash(&aystar->ClosedListHash, true);
 | 
				
			||||||
#ifdef AYSTAR_DEBUG
 | 
					#ifdef AYSTAR_DEBUG
 | 
				
			||||||
	printf("[AyStar] Memory free'd\n");
 | 
						printf("[AyStar] Memory free'd\n");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This function make the memory go back to zero
 | 
					 * This function make the memory go back to zero
 | 
				
			||||||
 *  This function should be called when you are using the same instance again.
 | 
					 *  This function should be called when you are using the same instance again.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void AyStarMain_Clear(AyStar *aystar) {
 | 
					void AyStarMain_Clear(AyStar *aystar) {
 | 
				
			||||||
	// Clean the Queue, but not the elements within. That will be done by
 | 
						// Clean the Queue, but not the elements within. That will be done by
 | 
				
			||||||
	// the hash.
 | 
						// the hash.
 | 
				
			||||||
	aystar->OpenListQueue.clear(&aystar->OpenListQueue, false);
 | 
						aystar->OpenListQueue.clear(&aystar->OpenListQueue, false);
 | 
				
			||||||
	// Clean the hashes
 | 
						// Clean the hashes
 | 
				
			||||||
	clear_Hash(&aystar->OpenListHash, true);
 | 
						clear_Hash(&aystar->OpenListHash, true);
 | 
				
			||||||
	clear_Hash(&aystar->ClosedListHash, true);
 | 
						clear_Hash(&aystar->ClosedListHash, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef AYSTAR_DEBUG
 | 
					#ifdef AYSTAR_DEBUG
 | 
				
			||||||
	printf("[AyStar] Cleared AyStar\n");
 | 
						printf("[AyStar] Cleared AyStar\n");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * This is the function you call to run AyStar.
 | 
					 * This is the function you call to run AyStar.
 | 
				
			||||||
 *  return values:
 | 
					 *  return values:
 | 
				
			||||||
 *	AYSTAR_FOUND_END_NODE : indicates we found an end node.
 | 
					 *	AYSTAR_FOUND_END_NODE : indicates we found an end node.
 | 
				
			||||||
 *	AYSTAR_NO_PATH : indicates that there was no path found.
 | 
					 *	AYSTAR_NO_PATH : indicates that there was no path found.
 | 
				
			||||||
 *	AYSTAR_STILL_BUSY : indicates we have done some checked, that we did not found the path yet, and that we still have items left to try.
 | 
					 *	AYSTAR_STILL_BUSY : indicates we have done some checked, that we did not found the path yet, and that we still have items left to try.
 | 
				
			||||||
 * When the algorithm is done (when the return value is not AYSTAR_STILL_BUSY)
 | 
					 * When the algorithm is done (when the return value is not AYSTAR_STILL_BUSY)
 | 
				
			||||||
 * aystar->clear() is called. Note that when you stop the algorithm halfway,
 | 
					 * aystar->clear() is called. Note that when you stop the algorithm halfway,
 | 
				
			||||||
 * you should still call clear() yourself!
 | 
					 * you should still call clear() yourself!
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int AyStarMain_Main(AyStar *aystar) {
 | 
					int AyStarMain_Main(AyStar *aystar) {
 | 
				
			||||||
	int r, i = 0;
 | 
						int r, i = 0;
 | 
				
			||||||
	// Loop through the OpenList
 | 
						// Loop through the OpenList
 | 
				
			||||||
	//  Quit if result is no AYSTAR_STILL_BUSY or is more then loops_per_tick
 | 
						//  Quit if result is no AYSTAR_STILL_BUSY or is more then loops_per_tick
 | 
				
			||||||
	while ((r = aystar->loop(aystar)) == AYSTAR_STILL_BUSY && (aystar->loops_per_tick == 0 || ++i < aystar->loops_per_tick)) { }
 | 
						while ((r = aystar->loop(aystar)) == AYSTAR_STILL_BUSY && (aystar->loops_per_tick == 0 || ++i < aystar->loops_per_tick)) { }
 | 
				
			||||||
#ifdef AYSTAR_DEBUG
 | 
					#ifdef AYSTAR_DEBUG
 | 
				
			||||||
	if (r == AYSTAR_FOUND_END_NODE)
 | 
						if (r == AYSTAR_FOUND_END_NODE)
 | 
				
			||||||
		printf("[AyStar] Found path!\n");
 | 
							printf("[AyStar] Found path!\n");
 | 
				
			||||||
	else if (r == AYSTAR_EMPTY_OPENLIST)
 | 
						else if (r == AYSTAR_EMPTY_OPENLIST)
 | 
				
			||||||
		printf("[AyStar] OpenList run dry, no path found\n");
 | 
							printf("[AyStar] OpenList run dry, no path found\n");
 | 
				
			||||||
	else if (r == AYSTAR_LIMIT_REACHED)
 | 
						else if (r == AYSTAR_LIMIT_REACHED)
 | 
				
			||||||
		printf("[AyStar] Exceeded search_nodes, no path found\n");
 | 
							printf("[AyStar] Exceeded search_nodes, no path found\n");
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	if (r != AYSTAR_STILL_BUSY)
 | 
						if (r != AYSTAR_STILL_BUSY)
 | 
				
			||||||
		/* We're done, clean up */
 | 
							/* We're done, clean up */
 | 
				
			||||||
		aystar->clear(aystar);
 | 
							aystar->clear(aystar);
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
	// Check result-value
 | 
						// Check result-value
 | 
				
			||||||
	if (r == AYSTAR_FOUND_END_NODE) return AYSTAR_FOUND_END_NODE;
 | 
						if (r == AYSTAR_FOUND_END_NODE) return AYSTAR_FOUND_END_NODE;
 | 
				
			||||||
	// Check if we have some left in the OpenList
 | 
						// Check if we have some left in the OpenList
 | 
				
			||||||
	if (r == AYSTAR_EMPTY_OPENLIST || r == AYSTAR_LIMIT_REACHED) return AYSTAR_NO_PATH;
 | 
						if (r == AYSTAR_EMPTY_OPENLIST || r == AYSTAR_LIMIT_REACHED) return AYSTAR_NO_PATH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Return we are still busy
 | 
						// Return we are still busy
 | 
				
			||||||
	return AYSTAR_STILL_BUSY;
 | 
						return AYSTAR_STILL_BUSY;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Adds a node from where to start an algorithm. Multiple nodes can be added
 | 
					 * Adds a node from where to start an algorithm. Multiple nodes can be added
 | 
				
			||||||
 * if wanted. You should make sure that clear() is called before adding nodes
 | 
					 * if wanted. You should make sure that clear() is called before adding nodes
 | 
				
			||||||
 * if the AyStar has been used before (though the normal main loop calls
 | 
					 * if the AyStar has been used before (though the normal main loop calls
 | 
				
			||||||
 * clear() automatically when the algorithm finishes 
 | 
					 * clear() automatically when the algorithm finishes 
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node) {
 | 
					void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node) {
 | 
				
			||||||
#ifdef AYSTAR_DEBUG
 | 
					#ifdef AYSTAR_DEBUG
 | 
				
			||||||
	printf("[AyStar] Starting A* Algorithm from node (%d, %d, %d)\n", GET_TILE_X(start_node->tile), GET_TILE_Y(start_node->tile), start_node->direction);
 | 
						printf("[AyStar] Starting A* Algorithm from node (%d, %d, %d)\n", GET_TILE_X(start_node->tile), GET_TILE_Y(start_node->tile), start_node->direction);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, 0, 0);
 | 
						AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, 0, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void init_AyStar(AyStar* aystar, Hash_HashProc hash, uint num_buckets) {
 | 
					void init_AyStar(AyStar* aystar, Hash_HashProc hash, uint num_buckets) {
 | 
				
			||||||
	// Allocated the Hash for the OpenList and ClosedList
 | 
						// Allocated the Hash for the OpenList and ClosedList
 | 
				
			||||||
	init_Hash(&aystar->OpenListHash, hash, num_buckets);
 | 
						init_Hash(&aystar->OpenListHash, hash, num_buckets);
 | 
				
			||||||
	init_Hash(&aystar->ClosedListHash, hash, num_buckets);
 | 
						init_Hash(&aystar->ClosedListHash, hash, num_buckets);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Set up our sorting queue
 | 
						// Set up our sorting queue
 | 
				
			||||||
	//  BinaryHeap allocates a block of 1024 nodes
 | 
						//  BinaryHeap allocates a block of 1024 nodes
 | 
				
			||||||
	//  When thatone gets full it reserves an otherone, till this number
 | 
						//  When thatone gets full it reserves an otherone, till this number
 | 
				
			||||||
	//  That is why it can stay this high
 | 
						//  That is why it can stay this high
 | 
				
			||||||
	init_BinaryHeap(&aystar->OpenListQueue, 102400);
 | 
						init_BinaryHeap(&aystar->OpenListQueue, 102400);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	aystar->addstart	= AyStarMain_AddStartNode;
 | 
						aystar->addstart	= AyStarMain_AddStartNode;
 | 
				
			||||||
	aystar->main		= AyStarMain_Main;
 | 
						aystar->main		= AyStarMain_Main;
 | 
				
			||||||
	aystar->loop		= AyStarMain_Loop;
 | 
						aystar->loop		= AyStarMain_Loop;
 | 
				
			||||||
	aystar->free		= AyStarMain_Free;
 | 
						aystar->free		= AyStarMain_Free;
 | 
				
			||||||
	aystar->clear		= AyStarMain_Clear;
 | 
						aystar->clear		= AyStarMain_Clear;
 | 
				
			||||||
	aystar->checktile	= AyStarMain_CheckTile;
 | 
						aystar->checktile	= AyStarMain_CheckTile;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1564,7 +1564,7 @@ Industry *CreateNewIndustry(uint tile, int type)
 | 
				
			|||||||
	return i;
 | 
						return i;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const byte _numof_industry_table[4][12] = {
 | 
					static const byte _numof_industry_table[4][12] = {
 | 
				
			||||||
	{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 | 
						{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
 | 
				
			||||||
	{0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5},
 | 
						{0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5},
 | 
				
			||||||
	{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
 | 
						{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
 | 
				
			||||||
@@ -1574,8 +1574,8 @@ static const byte _numof_industry_table[4][12] = {
 | 
				
			|||||||
static void PlaceInitialIndustry(byte type, int amount)
 | 
					static void PlaceInitialIndustry(byte type, int amount)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int num = _numof_industry_table[_opt.diff.number_industries][amount];
 | 
						int num = _numof_industry_table[_opt.diff.number_industries][amount];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (_opt.diff.number_industries != 0)
 | 
						if (_opt.diff.number_industries != 0)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		assert(num > 0);
 | 
							assert(num > 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1585,7 +1585,7 @@ static void PlaceInitialIndustry(byte type, int amount)
 | 
				
			|||||||
				if (CreateNewIndustry(TILE_MASK(Random()), type) != NULL)
 | 
									if (CreateNewIndustry(TILE_MASK(Random()), type) != NULL)
 | 
				
			||||||
					break; 
 | 
										break; 
 | 
				
			||||||
			} while (--i != 0);
 | 
								} while (--i != 0);
 | 
				
			||||||
		} while (--num);
 | 
							} while (--num);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										16
									
								
								network.c
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								network.c
									
									
									
									
									
								
							@@ -1252,14 +1252,14 @@ void NetworkIPListInit() {
 | 
				
			|||||||
	gethostname(hostname,250);
 | 
						gethostname(hostname,250);
 | 
				
			||||||
	DEBUG(misc,2) ("[NET][IP] init for host %s", hostname);
 | 
						DEBUG(misc,2) ("[NET][IP] init for host %s", hostname);
 | 
				
			||||||
	he=gethostbyname((char *) hostname);
 | 
						he=gethostbyname((char *) hostname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (he == NULL) {
 | 
						if (he == NULL) {
 | 
				
			||||||
		he = gethostbyname("localhost");
 | 
							he = gethostbyname("localhost");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	if (he == NULL) {
 | 
						if (he == NULL) {
 | 
				
			||||||
		bcaddr = inet_addr("127.0.0.1");
 | 
							bcaddr = inet_addr("127.0.0.1");
 | 
				
			||||||
		he = gethostbyaddr(inet_ntoa(*(struct in_addr *) &bcaddr), sizeof(bcaddr), AF_INET);
 | 
							he = gethostbyaddr(inet_ntoa(*(struct in_addr *) &bcaddr), sizeof(bcaddr), AF_INET);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (he == NULL) {
 | 
						if (he == NULL) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										406
									
								
								queue.h
									
									
									
									
									
								
							
							
						
						
									
										406
									
								
								queue.h
									
									
									
									
									
								
							@@ -1,203 +1,203 @@
 | 
				
			|||||||
#ifndef QUEUE_H
 | 
					#ifndef QUEUE_H
 | 
				
			||||||
#define QUEUE_H
 | 
					#define QUEUE_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//#define NOFREE
 | 
					//#define NOFREE
 | 
				
			||||||
//#define QUEUE_DEBUG
 | 
					//#define QUEUE_DEBUG
 | 
				
			||||||
//#define HASH_DEBUG
 | 
					//#define HASH_DEBUG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct Queue Queue;
 | 
					typedef struct Queue Queue;
 | 
				
			||||||
typedef bool Queue_PushProc(Queue* q, void* item, int priority);
 | 
					typedef bool Queue_PushProc(Queue* q, void* item, int priority);
 | 
				
			||||||
typedef void* Queue_PopProc(Queue* q);
 | 
					typedef void* Queue_PopProc(Queue* q);
 | 
				
			||||||
typedef bool Queue_DeleteProc(Queue* q, void* item, int priority);
 | 
					typedef bool Queue_DeleteProc(Queue* q, void* item, int priority);
 | 
				
			||||||
typedef void Queue_ClearProc(Queue* q, bool free_values);
 | 
					typedef void Queue_ClearProc(Queue* q, bool free_values);
 | 
				
			||||||
typedef void Queue_FreeProc(Queue* q, bool free_values);
 | 
					typedef void Queue_FreeProc(Queue* q, bool free_values);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct InsSortNode InsSortNode;
 | 
					typedef struct InsSortNode InsSortNode;
 | 
				
			||||||
struct InsSortNode {
 | 
					struct InsSortNode {
 | 
				
			||||||
	void* item;
 | 
						void* item;
 | 
				
			||||||
	int priority;
 | 
						int priority;
 | 
				
			||||||
	InsSortNode* next;
 | 
						InsSortNode* next;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
typedef struct BinaryHeapNode BinaryHeapNode;
 | 
					typedef struct BinaryHeapNode BinaryHeapNode;
 | 
				
			||||||
	struct BinaryHeapNode {
 | 
						struct BinaryHeapNode {
 | 
				
			||||||
	void* item;
 | 
						void* item;
 | 
				
			||||||
	int priority;
 | 
						int priority;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Queue{
 | 
					struct Queue{
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Pushes an element into the queue, at the appropriate place for the queue.
 | 
						 * Pushes an element into the queue, at the appropriate place for the queue.
 | 
				
			||||||
	 * Requires the queue pointer to be of an appropriate type, of course.
 | 
						 * Requires the queue pointer to be of an appropriate type, of course.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	Queue_PushProc* push;
 | 
						Queue_PushProc* push;
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Pops the first element from the queue. What exactly is the first element,
 | 
						 * Pops the first element from the queue. What exactly is the first element,
 | 
				
			||||||
	 * is defined by the exact type of queue.
 | 
						 * is defined by the exact type of queue.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	Queue_PopProc* pop;
 | 
						Queue_PopProc* pop;
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Deletes the item from the queue. priority should be specified if
 | 
						 * Deletes the item from the queue. priority should be specified if
 | 
				
			||||||
	 * known, which speeds up the deleting for some queue's. Should be -1
 | 
						 * known, which speeds up the deleting for some queue's. Should be -1
 | 
				
			||||||
	 * if not known.
 | 
						 * if not known.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	Queue_DeleteProc* del;
 | 
						Queue_DeleteProc* del;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Clears the queue, by removing all values from it. It's state is
 | 
						/* Clears the queue, by removing all values from it. It's state is
 | 
				
			||||||
	 * effectively reset. If free_items is true, each of the items cleared
 | 
						 * effectively reset. If free_items is true, each of the items cleared
 | 
				
			||||||
	 * in this way are free()'d.
 | 
						 * in this way are free()'d.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	Queue_ClearProc* clear;
 | 
						Queue_ClearProc* clear;
 | 
				
			||||||
	/* Frees the queue, by reclaiming all memory allocated by it. After
 | 
						/* Frees the queue, by reclaiming all memory allocated by it. After
 | 
				
			||||||
	 * this it is no longer usable. If free_items is true, any remaining
 | 
						 * this it is no longer usable. If free_items is true, any remaining
 | 
				
			||||||
	 * items are free()'d too. 
 | 
						 * items are free()'d too. 
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	Queue_FreeProc* free;
 | 
						Queue_FreeProc* free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	union {
 | 
						union {
 | 
				
			||||||
		struct {
 | 
							struct {
 | 
				
			||||||
			uint max_size;
 | 
								uint max_size;
 | 
				
			||||||
			uint size;
 | 
								uint size;
 | 
				
			||||||
			void** elements;
 | 
								void** elements;
 | 
				
			||||||
		} stack;
 | 
							} stack;
 | 
				
			||||||
		struct {
 | 
							struct {
 | 
				
			||||||
			uint max_size;
 | 
								uint max_size;
 | 
				
			||||||
			uint head; /* The index where the last element should be inserted */
 | 
								uint head; /* The index where the last element should be inserted */
 | 
				
			||||||
			uint tail; /* The index where the next element should be read */
 | 
								uint tail; /* The index where the next element should be read */
 | 
				
			||||||
			void** elements;
 | 
								void** elements;
 | 
				
			||||||
		} fifo;
 | 
							} fifo;
 | 
				
			||||||
		struct {
 | 
							struct {
 | 
				
			||||||
			InsSortNode* first;
 | 
								InsSortNode* first;
 | 
				
			||||||
		} inssort;
 | 
							} inssort;
 | 
				
			||||||
		struct {
 | 
							struct {
 | 
				
			||||||
			uint max_size;
 | 
								uint max_size;
 | 
				
			||||||
			uint size;
 | 
								uint size;
 | 
				
			||||||
			uint blocks; /* The amount of blocks for which space is reserved in elements */
 | 
								uint blocks; /* The amount of blocks for which space is reserved in elements */
 | 
				
			||||||
			BinaryHeapNode** elements;
 | 
								BinaryHeapNode** elements;
 | 
				
			||||||
		} binaryheap;
 | 
							} binaryheap;
 | 
				
			||||||
	} data;
 | 
						} data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If true, this struct will be free'd when the
 | 
						/* If true, this struct will be free'd when the
 | 
				
			||||||
	 * Queue is deleted. */
 | 
						 * Queue is deleted. */
 | 
				
			||||||
	bool freeq;
 | 
						bool freeq;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Initializes a stack and allocates internal memory. */
 | 
					/* Initializes a stack and allocates internal memory. */
 | 
				
			||||||
void init_Stack(Queue* q, uint max_size);
 | 
					void init_Stack(Queue* q, uint max_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Allocate a new stack with a maximum of max_size elements. */
 | 
					/* Allocate a new stack with a maximum of max_size elements. */
 | 
				
			||||||
Queue* new_Stack(uint max_size);
 | 
					Queue* new_Stack(uint max_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Fifo
 | 
					 * Fifo
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Initializes a fifo and allocates internal memory for maximum of max_size
 | 
					/* Initializes a fifo and allocates internal memory for maximum of max_size
 | 
				
			||||||
 * elements */
 | 
					 * elements */
 | 
				
			||||||
void init_Fifo(Queue* q, uint max_size);
 | 
					void init_Fifo(Queue* q, uint max_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Allocate a new fifo and initializes it with a maximum of max_size elements. */
 | 
					/* Allocate a new fifo and initializes it with a maximum of max_size elements. */
 | 
				
			||||||
Queue* new_Fifo(uint max_size);
 | 
					Queue* new_Fifo(uint max_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Queue* new_Fifo_in_buffer(uint max_size, void* buffer);
 | 
					Queue* new_Fifo_in_buffer(uint max_size, void* buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int build_Fifo(void* buffer, uint size);
 | 
					int build_Fifo(void* buffer, uint size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Insertion Sorter
 | 
					 * Insertion Sorter
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Initializes a inssort and allocates internal memory. There is no maximum
 | 
					/* Initializes a inssort and allocates internal memory. There is no maximum
 | 
				
			||||||
 * size */
 | 
					 * size */
 | 
				
			||||||
void init_InsSort(Queue* q);
 | 
					void init_InsSort(Queue* q);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Allocate a new fifo and initializes it. There is no maximum size */
 | 
					/* Allocate a new fifo and initializes it. There is no maximum size */
 | 
				
			||||||
Queue* new_InsSort();
 | 
					Queue* new_InsSort();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *  Binary Heap
 | 
					 *  Binary Heap
 | 
				
			||||||
 *  For information, see:
 | 
					 *  For information, see:
 | 
				
			||||||
 *   http://www.policyalmanac.org/games/binaryHeaps.htm
 | 
					 *   http://www.policyalmanac.org/games/binaryHeaps.htm
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* The amount of elements that will be malloc'd at a time */
 | 
					/* The amount of elements that will be malloc'd at a time */
 | 
				
			||||||
#define BINARY_HEAP_BLOCKSIZE_BITS 10
 | 
					#define BINARY_HEAP_BLOCKSIZE_BITS 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Initializes a binary heap and allocates internal memory for maximum of
 | 
					/* Initializes a binary heap and allocates internal memory for maximum of
 | 
				
			||||||
 * max_size elements */
 | 
					 * max_size elements */
 | 
				
			||||||
void init_BinaryHeap(Queue* q, uint max_size);
 | 
					void init_BinaryHeap(Queue* q, uint max_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Allocate a new binary heap and initializes it with a maximum of max_size
 | 
					/* Allocate a new binary heap and initializes it with a maximum of max_size
 | 
				
			||||||
 * elements. */
 | 
					 * elements. */
 | 
				
			||||||
Queue* new_BinaryHeap(uint max_size);
 | 
					Queue* new_BinaryHeap(uint max_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Hash
 | 
					 * Hash
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef struct HashNode HashNode;
 | 
					typedef struct HashNode HashNode;
 | 
				
			||||||
struct HashNode {
 | 
					struct HashNode {
 | 
				
			||||||
	uint key1;
 | 
						uint key1;
 | 
				
			||||||
	uint key2;
 | 
						uint key2;
 | 
				
			||||||
	void* value;
 | 
						void* value;
 | 
				
			||||||
	HashNode* next;
 | 
						HashNode* next;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
/* Generates a hash code from the given key pair. You should make sure that
 | 
					/* Generates a hash code from the given key pair. You should make sure that
 | 
				
			||||||
 * the resulting range is clearly defined.
 | 
					 * the resulting range is clearly defined.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
typedef uint Hash_HashProc(uint key1, uint key2);
 | 
					typedef uint Hash_HashProc(uint key1, uint key2);
 | 
				
			||||||
typedef struct Hash {
 | 
					typedef struct Hash {
 | 
				
			||||||
	/* The hash function used */
 | 
						/* The hash function used */
 | 
				
			||||||
	Hash_HashProc* hash;
 | 
						Hash_HashProc* hash;
 | 
				
			||||||
	/* The amount of items in the hash */
 | 
						/* The amount of items in the hash */
 | 
				
			||||||
	uint size;
 | 
						uint size;
 | 
				
			||||||
	/* The number of buckets allocated */
 | 
						/* The number of buckets allocated */
 | 
				
			||||||
	uint num_buckets;
 | 
						uint num_buckets;
 | 
				
			||||||
	/* A pointer to an array of num_buckets buckets. */
 | 
						/* A pointer to an array of num_buckets buckets. */
 | 
				
			||||||
	HashNode* buckets;
 | 
						HashNode* buckets;
 | 
				
			||||||
	/* A pointer to an array of numbuckets booleans, which will be true if
 | 
						/* A pointer to an array of numbuckets booleans, which will be true if
 | 
				
			||||||
	 * there are any Nodes in the bucket */
 | 
						 * there are any Nodes in the bucket */
 | 
				
			||||||
	bool* buckets_in_use;
 | 
						bool* buckets_in_use;
 | 
				
			||||||
	/* If true, buckets will be freed in delete_hash */
 | 
						/* If true, buckets will be freed in delete_hash */
 | 
				
			||||||
	bool freeb;
 | 
						bool freeb;
 | 
				
			||||||
	/* If true, the pointer to this struct will be freed in delete_hash */
 | 
						/* If true, the pointer to this struct will be freed in delete_hash */
 | 
				
			||||||
	bool freeh;
 | 
						bool freeh;
 | 
				
			||||||
} Hash;
 | 
					} Hash;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Call these function to manipulate a hash */
 | 
					/* Call these function to manipulate a hash */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Deletes the value with the specified key pair from the hash and returns
 | 
					/* Deletes the value with the specified key pair from the hash and returns
 | 
				
			||||||
 * that value. Returns NULL when the value was not present. The value returned
 | 
					 * that value. Returns NULL when the value was not present. The value returned
 | 
				
			||||||
 * is _not_ free()'d! */
 | 
					 * is _not_ free()'d! */
 | 
				
			||||||
void* Hash_Delete(Hash* h, uint key1, uint key2);
 | 
					void* Hash_Delete(Hash* h, uint key1, uint key2);
 | 
				
			||||||
/* Sets the value associated with the given key pair to the given value.
 | 
					/* Sets the value associated with the given key pair to the given value.
 | 
				
			||||||
 * Returns the old value if the value was replaced, NULL when it was not yet present. */
 | 
					 * Returns the old value if the value was replaced, NULL when it was not yet present. */
 | 
				
			||||||
void* Hash_Set(Hash* h, uint key1, uint key2, void* value);
 | 
					void* Hash_Set(Hash* h, uint key1, uint key2, void* value);
 | 
				
			||||||
/* Gets the value associated with the given key pair, or NULL when it is not
 | 
					/* Gets the value associated with the given key pair, or NULL when it is not
 | 
				
			||||||
 * present. */
 | 
					 * present. */
 | 
				
			||||||
void* Hash_Get(Hash* h, uint key1, uint key2);
 | 
					void* Hash_Get(Hash* h, uint key1, uint key2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Call these function to create/destroy a hash */
 | 
					/* Call these function to create/destroy a hash */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Builds a new hash, with num_buckets buckets. Make sure that hash() always
 | 
					/* Builds a new hash, with num_buckets buckets. Make sure that hash() always
 | 
				
			||||||
 * returns a hash less than num_buckets! Call delete_hash after use */
 | 
					 * returns a hash less than num_buckets! Call delete_hash after use */
 | 
				
			||||||
Hash* new_Hash(Hash_HashProc* hash, int num_buckets);
 | 
					Hash* new_Hash(Hash_HashProc* hash, int num_buckets);
 | 
				
			||||||
/* Builds a new hash in an existing struct. Make sure that hash() always
 | 
					/* Builds a new hash in an existing struct. Make sure that hash() always
 | 
				
			||||||
 * returns a hash less than num_buckets! Call delete_hash after use */
 | 
					 * returns a hash less than num_buckets! Call delete_hash after use */
 | 
				
			||||||
void init_Hash(Hash* h, Hash_HashProc* hash, int num_buckets);
 | 
					void init_Hash(Hash* h, Hash_HashProc* hash, int num_buckets);
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Deletes the hash and cleans up. Only cleans up memory allocated by new_Hash
 | 
					 * Deletes the hash and cleans up. Only cleans up memory allocated by new_Hash
 | 
				
			||||||
 * & friends. If free is true, it will call free() on all the values that
 | 
					 * & friends. If free is true, it will call free() on all the values that
 | 
				
			||||||
 * are left in the hash.
 | 
					 * are left in the hash.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void delete_Hash(Hash* h, bool free_values);
 | 
					void delete_Hash(Hash* h, bool free_values);
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Cleans the hash, but keeps the memory allocated
 | 
					 * Cleans the hash, but keeps the memory allocated
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void clear_Hash(Hash* h, bool free_values);
 | 
					void clear_Hash(Hash* h, bool free_values);
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Gets the current size of the Hash
 | 
					 * Gets the current size of the Hash
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
uint Hash_Size(Hash* h);
 | 
					uint Hash_Size(Hash* h);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* QUEUE_H */
 | 
					#endif /* QUEUE_H */
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user