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 }

Generated on Mon Sep 22 20:34:14 2008 for openttd by  doxygen 1.5.6