AroAI-1.1.119/ 0000755 0000617 0000617 00000000000 11542425514 012106 5 ustar abuild abuild AroAI-1.1.119/version.nut 0000644 0000617 0000617 00000000151 11542425514 014320 0 ustar abuild abuild /* version.nut - Wed Mar 23 17:18:04 UTC 2011 */
_major_ver <- 1;
_minor_ver <- 1;
_repos_ver <- 119;
AroAI-1.1.119/changelog.txt 0000644 0000617 0000617 00000006205 11542425514 014601 0 ustar abuild abuild AROAI CHANGELOG
1.1.1 (2010-12-29)
------------------------------------
- Fix: A temporary fix for an invalid engineID (r96)
- Add: GetEventName() so AI can print event names (r95)
- Add: Some debugs (r94)
- Codechange: some variables were global when they didn't have to be (r93)
- Codechange: Put lots of numbers into constants (r92)
- Change: AutoRenewMonths to -6 (r91)
- Codechange: A variable didn't have a very explanatory name (r90)
- Fix: A building of road failure didn't actually stop the building of roads (r89)
- Doc: Standardise comments (r88)
- Codechange: Standardise some debugs (r87)
- Clean-up: Delete unused variable (r86)
- Fix: BuildBusStop() was using wrong sqrt function (built-in instead of in code) (r85)
- Codechange: Merge BuildRoadDepot() and BuildBusStation() functions (r84)
- Codechange: Combine some unneeded event manager variables (r83)
- Change: Warning debugs were actually errors(ish) (r82)
- Codechange: Merge 2 if statements because they had the same output (r81)
- Fix: Out of money debug was appearing more than necessary (r80)
- Fix: Event debug was appearing when it shouldn't have (r79)
- Change: Increased manageOnly sleeping time (r78)
- Codechange: Make coding style more like OpenTTD (r77)
- Codechange: Make the company naming block a switch block (r76)
- Codechange: Streamline the build bus route code a bit (r75)
- Fix: Another possible lock when another AI built where AI was going to build (r74)
1.1.0.1 (2010-08-22)
------------------------------------
- Fix: Debug not changed properly [Brumi] (r73)
1.1.0 (2010-08-21)
------------------------------------
- Codechange: Simplify the sign remover (r72)
- Change: A debug in loan management to something that makes better sense (r71)
- Feature: Build Bus Stations when drive through bus stations cannot (r70)
- Add: noai.openttd.org url (r69)
- Fix: Rewrite build depot code as when out of money the AI could freeze/not build the depot (r68)
- Change: Fiddle around with build route errors (r67)
- Fix: AIAbstractList has been replaced with AIList, so needed to upgrade. AI NOW REQUIRES r20563 OR LATER (r66)
- Feature: Deal with build road depot errors (r65)
- Change: An Error() to a Warning() in Stop(); to make it clearer (r64)
- Codechange: Rename debugs.nut to util.nut and move some functions into it (r63)
- Feature: Reformed debug output (r62)
- Feature: Events Manager (r61)
- Change: Some debugs in manager.nut (r60)
1.0.2 (2010-08-09)
------------------------------------
- Add: Forum url (r59)
- Fix: Variable not declared properly in vehiclemanager.nut (r59)
- Codechange: Rename moneymanager.nut to manager.nut in preparation for something... (r58)
- Fix: Display town name in GetTowns (r57)
- Add: Properly limit AI to management only when vehicle limit reached or unable to build bus route properly (r56)
1.0.1 (2010-08-02)
------------------------------------
- Fix: A debug output was an Info instead of a Warning (r55)
- Fix: When out of money, the AI would not build the route properly [Brumi] (r54)
1.0.0 (2010-07-31)
------------------------------------
First release of AroAI (r53)
- Feature: Bus support
AroAI-1.1.119/manager.nut 0000644 0000617 0000617 00000015420 11542425514 014252 0 ustar abuild abuild /*
* This file is part of AroAI
*
* Copyright (C) 2010 - Charles Pigott (Lord Aro)
*
* AroAI is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AroAI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AroAI; if not, see or
* write to the Free Software Foundation, Inc., 51 Franklin St,
* Fifth Floor, Boston, MA 02110-1301 USA
*/
class Manager
{
LOAN_REDUCE_TO = 0; ///< Amount of money to reduce loan to
MONEY_BEFORE_LOAN_REDUCE = 750000; ///< Amount of money to have before reducing loan
}
function Manager::ManageLoan()
{
/* TODO: Something else...
* ...or maybe not; it's all I ever do with my loan */
if (AICompany.GetLoanAmount() == LOAN_REDUCE_TO) return; //Loan already been reduced to 0
Info("Managing loan");
if (AICompany.GetBankBalance(AICompany.COMPANY_SELF) >= MONEY_BEFORE_LOAN_REDUCE) {
Info("The company now has more than £" + MONEY_BEFORE_LOAN_REDUCE + ". Reducing Loan to minimum");
AICompany.SetLoanAmount(LOAN_REDUCE_TO);
return;
}
AICompany.SetLoanAmount(AICompany.GetMaxLoanAmount()); //Why not?
}
function Manager::ManageEvents()
{
local dealtWithEvent = null;
if (AIEventController.IsEventWaiting()) {
Info("Managing events");
}
while (AIEventController.IsEventWaiting()) {
dealtWithEvent = true;
local event = AIEventController.GetNextEvent();
switch (event.GetEventType()) {
case AIEvent.AI_ET_COMPANY_BANKRUPT:
local companyname = AICompany.GetName(AIEventCompanyBankrupt.Convert(event).GetCompanyID());
/* Can't always get company name because it's already gone */
if (!companyname) AILog.Info(Util.GameDate() + " [Manager] A company has gone bankrupt. FAILED!!");
else AILog.Info(Util.GameDate() + " [Manager] " + companyname + " has gone bankrupt. FAILED!!");
break;
case AIEvent.AI_ET_COMPANY_IN_TROUBLE:
local companyname = AICompany.GetName(AIEventCompanyInTrouble.Convert(event).GetCompanyID());
Info(companyname + " is in trouble and may go bankrupt soon. HA");
break;
case AIEvent.AI_ET_COMPANY_MERGER:
local oldcompanyname = AICompany.GetName(AIEventCompanyMerger.Convert(event).GetOldCompanyID());
local newcompanyname = AICompany.GetName(AIEventCompanyMerger.Convert(event).GetNewCompanyID());
Info(oldcompanyname + " has been bought by " + newcompanyname);
break;
case AIEvent.AI_ET_COMPANY_NEW:
local companyname = AICompany.GetName(AIEventCompanyNew.Convert(event).GetCompanyID());
Info(companyname + " has just started");
break;
case AIEvent.AI_ET_ENGINE_AVAILABLE:
local eng = AIEventEngineAvailable.Convert(event).GetEngineID();
local engname = AIEngine.GetName(eng);
Info("New engine available: " + engname);
break;
case AIEvent.AI_ET_ENGINE_PREVIEW:
AIEventEnginePreview.Convert(event).AcceptPreview();
Info("Accepted a preview of " + AIEventEnginePreview.Convert(event).GetName());
break;
case AIEvent.AI_ET_VEHICLE_CRASHED:
local veh = AIEventVehicleCrashed.Convert(event).GetVehicleID();
local vehname = AIVehicle.GetName(veh);
Warning(vehname + " has crashed");
Warning("Event is unhandled");
break;
case AIEvent.AI_ET_VEHICLE_LOST:
local veh = AIEventVehicleLost.Convert(event).GetVehicleID();
local vehname = AIVehicle.GetName(veh);
Info(vehname + " is lost");
Warning("Event is unhandled");
break;
/* Silent ignore these
* STATION_FIRST_VEHICLE will almost certainly never be handled
* May deal with the others at some point */
case AIEvent.AI_ET_VEHICLE_UNPROFITABLE:
case AIEvent.AI_ET_STATION_FIRST_VEHICLE:
case AIEvent.AI_ET_INDUSTRY_OPEN:
case AIEvent.AI_ET_INDUSTRY_CLOSE:
case AIEvent.AI_ET_SUBSIDY_OFFER:
case AIEvent.AI_ET_SUBSIDY_OFFER_EXPIRED:
case AIEvent.AI_ET_SUBSIDY_AWARDED:
case AIEvent.AI_ET_SUBSIDY_EXPIRED:
case AIEvent.AI_ET_DISASTER_ZEPPELINER_CRASHED:
case AIEvent.AI_ET_DISASTER_ZEPPELINER_CLEARED:
break;
/* These are unhandled (and will be handled in future) */
case AIEvent.AI_ET_COMPANY_ASK_MERGER: //TODO: Deal with it depending on amount of money
default:
Warning("Event is unhandled");
break;
}
}
if (dealtWithEvent) {
Info("No more events to manage");
}
}
function Manager::GetEventName(event) //OUT OF USE FOR NOW
{//TODO: Switch round the debug: display when event is unhandled
/* No function to get the name of events, so:
* False return cases are silent ignores*/
switch (event) {
case AIEvent.AI_ET_INVALID: return "AI_ET_INVALID";
case AIEvent.AI_ET_TEST: return "AI_ET_TEST";
case AIEvent.AI_ET_SUBSIDY_OFFER: return false;
case AIEvent.AI_ET_SUBSIDY_OFFER_EXPIRED: return false;
case AIEvent.AI_ET_SUBSIDY_AWARDED: return false;
case AIEvent.AI_ET_SUBSIDY_EXPIRED: return false;
case AIEvent.AI_ET_ENGINE_PREVIEW: return "AIEventEnginePreview";
case AIEvent.AI_ET_COMPANY_NEW: return "AIEventCompanyNew";
case AIEvent.AI_ET_COMPANY_IN_TROUBLE: return "AIEventCompanyInTrouble";
case AIEvent.AI_ET_COMPANY_ASK_MERGER: return "AIEventCompanyAskMerger";
case AIEvent.AI_ET_COMPANY_MERGER: return "AIEventCompanyMerger";
case AIEvent.AI_ET_COMPANY_BANKRUPT: return "AIEventCompanyBankrupt";
case AIEvent.AI_ET_VEHICLE_CRASHED: return "AIEventVehicleCrashed";
case AIEvent.AI_ET_VEHICLE_LOST: return "AIEventVehicleLost";
case AIEvent.AI_ET_VEHICLE_WAITING_IN_DEPOT: return "AIEventVehicleWaitingInDepot";
case AIEvent.AI_ET_VEHICLE_UNPROFITABLE: return false;
case AIEvent.AI_ET_INDUSTRY_OPEN: return false;
case AIEvent.AI_ET_INDUSTRY_CLOSE: return false;
case AIEvent.AI_ET_ENGINE_AVAILABLE: return "AIEventEngineAvailable";
case AIEvent.AI_ET_STATION_FIRST_VEHICLE: return false;
case AIEvent.AI_ET_DISASTER_ZEPPELINER_CRASHED: return false;
case AIEvent.AI_ET_DISASTER_ZEPPELINER_CLEARED: return false;
default: return "Unknown event name";
}
}
function Manager::Info(string)
{
AILog.Info(Util.GameDate() + " [Manager] " + string + ".");
}
function Manager::Warning(string)
{
AILog.Warning(Util.GameDate() + " [Manager] " + string + ".");
}
function Manager::Error(string)
{
AILog.Error(Util.GameDate() + " [Manager] " + string + ".");
}
function Manager::Debug(string)
{
AILog.Warning(Util.GameDate() + " [Manager] DEBUG: " + string + ".");
AILog.Warning(Util.GameDate() + " [Manager] (if you see this, please inform the AI Dev in charge, as it was supposed to be removed before release)");
}
AroAI-1.1.119/util.nut 0000644 0000617 0000617 00000003263 11542425514 013617 0 ustar abuild abuild /*
* This file is part of AroAI
*
* Copyright (C) 2010 - Charles Pigott (Lord Aro)
*
* AroAI is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AroAI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AroAI; if not, see or
* write to the Free Software Foundation, Inc., 51 Franklin St,
* Fifth Floor, Boston, MA 02110-1301 USA
*/
class Util
{
DATE_2_DIGITS = 10; ///< Make sure the date always has 2 digits
}
function Util::GameDate()
{
local date = AIDate.GetCurrentDate();
local year = AIDate.GetYear(date);
local month = AIDate.GetMonth(date);
if(month < DATE_2_DIGITS) {
month = "0" + month;
}
local day = AIDate.GetDayOfMonth(date);
if(day < DATE_2_DIGITS) {
day = "0" + day;
}
return day + "/" + month + "/" + year;
}
function Util::Sqrt(i) //From Rondje
{
if (i == 0) return 0; //Avoid divide by zero
local n = (i / 2) + 1; //Initial estimate, never low
local n1 = (n + (i / n)) / 2;
while (n1 < n) {
n = n1;
n1 = (n + (i / n)) / 2;
}
return n;
}
function Util::ClearAllSigns()
{
local sign_list = AISignList();
for(local i = sign_list.Begin(); !sign_list.IsEnd(); i = sign_list.Next()) {
AISign.RemoveSign(i);
}
}
AroAI-1.1.119/readme.txt 0000644 0000617 0000617 00000002603 11542425514 014105 0 ustar abuild abuild V1.1.1
AroAI - Lord Aro's feeble attempt at making an AI. Currently buses only.
NOTE: This AI uses the 1.1 version of the API and due to recent changes in it,
you now need OpenTTD r20563 or later for this AI to work properly
All code is released under GPL v2, as I have nicked a lot of code from others whose license is
also GPL v2!
N.B. I have no problem with releasing it as GPL v2 anyway!
Special thanks go to (in no particular order):
* Those who helped me out:
- Yexo;
- Michiel;
- planetmaker;
- Morloth;
- Dezmond_snz;
- Steffl;
- Dustin (if it were not for him, I might have
given up trying to make an AI altogether!);
- Kogut;
- Yexo (again, because he helped me so much);
* Those who I nicked bits of their AI from:
- Maninthebox - OTVI, Rondje om de Kerk;
- Team Rocket - RocketAI;
* Those who I nicked bits of their AI AND they helped me out:
- Xander - JAMI;
- fanioz - Trans;
- Brumi - SimpleAI;
- Zuu - SuperLib;
* orudge - for his wonderful forums;
* anybody else I've missed (please say if I have);
* and finally, just to be cheesy, all the OpenTTD developers for making this wonderful game!
Comments, bug reports, code optimisations and suggestions are always welcome at:
http://noai.openttdcoop.org/projects/ai-aroai/ (preferred)
OR
http://www.tt-forums.net/viewtopic.php?t=49496/
Hope you enjoy the AI,
Charles Pigott (Lord Aro)
AroAI-1.1.119/COPYING 0000644 0000617 0000617 00000043103 11542425514 013142 0 ustar abuild abuild GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
Copyright (C)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
AroAI-1.1.119/builder_busroute.nut 0000644 0000617 0000617 00000037346 11542425514 016231 0 ustar abuild abuild /*
* This file is part of AroAI
*
* Copyright (C) 2010 - Charles Pigott (Lord Aro)
*
* AroAI is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AroAI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AroAI; if not, see or
* write to the Free Software Foundation, Inc., 51 Franklin St,
* Fifth Floor, Boston, MA 02110-1301 USA
*/
class Builder_BusRoute
{
/* Declare constants */
MAX_TOWN_DISTANCE = 125; ///< Maximum distance from tile_a
PATHFINDER_ITERATIONS = 100; ///< Number of iterations to try before failing
SLEEP_TIME_MONEY = 50; ///< How long to sleep when not enough money
SLEEP_TIME_VEHICLE = 10; ///< How long to sleep when vehicle is in the way
/* Declare variables */
townList = null;
town_a = null;
town_b = null;
numToRemove = 1;
manageOnly = false;
stopMoneyDebug = 0;
}
function Builder_BusRoute::Main()
{
Info("Planning on building bus route");
if ((AIGameSettings.IsDisabledVehicleType(AIVehicle.VT_ROAD)) || (AIController.GetSetting("enable_road_vehs") == 0)) {
Error("ROAD VEHICLES ARE DISABLED. THIS VERSION OF AROAI ONLY USES ROAD VEHICLES");
Error("PLEASE RE-ENABLE THEM, THEN RESTART GAME");
AroAI.Stop();
}
/* TODO: Remove failed bus stops */
if (GetTowns() == null) return;
if (BuildRoad(town_a, town_b) == null) return;
local town = town_a;
local busStation_a = BuildBusStop(town);
if (busStation_a == null) return;
local depot_tile_a = BuildRVStation(town_a, "depot");
if (depot_tile_a == null) return;
town = town_b;
local busStation_b = BuildBusStop(town);
if (busStation_b == null) return;
local depot_tile_b = BuildRVStation(town_b, "depot");
if (depot_tile_b == null) return;
if (VehicleManager.BuildBusEngines(depot_tile_a, busStation_a, busStation_b) == null) return;
/* Never mind if this fails, there are five buses on the route already */
VehicleManager.BuildBusEngines(depot_tile_b, busStation_b, busStation_a);
}
function Builder_BusRoute::GetTowns()
{
/* Reset variables */
town_a = null;
town_b = null;
townList = AITownList();
townList.Valuate(AITown.GetPopulation);
townList.Sort(AIList.SORT_BY_VALUE, false);
townList.RemoveTop(numToRemove);
town_a = townList.Begin();
if (townList.IsEnd()) {
Warning("No towns left to build in. Now managing only");
manageOnly = true;
return null;
}
townList.RemoveTop(1);//Remove town_a
local tile_a = AITown.GetLocation(town_a);
townList.Valuate(AITown.GetDistanceManhattanToTile, tile_a);
townList.KeepBelowValue(MAX_TOWN_DISTANCE); //Keep towns within certain distance
townList.Valuate(AITown.GetRating, AICompany.COMPANY_SELF);
townList.KeepValue(AITown.TOWN_RATING_NONE);//TODO: Improve
if (townList.IsEmpty()) {
Warning("No serviceable towns within radius of " + AITown.GetName(town_a) + ". Moving to next town");
numToRemove++;
return null;
}
townList.Valuate(AITown.GetPopulation);
townList.Sort(AIList.SORT_BY_VALUE, false);
town_b = townList.Begin(); //Pick the top one
return town_a, town_b;
}
function Builder_BusRoute::BuildRoad(town_a, town_b)
{
AIRoad.SetCurrentRoadType(AIRoad.ROADTYPE_ROAD); //Set roadtype
stopMoneyDebug = 10; //Reset variable
Info("Planning route from " + AITown.GetName(town_a) + " to " + AITown.GetName(town_b));
local pathfinder = RoadPathFinder();
pathfinder.cost.turn = 1;
pathfinder.InitializePath([AITown.GetLocation(town_b)], [AITown.GetLocation(town_a)]);
local path = false;
local counter = 0;
while (path == false) {
/* Number of attempts at finding path TODO: check */
path = pathfinder.FindPath(PATHFINDER_ITERATIONS);
counter++;
AIController.Sleep(1);
}
/* No path was found */
if (path == null) {
Error("No route found");
return null;
}
Info("Route found. (Tried " + counter + " times) Building started");
/* If a path found, build a road over it */
while (path != null) {
local par = path.GetParent();
if (par != null) {
local last_node = path.GetTile();
if (AIMap.DistanceManhattan(path.GetTile(), par.GetTile()) == 1) {
if (!AIRoad.BuildRoad(path.GetTile(), par.GetTile())) {
local dwbre = this.DealWithBuildRouteErrors(AIError.GetLastError());
if (dwbre == 2) { //Not enough money
while (!AIRoad.BuildRoad(path.GetTile(), par.GetTile()));
}
if (dwbre == 3) { //Area not clear
local sign = AISign.BuildSign(path.GetTile(), "Clearing tile");
/* Demolish and retry */
AITile.DemolishTile(path.GetTile())
if (!AIRoad.BuildRoad(path.GetTile(), par.GetTile())) return null;
AISign.RemoveSign(sign);
}
if (dwbre == 4) { //Vehicle in the way
/* Keep trying until vehicle moved */
while (!AIRoad.BuildRoad(path.GetTile(), par.GetTile()));
}
if (dwbre == null) { //Unknown + land sloped wrong + one-way junction
AISign.BuildSign(path.GetTile(), AIError.GetLastErrorString());
return null;
}
}
} else {
/* Build a bridge or tunnel. */
if (!AIBridge.IsBridgeTile(path.GetTile()) && !AITunnel.IsTunnelTile(path.GetTile())) {
/* If it was a road tile, demolish it first. Do this to work around expended roadbits. */
if (AIRoad.IsRoadTile(path.GetTile())) AITile.DemolishTile(path.GetTile());
if (AITunnel.GetOtherTunnelEnd(path.GetTile()) == par.GetTile()) {
if (!AITunnel.BuildTunnel(AIVehicle.VT_ROAD, path.GetTile())) {
/* An error occured while building a tunnel. TODO: handle it. */
Error("Build tunnel error: " + AIError.GetLastErrorString());
Error("TODO: Handle it");
return null;
}
} else {
local bridge_list = AIBridgeList_Length(AIMap.DistanceManhattan(path.GetTile(), par.GetTile()) + 1);
bridge_list.Valuate(AIBridge.GetMaxSpeed);
bridge_list.Sort(AIList.SORT_BY_VALUE, false);
if (!AIBridge.BuildBridge(AIVehicle.VT_ROAD, bridge_list.Begin(), path.GetTile(), par.GetTile())) {
/* An error occured while building a bridge. TODO: handle it. */
Error("Build bridge error: " + AIError.GetLastErrorString());
Error("TODO: Handle it");
return null;
}
}
}
}
}
path = par;
}
Info("Road building finished");
Info(AITown.GetName(town_a) + " is now connected to " + AITown.GetName(town_b))
return true;
}
function Builder_BusRoute::BuildBusStop(town)
{
Info("Building bus stop in " + AITown.GetName(town));
/* Find empty square as close to town centre as possible */
local range = 1;
local max_range = Util.Sqrt(AITown.GetPopulation(town)/100) + 2; //TODO check value correctness
local area = AITileList();
while (range < max_range) {
area.AddRectangle(AITown.GetLocation(town) - AIMap.GetTileIndex(range, range), AITown.GetLocation(town) + AIMap.GetTileIndex(range, range));
area.Valuate(AIRoad.IsRoadTile);
area.KeepValue(1);
area.Valuate(AIRoad.IsDriveThroughRoadStationTile);
area.KeepValue(0);
area.Valuate(AITile.GetSlope);
area.KeepValue(AITile.SLOPE_FLAT);
area.Valuate(AIRoad.GetNeighbourRoadCount);
area.KeepValue(2); //Entrance and exit; allow 1 as well?
if (area.Count()) {
for (local station = area.Begin(); !area.IsEnd(); station = area.Next()) {
local opening = getRoadTile(station);
if (opening) {
if (!AIRoad.BuildDriveThroughRoadStation(station, opening, AIRoad.ROADVEHTYPE_BUS, AIStation.STATION_JOIN_ADJACENT)) {
switch (AIError.GetLastError()) {
case AIError.ERR_NOT_ENOUGH_CASH:
Warning("Not enough money to build bus stop. Waiting for more");
while (AICompany.GetBankBalance(AICompany.COMPANY_SELF) < AIRoad.GetBuildCost(AIRoad.ROADTYPE_ROAD, AIRoad.BT_BUS_STOP)) {
if (AIRoad.IsDriveThroughRoadStationTile(station)) continue;
AIController.Sleep(SLEEP_TIME_MONEY);
}
if (!AIRoad.BuildDriveThroughRoadStation(station, opening, AIRoad.ROADVEHTYPE_BUS, AIStation.STATION_JOIN_ADJACENT)) return null; //TODO: handle errors again
break;
case AIRoad.ERR_ROAD_CANNOT_BUILD_ON_TOWN_ROAD:
Info("Building on town roads disabled. Building a bus station instead");
station = BuildRVStation(town, "station");
if (station == null) return null;
else return station;
case AIError.ERR_VEHICLE_IN_THE_WAY: //TODO: handle it
default:
Warning("Unhandled error building bus stop: " + AIError.GetLastErrorString() + " Trying again");
continue;
}
}
Info("Successfully built bus stop");
townList.RemoveValue(town);
return station;
}
}
range++;
} else {
range++;
}
}
Error("Building bus stop in " + AITown.GetName(town) + " failed");
return null;
}
function Builder_BusRoute::BuildRVStation(townid, type)
{
local buildType = null;
Info("Building bus " + type + " in " + AITown.GetName(townid));
if (type == "station") {
buildType = AIRoad.BT_BUS_STOP;
}
else if (type == "depot") {
buildType = AIRoad.BT_DEPOT;
/* Check for depot in town. If yes, use that one */
Info("Checking for pre-built depots in " + AITown.GetName(townid));
local depotList = AIDepotList(AITile.TRANSPORT_ROAD);
depotList.Valuate(AITile.GetClosestTown);
depotList.KeepValue(townid);
if (!depotList.IsEmpty()) {
Info("Depot in " + AITown.GetName(townid) + " found. Using it instead of building one");
local depotTile = depotList.Begin();
return depotTile;
}
Info("No depot in " + AITown.GetName(townid) + " found");
}
/* Find empty square as close to station as possible */
local range = 1;
local area = AITileList();
local townLocation = AITown.GetLocation(townid);
while (range < 15) {
area.AddRectangle(townLocation - AIMap.GetTileIndex(range, range), townLocation + AIMap.GetTileIndex(range, range));
area.Valuate(AITile.IsBuildable);
area.KeepValue(1);
if (area.Count()) {
for (local buildTile = area.Begin(); !area.IsEnd(); buildTile = area.Next()) {
local buildFront = getRoadTile(buildTile);
if (buildFront) {
if (!AIRoad.BuildRoad(buildTile, buildFront)) {
switch (AIError.GetLastError()) {
case AIError.ERR_NOT_ENOUGH_CASH: //Wait for more money
Warning("Not enough money to build road for bus " + type + ". Waiting for more");
while (AICompany.GetBankBalance(AICompany.COMPANY_SELF) < AIRoad.GetBuildCost(AIRoad.ROADTYPE_ROAD, AIRoad.BT_ROAD)) {
if (!AITile.IsBuildable(buildTile)) continue;
AIController.Sleep(SLEEP_TIME_MONEY);
}
if (!AIRoad.BuildRoad(buildTile, buildFront)) return null; //TODO: Handle errors again
break;
case AIError.ERR_VEHICLE_IN_THE_WAY: //Wait for vehicle to get out of the way
while (!AIRoad.BuildRoad(buildTile, buildFront)) {
if (!AITile.IsBuildable(buildTile)) continue;
AIController.Sleep(SLEEP_TIME_VEHICLE);
}
break;
case AIError.ERR_ALREADY_BUILT: //Probably too much road, but build depot anyway TODO: Check I'm right
break;
case AIError.ERR_LAND_SLOPED_WRONG: //TODO: Handle it, give up for now
case AIError.ERR_AREA_NOT_CLEAR: //TODO: Handle it, give up for now
case AIRoad.ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS: //Can't happen? Just give up
case AIRoad.ERR_ROAD_WORKS_IN_PROGRESS: //Just give up
default:
Warning("Unhandled error while building bus " + type + ": " + AIError.GetLastErrorString() + ". Trying again");
continue;
}
}
local buildStructure = null;
if (type == "depot") buildStructure = AIRoad.BuildRoadDepot(buildTile, buildFront);
else if (type == "station") buildStructure = AIRoad.BuildRoadStation(buildTile, buildFront, AIRoad.ROADVEHTYPE_BUS, AIStation.STATION_JOIN_ADJACENT);
else return null; //Something wrong, shouldn't happen
if (!buildStructure) {
switch (AIError.GetLastError()) {
case AIError.ERR_NOT_ENOUGH_CASH:
Warning("Not enough money to build bus " + type + ". Waiting for more");
while (AICompany.GetBankBalance(AICompany.COMPANY_SELF) < AIRoad.GetBuildCost(AIRoad.ROADTYPE_ROAD, buildType)) {
if (!AITile.IsBuildable(buildTile)) continue;
AIController.Sleep(SLEEP_TIME_MONEY);
}
if (type == "depot" && !AIRoad.BuildRoadDepot(buildTile, buildFront)) return null; //TODO: handle errors again
else if (type == "station" && !AIRoad.BuildRoadStation(buildTile, buildFront, AIRoad.ROADVEHTYPE_BUS, AIStation.STATION_JOIN_ADJACENT)) return null; //TODO: handle errors again
break;
case AIError.ERR_FLAT_LAND_REQUIRED:
case AIError.ERR_AREA_NOT_CLEAR: //TODO: Handle them, for now just give up and try somewhere else
default:
Warning("Unhandled error while building bus " + type + ": " + AIError.GetLastErrorString() + ". Trying again");
continue;
}
}
Info("Successfully built bus " + type);
return buildTile;
}
}
/* The tiles found had no road connections; enlarge search area */
range++;
} else {
range++;
area.Clear;
}
}
Error("Building bus " + type + " in " + AITown.GetName(town) + " failed");
return null;
}
function Builder_BusRoute::getRoadTile(tile) //From OTVI
{
local adjacent = AITileList();
adjacent.AddTile(tile - AIMap.GetTileIndex(1,0));
adjacent.AddTile(tile - AIMap.GetTileIndex(0,1));
adjacent.AddTile(tile - AIMap.GetTileIndex(-1,0));
adjacent.AddTile(tile - AIMap.GetTileIndex(0,-1));
adjacent.Valuate(AIRoad.IsRoadTile);
adjacent.KeepValue(1);
adjacent.Valuate(AIRoad.IsRoadStationTile);
adjacent.KeepValue(0);
adjacent.Valuate(AITile.GetSlope);
adjacent.KeepValue(AITile.SLOPE_FLAT);
if (adjacent.Count()) return adjacent.Begin();
else return null;
}
function Builder_BusRoute::DealWithBuildRouteErrors(err)
{
switch (err) {
case AIError.ERR_VEHICLE_IN_THE_WAY:
Warning("Building road failed temporarily - vehicle in the way");
return 4;
case AIError.ERR_ALREADY_BUILT: return 1; //Someone else already built this - silent ignore
case AIError.ERR_AREA_NOT_CLEAR:
Warning("Building road failed: not clear, demolishing tile..");
return 3;
case AIError.ERR_NOT_ENOUGH_CASH:
if (stopMoneyDebug == 10) { //Only display debug every ten times
Warning("Not enough money to build road. Waiting for more");
stopMoneyDebug = 0;
}
stopMoneyDebug++;
return 2;
case AIError.ERR_LAND_SLOPED_WRONG: //TODO: Terraform
case AIRoad.ERR_ROAD_ONE_WAY_ROADS_CANNOT_HAVE_JUNCTIONS:
case AIRoad.ERR_ROAD_WORKS_IN_PROGRESS:
default:
Error("Unhandled error during road building " + AIError.GetLastErrorString());
return null;
}
}
function Builder_BusRoute::Info(string)
{
AILog.Info(Util.GameDate() + " [Bus Route Builder] " + string + ".");
}
function Builder_BusRoute::Warning(string)
{
AILog.Warning(Util.GameDate() + " [Bus Route Builder] " + string + ".");
}
function Builder_BusRoute::Error(string)
{
AILog.Error(Util.GameDate() + " [Bus Route Builder] " + string + ".");
}
function Builder_BusRoute::Debug(string)
{
AILog.Warning(Util.GameDate() + " [Bus Route Builder] DEBUG: " + string + ".");
AILog.Warning(Util.GameDate() + " [Bus Route Builder] (if you see this, please inform the AI Dev in charge, as it was supposed to be removed before release)");
}
AroAI-1.1.119/vehiclemanager.nut 0000644 0000617 0000617 00000013121 11542425514 015606 0 ustar abuild abuild /*
* This file is part of AroAI
*
* Copyright (C) 2010 - Charles Pigott (Lord Aro)
*
* AroAI is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AroAI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AroAI; if not, see or
* write to the Free Software Foundation, Inc., 51 Franklin St,
* Fifth Floor, Boston, MA 02110-1301 USA
*/
class VehicleManager
{
NUM_VEHICLES_PER_ROUTE = 5; ///< Number of vehicles to build per route
engine = -1;
}
function VehicleManager::BuildBusEngines(depot_tile, town_start, town_end)
{
Info("Using a " + AIEngine.GetName(VehicleManager.SelectVehicles()) + " to carry passengers");
local town_start_id = AITile.GetClosestTown(town_start);
Info("Buying buses in " + AITown.GetName(town_start_id));
local vehicle_id = AIVehicle.BuildVehicle(depot_tile, engine);
if(!AIVehicle.IsValidVehicle(vehicle_id)) {
local dwbve = VehicleManager.DealWithBuildVehicleErrors(AIError.GetLastError());
if(dwbve == 3) {
while(AICompany.GetBankBalance(AICompany.COMPANY_SELF) < AIEngine.GetPrice(engine)) {
AIController.Sleep(Builder_BusRoute.SLEEP_TIME_MONEY);
}
vehicle_id = AIVehicle.BuildVehicle(depot_tile, engine);
} else {
Error("Buying vehicles failed");
return null;
}
}
Info("1/" + NUM_VEHICLES_PER_ROUTE + " buses built");
/* Give vehicle its orders */
AIOrder.AppendOrder(vehicle_id, town_start, AIOrder.AIOF_NON_STOP_INTERMEDIATE);
AIOrder.AppendOrder(vehicle_id, town_end, AIOrder.AIOF_NON_STOP_INTERMEDIATE);
AIOrder.AppendOrder(vehicle_id, depot_tile, AIOrder.AIOF_SERVICE_IF_NEEDED);
/* If orders are not complete for some reason, give up */
if(AIOrder.GetOrderCount(vehicle_id) < 3) {
Error("Ordering vehicles failed");
/* TODO: Get rid of failed vehicle */
return null;
}
AIVehicle.StartStopVehicle(vehicle_id); //Start vehicle
local c = 2;
while (c <= NUM_VEHICLES_PER_ROUTE) {
local builtVehicle_id = vehicle_id;
vehicle_id = AIVehicle.CloneVehicle(depot_tile, builtVehicle_id, true);
if(!AIVehicle.IsValidVehicle(vehicle_id)) {
local dwbve = VehicleManager.DealWithBuildVehicleErrors(AIError.GetLastError());
if(dwbve == null) return null;
if(dwbve == 3) {
while(AICompany.GetBankBalance(AICompany.COMPANY_SELF) < AIEngine.GetPrice(engine)) {
AIController.Sleep(Builder_BusRoute.SLEEP_TIME_MONEY);
}
vehicle_id = AIVehicle.CloneVehicle(depot_tile, builtVehicle_id, true);
}
/* if(dwbve == 5) {
Debug("c = " + c); //Keep this for now
Debug("engine = " + engine);
Debug("depot_tile = " + depot_tile);
Debug("vehicle_id = " + vehicle_id);
Debug("old_vehicle_id = " + old_vehicle_id);
}*/
}
AIVehicle.StartStopVehicle(vehicle_id); //Start cloned vehicle
Info(c + "/" + NUM_VEHICLES_PER_ROUTE + " buses built");
c++; //Funny!
}
Info("Buses successfully bought");
/* TODO: Test return value without the return */
return true;
}
function VehicleManager::SelectVehicles()
{ //TODO: Better vehicle selector
/* Get passenger cargo ID */
local list = AICargoList();
local passenger_cargo_id = null;
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
if (AICargo.HasCargoClass(i, AICargo.CC_PASSENGERS) &&
AICargo.GetTownEffect(i) == AICargo.TE_PASSENGERS) {
passenger_cargo_id = i;
break;
}
}
local engine_list = AIEngineList(AIVehicle.VT_ROAD);
/* Don't want trams... */
engine_list.Valuate(AIEngine.GetRoadType);
engine_list.KeepValue(AIRoad.ROADTYPE_ROAD);
/* Only keep buses for now */
engine_list.Valuate(AIEngine.GetCargoType);
engine_list.KeepValue(passenger_cargo_id);
/* Use newest vehicle (It's what I do) */
engine_list.Valuate(AIEngine.GetDesignDate);
engine_list.Sort(AIList.SORT_BY_VALUE, false);
engine = engine_list.Begin();
return engine;
}
function VehicleManager::DealWithBuildVehicleErrors(err)
{
switch(err) {
case AIError.ERR_NOT_ENOUGH_CASH:
Warning("Not enough money to buy buses. Waiting for more");
return 3;
case AIVehicle.ERR_VEHICLE_TOO_MANY:
/* Gets dealt with in Start() */
Error("Too many vehicles");
return null;
case AIVehicle.ERR_VEHICLE_BUILD_DISABLED:
/* Shouldn't happen, but still... */
Error("ROADS VEHICLE TYPE IS DISABLED. THIS VERSION OF AROAI ONLY USES ROAD VEHICLES");
Error("PLEASE RE-ENABLE THEM, THEN RESTART GAME");
AroAI.Stop();
break;
case AIError.ERR_PRECONDITION_FAILED:
Warning("Error: ERR_PRECONDITION_FAILED");
return 5;
case AIVehicle.ERR_VEHICLE_WRONG_DEPOT:
default:
Warning("Unhandled error during vehicle buying: " + AIError.GetLastErrorString());
break;
}
}
function VehicleManager::Info(string)
{
AILog.Info(Util.GameDate() + " [Vehicle Manager] " + string + ".");
}
function VehicleManager::Warning(string)
{
AILog.Warning(Util.GameDate() + " [Vehicle Manager] " + string + ".");
}
function VehicleManager::Error(string)
{
AILog.Error(Util.GameDate() + " [Vehicle Manager] " + string + ".");
}
function VehicleManager::Debug(string)
{
AILog.Warning(Util.GameDate() + " [Vehicle Manager] DEBUG: " + string + ".");
AILog.Warning(Util.GameDate() + " [Vehicle Manager] (if you see this, please inform the AI Dev in charge, as it was supposed to be removed before release)");
}
AroAI-1.1.119/main.nut 0000644 0000617 0000617 00000015326 11542425514 013571 0 ustar abuild abuild /*
* This file is part of AroAI
*
* Copyright (C) 2010 - Charles Pigott (Lord Aro)
*
* AroAI is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AroAI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AroAI; if not, see or
* write to the Free Software Foundation, Inc., 51 Franklin St,
* Fifth Floor, Boston, MA 02110-1301 USA
*/
/*
BEFORE RELEASE CHECK:
run stress test - check for no crashes
update readme & changelog
run makefile
*/
import("pathfinder.road", "RoadPathFinder", 3);
require("vehiclemanager.nut");
require("builder_busroute.nut");
require("manager.nut");
require("util.nut");
require("version.nut");
class AroAI extends AIController
{
/* Declare constants */
AI_VERSION = _major_ver + "." + _minor_ver + "." + _repos_ver;
AUTO_RENEW_MONEY = 0; ///< Amount of money to have before starting autorenew
AUTO_RENEW_MONTHS = -6; ///< Before/after max age of a vehicle to autorenew
MANAGE_ONLY_SLEEP_TIME = 1000; ///< Time sleeping when managing only
/* Declare variables */
loaded = null;
constructor()
{
Builder_BusRoute = Builder_BusRoute();
VehicleManager = VehicleManager();
Manager = Manager();
Util = Util();
/* Initialise variables */
loaded = false;
}
}
function AroAI::Start()
{
this.Sleep(1);
if(!loaded) {
GetVersionsAndStuff();
SetCompany();
}
/* Keep running. If Start() exits, the AI dies */
for(;;) {
this.Sleep(1);
Warning("Main loop started");
Manager.ManageLoan();
Manager.ManageEvents();
if (!Builder_BusRoute.manageOnly) {
local vehList = AIVehicleList();
vehList.Valuate(AIVehicle.GetVehicleType);
vehList.KeepValue(AIVehicle.VT_ROAD);
local maxVehs = vehList.Count();
if (AIGameSettings.GetValue("vehicle.max_roadveh") <= maxVehs) {
Info("Max amount of road vehicles reached");
Builder_BusRoute.manageOnly = true;
} else {
Builder_BusRoute.Main();
}
} else {
Info("Sleeping because there is nothing to build");
this.Sleep(MANAGE_ONLY_SLEEP_TIME);
}
}
}
function AroAI::Stop()
{
Error("Something gone wrong. Clearing all signs");
Util.ClearAllSigns();
Error("Stopped");
Warning("(The error is on purpose)");
local crash = 1/0
}
function AroAI::Save()
{
//TODO: Add save data to the table...maybe
local table = {};
return table;
}
function AroAI::Load(version, data)
{
loaded = true;
Warning("Loaded");
}
function AroAI::SetCompany()
{ //TODO: More names, just to make sure it's always unique
local a = AIBase.RandRange(15);
switch (a) {
case 0:
AICompany.SetName("Arioa International");
break;
case 1:
AICompany.SetName("AroAI");
break;
case 2:
AICompany.SetName("Aro Transport");
break;
case 3:
AICompany.SetName("Aro & Co.");
break;
case 4:
AICompany.SetName("Aro");
break;
case 5:
AICompany.SetName("Aro Distribution");
break;
case 6:
AICompany.SetName("Aro Logistics");
break;
case 7:
AICompany.SetName("Aro Federal Delivery");
break;
case 8:
AICompany.SetName("Aro Ltd.");
break;
case 9:
AICompany.SetName("Aro Delivery");
break;
case 10:
AICompany.SetName("Aro Network");
break;
case 11:
AICompany.SetName("Aro Trans");
break;
case 12:
AICompany.SetName("Aro Services");
break;
case 13:
AICompany.SetName("Aro Management");
break;
case 14:
AICompany.SetName("Aro Constructions");
break;
}
Info(AICompany.GetName(AICompany.COMPANY_SELF) + " inaugurated");
if(AICompany.GetPresidentGender(AICompany.COMPANY_SELF) == 0) {
AICompany.SetPresidentName("Lord Aro");
} else {
AICompany.SetPresidentName("Lady Aro");
}
Info(AICompany.GetPresidentName(AICompany.COMPANY_SELF) + " is the new president");
AICompany.SetAutoRenewMonths(AUTO_RENEW_MONTHS);
AICompany.SetAutoRenewMoney(AUTO_RENEW_MONEY);
AICompany.SetAutoRenewStatus(true);
BuildHQ();
}
function AroAI::GetVersionsAndStuff()
{
Info("AroAI v" + AI_VERSION + " by Charles Pigott (Lord Aro) started");
Info("Special thanks to those who helped with the many problems had when making the AI")
local version = GetVersion();
Info("Currently playing on OpenTTD version " + ((version & (15 << 28)) >> 28) + "." +
((version & (15 << 24)) >> 24) + "." + ((version & (15 << 20)) >> 20) + "" +
(((version & (1 << 19)) >> 19)?" stable release, ":" r") + ((version & ((1 << 18) - 1))));
AILog.Info("=======================================")
}
function AroAI::BuildHQ() //From Rondje
{
if (AIMap.IsValidTile(AICompany.GetCompanyHQ(AICompany.COMPANY_SELF))) return; //From SimpleAI
/* Find SECOND biggest town for HQ, just to be different */
local towns = AITownList();
local HQtown = 0;
towns.Valuate(AITown.GetPopulation);
towns.Sort(AIList.SORT_BY_VALUE, false);
if (towns.Count == 1) {
HQtown = towns.Begin();
} else {
towns.RemoveTop(1);
HQtown = towns.Begin();
}
/* Find empty 2x2 square as close to town centre as possible */
local maxRange = Util.Sqrt(AITown.GetPopulation(HQtown)/100) + 5;
local HQArea = AITileList();
HQArea.AddRectangle(AITown.GetLocation(HQtown) - AIMap.GetTileIndex(maxRange, maxRange), AITown.GetLocation(HQtown) + AIMap.GetTileIndex(maxRange, maxRange));
HQArea.Valuate(AITile.IsBuildableRectangle, 2, 2);
HQArea.KeepValue(1);
HQArea.Valuate(AIMap.DistanceManhattan, AITown.GetLocation(HQtown));
HQArea.Sort(AIList.SORT_BY_VALUE, true);
for (local tile = HQArea.Begin(); !HQArea.IsEnd(); tile = HQArea.Next()) {
if (AICompany.BuildCompanyHQ(tile)) {
AISign.BuildSign(tile, "AroAI HQ");
Info("HQ building completed");
return;
}
}
Warning("No possible HQ location found");
}
function AroAI::Info(string)
{
AILog.Info(Util.GameDate() + " [AroAI] " + string + ".");
}
function AroAI::Warning(string)
{
AILog.Warning(Util.GameDate() + " [AroAI] " + string + ".");
}
function AroAI::Error(string)
{
AILog.Error(Util.GameDate() + " [AroAI] " + string + ".");
}
function AroAI::Debug(string)
{
AILog.Warning(Util.GameDate() + " [AroAI] DEBUG: " + string + ".");
AILog.Warning(Util.GameDate() + " [AroAI] (if you see this, please inform the AI Dev in charge, as it was supposed to be removed before release)");
}
AroAI-1.1.119/info.nut 0000644 0000617 0000617 00000003572 11542425514 013600 0 ustar abuild abuild /*
* This file is part of AroAI
*
* Copyright (C) 2010 - Charles Pigott (Lord Aro)
*
* AroAI is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* AroAI is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AroAI; if not, see or
* write to the Free Software Foundation, Inc., 51 Franklin St,
* Fifth Floor, Boston, MA 02110-1301 USA
*/
require("version.nut");
class AroAI extends AIInfo
{
function GetAuthor() {return "Charles Pigott (Lord Aro)";}
function GetName() {return "AroAI";}
function GetDescription() {return "Lord Aro's really feeble attempt at making an AI. Currently buses only. Version: " + _major_ver + "." + _minor_ver + "." + _repos_ver;}
function GetVersion() {return _repos_ver;}
function GetDate() {return "2010-10-03";}
function CreateInstance() {return "AroAI";}
// function UseAsRandomAI() {return false;}
function GetShortName() {return "A_AI";}
function GetAPIVersion() {return "1.1";}
function GetURL() {return "http://www.tt-forums.net/viewtopic.php?t=49496/ OR http://dev.openttdcoop.org/projects/ai-aroai/";}
function GetSettings()
{
AddSetting({
name = "enable_road_vehs",
description = "Enable road vehicles",
easy_value = 1,
medium_value = 1,
hard_value = 1,
custom_value = 1,
flags = AICONFIG_BOOLEAN
});
}
}
/* Tell the core we are an AI */
RegisterAI(AroAI());