# trolly.cpp

    00001 /* $Id: trolly.cpp 14267 2008-09-07 21:41:47Z rubidium $ */
    00002
    00003 /*
    00004  * This AI was created as a direct reaction to the big demand for some good AIs
    00005  * in OTTD. Too bad it never left alpha-stage, and it is considered dead in its
    00006  * current form.
    00007  * By the time of writing this, we, the creator of this AI and a good friend of
    00008  * mine, are designing a whole new AI-system that allows us to create AIs
    00009  * easier and without all the fuzz we encountered while I was working on this
    00010  * AI. By the time that system is finished, you can expect that this AI will
    00011  * dissapear, because it is pretty obselete and bad programmed.
    00012  *
    00013  * Meanwhile I wish you all much fun with this AI; if you are interested as
    00014  * AI-developer in this AI, I advise you not stare too long to some code, some
    00015  * things in here really are... strange ;) But in either way: enjoy :)
    00016  *
    00017  *  -- TrueLight :: 2005-09-01
    00018  */
    00019
    00020 #include "../../stdafx.h"
    00021 #include "../../openttd.h"
    00022 #include "../../debug.h"
    00023 #include "../../road_map.h"
    00024 #include "../../station_map.h"
    00025 #include "../../command_func.h"
    00026 #include "trolly.h"
    00027 #include "../../town.h"
    00028 #include "../../industry.h"
    00029 #include "../../station.h"
    00030 #include "../../engine.h"
    00031 #include "../../gui.h"
    00032 #include "../../depot.h"
    00033 #include "../../vehicle_base.h"
    00034 #include "../../vehicle_func.h"
    00035 #include "../../date_func.h"
    00036 #include "../ai.h"
    00037 #include "../../order.h"
    00038 #include "../../player_base.h"
    00039 #include "../../player_func.h"
    00040
    00041 #include "table/strings.h"
    00042
    00043 PlayerAiNew _players_ainew[MAX_PLAYERS];
    00044
    00045 // This function is called after StartUp. It is the init of an AI
    00046 static void AiNew_State_FirstTime(Player *p)
    00047 {
    00048   // This assert is used to protect those function from misuse
    00049   //   You have quickly a small mistake in the state-array
    00050   //   With that, everything would go wrong. Finding that, is almost impossible
    00051   //   With this assert, that problem can never happen.
    00052   assert(_players_ainew[p->index].state == AI_STATE_FIRST_TIME);
    00053   // We first have to init some things
    00054
    00055   if (_current_player == 1) ShowErrorMessage(INVALID_STRING_ID, TEMP_AI_IN_PROGRESS, 0, 0);
    00056
    00057   // The PathFinder (AyStar)
    00058   // TODO: Maybe when an AI goes bankrupt, this is de-init
    00059   //  or when coming from a savegame.. should be checked out!
    00060   _players_ainew[p->index].path_info.start_tile_tl = 0;
    00061   _players_ainew[p->index].path_info.start_tile_br = 0;
    00062   _players_ainew[p->index].path_info.end_tile_tl = 0;
    00063   _players_ainew[p->index].path_info.end_tile_br = 0;
    00064   _players_ainew[p->index].pathfinder = new_AyStar_AiPathFinder(12, &_players_ainew[p->index].path_info);
    00065
    00066   _players_ainew[p->index].idle = 0;
    00067   _players_ainew[p->index].last_vehiclecheck_date = _date;
    00068
    00069   // We ALWAYS start with a bus route.. just some basic money ;)
    00070   _players_ainew[p->index].action = AI_ACTION_BUS_ROUTE;
    00071
    00072   // Let's popup the news, and after that, start building..
    00073   _players_ainew[p->index].state = AI_STATE_WAKE_UP;
    00074 }
    00075
    00076
    00077 // This function just waste some time
    00078 //  It keeps it more real. The AI can build on such tempo no normal user
    00079 //  can ever keep up with that. The competitor_speed already delays a bit
    00080 //  but after the AI finished a track it really needs to go to sleep.
    00081 //
    00082 // Let's say, we sleep between one and three days if the AI is put on Very Fast.
    00083 //  This means that on Very Slow it will be between 16 and 48 days.. slow enough?
    00084 static void AiNew_State_Nothing(Player *p)
    00085 {
    00086   assert(_players_ainew[p->index].state == AI_STATE_NOTHING);
    00087   // If we are done idling, start over again
    00088   if (_players_ainew[p->index].idle == 0) _players_ainew[p->index].idle = AI_RandomRange(DAY_TICKS * 2) + DAY_TICKS;
    00089   if (--_players_ainew[p->index].idle == 0) {
    00090     // We are done idling.. what you say? Let's do something!
    00091     // I mean.. the next tick ;)
    00092     _players_ainew[p->index].state = AI_STATE_WAKE_UP;
    00093   }
    00094 }
    00095
    00096
    00097 // This function picks out a task we are going to do.
    00098 //  Currently supported:
    00099 //    - Make new route
    00100 //    - Check route
    00101 //    - Build HQ
    00102 static void AiNew_State_WakeUp(Player *p)
    00103 {
    00104   int c;
    00105   assert(_players_ainew[p->index].state == AI_STATE_WAKE_UP);
    00106   // First, check if we have a HQ
    00107   if (p->location_of_house == 0) {
    00108     // We have no HQ yet, build one on a random place
    00109     // Random till we found a place for it!
    00110     // TODO: this should not be on a random place..
    00111     AiNew_Build_CompanyHQ(p, AI_Random() % MapSize());
    00112     // Enough for now, but we want to come back here the next time
    00113     //  so we do not change any status
    00114     return;
    00115   }
    00116
    00117   Money money = p->player_money - AI_MINIMUM_MONEY;
    00118
    00119   // Let's pick an action!
    00120   if (_players_ainew[p->index].action == AI_ACTION_NONE) {
    00121     c = AI_Random() & 0xFF;
    00122     if (p->current_loan > 0 &&
    00123         p->old_economy[1].income > AI_MINIMUM_INCOME_FOR_LOAN &&
    00124         c < 10) {
    00125       _players_ainew[p->index].action = AI_ACTION_REPAY_LOAN;
    00126     } else if (_players_ainew[p->index].last_vehiclecheck_date + AI_DAYS_BETWEEN_VEHICLE_CHECKS < _date) {
    00127       // Check all vehicles once in a while
    00128       _players_ainew[p->index].action = AI_ACTION_CHECK_ALL_VEHICLES;
    00129       _players_ainew[p->index].last_vehiclecheck_date = _date;
    00130     } else if (c < 100 && !_patches.ai_disable_veh_roadveh) {
    00131       // Do we have any spots for road-vehicles left open?
    00132       if (GetFreeUnitNumber(VEH_ROAD) <= _patches.max_roadveh) {
    00133         if (c < 85) {
    00134           _players_ainew[p->index].action = AI_ACTION_TRUCK_ROUTE;
    00135         } else {
    00136           _players_ainew[p->index].action = AI_ACTION_BUS_ROUTE;
    00137         }
    00138       }
    00139 #if 0
    00140     } else if (c < 200 && !_patches.ai_disable_veh_train) {
    00141       if (GetFreeUnitNumber(VEH_TRAIN) <= _patches.max_trains) {
    00142         _players_ainew[p->index].action = AI_ACTION_TRAIN_ROUTE;
    00143       }
    00144 #endif
    00145     }
    00146
    00147     _players_ainew[p->index].counter = 0;
    00148   }
    00149
    00150   if (_players_ainew[p->index].counter++ > AI_MAX_TRIES_FOR_SAME_ROUTE) {
    00151     _players_ainew[p->index].action = AI_ACTION_NONE;
    00152     return;
    00153   }
    00154
    00155   if (_patches.ai_disable_veh_roadveh && (
    00156         _players_ainew[p->index].action == AI_ACTION_BUS_ROUTE ||
    00157         _players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE
    00158       )) {
    00159     _players_ainew[p->index].action = AI_ACTION_NONE;
    00160     return;
    00161   }
    00162
    00163   if (_players_ainew[p->index].action == AI_ACTION_REPAY_LOAN &&
    00164       money > AI_MINIMUM_LOAN_REPAY_MONEY) {
    00165     // We start repaying some money..
    00166     _players_ainew[p->index].state = AI_STATE_REPAY_MONEY;
    00167     return;
    00168   }
    00169
    00170   if (_players_ainew[p->index].action == AI_ACTION_CHECK_ALL_VEHICLES) {
    00171     _players_ainew[p->index].state = AI_STATE_CHECK_ALL_VEHICLES;
    00172     return;
    00173   }
    00174
    00175   // It is useless to start finding a route if we don't have enough money
    00176   //  to build the route anyway..
    00177   if (_players_ainew[p->index].action == AI_ACTION_BUS_ROUTE &&
    00178       money > AI_MINIMUM_BUS_ROUTE_MONEY) {
    00179     if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) {
    00180       _players_ainew[p->index].action = AI_ACTION_NONE;
    00181       return;
    00182     }
    00183     _players_ainew[p->index].cargo = AI_NEED_CARGO;
    00184     _players_ainew[p->index].state = AI_STATE_LOCATE_ROUTE;
    00185     _players_ainew[p->index].tbt = AI_BUS; // Bus-route
    00186     return;
    00187   }
    00188   if (_players_ainew[p->index].action == AI_ACTION_TRUCK_ROUTE &&
    00189       money > AI_MINIMUM_TRUCK_ROUTE_MONEY) {
    00190     if (GetFreeUnitNumber(VEH_ROAD) > _patches.max_roadveh) {
    00191       _players_ainew[p->index].action = AI_ACTION_NONE;
    00192       return;
    00193     }
    00194     _players_ainew[p->index].cargo = AI_NEED_CARGO;
    00195     _players_ainew[p->index].last_id = 0;
    00196     _players_ainew[p->index].state = AI_STATE_LOCATE_ROUTE;
    00197     _players_ainew[p->index].tbt = AI_TRUCK;
    00198     return;
    00199   }
    00200
    00201   _players_ainew[p->index].state = AI_STATE_NOTHING;
    00202 }
    00203
    00204
    00205 static void AiNew_State_ActionDone(Player *p)
    00206 {
    00207   _players_ainew[p->index].action = AI_ACTION_NONE;
    00208   _players_ainew[p->index].state = AI_STATE_NOTHING;
    00209 }
    00210
    00211
    00212 // Check if a city or industry is good enough to start a route there
    00213 static bool AiNew_Check_City_or_Industry(Player *p, int ic, byte type)
    00214 {
    00215   if (type == AI_CITY) {
    00216     const Town* t = GetTown(ic);
    00217     const Station* st;
    00218     uint count = 0;
    00219     int j = 0;
    00220
    00221     // We don't like roadconstructions, don't even true such a city
    00222     if (t->road_build_months != 0) return false;
    00223
    00224     // Check if the rating in a city is high enough
    00225     //  If not, take a chance if we want to continue
    00226     if (t->ratings[_current_player] < 0 && AI_CHANCE16(1, 4)) return false;
    00227
    00228     if (t->max_pass - t->act_pass < AI_CHECKCITY_NEEDED_CARGO && !AI_CHANCE16(1, AI_CHECKCITY_CITY_CHANCE)) return false;
    00229
    00230     // Check if we have build a station in this town the last 6 months
    00231     //  else we don't do it. This is done, because stat updates can be slow
    00232     //  and sometimes it takes up to 4 months before the stats are corectly.
    00233     //  This way we don't get 12 busstations in one city of 100 population ;)
    00234     FOR_ALL_STATIONS(st) {
    00235       // Do we own it?
    00236       if (st->owner == _current_player) {
    00237         // Are we talking busses?
    00238         if (_players_ainew[p->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) != FACIL_BUS_STOP) continue;
    00239         // Is it the same city as we are in now?
    00240         if (st->town != t) continue;
    00241         // When was this station build?
    00242         if (_date - st->build_date < AI_CHECKCITY_DATE_BETWEEN) return false;
    00243         // Cound the amount of stations in this city that we own
    00244         count++;
    00245       } else {
    00246         // We do not own it, request some info about the station
    00247         //  we want to know if this station gets the same good. If so,
    00248         //  we want to know its rating. If it is too high, we are not going
    00249         //  to build there
    00250         if (!st->goods[CT_PASSENGERS].last_speed) continue;
    00251         // Is it around our city
    00252         if (DistanceManhattan(st->xy, t->xy) > 10) continue;
    00253         // It does take this cargo.. what is his rating?
    00254         if (st->goods[CT_PASSENGERS].rating < AI_CHECKCITY_CARGO_RATING) continue;
    00255         j++;
    00256         // When this is the first station, we build a second with no problem ;)
    00257         if (j == 1) continue;
    00258         // The rating is high.. second station...
    00259         //  a little chance that we still continue
    00260         //  But if there are 3 stations of this size, we never go on...
    00261         if (j == 2 && AI_CHANCE16(1, AI_CHECKCITY_CARGO_RATING_CHANCE)) continue;
    00262         // We don't like this station :(
    00263         return false;
    00264       }
    00265     }
    00266
    00267     // We are about to add one...
    00268     count++;
    00269     // Check if we the city can provide enough cargo for this amount of stations..
    00270     if (count * AI_CHECKCITY_CARGO_PER_STATION > t->max_pass) return false;
    00271
    00272     // All check are okay, so we can build here!
    00273     return true;
    00274   }
    00275   if (type == AI_INDUSTRY) {
    00276     const Industry* i = GetIndustry(ic);
    00277     const Station* st;
    00278     int count = 0;
    00279     int j = 0;
    00280
    00281     if (i->town != NULL && i->town->ratings[_current_player] < 0 && AI_CHANCE16(1, 4)) return false;
    00282
    00283     // No limits on delevering stations!
    00284     //  Or for industry that does not give anything yet
    00285     if (i->produced_cargo[0] == CT_INVALID || i->last_month_production[0] == 0) return true;
    00286
    00287     if (i->last_month_production[0] - i->last_month_transported[0] < AI_CHECKCITY_NEEDED_CARGO) return false;
    00288
    00289     // Check if we have build a station in this town the last 6 months
    00290     //  else we don't do it. This is done, because stat updates can be slow
    00291     //  and sometimes it takes up to 4 months before the stats are corectly.
    00292     FOR_ALL_STATIONS(st) {
    00293       // Do we own it?
    00294       if (st->owner == _current_player) {
    00295         // Are we talking trucks?
    00296         if (_players_ainew[p->index].tbt == AI_TRUCK && (FACIL_TRUCK_STOP & st->facilities) != FACIL_TRUCK_STOP) continue;
    00297         // Is it the same city as we are in now?
    00298         if (st->town != i->town) continue;
    00299         // When was this station build?
    00300         if (_date - st->build_date < AI_CHECKCITY_DATE_BETWEEN) return false;
    00301         // Cound the amount of stations in this city that we own
    00302         count++;
    00303       } else {
    00304         // We do not own it, request some info about the station
    00305         //  we want to know if this station gets the same good. If so,
    00306         //  we want to know its rating. If it is too high, we are not going
    00307         //  to build there
    00308         if (i->produced_cargo[0] == CT_INVALID) continue;
    00309         // It does not take this cargo
    00310         if (!st->goods[i->produced_cargo[0]].last_speed) continue;
    00311         // Is it around our industry
    00312         if (DistanceManhattan(st->xy, i->xy) > 5) continue;
    00313         // It does take this cargo.. what is his rating?
    00314         if (st->goods[i->produced_cargo[0]].rating < AI_CHECKCITY_CARGO_RATING) continue;
    00315         j++;
    00316         // The rating is high.. a little chance that we still continue
    00317         //  But if there are 2 stations of this size, we never go on...
    00318         if (j == 1 && AI_CHANCE16(1, AI_CHECKCITY_CARGO_RATING_CHANCE)) continue;
    00319         // We don't like this station :(
    00320         return false;
    00321       }
    00322     }
    00323
    00324     // We are about to add one...
    00325     count++;
    00326     // Check if we the city can provide enough cargo for this amount of stations..
    00327     if (count * AI_CHECKCITY_CARGO_PER_STATION > i->last_month_production[0]) return false;
    00328
    00329     // All check are okay, so we can build here!
    00330     return true;
    00331   }
    00332
    00333   return true;
    00334 }
    00335
    00336
    00337 // This functions tries to locate a good route
    00338 static void AiNew_State_LocateRoute(Player *p)
    00339 {
    00340   assert(_players_ainew[p->index].state == AI_STATE_LOCATE_ROUTE);
    00341   // For now, we only support PASSENGERS, CITY and BUSSES
    00342
    00343   // We don't have a route yet
    00344   if (_players_ainew[p->index].cargo == AI_NEED_CARGO) {
    00345     _players_ainew[p->index].new_cost = 0; // No cost yet
    00346     _players_ainew[p->index].temp = -1;
    00347     // Reset the counter
    00348     _players_ainew[p->index].counter = 0;
    00349
    00350     _players_ainew[p->index].from_ic = -1;
    00351     _players_ainew[p->index].to_ic = -1;
    00352     if (_players_ainew[p->index].tbt == AI_BUS) {
    00353       // For now we only have a passenger route
    00354       _players_ainew[p->index].cargo = CT_PASSENGERS;
    00355
    00356       // Find a route to cities
    00357       _players_ainew[p->index].from_type = AI_CITY;
    00358       _players_ainew[p->index].to_type = AI_CITY;
    00359     } else if (_players_ainew[p->index].tbt == AI_TRUCK) {
    00360       _players_ainew[p->index].cargo = AI_NO_CARGO;
    00361
    00362       _players_ainew[p->index].from_type = AI_INDUSTRY;
    00363       _players_ainew[p->index].to_type = AI_INDUSTRY;
    00364     }
    00365
    00366     // Now we are doing initing, we wait one tick
    00367     return;
    00368   }
    00369
    00370   // Increase the counter and abort if it is taking too long!
    00371   _players_ainew[p->index].counter++;
    00372   if (_players_ainew[p->index].counter > AI_LOCATE_ROUTE_MAX_COUNTER) {
    00373     // Switch back to doing nothing!
    00374     _players_ainew[p->index].state = AI_STATE_NOTHING;
    00375     return;
    00376   }
    00377
    00378   // We are going to locate a city from where we are going to connect
    00379   if (_players_ainew[p->index].from_ic == -1) {
    00380     if (_players_ainew[p->index].temp == -1) {
    00381       // First, we pick a random spot to search from
    00382       if (_players_ainew[p->index].from_type == AI_CITY) {
    00383         _players_ainew[p->index].temp = AI_RandomRange(GetMaxTownIndex() + 1);
    00384       } else {
    00385         _players_ainew[p->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1);
    00386       }
    00387     }
    00388
    00389     if (!AiNew_Check_City_or_Industry(p, _players_ainew[p->index].temp, _players_ainew[p->index].from_type)) {
    00390       // It was not a valid city
    00391       //  increase the temp with one, and return. We will come back later here
    00392       //  to try again
    00393       _players_ainew[p->index].temp++;
    00394       if (_players_ainew[p->index].from_type == AI_CITY) {
    00395         if (_players_ainew[p->index].temp > GetMaxTownIndex()) _players_ainew[p->index].temp = 0;
    00396       } else {
    00397         if (_players_ainew[p->index].temp > GetMaxIndustryIndex()) _players_ainew[p->index].temp = 0;
    00398       }
    00399
    00400       // Don't do an attempt if we are trying the same id as the last time...
    00401       if (_players_ainew[p->index].last_id == _players_ainew[p->index].temp) return;
    00402       _players_ainew[p->index].last_id = _players_ainew[p->index].temp;
    00403
    00404       return;
    00405     }
    00406
    00407     // We found a good city/industry, save the data of it
    00408     _players_ainew[p->index].from_ic = _players_ainew[p->index].temp;
    00409
    00410     // Start the next tick with finding a to-city
    00411     _players_ainew[p->index].temp = -1;
    00412     return;
    00413   }
    00414
    00415   // Find a to-city
    00416   if (_players_ainew[p->index].temp == -1) {
    00417     // First, we pick a random spot to search to
    00418     if (_players_ainew[p->index].to_type == AI_CITY) {
    00419       _players_ainew[p->index].temp = AI_RandomRange(GetMaxTownIndex() + 1);
    00420     } else {
    00421       _players_ainew[p->index].temp = AI_RandomRange(GetMaxIndustryIndex() + 1);
    00422     }
    00423   }
    00424
    00425   // The same city is not allowed
    00426   // Also check if the city is valid
    00427   if (_players_ainew[p->index].temp != _players_ainew[p->index].from_ic && AiNew_Check_City_or_Industry(p, _players_ainew[p->index].temp, _players_ainew[p->index].to_type)) {
    00428     // Maybe it is valid..
    00429
    00430     /* We need to know if they are not to far apart from eachother..
    00431      * We do that by checking how much cargo we have to move and how long the
    00432      * route is.
    00433      */
    00434
    00435     if (_players_ainew[p->index].from_type == AI_CITY && _players_ainew[p->index].tbt == AI_BUS) {
    00436       const Town* town_from = GetTown(_players_ainew[p->index].from_ic);
    00437       const Town* town_temp = GetTown(_players_ainew[p->index].temp);
    00438       uint distance = DistanceManhattan(town_from->xy, town_temp->xy);
    00439       int max_cargo;
    00440
    00441       max_cargo  = town_from->max_pass + town_temp->max_pass;
    00442       max_cargo -= town_from->act_pass + town_temp->act_pass;
    00443
    00444       // max_cargo is now the amount of cargo we can move between the two cities
    00445       // If it is more than the distance, we allow it
    00446       if (distance <= max_cargo * AI_LOCATEROUTE_BUS_CARGO_DISTANCE) {
    00447         // We found a good city/industry, save the data of it
    00448         _players_ainew[p->index].to_ic = _players_ainew[p->index].temp;
    00449         _players_ainew[p->index].state = AI_STATE_FIND_STATION;
    00450
    00451         DEBUG(ai, 1, "[LocateRoute] found bus-route of %d tiles long (from %d to %d)",
    00452           distance,
    00453           _players_ainew[p->index].from_ic,
    00454           _players_ainew[p->index].temp
    00455         );
    00456
    00457         _players_ainew[p->index].from_tile = 0;
    00458         _players_ainew[p->index].to_tile = 0;
    00459
    00460         return;
    00461       }
    00462     } else if (_players_ainew[p->index].tbt == AI_TRUCK) {
    00463       const Industry* ind_from = GetIndustry(_players_ainew[p->index].from_ic);
    00464       const Industry* ind_temp = GetIndustry(_players_ainew[p->index].temp);
    00465       bool found = false;
    00466       int max_cargo = 0;
    00467       uint i;
    00468
    00469       // TODO: in max_cargo, also check other cargo (beside [0])
    00470       // First we check if the from_ic produces cargo that this ic accepts
    00471       if (ind_from->produced_cargo[0] != CT_INVALID && ind_from->last_month_production[0] != 0) {
    00472         for (i = 0; i < lengthof(ind_temp->accepts_cargo); i++) {
    00473           if (ind_temp->accepts_cargo[i] == CT_INVALID) break;
    00474           if (ind_from->produced_cargo[0] == ind_temp->accepts_cargo[i]) {
    00475             // Found a compatible industry
    00476             max_cargo = ind_from->last_month_production[0] - ind_from->last_month_transported[0];
    00477             found = true;
    00478             _players_ainew[p->index].from_deliver = true;
    00479             _players_ainew[p->index].to_deliver = false;
    00480             break;
    00481           }
    00482         }
    00483       }
    00484       if (!found && ind_temp->produced_cargo[0] != CT_INVALID && ind_temp->last_month_production[0] != 0) {
    00485         // If not check if the current ic produces cargo that the from_ic accepts
    00486         for (i = 0; i < lengthof(ind_from->accepts_cargo); i++) {
    00487           if (ind_from->accepts_cargo[i] == CT_INVALID) break;
    00488           if (ind_from->produced_cargo[0] == ind_from->accepts_cargo[i]) {
    00489             // Found a compatbiel industry
    00490             found = true;
    00491             max_cargo = ind_temp->last_month_production[0] - ind_temp->last_month_transported[0];
    00492             _players_ainew[p->index].from_deliver = false;
    00493             _players_ainew[p->index].to_deliver = true;
    00494             break;
    00495           }
    00496         }
    00497       }
    00498       if (found) {
    00499         // Yeah, they are compatible!!!
    00500         // Check the length against the amount of goods
    00501         uint distance = DistanceManhattan(ind_from->xy, ind_temp->xy);
    00502
    00503         if (distance > AI_LOCATEROUTE_TRUCK_MIN_DISTANCE &&
    00504             distance <= max_cargo * AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE) {
    00505           _players_ainew[p->index].to_ic = _players_ainew[p->index].temp;
    00506           if (_players_ainew[p->index].from_deliver) {
    00507             _players_ainew[p->index].cargo = ind_from->produced_cargo[0];
    00508           } else {
    00509             _players_ainew[p->index].cargo = ind_temp->produced_cargo[0];
    00510           }
    00511           _players_ainew[p->index].state = AI_STATE_FIND_STATION;
    00512
    00513           DEBUG(ai, 1, "[LocateRoute] found truck-route of %d tiles long (from %d to %d)",
    00514             distance,
    00515             _players_ainew[p->index].from_ic,
    00516             _players_ainew[p->index].temp
    00517           );
    00518
    00519           _players_ainew[p->index].from_tile = 0;
    00520           _players_ainew[p->index].to_tile = 0;
    00521
    00522           return;
    00523         }
    00524       }
    00525     }
    00526   }
    00527
    00528   // It was not a valid city
    00529   //  increase the temp with one, and return. We will come back later here
    00530   //  to try again
    00531   _players_ainew[p->index].temp++;
    00532   if (_players_ainew[p->index].to_type == AI_CITY) {
    00533     if (_players_ainew[p->index].temp > GetMaxTownIndex()) _players_ainew[p->index].temp = 0;
    00534   } else {
    00535     if (_players_ainew[p->index].temp > GetMaxIndustryIndex()) _players_ainew[p->index].temp = 0;
    00536   }
    00537
    00538   // Don't do an attempt if we are trying the same id as the last time...
    00539   if (_players_ainew[p->index].last_id == _players_ainew[p->index].temp) return;
    00540   _players_ainew[p->index].last_id = _players_ainew[p->index].temp;
    00541 }
    00542
    00543
    00544 // Check if there are not more than a certain amount of vehicles pointed to a certain
    00545 //  station. This to prevent 10 busses going to one station, which gives... problems ;)
    00546 static bool AiNew_CheckVehicleStation(Player *p, Station *st)
    00547 {
    00548   int count = 0;
    00549   Vehicle *v;
    00550
    00551   // Also check if we don't have already a lot of busses to this city...
    00552   FOR_ALL_VEHICLES(v) {
    00553     if (v->owner == _current_player) {
    00554       const Order *order;
    00555
    00556       FOR_VEHICLE_ORDERS(v, order) {
    00557         if (order->type == OT_GOTO_STATION && GetStation(order->dest) == st) {
    00558           // This vehicle has this city in its list
    00559           count++;
    00560         }
    00561       }
    00562     }
    00563   }
    00564
    00565   if (count > AI_CHECK_MAX_VEHICLE_PER_STATION) return false;
    00566   return true;
    00567 }
    00568
    00569 // This function finds a good spot for a station
    00570 static void AiNew_State_FindStation(Player *p)
    00571 {
    00572   TileIndex tile;
    00573   Station *st;
    00574   int count = 0;
    00575   EngineID i;
    00576   TileIndex new_tile = 0;
    00577   DiagDirection direction = DIAGDIR_NE;
    00578   Town *town = NULL;
    00579   assert(_players_ainew[p->index].state == AI_STATE_FIND_STATION);
    00580
    00581   if (_players_ainew[p->index].from_tile == 0) {
    00582     // First we scan for a station in the from-city
    00583     if (_players_ainew[p->index].from_type == AI_CITY) {
    00584       town = GetTown(_players_ainew[p->index].from_ic);
    00585       tile = town->xy;
    00586     } else {
    00587       tile = GetIndustry(_players_ainew[p->index].from_ic)->xy;
    00588     }
    00589   } else if (_players_ainew[p->index].to_tile == 0) {
    00590     // Second we scan for a station in the to-city
    00591     if (_players_ainew[p->index].to_type == AI_CITY) {
    00592       town = GetTown(_players_ainew[p->index].to_ic);
    00593       tile = town->xy;
    00594     } else {
    00595       tile = GetIndustry(_players_ainew[p->index].to_ic)->xy;
    00596     }
    00597   } else {
    00598     // Unsupported request
    00599     // Go to FIND_PATH
    00600     _players_ainew[p->index].temp = -1;
    00601     _players_ainew[p->index].state = AI_STATE_FIND_PATH;
    00602     return;
    00603   }
    00604
    00605   // First, we are going to look at the stations that already exist inside the city
    00606   //  If there is enough cargo left in the station, we take that station
    00607   //  If that is not possible, and there are more than 2 stations in the city, abort
    00608   i = AiNew_PickVehicle(p);
    00609   // Euhmz, this should not happen _EVER_
    00610   // Quit finding a route...
    00611   if (i == INVALID_ENGINE) {
    00612     _players_ainew[p->index].state = AI_STATE_NOTHING;
    00613     return;
    00614   }
    00615
    00616   FOR_ALL_STATIONS(st) {
    00617     if (st->owner == _current_player) {
    00618       if (_players_ainew[p->index].tbt == AI_BUS && (FACIL_BUS_STOP & st->facilities) == FACIL_BUS_STOP) {
    00619         if (st->town == town) {
    00620           // Check how much cargo there is left in the station
    00621           if ((int)st->goods[_players_ainew[p->index].cargo].cargo.Count() > RoadVehInfo(i)->capacity * AI_STATION_REUSE_MULTIPLER) {
    00622             if (AiNew_CheckVehicleStation(p, st)) {
    00623               // We did found a station that was good enough!
    00624               new_tile = st->xy;
    00625               direction = GetRoadStopDir(st->xy);
    00626               break;
    00627             }
    00628           }
    00629           count++;
    00630         }
    00631       }
    00632     }
    00633   }
    00634   // We are going to add a new station...
    00635   if (new_tile == 0) count++;
    00636   // No more than 2 stations allowed in a city
    00637   //  This is because only the best 2 stations of one cargo do get any cargo
    00638   if (count > 2) {
    00639     _players_ainew[p->index].state = AI_STATE_NOTHING;
    00640     return;
    00641   }
    00642
    00643   if (new_tile == 0 && _players_ainew[p->index].tbt == AI_BUS) {
    00644     uint x, y, i = 0;
    00645     CommandCost r;
    00646     uint best;
    00647     uint accepts[NUM_CARGO];
    00648     TileIndex found_spot[AI_FINDSTATION_TILE_RANGE*AI_FINDSTATION_TILE_RANGE * 4];
    00649     uint found_best[AI_FINDSTATION_TILE_RANGE*AI_FINDSTATION_TILE_RANGE * 4];
    00650     // To find a good spot we scan a range from the center, a get the point
    00651     //  where we get the most cargo and where it is buildable.
    00652     // TODO: also check for station of myself and make sure we are not
    00653     //   taking eachothers passengers away (bad result when it does not)
    00654     for (x = TileX(tile) - AI_FINDSTATION_TILE_RANGE; x <= TileX(tile) + AI_FINDSTATION_TILE_RANGE; x++) {
    00655       for (y = TileY(tile) - AI_FINDSTATION_TILE_RANGE; y <= TileY(tile) + AI_FINDSTATION_TILE_RANGE; y++) {
    00656         new_tile = TileXY(x, y);
    00657         if (IsTileType(new_tile, MP_CLEAR) || IsTileType(new_tile, MP_TREES)) {
    00658           // This tile we can build on!
    00659           // Check acceptance
    00660           // XXX - Get the catchment area
    00661           GetAcceptanceAroundTiles(accepts, new_tile, 1, 1, 4);
    00662           // >> 3 == 0 means no cargo
    00663           if (accepts[_players_ainew[p->index].cargo] >> 3 == 0) continue;
    00664           // See if we can build the station
    00665           r = AiNew_Build_Station(p, _players_ainew[p->index].tbt, new_tile, 0, 0, 0, DC_QUERY_COST);
    00666           if (CmdFailed(r)) continue;
    00667           // We can build it, so add it to found_spot
    00668           found_spot[i] = new_tile;
    00669           found_best[i++] = accepts[_players_ainew[p->index].cargo];
    00670         }
    00671       }
    00672     }
    00673
    00674     // If i is still zero, we did not find anything
    00675     if (i == 0) {
    00676       _players_ainew[p->index].state = AI_STATE_NOTHING;
    00677       return;
    00678     }
    00679
    00680     // Go through all the found_best and check which has the highest value
    00681     best = 0;
    00682     new_tile = 0;
    00683
    00684     for (x = 0; x < i; x++) {
    00685       if (found_best[x] > best ||
    00686           (found_best[x] == best && DistanceManhattan(tile, new_tile) > DistanceManhattan(tile, found_spot[x]))) {
    00687         new_tile = found_spot[x];
    00688         best = found_best[x];
    00689       }
    00690     }
    00691
    00692     // See how much it is going to cost us...
    00693     r = AiNew_Build_Station(p, _players_ainew[p->index].tbt, new_tile, 0, 0, 0, DC_QUERY_COST);
    00694     _players_ainew[p->index].new_cost += r.GetCost();
    00695
    00696     direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION;
    00697   } else if (new_tile == 0 && _players_ainew[p->index].tbt == AI_TRUCK) {
    00698     // Truck station locater works differently.. a station can be on any place
    00699     //  as long as it is in range. So we give back code AI_STATION_RANGE
    00700     //  so the pathfinder routine can work it out!
    00701     new_tile = AI_STATION_RANGE;
    00702     direction = (DiagDirection)AI_PATHFINDER_NO_DIRECTION;
    00703   }
    00704
    00705   if (_players_ainew[p->index].from_tile == 0) {
    00706     _players_ainew[p->index].from_tile = new_tile;
    00707     _players_ainew[p->index].from_direction = direction;
    00708     // Now we found thisone, go in for to_tile
    00709     return;
    00710   } else if (_players_ainew[p->index].to_tile == 0) {
    00711     _players_ainew[p->index].to_tile = new_tile;
    00712     _players_ainew[p->index].to_direction = direction;
    00713     // K, done placing stations!
    00714     _players_ainew[p->index].temp = -1;
    00715     _players_ainew[p->index].state = AI_STATE_FIND_PATH;
    00716     return;
    00717   }
    00718 }
    00719
    00720
    00721 // We try to find a path between 2 points
    00722 static void AiNew_State_FindPath(Player *p)
    00723 {
    00724   int r;
    00725   assert(_players_ainew[p->index].state == AI_STATE_FIND_PATH);
    00726
    00727   // First time, init some data
    00728   if (_players_ainew[p->index].temp == -1) {
    00729     // Init path_info
    00730     if (_players_ainew[p->index].from_tile == AI_STATION_RANGE) {
    00731       const Industry* i = GetIndustry(_players_ainew[p->index].from_ic);
    00732
    00733       // For truck routes we take a range around the industry
    00734       _players_ainew[p->index].path_info.start_tile_tl = i->xy - TileDiffXY(1, 1);
    00735       _players_ainew[p->index].path_info.start_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1);
    00736       _players_ainew[p->index].path_info.start_direction = _players_ainew[p->index].from_direction;
    00737     } else {
    00738       _players_ainew[p->index].path_info.start_tile_tl = _players_ainew[p->index].from_tile;
    00739       _players_ainew[p->index].path_info.start_tile_br = _players_ainew[p->index].from_tile;
    00740       _players_ainew[p->index].path_info.start_direction = _players_ainew[p->index].from_direction;
    00741     }
    00742
    00743     if (_players_ainew[p->index].to_tile == AI_STATION_RANGE) {
    00744       const Industry* i = GetIndustry(_players_ainew[p->index].to_ic);
    00745
    00746       _players_ainew[p->index].path_info.end_tile_tl = i->xy - TileDiffXY(1, 1);
    00747       _players_ainew[p->index].path_info.end_tile_br = i->xy + TileDiffXY(i->width + 1, i->height + 1);
    00748       _players_ainew[p->index].path_info.end_direction = _players_ainew[p->index].to_direction;
    00749     } else {
    00750       _players_ainew[p->index].path_info.end_tile_tl = _players_ainew[p->index].to_tile;
    00751       _players_ainew[p->index].path_info.end_tile_br = _players_ainew[p->index].to_tile;
    00752       _players_ainew[p->index].path_info.end_direction = _players_ainew[p->index].to_direction;
    00753     }
    00754
    00755     _players_ainew[p->index].path_info.rail_or_road = (_players_ainew[p->index].tbt == AI_TRAIN);
    00756
    00757     // First, clean the pathfinder with our new begin and endpoints
    00758     clean_AyStar_AiPathFinder(_players_ainew[p->index].pathfinder, &_players_ainew[p->index].path_info);
    00759
    00760     _players_ainew[p->index].temp = 0;
    00761   }
    00762
    00763   // Start the pathfinder
    00764   r = _players_ainew[p->index].pathfinder->main(_players_ainew[p->index].pathfinder);
    00765   switch (r) {
    00766     case AYSTAR_NO_PATH:
    00767       DEBUG(ai, 1, "No route found by pathfinder");
    00768       // Start all over again
    00769       _players_ainew[p->index].state = AI_STATE_NOTHING;
    00770       break;
    00771
    00772     case AYSTAR_FOUND_END_NODE: // We found the end-point
    00773       _players_ainew[p->index].temp = -1;
    00774       _players_ainew[p->index].state = AI_STATE_FIND_DEPOT;
    00775       break;
    00776
    00777     // In any other case, we are still busy finding the route
    00778     default: break;
    00779   }
    00780 }
    00781
    00782
    00783 // This function tries to locate a good place for a depot!
    00784 static void AiNew_State_FindDepot(Player *p)
    00785 {
    00786   // To place the depot, we walk through the route, and if we find a lovely spot (MP_CLEAR, MP_TREES), we place it there..
    00787   // Simple, easy, works!
    00788   // To make the depot stand in the middle of the route, we start from the center..
    00789   // But first we walk through the route see if we can find a depot that is ours
    00790   //  this keeps things nice ;)
    00791   int g, i;
    00792   CommandCost r;
    00793   DiagDirection j;
    00794   TileIndex tile;
    00795   assert(_players_ainew[p->index].state == AI_STATE_FIND_DEPOT);
    00796
    00797   _players_ainew[p->index].depot_tile = 0;
    00798
    00799   for (i=2;i<_players_ainew[p->index].path_info.route_length-2;i++) {
    00800     tile = _players_ainew[p->index].path_info.route[i];
    00801     for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) {
    00802       TileIndex t = tile + TileOffsByDiagDir(j);
    00803
    00804       if (IsRoadDepotTile(t) &&
    00805           IsTileOwner(t, _current_player) &&
    00806           GetRoadDepotDirection(t) == ReverseDiagDir(j)) {
    00807         _players_ainew[p->index].depot_tile = t;
    00808         _players_ainew[p->index].depot_direction = ReverseDiagDir(j);
    00809         _players_ainew[p->index].state = AI_STATE_VERIFY_ROUTE;
    00810         return;
    00811       }
    00812     }
    00813   }
    00814
    00815   // This routine let depot finding start in the middle, and work his way to the stations
    00816   // It makes depot placing nicer :)
    00817   i = _players_ainew[p->index].path_info.route_length / 2;
    00818   g = 1;
    00819   while (i > 1 && i < _players_ainew[p->index].path_info.route_length - 2) {
    00820     i += g;
    00821     g *= -1;
    00822     (g < 0?g--:g++);
    00823
    00824     if (_players_ainew[p->index].path_info.route_extra[i] != 0 || _players_ainew[p->index].path_info.route_extra[i+1] != 0) {
    00825       // Bridge or tunnel.. we can't place a depot there
    00826       continue;
    00827     }
    00828
    00829     tile = _players_ainew[p->index].path_info.route[i];
    00830
    00831     for (j = DIAGDIR_BEGIN; j < DIAGDIR_END; j++) {
    00832       TileIndex t = tile + TileOffsByDiagDir(j);
    00833
    00834       // It may not be placed on the road/rail itself
    00835       // And because it is not build yet, we can't see it on the tile..
    00836       // So check the surrounding tiles :)
    00837       if (t == _players_ainew[p->index].path_info.route[i - 1] ||
    00838           t == _players_ainew[p->index].path_info.route[i + 1]) {
    00839         continue;
    00840       }
    00841       // Not around a bridge?
    00842       if (_players_ainew[p->index].path_info.route_extra[i] != 0) continue;
    00843       if (IsTileType(tile, MP_TUNNELBRIDGE)) continue;
    00844       // Is the terrain clear?
    00845       if (IsTileType(t, MP_CLEAR) || IsTileType(t, MP_TREES)) {
    00846         // If the current tile is on a slope then we do not allow this
    00847         if (GetTileSlope(tile, NULL) != SLOPE_FLAT) continue;
    00848         // Check if everything went okay..
    00849         r = AiNew_Build_Depot(p, t, ReverseDiagDir(j), 0);
    00850         if (CmdFailed(r)) continue;
    00851         // Found a spot!
    00852         _players_ainew[p->index].new_cost += r.GetCost();
    00853         _players_ainew[p->index].depot_tile = t;
    00854         _players_ainew[p->index].depot_direction = ReverseDiagDir(j); // Reverse direction
    00855         _players_ainew[p->index].state = AI_STATE_VERIFY_ROUTE;
    00856         return;
    00857       }
    00858     }
    00859   }
    00860
    00861   // Failed to find a depot?
    00862   _players_ainew[p->index].state = AI_STATE_NOTHING;
    00863 }
    00864
    00865
    00866 // This function calculates how many vehicles there are needed on this
    00867 //  traject.
    00868 // It works pretty simple: get the length, see how much we move around
    00869 //  and hussle that, and you know how many vehicles there are needed.
    00870 // It returns the cost for the vehicles
    00871 static int AiNew_HowManyVehicles(Player *p)
    00872 {
    00873   if (_players_ainew[p->index].tbt == AI_BUS) {
    00874     // For bus-routes we look at the time before we are back in the station
    00875     EngineID i;
    00876     int length, tiles_a_day;
    00877     int amount;
    00878     i = AiNew_PickVehicle(p);
    00879     if (i == INVALID_ENGINE) return 0;
    00880     // Passenger run.. how long is the route?
    00881     length = _players_ainew[p->index].path_info.route_length;
    00882     // Calculating tiles a day a vehicle moves is not easy.. this is how it must be done!
    00883     tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
    00884     if (tiles_a_day == 0) tiles_a_day = 1;
    00885     // We want a vehicle in a station once a month at least, so, calculate it!
    00886     // (the * 2 is because we have 2 stations ;))
    00887     amount = length * 2 * 2 / tiles_a_day / 30;
    00888     if (amount == 0) amount = 1;
    00889     return amount;
    00890   } else if (_players_ainew[p->index].tbt == AI_TRUCK) {
    00891     // For truck-routes we look at the cargo
    00892     EngineID i;
    00893     int length, amount, tiles_a_day;
    00894     int max_cargo;
    00895     i = AiNew_PickVehicle(p);
    00896     if (i == INVALID_ENGINE) return 0;
    00897     // Passenger run.. how long is the route?
    00898     length = _players_ainew[p->index].path_info.route_length;
    00899     // Calculating tiles a day a vehicle moves is not easy.. this is how it must be done!
    00900     tiles_a_day = RoadVehInfo(i)->max_speed * DAY_TICKS / 256 / 16;
    00901     if (tiles_a_day == 0) tiles_a_day = 1;
    00902     if (_players_ainew[p->index].from_deliver) {
    00903       max_cargo = GetIndustry(_players_ainew[p->index].from_ic)->last_month_production[0];
    00904     } else {
    00905       max_cargo = GetIndustry(_players_ainew[p->index].to_ic)->last_month_production[0];
    00906     }
    00907
    00908     // This is because moving 60% is more than we can dream of!
    00909     max_cargo *= 6;
    00910     max_cargo /= 10;
    00911     // We want all the cargo to be gone in a month.. so, we know the cargo it delivers
    00912     //  we know what the vehicle takes with him, and we know the time it takes him
    00913     //  to get back here.. now let's do some math!
    00914     amount = 2 * length * max_cargo / tiles_a_day / 30 / RoadVehInfo(i)->capacity;
    00915     amount += 1;
    00916     return amount;
    00917   } else {
    00918     // Currently not supported
    00919     return 0;
    00920   }
    00921 }
    00922
    00923
    00924 // This function checks:
    00925 //   - If the route went okay
    00926 //   - Calculates the amount of money needed to build the route
    00927 //   - Calculates how much vehicles needed for the route
    00928 static void AiNew_State_VerifyRoute(Player *p)
    00929 {
    00930   int res, i;
    00931   assert(_players_ainew[p->index].state == AI_STATE_VERIFY_ROUTE);
    00932
    00933   // Let's calculate the cost of the path..
    00934   //  new_cost already contains the cost of the stations
    00935   _players_ainew[p->index].path_info.position = -1;
    00936
    00937   do {
    00938     _players_ainew[p->index].path_info.position++;
    00939     _players_ainew[p->index].new_cost += AiNew_Build_RoutePart(p, &_players_ainew[p->index].path_info, DC_QUERY_COST).GetCost();
    00940   } while (_players_ainew[p->index].path_info.position != -2);
    00941
    00942   // Now we know the price of build station + path. Now check how many vehicles
    00943   //  we need and what the price for that will be
    00944   res = AiNew_HowManyVehicles(p);
    00945   // If res == 0, no vehicle was found, or an other problem did occour
    00946   if (res == 0) {
    00947     _players_ainew[p->index].state = AI_STATE_NOTHING;
    00948     return;
    00949   }
    00950   _players_ainew[p->index].amount_veh = res;
    00951   _players_ainew[p->index].cur_veh = 0;
    00952
    00953   // Check how much it it going to cost us..
    00954   for (i=0;i<res;i++) {
    00955     _players_ainew[p->index].new_cost += AiNew_Build_Vehicle(p, 0, DC_QUERY_COST).GetCost();
    00956   }
    00957
    00958   // Now we know how much the route is going to cost us
    00959   //  Check if we have enough money for it!
    00960   if (_players_ainew[p->index].new_cost > p->player_money - AI_MINIMUM_MONEY) {
    00961     // Too bad..
    00962     DEBUG(ai, 1, "Insufficient funds to build route (%" OTTD_PRINTF64 "d)", (int64)_players_ainew[p->index].new_cost);
    00963     _players_ainew[p->index].state = AI_STATE_NOTHING;
    00964     return;
    00965   }
    00966
    00967   // Now we can build the route, check the direction of the stations!
    00968   if (_players_ainew[p->index].from_direction == AI_PATHFINDER_NO_DIRECTION) {
    00969     _players_ainew[p->index].from_direction = AiNew_GetDirection(_players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 1], _players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 2]);
    00970   }
    00971   if (_players_ainew[p->index].to_direction == AI_PATHFINDER_NO_DIRECTION) {
    00972     _players_ainew[p->index].to_direction = AiNew_GetDirection(_players_ainew[p->index].path_info.route[0], _players_ainew[p->index].path_info.route[1]);
    00973   }
    00974   if (_players_ainew[p->index].from_tile == AI_STATION_RANGE)
    00975     _players_ainew[p->index].from_tile = _players_ainew[p->index].path_info.route[_players_ainew[p->index].path_info.route_length - 1];
    00976   if (_players_ainew[p->index].to_tile == AI_STATION_RANGE)
    00977     _players_ainew[p->index].to_tile = _players_ainew[p->index].path_info.route[0];
    00978
    00979   _players_ainew[p->index].state = AI_STATE_BUILD_STATION;
    00980   _players_ainew[p->index].temp = 0;
    00981
    00982   DEBUG(ai, 1, "The route is set and buildable, building 0x%X to 0x%X...", _players_ainew[p->index].from_tile, _players_ainew[p->index].to_tile);
    00983 }
    00984
    00985
    00986 // Build the stations
    00987 static void AiNew_State_BuildStation(Player *p)
    00988 {
    00989   CommandCost res;
    00990   assert(_players_ainew[p->index].state == AI_STATE_BUILD_STATION);
    00991   if (_players_ainew[p->index].temp == 0) {
    00992     if (!IsTileType(_players_ainew[p->index].from_tile, MP_STATION))
    00993       res = AiNew_Build_Station(p, _players_ainew[p->index].tbt, _players_ainew[p->index].from_tile, 0, 0, _players_ainew[p->index].from_direction, DC_EXEC);
    00994   } else {
    00995     if (!IsTileType(_players_ainew[p->index].to_tile, MP_STATION))
    00996       res = AiNew_Build_Station(p, _players_ainew[p->index].tbt, _players_ainew[p->index].to_tile, 0, 0, _players_ainew[p->index].to_direction, DC_EXEC);
    00997     _players_ainew[p->index].state = AI_STATE_BUILD_PATH;
    00998   }
    00999   if (CmdFailed(res)) {
    01000     DEBUG(ai, 0, "[BuildStation] station could not be built (0x%X)", _players_ainew[p->index].to_tile);
    01001     _players_ainew[p->index].state = AI_STATE_NOTHING;
    01002     // If the first station _was_ build, destroy it
    01003     if (_players_ainew[p->index].temp != 0)
    01004       AI_DoCommand(_players_ainew[p->index].from_tile, 0, 0, DC_EXEC, CMD_LANDSCAPE_CLEAR);
    01005     return;
    01006   }
    01007   _players_ainew[p->index].temp++;
    01008 }
    01009
    01010
    01011 // Build the path
    01012 static void AiNew_State_BuildPath(Player *p)
    01013 {
    01014   assert(_players_ainew[p->index].state == AI_STATE_BUILD_PATH);
    01015   // _players_ainew[p->index].temp is set to -1 when this function is called for the first time
    01016   if (_players_ainew[p->index].temp == -1) {
    01017     DEBUG(ai, 1, "Starting to build new path");
    01018     // Init the counter
    01019     _players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
    01020     // Set the position to the startingplace (-1 because in a minute we do ++)
    01021     _players_ainew[p->index].path_info.position = -1;
    01022     // And don't do this again
    01023     _players_ainew[p->index].temp = 0;
    01024   }
    01025   // Building goes very fast on normal rate, so we are going to slow it down..
    01026   //  By let the counter count from AI_BUILDPATH_PAUSE to 0, we have a nice way :)
    01027   if (--_players_ainew[p->index].counter != 0) return;
    01028   _players_ainew[p->index].counter = (4 - _opt.diff.competitor_speed) * AI_BUILDPATH_PAUSE + 1;
    01029
    01030   // Increase the building position
    01031   _players_ainew[p->index].path_info.position++;
    01032   // Build route
    01033   AiNew_Build_RoutePart(p, &_players_ainew[p->index].path_info, DC_EXEC);
    01034   if (_players_ainew[p->index].path_info.position == -2) {
    01035     // This means we are done building!
    01036
    01037     if (_players_ainew[p->index].tbt == AI_TRUCK && !_patches.roadveh_queue) {
    01038       // If they not queue, they have to go up and down to try again at a station...
    01039       // We don't want that, so try building some road left or right of the station
    01040       DiagDirection dir1, dir2, dir3;
    01041       TileIndex tile;
    01042       CommandCost ret;
    01043       for (int i = 0; i < 2; i++) {
    01044         if (i == 0) {
    01045           tile = _players_ainew[p->index].from_tile + TileOffsByDiagDir(_players_ainew[p->index].from_direction);
    01046           dir1 = ChangeDiagDir(_players_ainew[p->index].from_direction, DIAGDIRDIFF_90LEFT);
    01047           dir2 = ChangeDiagDir(_players_ainew[p->index].from_direction, DIAGDIRDIFF_90RIGHT);
    01048           dir3 = _players_ainew[p->index].from_direction;
    01049         } else {
    01050           tile = _players_ainew[p->index].to_tile + TileOffsByDiagDir(_players_ainew[p->index].to_direction);
    01051           dir1 = ChangeDiagDir(_players_ainew[p->index].to_direction, DIAGDIRDIFF_90LEFT);
    01052           dir2 = ChangeDiagDir(_players_ainew[p->index].to_direction, DIAGDIRDIFF_90RIGHT);
    01053           dir3 = _players_ainew[p->index].to_direction;
    01054         }
    01055
    01056         ret = AI_DoCommand(tile, DiagDirToRoadBits(ReverseDiagDir(dir1)), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
    01057         if (CmdSucceeded(ret)) {
    01058           TileIndex offset = TileOffsByDiagDir(dir1);
    01059           if (IsTileType(tile + offset, MP_CLEAR) || IsTileType(tile + offset, MP_TREES)) {
    01060             ret = AI_DoCommand(tile + offset, AiNew_GetRoadDirection(tile, tile + offset, tile + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
    01061             if (CmdSucceeded(ret)) {
    01062               if (IsTileType(tile + offset + offset, MP_CLEAR) || IsTileType(tile + offset + offset, MP_TREES))
    01063                 AI_DoCommand(tile + offset + offset, AiNew_GetRoadDirection(tile + offset, tile + offset + offset, tile + offset + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
    01064             }
    01065           }
    01066         }
    01067
    01068         ret = AI_DoCommand(tile, DiagDirToRoadBits(ReverseDiagDir(dir2)), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
    01069         if (CmdSucceeded(ret)) {
    01070           TileIndex offset = TileOffsByDiagDir(dir2);
    01071           if (IsTileType(tile + offset, MP_CLEAR) || IsTileType(tile + offset, MP_TREES)) {
    01072             ret = AI_DoCommand(tile + offset, AiNew_GetRoadDirection(tile, tile + offset, tile + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
    01073             if (CmdSucceeded(ret)) {
    01074               if (IsTileType(tile + offset + offset, MP_CLEAR) || IsTileType(tile + offset + offset, MP_TREES))
    01075                 AI_DoCommand(tile + offset + offset, AiNew_GetRoadDirection(tile + offset, tile + offset + offset, tile + offset + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
    01076             }
    01077           }
    01078         }
    01079
    01080         ret = AI_DoCommand(tile, DiagDirToRoadBits(dir3), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
    01081         if (CmdSucceeded(ret)) {
    01082           TileIndex offset = TileOffsByDiagDir(dir3);
    01083           if (IsTileType(tile + offset, MP_CLEAR) || IsTileType(tile + offset, MP_TREES)) {
    01084             ret = AI_DoCommand(tile + offset, AiNew_GetRoadDirection(tile, tile + offset, tile + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
    01085             if (CmdSucceeded(ret)) {
    01086               if (IsTileType(tile + offset + offset, MP_CLEAR) || IsTileType(tile + offset + offset, MP_TREES))
    01087                 AI_DoCommand(tile + offset + offset, AiNew_GetRoadDirection(tile + offset, tile + offset + offset, tile + offset + offset + offset), 0, DC_EXEC | DC_NO_WATER, CMD_BUILD_ROAD);
    01088             }
    01089           }
    01090         }
    01091       }
    01092     }
    01093
    01094     DEBUG(ai, 1, "Finished building path, cost: %" OTTD_PRINTF64 "d", (int64)_players_ainew[p->index].new_cost);
    01095     _players_ainew[p->index].state = AI_STATE_BUILD_DEPOT;
    01096   }
    01097 }
    01098
    01099
    01100 // Builds the depot
    01101 static void AiNew_State_BuildDepot(Player *p)
    01102 {
    01103   CommandCost res;
    01104   assert(_players_ainew[p->index].state == AI_STATE_BUILD_DEPOT);
    01105
    01106   if (IsRoadDepotTile(_players_ainew[p->index].depot_tile)) {
    01107     if (IsTileOwner(_players_ainew[p->index].depot_tile, _current_player)) {
    01108       // The depot is already built
    01109       _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
    01110       return;
    01111     } else {
    01112       // There is a depot, but not of our team! :(
    01113       _players_ainew[p->index].state = AI_STATE_NOTHING;
    01114       return;
    01115     }
    01116   }
    01117
    01118   // There is a bus on the tile we want to build road on... idle till he is gone! (BAD PERSON! :p)
    01119   if (!EnsureNoVehicleOnGround(_players_ainew[p->index].depot_tile + TileOffsByDiagDir(_players_ainew[p->index].depot_direction)))
    01120     return;
    01121
    01122   res = AiNew_Build_Depot(p, _players_ainew[p->index].depot_tile, _players_ainew[p->index].depot_direction, DC_EXEC);
    01123   if (CmdFailed(res)) {
    01124     DEBUG(ai, 0, "[BuildDepot] depot could not be built (0x%X)", _players_ainew[p->index].depot_tile);
    01125     _players_ainew[p->index].state = AI_STATE_NOTHING;
    01126     return;
    01127   }
    01128
    01129   _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
    01130   _players_ainew[p->index].idle = 10;
    01131   _players_ainew[p->index].veh_main_id = INVALID_VEHICLE;
    01132 }
    01133
    01134
    01135 // Build vehicles
    01136 static void AiNew_State_BuildVehicle(Player *p)
    01137 {
    01138   CommandCost res;
    01139   assert(_players_ainew[p->index].state == AI_STATE_BUILD_VEHICLE);
    01140
    01141   // Check if we need to build a vehicle
    01142   if (_players_ainew[p->index].amount_veh == 0) {
    01143     // Nope, we are done!
    01144     // This means: we are all done! The route is open.. go back to NOTHING
    01145     //  He will idle some time and it will all start over again.. :)
    01146     _players_ainew[p->index].state = AI_STATE_ACTION_DONE;
    01147     return;
    01148   }
    01149   if (--_players_ainew[p->index].idle != 0) return;
    01150   // It is realistic that the AI can only build 1 vehicle a day..
    01151   // This makes sure of that!
    01152   _players_ainew[p->index].idle = AI_BUILD_VEHICLE_TIME_BETWEEN;
    01153
    01154   // Build the vehicle
    01155   res = AiNew_Build_Vehicle(p, _players_ainew[p->index].depot_tile, DC_EXEC);
    01156   if (CmdFailed(res)) {
    01157     // This happens when the AI can't build any more vehicles!
    01158     _players_ainew[p->index].state = AI_STATE_NOTHING;
    01159     return;
    01160   }
    01161   // Increase the current counter
    01162   _players_ainew[p->index].cur_veh++;
    01163   // Decrease the total counter
    01164   _players_ainew[p->index].amount_veh--;
    01165   // Go give some orders!
    01166   _players_ainew[p->index].state = AI_STATE_WAIT_FOR_BUILD;
    01167 }
    01168
    01169
    01170 // Put the stations in the order list
    01171 static void AiNew_State_GiveOrders(Player *p)
    01172 {
    01173   int idx;
    01174   Order order;
    01175
    01176   assert(_players_ainew[p->index].state == AI_STATE_GIVE_ORDERS);
    01177
    01178   if (_players_ainew[p->index].veh_main_id != INVALID_VEHICLE) {
    01179     AI_DoCommand(0, _players_ainew[p->index].veh_id + (_players_ainew[p->index].veh_main_id << 16), CO_SHARE, DC_EXEC, CMD_CLONE_ORDER);
    01180
    01181     _players_ainew[p->index].state = AI_STATE_START_VEHICLE;
    01182     return;
    01183   } else {
    01184     _players_ainew[p->index].veh_main_id = _players_ainew[p->index].veh_id;
    01185   }
    01186
    01187   // Very handy for AI, goto depot.. but yeah, it needs to be activated ;)
    01188   if (_patches.gotodepot) {
    01189     idx = 0;
    01190     order.type = OT_GOTO_DEPOT;
    01191     order.flags = OFB_UNLOAD;
    01192     order.dest = GetDepotByTile(_players_ainew[p->index].depot_tile)->index;
    01193     AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
    01194   }
    01195
    01196   idx = 0;
    01197   order.type = OT_GOTO_STATION;
    01198   order.flags = 0;
    01199   order.dest = GetStationIndex(_players_ainew[p->index].to_tile);
    01200   if (_players_ainew[p->index].tbt == AI_TRUCK && _players_ainew[p->index].to_deliver)
    01201     order.flags |= OFB_FULL_LOAD;
    01202   AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
    01203
    01204   idx = 0;
    01205   order.type = OT_GOTO_STATION;
    01206   order.flags = 0;
    01207   order.dest = GetStationIndex(_players_ainew[p->index].from_tile);
    01208   if (_players_ainew[p->index].tbt == AI_TRUCK && _players_ainew[p->index].from_deliver)
    01209     order.flags |= OFB_FULL_LOAD;
    01210   AI_DoCommand(0, _players_ainew[p->index].veh_id + (idx << 16), PackOrder(&order), DC_EXEC, CMD_INSERT_ORDER);
    01211
    01212   // Start the engines!
    01213   _players_ainew[p->index].state = AI_STATE_START_VEHICLE;
    01214 }
    01215
    01216
    01217 // Start the vehicle
    01218 static void AiNew_State_StartVehicle(Player *p)
    01219 {
    01220   assert(_players_ainew[p->index].state == AI_STATE_START_VEHICLE);
    01221
    01222   // Skip the first order if it is a second vehicle
    01223   //  This to make vehicles go different ways..
    01224   if (_players_ainew[p->index].cur_veh & 1)
    01225     AI_DoCommand(0, _players_ainew[p->index].veh_id, 1, DC_EXEC, CMD_SKIP_TO_ORDER);
    01226
    01227   // 3, 2, 1... go! (give START_STOP command ;))
    01228   AI_DoCommand(0, _players_ainew[p->index].veh_id, 0, DC_EXEC, CMD_START_STOP_ROADVEH);
    01229   // Try to build an other vehicle (that function will stop building when needed)
    01230   _players_ainew[p->index].idle  = 10;
    01231   _players_ainew[p->index].state = AI_STATE_BUILD_VEHICLE;
    01232 }
    01233
    01234
    01235 // Repays money
    01236 static void AiNew_State_RepayMoney(Player *p)
    01237 {
    01238   uint i;
    01239
    01240   for (i = 0; i < AI_LOAN_REPAY; i++) {
    01241     AI_DoCommand(0, 0, 0, DC_EXEC, CMD_DECREASE_LOAN);
    01242   }
    01243   _players_ainew[p->index].state = AI_STATE_ACTION_DONE;
    01244 }
    01245
    01246
    01247 static void AiNew_CheckVehicle(Player *p, Vehicle *v)
    01248 {
    01249   // When a vehicle is under the 6 months, we don't check for anything
    01250   if (v->age < 180) return;
    01251
    01252   // When a vehicle is older then 1 year, it should make money...
    01253   if (v->age > 360) {
    01254     // If both years together are not more than AI_MINIMUM_ROUTE_PROFIT,
    01255     //  it is not worth the line I guess...
    01256     if (v->profit_last_year + v->profit_this_year < (Money)256 * AI_MINIMUM_ROUTE_PROFIT ||
    01257         (v->reliability * 100 >> 16) < 40) {
    01258       // There is a possibility that the route is fucked up...
    01259       if (v->cargo.DaysInTransit() > AI_VEHICLE_LOST_DAYS) {
    01260         // The vehicle is lost.. check the route, or else, get the vehicle
    01261         //  back to a depot
    01262         // TODO: make this piece of code
    01263       }
    01264
    01265
    01266       // We are already sending him back
    01267       if (AiNew_GetSpecialVehicleFlag(p, v) & AI_VEHICLEFLAG_SELL) {
    01268         if (v->type == VEH_ROAD && IsTileDepotType(v->tile, TRANSPORT_ROAD) &&
    01269             (v->vehstatus&VS_STOPPED)) {
    01270           // We are at the depot, sell the vehicle
    01271           AI_DoCommand(0, v->index, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
    01272         }
    01273         return;
    01274       }
    01275
    01276       if (!AiNew_SetSpecialVehicleFlag(p, v, AI_VEHICLEFLAG_SELL)) return;
    01277       {
    01278         CommandCost ret;
    01279         if (v->type == VEH_ROAD)
    01280           ret = AI_DoCommand(0, v->index, 0, DC_EXEC, CMD_SEND_ROADVEH_TO_DEPOT);
    01281         // This means we can not find a depot :s
    01282         //        if (CmdFailed(ret))
    01283       }
    01284     }
    01285   }
    01286 }
    01287
    01288
    01289 // Checks all vehicles if they are still valid and make money and stuff
    01290 static void AiNew_State_CheckAllVehicles(Player *p)
    01291 {
    01292   Vehicle *v;
    01293
    01294   FOR_ALL_VEHICLES(v) {
    01295     if (v->owner != p->index) continue;
    01296     // Currently, we only know how to handle road-vehicles
    01297     if (v->type != VEH_ROAD) continue;
    01298
    01299     AiNew_CheckVehicle(p, v);
    01300   }
    01301
    01302   _players_ainew[p->index].state = AI_STATE_ACTION_DONE;
    01303 }
    01304
    01305
    01306 // Using the technique simular to the original AI
    01307 //   Keeps things logical
    01308 // It really should be in the same order as the AI_STATE's are!
    01309 static AiNew_StateFunction* const _ainew_state[] = {
    01310   NULL,
    01311   AiNew_State_FirstTime,
    01312   AiNew_State_Nothing,
    01313   AiNew_State_WakeUp,
    01314   AiNew_State_LocateRoute,
    01315   AiNew_State_FindStation,
    01316   AiNew_State_FindPath,
    01317   AiNew_State_FindDepot,
    01318   AiNew_State_VerifyRoute,
    01319   AiNew_State_BuildStation,
    01320   AiNew_State_BuildPath,
    01321   AiNew_State_BuildDepot,
    01322   AiNew_State_BuildVehicle,
    01323   NULL,
    01324   AiNew_State_GiveOrders,
    01325   AiNew_State_StartVehicle,
    01326   AiNew_State_RepayMoney,
    01327   AiNew_State_CheckAllVehicles,
    01328   AiNew_State_ActionDone,
    01329   NULL,
    01330 };
    01331
    01332 static void AiNew_OnTick(Player *p)
    01333 {
    01334   if (_ainew_state[_players_ainew[p->index].state] != NULL)
    01335     _ainew_state[_players_ainew[p->index].state](p);
    01336 }
    01337
    01338
    01339 void AiNewDoGameLoop(Player *p)
    01340 {
    01341   if (_players_ainew[p->index].state == AI_STATE_STARTUP) {
    01342     // The AI just got alive!
    01343     _players_ainew[p->index].state = AI_STATE_FIRST_TIME;
    01344     _players_ainew[p->index].tick = 0;
    01345
    01346     // Only startup the AI
    01347     return;
    01348   }
    01349
    01350   // We keep a ticker. We use it for competitor_speed
    01351   _players_ainew[p->index].tick++;
    01352
    01353   // If we come here, we can do a tick.. do so!
    01354   AiNew_OnTick(p);
    01355 }