1
0
mirror of https://github.com/OpenTTD/OpenTTD.git synced 2025-08-13 17:49:10 +00:00

Compare commits

..

135 Commits

Author SHA1 Message Date
rubidium
52abb70c44 (svn r9661) -Release 0.5.1-RC3. 2007-04-17 20:19:44 +00:00
rubidium
635eff5e51 (svn r9660) [0.5] -Prepare 0.5 branch for release of 0.5.1-RC3. 2007-04-17 20:11:11 +00:00
truelight
4cd6870777 (svn r9659) [0.5] -Fix r9656: missed 2 hunks in last commit 2007-04-17 19:08:08 +00:00
truelight
54cfb12334 (svn r9657) [0.5] -Backport from trunk (r9585, r9613, r9615, r9633, r9640, r9649):
- Language updates (r9585, r9613, r9615, r9633, r9640, r9649)
2007-04-17 19:05:47 +00:00
rubidium
2d746c52c8 (svn r9656) [0.5] -Backport from trunk (r9602, r9641, r9647):
- Fix: Building rail on steep slopes ignored build_on_slopes patch setting (r9602)
- Fix: namegen.cpp was not UTF-8, which caused artefacts in Finnish town names (r9641)
- Fix: Select "Custom" in the difficulty settings gui when changing a setting [FS#733] (r9647)
2007-04-17 18:09:12 +00:00
truelight
cb001e017a (svn r9589) [0.5] -Fix (r9587, r9588): this time I really do hope turkish.txt went okay... 2007-04-10 13:12:15 +00:00
truelight
9bee2fc641 (svn r9588) [0.5] -Fix r9587: something went wrong in turkish.txt update 2007-04-10 13:04:44 +00:00
truelight
7399e107e1 (svn r9587) [0.5] -Backport from trunk (r9585):
- Language updates (r9585)
2007-04-10 13:02:01 +00:00
truelight
70db6b3f40 (svn r9586) [0.5] -Backport from trunk (r9525, r9527, r9547, r9548, r9570, r9571, r9572, r9576):
- Language updates (r9525, r9527, r9547, r9548, r9570, r9571, r9572, r9576)
2007-04-10 12:58:05 +00:00
truelight
ac6aefa07b (svn r9584) [0.5] -Backport frmo trunk (r9542, r9565, r9573):
- Fix: when checking for no vehicle on ground-tiles, don't take into account vehicles that are in the air (r9542)
- Feature: add list_patches to console commands; shows all patches and values (r9565)
- Fix: enclose settings names containing spaces with quotes (r9573)
2007-04-10 09:57:35 +00:00
truelight
c04f0af19b (svn r9583) [0.5] -Backport from trunk (r9529, r9533, r9540, r9541):
- Fix: when 2 clients joined together, the second asserted on the NewCompany command of the first (r9529)
- Fix: when company is removed, sell all shares he has first, then sell all shares other people might have in this company (r9533)
- Fix: bankrupt AIs no longer buy over themselves (also added safeguards to prevent in future) (r9540 / r9541)
2007-04-10 09:49:41 +00:00
truelight
c8c8667dc8 (svn r9582) [0.5] -Backport from trunk (r9425, r9437, r9455, r9519):
- Fix: housekeeping in convert rail functions (r9425)
- Fix: dedicated server crashed when the y part of the resolution was less than 10 (r9437)
- Fix: values of diff_custom and snow_line in .cfg weren't checked properly (r9455)
- Fix: free the malloc'd variable, not the pointer to that variable (r9519)
2007-04-10 09:40:36 +00:00
belugas
a0688e8d85 (svn r9471) [0.5] -Backport from trunk (r9467 & r9469):
Reset the whole currency array while preserving custom one.  Also, max data of to_euro is now 300, not 1000, disabling any proper loading of the patch setting
2007-03-26 00:20:22 +00:00
truelight
c85022e3db (svn r9430) [0.5] -Backport r9429: when deleting a vehicle which has shared orders with one more vehicle and no orders, segfaulted 2007-03-24 15:16:41 +00:00
rubidium
be39b87154 (svn r9422) [0.5] -Prepare 0.5 branch for release of 0.5.1-RC2. 2007-03-23 22:54:19 +00:00
rubidium
71aa3a4de2 (svn r9421) [0.5] -Backport from trunk (r9392, r9415, r9420, custom):
- Fix: crashes when the chatbox would be drawn outside of the main window [FS#701] (r9420)
- Language updates (r9392, r9414, custom Simplified Chinese)
2007-03-23 22:44:03 +00:00
rubidium
f7fd8eca21 (svn r9394) [0.5] -Fix (r9343): reading out of an array caused a segmentation fault. 2007-03-21 23:06:01 +00:00
bjarni
ab77a35093 (svn r9384) [0.5] -Fix: [MorphOS] updated make release to avoid the need to specify RELEASE when building 2007-03-21 00:00:08 +00:00
rubidium
a808b77b2b (svn r9382) [0.5] -Prepare 0.5 branch for release of 0.5.1-RC1. 2007-03-20 21:12:18 +00:00
rubidium
52a0d04473 (svn r9380) [0.5] -Backport from trunk (r9378):
- Fix: cancel in password queries reduces amount of players in the network game when they haven't joined the game yet (r9378)
2007-03-20 20:36:45 +00:00
glx
64f7b3a059 (svn r9358) [0.5] -Backport from trunk (r9055, r9082, r9083, r9084, r9085, r9086):
- Codechange: Change windows unicode handling and allow a pure non-unicode build to function. (r9055)
- Codechange: [win32] Update VS2003 and VS2005 project files to build in UNICODE mode. When making a release it is probably better to make two binaries, one without UNICODE, the other with, guaranteeing full Win9x compatibility (UNICODE with MSLU also works, without it's even better). (r9082)
- Codechange: Be more lenient when trimming UTF-8 strings and don't terminate the string when an invalid encoding is encountered, but only focus on maximum length. (r9083)
- Fix: [win9x] Clipboard paste for Windows95 (doesn't have CF_UNICODETEXT) correctly converts the input to the current locale. (r9084)
- Fix: [win32] Move the initialisation of _codepage (non-UNICODE) to winMain as a dedicated server, or different video driver will not have a win32 messageloop. (r9085)
- Fix: [win32] Rewrite keyboard input and handle all keypresses in a WM_CHAR event. This saves us from doing translation (ToUnicode[Ex], ToAscii[Ex]), and we get free IME-input support as a plus. (r9086)
2007-03-20 00:02:18 +00:00
rubidium
b70c3613fa (svn r9355) [0.5] -Backport from trunk (r8906):
- Feature: translation dependant formatting of dates (r8906)
2007-03-19 22:08:18 +00:00
glx
3158cdaa7a (svn r9354) [0.5] -Backport from trunk (r8975, r9003, r9011, r9012):
-Regression: [win32] Possible buffer overflow if unicode text is pasted into an input box and needs trimming. (r8975)
-Codechange: Introduce a function Utf8PrevCharLen that finds the starting character of an UTF-8 sequence from a given position and returns the length to the first UTF-8 encoding byte of that sequence. (r9003)
-Codechange: Rework Utf8PrevChar so that it returns a pointer to the previous UTF8 character's first byte instead of a byte-length offset (r9011)
-Fix: When cutting strings into multiple lines also take into consideration whitespace characters of more than 1 byte length (eg IDEOGRAPHIC SPACE, IsWhitespace() function). When trimming such strings, account for multiple-byte long sequences so use *Utf8PrevChar(v) = '\0'. (r9012)
-Codechange: Add a function Utf8TrimString() that properly trims a string to an UTF8 encoding seperation instead of somewhere in the wild (and use it in the chat area) (r9012)
2007-03-19 21:42:05 +00:00
rubidium
140abde4ef (svn r9353) [0.5] -Backport language updates from trunk (r8957, r9002, r9005, r9013, r9014, r9020, r9021, r9054, r9116, r9118, r9132, r9286, r9292) 2007-03-19 21:04:06 +00:00
rubidium
850f73719f (svn r9351) [0.5] -Backport from trunk (r9147, r9205, r9251, r9298):
- Fix: when loadin games, enroute_from was updated in the wrong place, causing issues with TTD savegames/scenarios (r9147)
- Fix: when you started openttd with '-g' you got the same map every run (r9205)
- Fix: use a less CPU-intensive algorithm to find a random industry for the AI to prevent it slowing down the game (r9251)
- Fix: A34-1000, Z-Shuttle, and Kelling K1 are now listed as small aircraft (r9298)
2007-03-19 20:38:26 +00:00
rubidium
d2ce2009b5 (svn r9350) [0.5] -Backport from trunk (r9105, r9115, r9117, r9146):
- Fix: disable the ability to make flooding water with the canal build tool. In the scenario editor you can still make both canals and flooding water at height level 0 (r9105)
- Fix: make clear in the tooltips when the canal build tool (in the scenario editor) makes flooding water (r9115)
- Fix: difficulty level button was not selected when opening the difficulty window (r9117)
- Fix: "Train is lost" message is generated incorrectly (r9146)
2007-03-19 20:23:27 +00:00
rubidium
6ad4716dc1 (svn r9349) [0.5] -Backport from trunk (r9043, r9062, r9064, r9070):
- Fix: the personal (.openttd) directories were hidden in the load/save directory listings (r9043)
- Fix: the station list, sorted by cargo rating, now takes stations into account that have no cargo waiting (r9062)
- Fix: don't keep on scrolling for non-numeric values in settings, but require reclick (r9064)
- Fix: when a bribe failed and you haven't picked up cargo yet, you would never be able to do so for a given station (r9070)
2007-03-19 20:17:24 +00:00
rubidium
0ec558f99f (svn r9348) [0.5] -Backport from trunk (r8974, r8994, r9074):
- Fix: support compilation with the Vista Platform SDK (r8974)
- Fix: resolution doubled in cfg file when fullscreen mode used (r8994)
- Fix: win32 dedicated console now doesn't need an extra 'enter' to fully quit (r9074)
2007-03-19 20:05:49 +00:00
rubidium
41727b6e23 (svn r9347) [0.5] -Backport from trunk (r9019, r9076, r9077):
- Fix: use <> for system-headers (r9019)
- Fix: the intercontinental airport used 'T-junction' runway sprites when there is no exit in the middle of the runway as in the city airport (r9076)
- Fix: the wrong catenary wires were drawn for tunnel entrances (r9077)
2007-03-19 19:56:16 +00:00
rubidium
c559703312 (svn r9345) [0.5] -Backport from trunk (r9277, r9337, r9338):
- Fix: shared orders got messed up when the 'first' trains got removed in the depot (r9277)
- Fix: assert() when you removed the orders of a shared list while having the shared order vehicle list open (r9337)
- Fix: close the Shared Order Vehicle List if you remove the shared link with only 2 vehicles (r9338)
2007-03-19 19:42:40 +00:00
rubidium
1e7cca8f8b (svn r9344) [0.5] -Backport from trunk (r9027, r9038, r9061, r9071):
- Fix: desync caused by buffer overflow (r9027)
- Feature: kick inactive initial network connections after some time (r9038, r9061)
- Fix: take over companies properly in multiplayer games (r9071)
2007-03-19 19:34:44 +00:00
rubidium
759d155b08 (svn r9343) [0.5] -Backport from trunk (r9000, r9001, r9097, r9137):
- Fix: new locomotive names were not announced in the news, it said "new railway locomotive available - railway locomotive" (r9000, r9001)
- Feature: add an extra news group for opening and closing of industries (r9097)
- Fix: when all news-setting buttons are 'full', make the for-all button show 'full' too (r9137)
2007-03-19 19:22:26 +00:00
rubidium
11b1c6f2ee (svn r9342) [0.5] -Backport from trunk (r8980, r9065, r9339):
- Fix: the industry list should also be (re)set when the number of industries is 0 (r8980)
- Fix: possible dereference of NULL pointer (r9065)
- Codechange: disable shares by default and increase the default maximum distance from edge for oil refineries (r9339)
2007-03-19 18:54:48 +00:00
rubidium
98f77876e6 (svn r9341) [0.5] -Backport from trunk (r8943, r8955, r8976, r8999, r9009):
- Fix: NewGRF support for vehicle variable 48 (r8943)
- Fix: crash on loading savegames with GRFs that do not have their GRF info/name set (r8955)
- Fix: reinitialize all engines after grf files have been reloaded/changed (r8976)
- Fix: do not select a disabled platform length/number of track count when going out of drag-drop mode (r8999)
- Fix: play the correct engine sound based on the engine type instead of the sprite (r9009)
2007-03-19 18:47:10 +00:00
rubidium
5a703390ec (svn r9128) [0.5] -Fix: trains slow down under bridges when they were going down on the tile before the bridge tile. 2007-03-11 23:03:14 +00:00
Darkvater
e925f8b2c3 (svn r8930) [0.5] -Backport from trunk (r8929):
- [win32] Installer update (r8929)
2007-02-27 22:13:15 +00:00
Darkvater
01e3d92118 (svn r8923) [0.5] -Prepare (again) 0.5 branch for release, update a few dates and changelog 2007-02-27 16:29:22 +00:00
Darkvater
9321458918 (svn r8922) [0.5] -Backport from trunk (r8907, r8919, r8920, r8921):
- [OSX] Reading from an unitialized variable (r8907)
 - [Win9x] FindFile with C:\\* doesn't work, don't append a slash doubly (r8919)
 - Do not require to press 'Apply changes' in the newgrf GUI if the changes in there are not activated (this happens in the title screen) (r8920)
 - Possible crashes, problems with aircraft and airport removal (r8921)
2007-02-27 16:23:02 +00:00
Darkvater
cd6d6d32d3 (svn r8917) [0.5] -Codechange (win32): Do not empty the data-path for the installer if you press the 'Back' button. 2007-02-27 15:51:52 +00:00
Darkvater
5bfdc6e75a (svn r8916) [0.5] -Codechange (win32): Update the installer, add proper indentation, use MUI throughout and add a custom page about UNICODE and MSLU (remove some obsolete files) 2007-02-27 15:29:11 +00:00
Darkvater
274f841c61 (svn r8915) [0.5] -Codechange: Renamed remotely 2007-02-27 15:19:36 +00:00
matthijs
2b8a0dfacb (svn r8910) [Debian] -Fix: Remove old reference to rc4. 2007-02-26 21:37:14 +00:00
matthijs
4ba3761ab1 (svn r8909) [Debian] -Change: Update debian packaging files to those used for releases.
- Compile with freetype / fontconfig support.
	- Make menu files translatable.
	- Other packaging cleanups.
	- Bump version number to 0.5.0-1.
2007-02-26 21:18:57 +00:00
Darkvater
93586cb6b6 (svn r8905) [0.5] -Update readme's, bugs, installers, changelogs etc. to prepare for 0.5.0.
[0.5] -Remove the limitation that games are refused to be loaded if no newgrf is present (was already like this in trunk/).
2007-02-26 00:19:31 +00:00
Darkvater
c4768438b7 (svn r8895) [0.5] -Backport from trunk (r8645, r8671, r8686, r8690, r8719, r8728, r8729,
r8736, r8742, r8751, r8764, r8788, r8829, r8848, custom):
 - Language file updates.
 - Ukrainian(2), Lithuanian(15), Galician(151)
2007-02-25 10:05:33 +00:00
Darkvater
b3b28dced2 (svn r8883) [0.5] -Backport from trunk (r8740, r8793, r8865, r8878):
- GCC warnings for r8738 (r8740)
 - Correct spelling of real french townnames and 'remove' a duplicate (r8793)
 - (NewGRF) Ignore 1 byte action 0s during safety check (r8865)
 - Stricter checks for CmdMoveRailVehicle() parameters (r8878)
2007-02-24 16:46:36 +00:00
Darkvater
3b2bcbf0f0 (svn r8874) [0.5] -Backport from trunk (r8744, r8685):
- Call GetFirstVehicleInChain only for trains thus increasing performance in large games (r8744)
 - (Feature) Selecting "end of orders" and deleting will delete all the vehicle's orders (in unshared mode, shared is unchanged) (r8685)
2007-02-24 01:47:26 +00:00
Darkvater
1cdfa87b21 (svn r8873) [0.5] -Backport from trunk (r8766, r8836, r8869):
- Rail station platform penalty not calculated properly (r8766)
 - Don't tell destination was found if it was only guessed (r8836)
 - Large Train Stations/Trains causes assert due to wrong cost calculation (r8869)
2007-02-24 01:39:59 +00:00
Darkvater
9e3f020ae8 (svn r8872) [0.5] -Backport from trunk (r8784, r8821, r8823, r8824):
- Unable to load TTDP (on *NIX) games (r8784)
 - Unable to browse directories on *nix if the filesystem is not in UTF-8 charset and special characters are used (r8821, r8823, r8824)
2007-02-24 01:21:31 +00:00
Darkvater
36134a7285 (svn r8871) [0.5] -Backport from trunk (r8689, r8794, r8802, r8808):
- Crash when an old savegame had buoys on the northern edge of the map (r8689)
 - It was possible to take over buoys by building a station next to them (r8794)
 - Adhere order types for ship order insertion to determine destination type (r8802)
 - Do not show the 'edit sign' window for spectators (r8808)
2007-02-24 01:14:54 +00:00
Darkvater
edc2ac8bbf (svn r8870) [0.5] -Backport from trunk (r8684, r8709, r8738, r8777, r8828):
- Bool (uint32 in PPC) was written to as a uint8 (r8684)
 - Fix a problem where loading times for overhanging trains are miscomputed (r8709)
 - Load newer TTDP games (update coastal tiles) (r8738)
 - Cloning unaware of articulated locomotives that could refit without refitting the front unit (r8777)
 - Load station rectangle for all savegames, not only after version 27 (r8828)
2007-02-24 01:02:15 +00:00
Darkvater
c92b6e1e8b (svn r8861) [0.5] -Backport from trunk (r8526, r8792, r8825, r8843):
- Add stubs for unsupported newgrf station properties (r8526)
 - Be more strict about grf-string input (r8792, r8825)
 - Fix an off-by-one error in GRFComment (r8843)
2007-02-23 18:25:11 +00:00
rubidium
524919326b (svn r8761) [0.5] -Update: add some missing strings that are in 0.5, but not in trunk. 2007-02-16 18:36:36 +00:00
rubidium
2d3a64ffcc (svn r8687) [0.5] -Fix [FS#617]: assertion when getting the height of a bridge from the ramp tile. 2007-02-12 10:03:42 +00:00
rubidium
9aa9579283 (svn r8650) [0.5] -Fix: 'Searching Server' is not worthy of debug level 0, as this opens an extra window on MorphOS for no reason. 2007-02-09 11:13:03 +00:00
rubidium
3f987f460d (svn r8649) [0.5] -Fix (8630): accidentally removed strings that were still in use for by 0.5 and forgot to add new languages to langs*.vcproj. 2007-02-09 10:52:21 +00:00
bjarni
23e62bfb15 (svn r8643) [0.5] -Fix: [OSX] link statically to freetype when STATIC is set 2007-02-08 19:24:36 +00:00
rubidium
bbbe65e1e5 (svn r8639) [0.5] -Update readme's, bugs, installers, changelogs etc. to prepare for 0.5.0-RC5. 2007-02-08 16:18:11 +00:00
rubidium
e3c71534e1 (svn r8638) [0.5] -Backport from trunk (8637):
-Fix: CTRL-clicking on a hangar in the order list segfaulted as hangars are part of a station instead of real depots
2007-02-08 16:17:15 +00:00
rubidium
f8b2fb4484 (svn r8636) [0.5] -Backport from trunk (8634, 8635):
-Fix: draw canal edges under buoys that are in a canal
-Codechange: replace missing sprites with a red question mark
2007-02-08 14:10:14 +00:00
rubidium
87bbb7a413 (svn r8630) [0.5] -Backport lots of language updates from trunk 2007-02-08 11:26:09 +00:00
rubidium
61b95ff1fc (svn r8627) [0.5] -Backport from trunk (8409, 8420 + 8421, 8533, 8612):
-Regression: When the latest news was deleted, the news queue wrapped back to the oldest item, showing all news again.
-Regression [FS#573]: ShowLastNewsMessage could show an out-of-bounds news item because it did not checked if a previous item actually existed the first time it is called (forced news is INVALID_NEWS).
-Codechange: Rename the 'New <vehtype>' button of the global vehicle lists to 'Available <vehtype>' as it is a view-only list, not one from which you can purchase (rolling) stock.
-Fix: segmentation fault when the toolbar gets removed and you have selected one of the items in a submenu of the toolbar. 
-Fix [FS#582]: When the currently selected player in the performance details window is no longer active, choose the first active player instead of the first player as that may also be inactive.
2007-02-08 11:03:00 +00:00
rubidium
0543461f5e (svn r8626) [0.5] -Backport from trunk (8294, 8296, 8536, 8540, 8609):
-Fix: deleting a vehicle with shared orders, but no orders would fail to reset prev_shared and next_shared
-Fix: GenerateVehicleSortList()/CmdMassStartStopVehicle() tried to put a TileIndex into an uint16
-Fix (FS#577): Road Vehicles now can obtain a slot even if the station is very spread out 
-Fix[YAPF]: Assert when buoy is placed on NE or NW map edge (Dan)
-Fix: a road vehicle that is very close after another (slower) road vehicle gets its speed reset to 0 when entering a tunnel, which causes a traffic jam outside of the tunnel.
2007-02-08 10:41:45 +00:00
rubidium
4e3652f337 (svn r8625) [0.5] -Backport from trunk (8253, 8273, 8497, 8520 + 8542):
-Codechange: Be more strict about language generation and fail any languages not having the mandatory ##name, ##ownname and ##isocode pragma's.
-Fix: return value from clamp was ignored 
-Codechange: Increase the size of the sound/video/music-drivers to 32 bytes (instead of 16) so their actual parameters can be passed. Sound has for example 'bufsize' and 'hz'.
-Fix/Feature: requery gameservers that did not respond to their first query.
2007-02-08 10:19:03 +00:00
rubidium
1584e061eb (svn r8624) [0.5] -Backport from trunk (8239, 8240, 8315):
-Regression (r7278): Help window was empty for UNICODE builds 
-Fix (r8013): Put the output of -h to stdout and not to stderr (through ShowInfo) 
-Fix: use ShowInfo over fprintf(stderr, as Windows doesn't always have a stderr visible/available
2007-02-08 10:04:57 +00:00
rubidium
03bfa6e525 (svn r8623) [0.5] -Backport from trunk (8593, 8608, 8619, 8620)
-Fix (FS#564): bridges do not get destroyed when the bridge head gets flooded and there is a vehicle on the bridge.
-Fix: you were unable to build roads in the scenario editor when there is no town 0, even though there are other towns. 
-Fix: store the ownership of a water tile in the buoy tile and set the ownership of the water tile when the buoy is removed. This solves the issue of removing ownership from canal tiles thus making is possible for other players to remove the canal tile.
-Fix: buoys on canal tiles do not flood anymore.
2007-02-08 10:00:22 +00:00
bjarni
5467635bf9 (svn r8500) [0.5] -Fix: [OSX] freetype failed to be detected (now it's always enabled because Xcode installs it)
-Fix: [OSX] fontconfig is disabled even if it's found because the default one in OSX is 2.1.0 and OpenTTD needs at least 2.3.0
      -Fix: FREETYPE_CONFIG is only set when it's undefined. This makes it possible to add it as argument to make
2007-01-31 22:08:23 +00:00
rubidium
47c158bbc5 (svn r8490) [0.5] -Add: logging of the IP address and port of invalid/illegal UDP packets. 2007-01-31 12:47:35 +00:00
rubidium
4e1c7b8197 (svn r8489) [0.5] -Backport from trunk (8459, 8461): check for NewGRF compatability before actually downloading the map from a game server when connecting from the command prompt and internal console. 2007-01-31 12:39:41 +00:00
Darkvater
1ec915e1c8 (svn r8228) [0.5] -Revert win32 changes 2007-01-18 00:52:33 +00:00
Darkvater
b30c56d15a (svn r8227) [0.5] -Fix:?
- Prepare 0.5 branch for release. Update readme's, bugs, installers, changelog, etc. to 0.5.0-RC4
2007-01-18 00:50:56 +00:00
Darkvater
c3fcb2ef2a (svn r8222) [0.5] -Backport from trunk (lang, r8171, r8186, r8218):
- last missed chunk of danish language changes (lang)
 - (FS#556) return SL_ERROR when unthreaded saves failed (r8171)
 - (FS#557) apply railtype offset to station graphics if no custom station is in use (r8186)
 - Increase spritecache size to 2MB (r8218).
2007-01-17 23:39:13 +00:00
Darkvater
1a5957ef7f (svn r8217) [0.5] -Backport some mixed changes for WT2, remove wrong norwegian languages:
- Untranslated strings: Polish (4), Icelandic (221!), Galician (144)
2007-01-17 23:13:19 +00:00
Darkvater
0867ed49a3 (svn r8213) [0.5] -Backport from trunk (r7975, r7983, r7986, r7987, r8012, r8039, r8051,
r8053,  r8068, r8069, r8073, r8082, r8084, r8085, r8086, r8087, r8088, r8108,
 r8121, r8122, r8148, r8162, r8163, r8193, r8206):
 - Language file updates.
 - Untranslated strings: Polish (4), Icelandic (221!), Galician (144), Brazilian-Portugese (4).
 - Add Japanese, Norwegian bokmal/nynorsk, Slovenian as finished.
2007-01-17 22:37:14 +00:00
Darkvater
6c3b245d88 (svn r8182) -Backport from trunk (r8137, r8147, r8157):
- (FS#551) roadstop->num_vehicles was wrong for old savegames loaded for MP (r8137)
 - v->leave_depot_instantly was not always reset correctly (r8147)
 - moving cargo during auto replaces did not update the cached vehicle weight for trains properly (r8157)
 *NOTE* This fixes several desync issues. Big props to Rubidium for finding, debugging
 and fixing them!
2007-01-17 01:23:50 +00:00
Darkvater
a74b15af79 (svn r8181) -Backport from trunk (r8133):
- (FS#535) "out of sprite memory" warning messages (smatz)
2007-01-17 01:19:09 +00:00
Darkvater
ac3b1883ed (svn r8180) -Backport from trunk (r8093, r8094, r8105, r8106, (r8107), r8111, r8165):
- Show the activated status of the GRF after pressing apply in window (r8094)
 - Add the ability to load savegames without matching grf's.
   *NOTE*: currently this feature is different from trunk in behaviour as it does NOT
   allow you to load savegames with MISSING grfs only compatible (matching GRFID, non-
   matching MD5SUM).
2007-01-17 01:17:44 +00:00
Darkvater
40245ce496 (svn r8179) -Backport from trunk (r8065, r8101, r8119, r8123, r8140, r8150):
- The station list does now remember the sort settings (r8065)
 - Uninitializing windows calls WE_DESTROY to free dynamic memory used (r8101, r8119)
 - (FS#538) Findfirstbit returns first bit (bouys now numbered 1..9) (r8123)
 - FS#54) Combat helicopter shoots from right position, (r8140)
 - Submarine disaster did not move around (r8158)
2007-01-17 01:02:51 +00:00
Darkvater
c73bbe531e (svn r8178) -Backport from turnk (r8049, r8079, r8080, r8135):
- oe more news-window fix and fix up ShowLastNewsMessage (r8049)
 - float division by 0 in YAPF code on Win9x (r8079, r8080)
 - do not assert when removing duplicates would remove non-static grf (r8135)
2007-01-17 00:51:04 +00:00
matthijs
8576c2cc40 (svn r8177) - [Debian] Prepare debian packaging files for 0.5.0-rc4 2007-01-17 00:38:51 +00:00
Darkvater
1778566ab8 (svn r8176) -Backport from trunk (r8042, r8089, r8090, r8112):
- OS/2 compilation with GCC (thanks to Paul Smedley and TrueBrain for help) (r8042)
 - [win32] *nprintf functions are broken, 'len = count' wasn't handled (r8089, r8090)
 - MSVC solution files will make openttd THE startup project (r8112)
2007-01-17 00:38:27 +00:00
Darkvater
a4bab5f17f (svn r8175) -Backport from trunk (r8030, r8070, r8071, r8074):
- crash when removing a town in the scenario editor and the query tool is open for a town's tile (r8030)
 - (FS#537) heightmap crashes when rescaling, or using 24bpp bitmaps (r8070, r8074)
 - (FS#536) inauguration date of companies from TTDP games was wrong (r8071)
2007-01-17 00:29:16 +00:00
Darkvater
06367834c6 (svn r8174) -Backport from trunk (r8027, r8028, r8043, r8132):
- (FS#486) pause command issues with shift-pressed did not pause the game, interference with pause_on_join (r8027)
 - overflow of ticks was not handled properly, possibly resulting a non-reacting gameserver/gameclient (r8028, r8043)
 - The game could crash when the chat key (<ENTER>) is pressed too quickly during join (r8132)
2007-01-17 00:20:23 +00:00
Darkvater
f08141ae48 (svn r8173) -Backport from trunk (r8026):
- picking up transferring cargo, trains will now also have the virtual profit deducted
2007-01-17 00:08:49 +00:00
Darkvater
25059d28df (svn r8172) -Backport from trunk (r8013, r8134):
- Show error messages about our own data files as ShowInfo(F) and output console error to stderr and not stdout.
2007-01-17 00:05:51 +00:00
Darkvater
b57b2224e9 (svn r8170) -Backport from trunk (r7984, r8118, r8167, r8168):
- out-of-bounds read access on _clients array (Quark) (r7984)
 - change the ordering of the network list (r8118)
 - (FS#556): a network client crashes, due to a division by zero (r8167)
 - ParseConnectionstring didn't use the port parameter if a player was also specified (r8168)
2007-01-16 23:59:03 +00:00
celestar
70920944d8 (svn r7979) [0.5] - Fix: Segfault in the newgrf loading code (grfmsg => DEBUG). Do it in the right directory this time. Sorry for da mess :S 2007-01-08 14:01:05 +00:00
Darkvater
06b5d32983 (svn r7970) -Backport from trunk (r7968, r7969):
- Update year throughout the program to 2007
 - Minor update to changelog, known-bugs file (Bjarni)
2007-01-07 17:38:58 +00:00
Darkvater
34f8ab2f81 (svn r7967) - Prepare 0.5 branch for release. Update readme's, bugs, installers, changelog, etc. to 0.5.0-RC3 2007-01-07 16:43:46 +00:00
Darkvater
315ec78344 (svn r7963) -Backport from trunk (r7716, r7717, r7718):
- Bad signal propagation through tunnel-ends, incompatible railtype signal propagation
 still possible (not fixed).
2007-01-07 14:10:56 +00:00
Darkvater
0bf1d6c49d (svn r7962) -Backport from trunk (r7689, r7696, r7699, r7701, r7704, r7706, r7707, r7713,
r7715, r7723, r7732, r7738, r7742, r7743, r7746, r7754, r7756, r7787, r7800,
 r7803, r7806, r7807, r7819, r7828, r7857, r7884, r7896, r7905):
 - Language file updates.
 - Untranslated strings: Icelandic (217!), Hungarian (2), Galician (140), Finnish (3),
   Brazilian-Portugese (3).
 - Moved Lithuanian from unfinished to finished.
2007-01-07 13:49:54 +00:00
matthijs
6f291a7e6d (svn r7958) - [Debian] Prepare debian packing files for 0.5.0-rc3 2007-01-07 12:44:45 +00:00
Darkvater
04d77258c5 (svn r7957) -Backport from trunk (r7936):
- Only update the signals and YAPF cache on a DC_EXEC action for bridge-building
2007-01-07 12:20:48 +00:00
Darkvater
fbfa0b8009 (svn r7956) -Backport from trunk (r7930):
- wrong TTDPatch GRF flag was set for gradual loading
2007-01-07 12:19:56 +00:00
Darkvater
8960b5740f (svn r7955) -Backport from trunk (r7886):
- [osx] control+enter no longer fullscreens, interfered with team-chat.
2007-01-07 12:19:08 +00:00
Darkvater
30fadfb54b (svn r7954) -Backport from trunk (r7864):
- offset engines/wagons by half width in details window; fixes overflowing for display
2007-01-07 12:18:05 +00:00
Darkvater
b342991853 (svn r7953) -Backport from trunk (r7840, r7843):
- [win32] Update crash window text (+crash.dmp -submit)
2007-01-07 12:16:53 +00:00
Darkvater
0a635c692e (svn r7952) -Backport from trunk (r7823, r7861):
- News windows could still crash due to moving news items around while a news window was still open.
2007-01-07 12:15:36 +00:00
Darkvater
0a211097ac (svn r7951) -Backport from trunk (r7810, r7812):
- Building airport whose size exceeds max station spread-out caused assert. (r7810)
 - rail station build window was not correctly updated after station_spread change (r7812)
2007-01-07 12:13:57 +00:00
Darkvater
1277599c30 (svn r7950) -Backport from trunk (r7760, r7766):
- Sprite usage debug message showed the starting sprite, not current sprite, and only do this during activation (r7760).
 - [OSX] Remove incorrect debug message about missing grf files.
2007-01-07 12:11:54 +00:00
Darkvater
bae0695ac9 (svn r7949) -Backport from trunk (r7733):
- do not use WP(w, querystr_d) and WP(w, def_d) for the same window
2007-01-07 12:07:07 +00:00
Darkvater
630f81c382 (svn r7948) -Backport from trunk (r7731):
- off-by-one error in the date to YMD calculation for first 4 years of a century that was not divisable by 400
2007-01-07 12:06:34 +00:00
Darkvater
2684cb2525 (svn r7947) -Backport from trunk (r7727):
- [sdl] sometimes ALT-TAB could trigger the fast forward
2007-01-07 12:05:47 +00:00
Darkvater
610b6e3953 (svn r7946) -Backport from trunk (r7711, r7795, r7831):
- NewGRF Action 7, GRF check condition 10 didn't ignore unknown GRF IDs (r7354)
 - NewGRF safety scan fixes action E (allow unifont.grf) and Action 0 prop D (bridge) (r7795, r7831)
2007-01-07 11:53:12 +00:00
Darkvater
563857d5bd (svn r7945) -Backport from trunk (r7700):
- Caret randomly jumping back&forth for new randomseed (r7182)
2007-01-07 11:37:23 +00:00
Darkvater
58d18a3ef3 (svn r7944) -Backport from trunk (r7692):
- -OpenTTD didn't compile without network enabled (newgrf sync code)
2007-01-07 11:34:20 +00:00
rubidium
0b7ab719f3 (svn r7893) [0.5] -Fix (FS#485): the configure script did not work work for dash, a sh compatible shell. 2007-01-05 23:43:20 +00:00
Darkvater
f5439821c1 (svn r7694) -Update known-bugs file. 2006-12-31 11:28:42 +00:00
Darkvater
d11a6a439a (svn r7685) - Prepare 0.5 branch for release. Update readme's, bugs, installers, changelog, etc. to 0.5.0-RC2 2006-12-31 01:21:00 +00:00
Darkvater
99096b83bd (svn r7684) -Backport from trunk (r7620):
- Bad signal update through incompatible rail types, bridge.
2006-12-31 00:52:33 +00:00
Darkvater
75c538962d (svn r7683) -Backport from trunk (r7552, r7553, r7574, r7581, r7601, r7611, r7654, r7658):
- Language file updates.
 - Untranslated strings: Turkish (2), Swedish (1), Romanian (3), Norwegian (2),
   Icelandic (217!), Hungarian (2), German (1), Galician (173), Finnish (26),
   Danish (23), Czech (34), Bulgarian (39), Brazilian-Portugese (3)
2006-12-31 00:01:07 +00:00
Darkvater
51cd7bd43b (svn r7682) -Backport from trunk (r7539, r7541, r7603):
- Added esperanto language files to MS projects (r7539).
 - Polish townname generator uses proper UNICODE characters (r7603).
2006-12-30 23:38:41 +00:00
Darkvater
0b67caa8ad (svn r7681) -Backport from trunk (r7585, r7590, r7599):
- Drastically reduce CheckStationSpreadOut CPU usage which got called way too much by the AI.
2006-12-30 23:35:01 +00:00
Darkvater
4ec96ba2d0 (svn r7680) -Backport from trunk (r7586):
- Remove landscaping toolbar from road-toolbar in scenario editor
2006-12-30 23:32:22 +00:00
Darkvater
b93e8d6c71 (svn r7679) -Backport from trunk (r7628):
- [YAPF] suppress 'Train is lost' message if pathfinding ended on the first
   two-way red signal
2006-12-30 23:30:21 +00:00
Darkvater
ac945ced7e (svn r7678) -Fix (r7674): DEBUG macro has been changed 2006-12-30 23:29:33 +00:00
Darkvater
5c190a0c33 (svn r7677) -Backport from trunk (r7657):
- 'Goto Depot' did not work for helicopters going to an airport without depot
2006-12-30 23:26:47 +00:00
Darkvater
b5715acaf8 (svn r7676) -Backport from trunk (r7630, r7631):
- cur/old economy memmove magic (r7630).
 - wrong pointer arithmetic that totally corrupted animated_tiles table, desyncing
   between different endiannes-machines in multiplayer (r7631).
2006-12-30 23:25:57 +00:00
Darkvater
0e7701fbe6 (svn r7675) -Backport from trunk (r7606):
- [NewStations] Add support for variables 45 and 65.
2006-12-30 23:23:43 +00:00
Darkvater
59167f686e (svn r7674) -Backport from trunk (r7580):
- Wrong bounding boxes were computed for certain strings.
2006-12-30 23:22:55 +00:00
Darkvater
0adf61e7fa (svn r7673) -Backport from trunk (r7563):
- [FS#468] Removing towns in scenario editor didn't remove their subsidies.
2006-12-30 23:21:55 +00:00
Darkvater
6fa93f4a7a (svn r7672) -Backport from trunk (r7562):
- [win32] OpenTTD didn't always remember its maximized state on restart.
2006-12-30 23:21:02 +00:00
Darkvater
f3424f51bc (svn r7671) -Backport from trunk (r7560, r7561, r7566):
- No new company could join if 8 clients were connected in less than 8 companies (r7560).
 - [FS#431] internal and visible settings of autorenew could go out of sync (r8561).
 - Server told clients to start syncing from a bad position, causing asserts/crashes (r7566).
2006-12-30 23:20:00 +00:00
Darkvater
6c8f12de78 (svn r7670) -Backport from trunk (r7558, r7559):
- [FS#464] do not wait till a crashed vehicle is removed before starting to load
 other vehicles (r7558).
 - [FS#456] clicking 'full load' can change depot order under certain circumstances (r7559).
2006-12-30 23:14:39 +00:00
Darkvater
953fc9e196 (svn r7669) -Backport from trunk (r7556):
- screenshot no_con didn't remove console from screenshot.
2006-12-30 23:12:05 +00:00
Darkvater
737220f39c (svn r7668) -Backport from trunk (r7555):
- off-by-one error due do truncation on division by 2 in heightmap code.
2006-12-30 23:11:14 +00:00
Darkvater
e00a47d47d (svn r7667) -Backport from trunk (r7549, r7551, r7554, r7582, r7594):
- change size of newgrf GUI to same size as TTDP (no overflows) (r7549).
 - segmentation fault on showing NewGRF settings of a network game (r7551).
 - in Action 0xE, don't deactivate the current GRF (r7554).
 - appending static GRF's could cause duplicate GRF's in the list (r7582).
 - GRF config not cleared when no GRF's are used (r7594).
2006-12-30 23:09:27 +00:00
Darkvater
cf52f00f46 (svn r7666) -Backport from trunk (r7548):
- Some MorphOS changes to get OpenTTD compiled, packaged.
2006-12-30 23:04:14 +00:00
Darkvater
d4b335fffb (svn r7665) -Backport from trunk (r7547):
- When removing a rail station, the cost was added for the full rectangle not for
   only the removed tiles themselves.
2006-12-30 23:03:15 +00:00
Darkvater
652e834ee7 (svn r7664) -Backport from trunk (r7587, r7588, r7600, r7605, r7626, r7629):
- [OSX] universal binary docs, makefile (r7587, r7588, r7626).
 - General documentation update (r7600, r7605).
 - openttd -h showed outdated help for '-n' switch (r7629).
2006-12-30 23:00:52 +00:00
Darkvater
dfab8c779b (svn r7662) -Backport from trunk (r7557, r7624):
- [OSX] makefile fixes (static libfontconfig) (r7557).
 - [FS#470] Install openttd.32.bmp on install so that SDL window has icon (r76240.
2006-12-30 22:55:31 +00:00
Darkvater
bbdbdf3818 (svn r7661) -Backport from trunk (r7550):
- [win32] x64 compile fixed.
2006-12-30 22:53:05 +00:00
Darkvater
0264283116 (svn r7660) -Backport from trunk (r7537, r7539):
- Changelog updates
2006-12-30 22:50:49 +00:00
matthijs
6f97748c80 (svn r7659) - [Debian] Prepare debian packing files for 0.5.0-rc2 2006-12-30 22:36:22 +00:00
Darkvater
65d6403497 (svn r7536) -Branch: add 0.5 branch 2006-12-21 20:56:57 +00:00
2054 changed files with 288541 additions and 733272 deletions

View File

@@ -1,15 +0,0 @@
notifications:
global:
irc:
- openttd
- openttd.notice
push:
only:
- master
only-by:
- DorpsGek
commit-comment:
pull-request:
issue:
tag-created:

View File

@@ -1,9 +0,0 @@
root = true
[*]
insert_final_newline = true
trim_trailing_whitespace = true
[*.{c,cpp,h,hpp}]
indent_style = tab
charset = utf-8

1
.github/FUNDING.yml vendored
View File

@@ -1 +0,0 @@
custom: https://www.openttd.org/donate.html

View File

@@ -1,7 +0,0 @@
## Version of OpenTTD
## Expected result
## Actual result
## Steps to reproduce

34
.github/stale.yml vendored
View File

@@ -1,34 +0,0 @@
daysUntilClose: 7
staleLabel: stale
closeComment: false
exemptMilestones: true
exemptAssignees: true
issues:
daysUntilStale: 60
exemptLabels:
- pinned
- security
- "good first issue"
- regression
markComment: >
This issue has been automatically marked as stale because it has not had any activity in the last two months.
If you believe the issue is still relevant, please test on the latest nightly and report back.
It will be closed if no further activity occurs within 7 days.
Thank you for your contributions.
pulls:
daysUntilStale: 30
exemptLabels:
- pinned
markComment: >
This pull request has been automatically marked as stale because it has not had any activity in the last month.
Please feel free to give a status update now, ping for review, or re-open when it's ready.
It will be closed if no further activity occurs within 7 days.
Thank you for your contributions.

View File

@@ -1,45 +0,0 @@
name: Commit checker
on:
pull_request:
jobs:
commit-checker:
name: Commit checker
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 4
- name: Get pull-request commits
run: |
set -x
# actions/checkout did a merge checkout of the pull-request. As such, the first
# commit is the merge commit. This means that on HEAD^ is the base branch, and
# on HEAD^2 are the commits from the pull-request. We now check if those trees
# have a common parent. If not, we fetch a few more commits till we do. In result,
# the log between HEAD^ and HEAD^2 will be the commits in the pull-request.
DEPTH=4
while [ -z "$(git merge-base HEAD^ HEAD^2)" ]; do
git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules --deepen=${DEPTH} origin HEAD
DEPTH=$(( ${DEPTH} * 4 ))
done
# Just to show which commits we are going to evaluate.
git log --oneline HEAD^..HEAD^2
- name: Checkout commit-checker
uses: actions/checkout@v2
with:
repository: OpenTTD/OpenTTD-git-hooks
path: git-hooks
ref: master
- name: Check commits
run: |
set -x
HOOKS_DIR=./git-hooks/hooks GIT_DIR=.git ./git-hooks/hooks/check-commits.sh HEAD^..HEAD^2
echo "Commit checks passed"

55
.gitignore vendored
View File

@@ -1,55 +0,0 @@
bin/*
!bin/ai
bin/ai/*
!bin/ai/compat*.nut
!bin/ai/regression
!bin/data
bin/baseset/*
!bin/baseset/openttd.grf
!bin/baseset/opntitle.dat
!bin/baseset/orig_extra.grf
!bin/baseset/orig_*.obg
!bin/baseset/orig_*.obs
!bin/baseset/no_sound.obs
!bin/baseset/no_music.obm
!bin/baseset/orig_*.obm
!bin/game
bin/game/*
!bin/game/compat*.nut
!bin/scripts
bin/scripts/*
!bin/scripts/*.example
!bin/scripts/readme.txt
*.aps
bundle/*
bundles/*
docs/aidocs/*
docs/gamedocs/*
docs/source/*
.kdev4
.kdev4/*
*.kdev4
media/openttd.desktop
media/openttd.desktop.install
objs/*
projects/.vs
projects/Debug
projects/Release
projects/*.ncb
projects/*.suo
projects/*.sdf
projects/*.opensdf
projects/*.vcproj.*.user
projects/*.vcxproj.user
projects/*.VC.db
projects/*.VC.opendb
src/rev.cpp
src/os/windows/ottdres.rc
/Makefile*
!/Makefile.msvc
/config.*
!/config.lib
!*.in
*.tmp

View File

@@ -1,34 +0,0 @@
syntax: glob
.svn
*.aps
bin/baseset/openttd.32.bmp
bin/lang/*
bin/openttd*
bin/*.cfg
bundle/*
bundles/*
config.cache*
config.log
config.pwd
docs/aidocs/*
docs/gamedocs/*
docs/source/*
.kdev4
.kdev4/*
*.kdev4
Makefile
Makefile.am
Makefile.bundle
media/openttd.desktop
media/openttd.desktop.install
objs/*
projects/.vs
projects/*.ncb
projects/*.suo
projects/*.sdf
projects/*.opensdf
projects/*.vcproj.*.user
projects/*.vcxproj.user
src/rev.cpp
src/os/windows/ottdres.rc

7
BUGS Normal file
View File

@@ -0,0 +1,7 @@
/* $Id$ */
KNOWN BUGS / PROBLEMS:
Normal and elrail depots look the same. Use 'X' (transparent buildings)
to distinguish between them
Missing curors / icons for construction (currently using the conventional ones)

View File

@@ -1,141 +0,0 @@
# Compiling OpenTTD
## Required/optional libraries
The following libraries are used by OpenTTD for:
- zlib: (de)compressing of old (0.3.0-1.0.5) savegames, content downloads,
heightmaps
- liblzo2: (de)compressing of old (pre 0.3.0) savegames
- liblzma: (de)compressing of savegames (1.1.0 and later)
- libpng: making screenshots and loading heightmaps
- libfreetype: loading generic fonts and rendering them
- libfontconfig: searching for fonts, resolving font names to actual fonts
- libicu: handling of right-to-left scripts (e.g. Arabic and Persian) and
natural sorting of strings (Linux only)
- libSDL2: hardware access (video, sound, mouse) (not required for Windows or macOS)
OpenTTD does not require any of the libraries to be present, but without
liblzma you cannot open most recent savegames and without zlib you cannot
open most older savegames or use the content downloading system.
Without libSDL/liballegro on non-Windows and non-macOS machines you have
no graphical user interface; you would be building a dedicated server.
## Windows:
You need Microsoft Visual Studio 2015 Update 3 or newer.
You can download the free Visual Studio Community Edition from Microsoft at
https://visualstudio.microsoft.com/vs/community/.
OpenTTD needs the Platform SDK, if it isn't installed already. This can be
done during installing Visual Studio, by selecting
`Visual C++ MFC for x86 and x64` (and possibly
`Visual C++ ATL for x86 and x64` depending on your version). If not, you
can get download it as [MS Windows Platform SDK](https://developer.microsoft.com/en-US/windows/downloads/windows-10-sdk).
Install the SDK by following the instructions as given.
Dependencies for OpenTTD on Windows are handled via
[vcpkg](https://github.com/Microsoft/vcpkg/). First you need to install vcpkg
by following the `Quick Start` instructions of their
[README](https://github.com/Microsoft/vcpkg/blob/master/README.md).
After this, you can install the dependencies OpenTTD needs. We advise to use
the `static` versions, and OpenTTD currently needs the following dependencies:
- liblzma
- libpng
- lzo
- zlib
To install both the x64 (64bit) and x86 (32bit) variants (though only one is necessary), you can use:
```ps
.\vcpkg install liblzma:x64-windows-static libpng:x64-windows-static lzo:x64-windows-static zlib:x64-windows-static
.\vcpkg install liblzma:x86-windows-static libpng:x86-windows-static lzo:x86-windows-static zlib:x86-windows-static
```
Open the relevant project file and it should build automatically.
- VS 2015: projects/openttd_vs140.sln
- VS 2017: projects/openttd_vs141.sln
- VS 2019: projects/openttd_vs142.sln
Set the build mode to `Release` in
`Build > Configuration manager > Active solution configuration`.
You can now compile.
If everything works well the binary should be in `objs\Win[32|64]\Release\openttd.exe`
and in `bin\openttd.exe`
The OpenTTD wiki may provide additional help with [compiling for Windows](https://wiki.openttd.org/Compiling_on_Windows_using_Microsoft_Visual_C%2B%2B_2015).
You can also build OpenTTD with MSYS2/MinGW-w64 or Cygwin/MinGW using the Makefile. The OpenTTD wiki may provide additional help with [MSYS2](https://wiki.openttd.org/Compiling_on_Windows_using_MSYS2)
## Linux, Unix, Solaris:
OpenTTD can be built with GNU '`make`'. On non-GNU systems it is called '`gmake`'.
However, for the first build one has to do a '`./configure`' first.
The OpenTTD wiki may provide additional help with:
- [compiling for Linux and *BSD](https://wiki.openttd.org/Compiling_on_%28GNU/%29Linux_and_*BSD)
- [compiling for Solaris](https://wiki.openttd.org/Compiling_on_Solaris)
## macOS:
Use '`make`' or Xcode (which will then call make for you)
This will give you a binary for your CPU type (PPC/Intel)
However, for the first build one has to do a '`./configure`' first.
To make a universal binary type '`./configure --enable-universal`'
instead of '`./configure`'.
The OpenTTD wiki may provide additional help with [compiling for macOS](https://wiki.openttd.org/Compiling_on_Mac_OS_X).
## Haiku:
Use '`make`', but do a '`./configure`' before the first build.
The OpenTTD wiki may provide additional help with [compiling for Haiku](https://wiki.openttd.org/Compiling_on_Haiku).
## OS/2:
A comprehensive GNU build environment is required to build the OS/2 version.
The OpenTTD wiki may provide additional help with [compiling for OS/2](https://wiki.openttd.org/Compiling_on_OS/2).
## Supported compilers
The following compilers are tested with and known to compile OpenTTD:
- Microsoft Visual C++ (MSVC) 2015, 2017 and 2019.
- GNU Compiler Collection (GCC) 4.8 - 9.
- Clang/LLVM 3.9 - 8
The following compilers are known not to compile OpenTTD:
In general, this is because these old versions do not (fully) support modern
C++11 language features.
- Microsoft Visual C++ (MSVC) 2013 and earlier.
- GNU Compiler Collection (GCC) 4.7 and earlier.
- Clang/LLVM 3.8 and earlier.
If any of these, or any other, compilers can compile OpenTTD, let us know.
Pull requests to support more compilers are welcome.
## Compilation of base sets
To recompile the extra graphics needed to play with the original Transport
Tycoon Deluxe graphics you need GRFCodec (which includes NFORenum) as well.
GRFCodec can be found at https://www.openttd.org/download-grfcodec.
The compilation of these extra graphics does generally not happen, unless
you remove the graphics file using '`make maintainer-clean`'.
Re-compilation of the base sets, thus also use of '`--maintainer-clean`' can
leave the repository in a modified state as different grfcodec versions can
cause binary differences in the resulting grf. Also translations might have
been added for the base sets which are not yet included in the base set
information files. Use the configure option '`--without-grfcodec`' to avoid
modification of the base set files by the build process.

View File

@@ -1,267 +0,0 @@
# Contributing to OpenTTD
Looking to contribute something to OpenTTD? **Here's how you can help.**
Please take a moment to review this document in order to make the contribution process easy and effective for everyone involved.
Following these guidelines helps to communicate that you respect the time of the developers managing and developing this open source project.
In return, they should reciprocate that respect in addressing your issue or assessing patches and features.
## Using the issue tracker
The [issue tracker](https://github.com/OpenTTD/OpenTTD/issues) is the preferred channel for [bug reports](#bug-reports), but please respect the following restrictions:
* Please **do not** use the issue tracker for help playing or using OpenTTD.
Please try [irc](https://wiki.openttd.org/IRC_channel), or the [forums](https://www.tt-forums.net/)
* Please **do not** derail or troll issues. Keep the discussion on topic and respect the opinions of others.
* Please **do not** post comments consisting solely of "+1" or ":thumbsup:".
Use [GitHub's "reactions" feature](https://github.com/blog/2119-add-reactions-to-pull-requests-issues-and-comments) instead.
We reserve the right to delete comments which violate this rule.
* Please **do not** open issues or pull requests regarding add-on content in NewGRF, GameScripts, AIs, etc.
These are created by third-parties. Please try [irc](https://wiki.openttd.org/IRC_channel) or the [forums](https://www.tt-forums.net/) to discuss these.
## Bug reports
A bug is a _demonstrable problem_ that is caused by the code in the repository.
Good bug reports are extremely helpful, so thanks!
Guidelines for bug reports:
0. Please don't report issues with games where you changed NewGRFs.
1. Please don't report issues with modified versions of OpenTTD (patchpacks and similar).
2. **Use the GitHub issue search** --- check if the issue has already been
reported.
3. **Check if the issue has been fixed** --- try to reproduce it using the latest `nightly` build of OpenTTD, available from https://www.openttd.org
4. **Isolate the problem** --- ideally create reproduceable steps with an attached savegame and screenshots. Try to use few or no NewGRFs, AIs etc if possible.
A good bug report shouldn't leave others needing to chase you up for more information.
Please try to be as detailed as possible in your report.
* What is your environment?
* What steps will reproduce the issue?
* Which operating system(s) experience the problem?
* What would you expect to be the outcome?
All these details will help people to fix any potential bugs.
Example:
> Short and descriptive example bug report title
>
> A summary of the issue and the OS environment in which it occurs. If
> suitable, include the steps required to reproduce the bug.
>
> 1. This is the first step
> 2. This is the second step
> 3. Further steps, etc.
>
> Attached savegame
> Attached screenshots showing the issue
> Crashlogs if the bug causes a crash
>
> Any other information you want to share that is relevant to the issue being
> reported. This might include the lines of code that you have identified as
> causing the bug, and potential solutions (and your opinions on their
> merits).
## Feature requests
Before opening a feature request, please take a moment to find out whether your idea fits with the [scope and goals](./CONTRIBUTING.md#project-goals) of the project.
It's up to *you* to make a strong case to convince the project's developers of the merits of this feature.
Please provide as much detail and context as possible.
This means don't request for a solution, but describe the problem you see and how/why you think it should be fixed.
For feature request we have a strict policy.
Keeping issues around with "a good idea" or "not really a bug but we should maybe fix it" turns out to have the reversed effect: nobody looks at it anymore.
Although we really appreciate feedback and ideas, we will close feature requests that we don't expect to fulfill in the next year.
Many of those ideas etc do have a place on the [forums](https://www.tt-forums.net); and if enough people like it, someone will stand up and make it.
It's usually best discuss in [irc](https://wiki.openttd.org/IRC_channel) before opening a feature request or working on a large feature in a fork.
Discussion in irc can take time, but it can be productive and avoid disappointment :)
## Pull requests
Good pull requests—patches, improvements, new features—are a fantastic help.
Pull requests should fit with the [goals of the project](./CONTRIBUTING.md#project-goals).
**Please do ask first** before embarking on any significant pull request (e.g. implementing features, refactoring code, porting to a different language), otherwise you risk spending a lot of time working on something that the project's developers might not want to merge into the project.
Every pull request should have a clear scope, with no unrelated commits.
[Code style](https://wiki.openttd.org/Coding_style) must be complied with for pull requests to be accepted; this also includes [commit message format](https://wiki.openttd.org/Coding_style#Commit_message).
Adhering to the following process is the best way to get your work included in the project:
1. [Fork](https://help.github.com/fork-a-repo/) the project, clone your fork, and configure the remotes:
```bash
git clone https://github.com/<your-username>/OpenTTD.git openttd
git clone https://github.com/OpenTTD/OpenTTD-git-hooks.git openttd_hooks
cd openttd
git remote add upstream https://github.com/OpenTTD/OpenTTD.git
cd .git/hooks
ln -s ../../../openttd_hooks/hooks/* .
```
2. If you cloned a while ago, get the latest changes from upstream:
```bash
git fetch upstream
```
3. Create a new topic branch (off the main project development branch) to
contain your feature, change, or fix:
```bash
git checkout upstream/master -b <topic-branch-name>
```
4. Commit your changes in logical chunks. Please adhere to these [git commit message guidelines](https://wiki.openttd.org/Commit_style#Commit_message) or your code is unlikely to be merged into the main project.
Use Git's [interactive rebase](https://help.github.com/articles/interactive-rebase) feature to tidy up your commits before making them public.
5. Locally rebase the upstream development branch into your topic branch:
```bash
git fetch upstream
git rebase upstream/master
```
6. Push your topic branch up to your fork the first time:
```bash
git push --set-upstream origin <topic-branch-name>
```
And any time after that:
```bash
git push
```
7. [Open a Pull Request](https://help.github.com/articles/using-pull-requests/) with a clear title and description against the `master` branch.
**IMPORTANT**: By submitting a pull request or patch, you agree to the [License](#license) and the [Privacy Notice](CONTRIBUTING.md#privacy-notice).
### Pull request validation
Continuous integration (CI) tools monitor pull requests, and help us identify build and code quality issues.
The results of the CI tests will show on your pull request.
By clicking on Details you can further zoom in; in case of a failure it will show you why it failed.
In case of success it will report how awesome you were.
Tip: [commit message format](https://wiki.openttd.org/Coding_style#Commit_message) is a common reason for pull requests to fail validation.
### Are there any development docs?
There is no single source for OpenTTD development docs. It's a complex project with a long history, and multiple APIs.
A good entry point is [Development](https://wiki.openttd.org/Development) on the OpenTTD wiki; this provides links to wiki documentation and other sources.
The GitHub repo also includes some non-comprehensive documentation in [/docs](./docs).
You may also want the guide to [compiling OpenTTD](./COMPILING.md).
## Project goals
### What are the goals of the official branch?
The main goals of the official branch are:
- Stay faithful to the original gameplay from Transport Tycoon Deluxe
- Improve the user interface
- Allow extending the gameplay with add-ons / mods via supported content APIs
- Provide a (relatively) stable core for both players of the official branch, and for authors of add-ons and maintainers of patchpacks
In contrast, extending or altering the gameplay of the base game is not encouraged.
The rationale behind these goals is that people have different opinions about what OpenTTD is and what it should be.
When it comes to gameplay, there are at least these groups of people:
- *Model railway (mostly singleplayer)*: build "realistic" landscapes, roleplay a world, or even replicate historical scenarios
- *Economical challenge (mostly singleplayer)*: run a business with economical challenges
- *Transport challenge (singleplayer or cooperative multiplayer)*: build efficient track layouts with high cargo throughput and tons of vehicles
- *Competitive speed run (competitive multiplayer)*: maximize some goal in some limited amount of time
When it comes to gameplay features there are at least these groups of interests:
- *Control freak:* micromanagement like conditional orders, refitting and loading etc.
- *Casual:* automatisation like cargodist, path based signalling etc.
To please everyone, the official branch tries to stay close to the original gameplay; after all, that is what everyone brought here.
The preferred method to alter and extent the gameplay is via add-ons like NewGRF and GameScripts.
For a long time, the official branch was also open to features which could be enabled/disabled, but the corner-cases that came with some configurations have rendered some parts of the code very complicated.
Today, new features have to work with all the already existing features, which is not only challenging in corner cases, but also requires spending considerable more work than just "making it work in the game mode that I play".
The preferred method to introduce new gameplay features is to extend the content APIs, supporting ever more add-on content / mods.
This moves conflict-solving away from the codebase to content authors / players.
It is more accepted for add-ons not working together than the base game not working with certain setting combinations.
In general the game should allow anything that doesn't violate basic rules, but it should warn players if they take potentially dangerous or "stupid" actions.
For example, players are not prevented from starting vehicles without orders, but will receive a warning about vehicles having too few orders.
This lack of limitation has led to players challenging themselves to create networks where all vehicles have no orders, increasing gameplay possibilities.
### I do not agree with the goals of the official branch, what can I do instead?
Fork! There is a rich history of experimental patches for OpenTTD.
Many of these will never be accepted for core, but are creative and interesting ways to modify OpenTTD.
Sometimes patches are combined into long-running patchpacks, modified OpenTTD versions which can be downloaded by anyone, or modified OpenTTD clients for dedicated multiplayer servers.
One of the reasons to keep core relatively stable is to make life easier for patch authors and patchpack maintainers where possible.
Patchpack discussions and related topics may be found in community sites such as [TT-Forums development section](https://www.tt-forums.net/viewforum.php?f=33).
## Legal stuff
### License
By contributing your code, you agree to license your contribution under the [GPL v2](https://github.com/OpenTTD/OpenTTD/blob/master/COPYING.md).
### Privacy Notice
We would like to make you aware that contributing to OpenTTD via git will permanently store the name and email address you provide as well as the actual changes and the time and date you made it inside git's version history.
This is inevitable, because it is a main feature of git.
If you are concerned about your privacy, we strongly recommend to use "Anonymous &lt;anonymous@openttd.org&gt;" as the git commit author. We might refuse anonymous contributions if malicious intent is suspected.
Please note that the contributor identity, once given, is used for copyright verification and to provide proof should a malicious commit be made.
As such, the [EU GDPR](https://www.eugdpr.org/key-changes.html) "right to be forgotten" does not apply, as this is an overriding legitimate interest.
Please also note that your commit is public and as such will potentially be processed by many third-parties.
Git's distributed nature makes it impossible to track where exactly your commit, and thus your personal data, will be stored and be processed.
If you would not like to accept this risk, please do either commit anonymously or refrain from contributing to the OpenTTD project.
### Attribution of this Contributing Guide
This contributing guide is adapted from [Bootstrap](https://github.com/twbs/bootstrap/blob/master/CONTRIBUTING.md) under the [Creative Commons Attribution 3.0 Unported License](https://github.com/twbs/bootstrap/blob/master/docs/LICENSE) terms for Bootstrap documentation.
The GDPR notice is adapted from [rsyslog](https://github.com/rsyslog/rsyslog/blob/master/CONTRIBUTING.md) under the [GNU General Public License](https://github.com/rsyslog/rsyslog/blob/master/COPYING).

View File

@@ -1,19 +1,14 @@
This is the license which applies to OpenTTD with the exception of some
3rd party modules. See [./README.md](./README.md) for details
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU General Public License
==========================
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.
_Version 2, June 1991_
_Copyright © 1989, 1991 Free Software Foundation, Inc.,_
_51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA_
Preamble
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
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
@@ -23,47 +18,48 @@ 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
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
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
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,
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
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
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
The precise terms and conditions for copying, distribution and
modification follow.
### TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
**0.** This License applies to any program or other work which contains
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"
@@ -80,7 +76,7 @@ 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
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
@@ -91,27 +87,29 @@ 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
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.)
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,
@@ -133,24 +131,26 @@ 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,
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.)
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
@@ -169,7 +169,7 @@ 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
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.
@@ -177,7 +177,7 @@ 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
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
@@ -186,7 +186,7 @@ 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
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
@@ -194,7 +194,7 @@ 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
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
@@ -226,7 +226,7 @@ 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
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
@@ -234,7 +234,7 @@ 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
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.
@@ -247,7 +247,7 @@ 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
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
@@ -255,9 +255,9 @@ 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
NO WARRANTY
**11.** BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS 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
@@ -267,7 +267,7 @@ 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
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
@@ -277,15 +277,15 @@ 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
END OF TERMS AND CONDITIONS
### How to Apply These Terms to Your New Programs
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
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 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.
@@ -317,20 +317,20 @@ when it starts in an interactive mode:
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
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
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.
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
<signature of Ty Coon>, 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

View File

@@ -1,60 +0,0 @@
### The OpenTTD team (in alphabetical order):
- Grzegorz Duczyński (adf88) - General coding (since 1.7.2)
- Albert Hofkamp (Alberth) - GUI expert (since 0.7)
- Matthijs Kooijman (blathijs) - Pathfinder-guru, Debian port (since 0.3)
- Ulf Hermann (fonsinchen) - Cargo Distribution (since 1.3)
- Christoph Elsenhans (frosch) - General coding (since 0.6)
- Loïc Guilloux (glx) - Windows Expert (since 0.4.5)
- Charles Pigott (LordAro) - General / Correctness police (since 1.9)
- Michael Lutz (michi_cc) - Path based signals (since 0.7)
- Niels Martin Hansen (nielsm) - Music system, general coding (since 1.9)
- Owen Rudge (orudge) - Forum host, OS/2 port (since 0.1)
- Peter Nelson (peter1138) - Spiritual descendant from newGRF gods (since 0.4.5)
- Ingo von Borstel (planetmaker) - General coding, Support (since 1.1)
- Remko Bijker (Rubidium) - Lead coder and way more (since 0.4.5)
- José Soler (Terkhen) - General coding (since 1.0)
- Leif Linse (Zuu) - AI/Game Script (since 1.2)
### Inactive Developers:
- Jean-François Claeys (Belugas) - GUI, newindustries and more (0.4.5 - 1.0)
- Bjarni Corfitzen (Bjarni) - macOS port, coder and vehicles (0.3 - 0.7)
- Victor Fischer (Celestar) - Programming everywhere you need him to (0.3 - 0.6)
- Jaroslav Mazanec (KUDr) - YAPG (Yet Another Pathfinder God) ;) (0.4.5 - 0.6)
- Jonathan Coome (Maedhros) - High priest of the NewGRF Temple (0.5 - 0.6)
- Attila Bán (MiHaMiX) - WebTranslator 1 and 2 (0.3 - 0.5)
- Zdeněk Sojka (SmatZ) - Bug finder and fixer (0.6 - 1.3)
- Christoph Mallon (Tron) - Programmer, code correctness police (0.3 - 0.5)
- Patric Stout (TrueBrain) - NoProgrammer (0.3 - 1.2), sys op (active)
- Thijs Marinussen (Yexo) - AI Framework, General (0.6 - 1.3)
### Retired Developers:
- Tamás Faragó (Darkvater) - Ex-Lead coder (0.3 - 0.5)
- Dominik Scherer (dominik81) - Lead programmer, GUI expert (0.3 - 0.3)
- Emil Djupfeld (egladil) - macOS port (0.4 - 0.6)
- Simon Sasburg (HackyKid) - Bug fixer (0.4 - 0.4.5)
- Ludvig Strigeus (ludde) - Original author of OpenTTD, main coder (0.1 - 0.3)
- Cian Duffy (MYOB) - BeOS port / manual writing (0.1 - 0.3)
- Petr Baudiš (pasky) - Many patches, newgrf support, etc. (0.3 - 0.3)
- Benedikt Brüggemeier (skidd13) - Bug fixer and code reworker (0.6 - 0.7)
- Serge Paquet (vurlix) - 2nd contributor after ludde (0.1 - 0.3)
### Thanks to:
- Josef Drexler - For his great work on TTDPatch.
- Marcin Grzegorczyk - For his TTDPatch work and documentation of Transport Tycoon Deluxe internals and track foundations
- Stefan Meißner (sign_de) - For his work on the console
- Mike Ragsdale - OpenTTD installer
- Christian Rosentreter (tokai) - MorphOS / AmigaOS port
- Richard Kempton (RichK67) - Additional airports, initial TGP implementation
- Alberto Demichelis - Squirrel scripting language
- L. Peter Deutsch - MD5 implementation
- Michael Blunck - For revolutionizing TTD with awesome graphics
- George - Canal graphics
- Andrew Parkhouse (andythenorth) - River graphics
- David Dallaston (Pikka) - Tram tracks
- All Translators - For their support to make OpenTTD a truly international game
- Bug Reporters - Thanks for all bug reports
- Chris Sawyer - For an amazing game!

195
Doxyfile
View File

@@ -1,20 +1,11 @@
# This file is part of OpenTTD.
# OpenTTD 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, version 2.
# OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "OpenTTD Source"
PROJECT_NUMBER = $(VERSION)
PROJECT_BRIEF =
PROJECT_LOGO =
PROJECT_NAME = openttd
OUTPUT_DIRECTORY = docs/source/
CREATE_SUBDIRS = YES
ALLOW_UNICODE_NAMES = NO
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
@@ -35,42 +26,23 @@ STRIP_FROM_PATH = ./
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 2
ALIASES =
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 0
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = YES
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = YES
EXTRACT_ANON_NSPACES = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
@@ -78,17 +50,11 @@ HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = YES
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = NO
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
@@ -96,69 +62,57 @@ GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_FILES = YES
SHOW_NAMESPACES = YES
SHOW_DIRECTORIES = YES
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ./src/
INPUT_ENCODING = UTF-8
INPUT = ./
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.h \
*.hpp
table/*.h
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */3rdparty \
*/script/api
EXCLUDE_SYMBOLS =
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH = ./docs/
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
@@ -166,58 +120,19 @@ HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_MENUS = YES
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = YES
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = YES
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = YES
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = YES
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = NO
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
@@ -227,18 +142,12 @@ COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
@@ -246,33 +155,27 @@ COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
GENERATE_MAN = YES
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
@@ -282,71 +185,49 @@ PERLMOD_MAKEVAR_PREFIX =
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = WITH_ZLIB \
WITH_LZO \
WITH_LIBLZMA \
WITH_SDL \
WITH_PNG \
WITH_FONTCONFIG \
WITH_FREETYPE \
WITH_ICU_I18N \
WITH_ICU_LX \
UNICODE \
_UNICODE \
_GNU_SOURCE \
FINAL=
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE = objs/openttd.tag
GENERATE_TAGFILE = openttd.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
MSCGEN_PATH =
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_CFG_FILE =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
MAX_DOT_GRAPH_DEPTH = 1000
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::additions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO

1125
Makefile Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,221 +0,0 @@
# This file is part of OpenTTD.
# OpenTTD 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, version 2.
# OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
#
# Creation of bundles
#
# The revision is needed for the bundle name and creating an OSX application bundle.
# Detect the revision
VERSIONS := $(shell AWK="$(AWK)" "$(ROOT_DIR)/findversion.sh")
VERSION := $(shell echo "$(VERSIONS)" | cut -f 1 -d' ')
# Make sure we have something in VERSION
ifeq ($(VERSION),)
VERSION := norev000
endif
ifndef BUNDLE_NAME
BUNDLE_NAME = openttd-custom-$(VERSION)-$(OS)
endif
# An OSX application bundle needs the data files, lang files and openttd executable in a different location.
ifdef OSXAPP
AI_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/ai
GAME_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/game
BASESET_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/baseset
LANG_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/lang
TTD_DIR = $(BUNDLE_DIR)/$(OSXAPP)/Contents/MacOS
else
AI_DIR = $(BUNDLE_DIR)/ai
GAME_DIR = $(BUNDLE_DIR)/game
BASESET_DIR = $(BUNDLE_DIR)/baseset
LANG_DIR = $(BUNDLE_DIR)/lang
TTD_DIR = $(BUNDLE_DIR)
endif
bundle: all
@echo '[BUNDLE] Constructing bundle'
$(Q)rm -rf "$(BUNDLE_DIR)"
$(Q)mkdir -p "$(BUNDLE_DIR)"
$(Q)mkdir -p "$(BUNDLE_DIR)/docs"
$(Q)mkdir -p "$(BUNDLE_DIR)/media"
$(Q)mkdir -p "$(BUNDLE_DIR)/scripts"
$(Q)mkdir -p "$(TTD_DIR)"
$(Q)mkdir -p "$(AI_DIR)"
$(Q)mkdir -p "$(GAME_DIR)"
$(Q)mkdir -p "$(BASESET_DIR)"
$(Q)mkdir -p "$(LANG_DIR)"
ifdef OSXAPP
$(Q)mkdir -p "$(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources"
$(Q)echo "APPL????" > "$(BUNDLE_DIR)/$(OSXAPP)/Contents/PkgInfo"
$(Q)cp "$(ROOT_DIR)/os/macosx/openttd.icns" "$(BUNDLE_DIR)/$(OSXAPP)/Contents/Resources/openttd.icns"
$(Q)$(ROOT_DIR)/os/macosx/plistgen.sh "$(BUNDLE_DIR)/$(OSXAPP)" "$(VERSION)"
$(Q)cp "$(ROOT_DIR)/os/macosx/splash.png" "$(BASESET_DIR)"
endif
ifeq ($(OS),UNIX)
$(Q)cp "$(ROOT_DIR)/media/openttd.32.bmp" "$(BASESET_DIR)/"
endif
$(Q)cp "$(BIN_DIR)/$(TTD)" "$(TTD_DIR)/"
$(Q)cp "$(BIN_DIR)/ai/"compat_*.nut "$(AI_DIR)/"
$(Q)cp "$(BIN_DIR)/game/"compat_*.nut "$(GAME_DIR)/"
$(Q)cp "$(BIN_DIR)/baseset/"*.grf "$(BASESET_DIR)/"
$(Q)cp "$(BIN_DIR)/baseset/"*.obg "$(BASESET_DIR)/"
$(Q)cp "$(BIN_DIR)/baseset/"*.obs "$(BASESET_DIR)/"
$(Q)cp "$(BIN_DIR)/baseset/opntitle.dat" "$(BASESET_DIR)/"
$(Q)cp "$(BIN_DIR)/baseset/"*.obm "$(BASESET_DIR)/"
$(Q)cp "$(BIN_DIR)/lang/"*.lng "$(LANG_DIR)/"
$(Q)cp "$(ROOT_DIR)/README.md" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/COPYING.md" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/known-bugs.txt" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/docs/multiplayer.md" "$(BUNDLE_DIR)/docs/"
$(Q)cp "$(ROOT_DIR)/changelog.txt" "$(BUNDLE_DIR)/"
ifdef MAN_DIR
$(Q)mkdir -p "$(BUNDLE_DIR)/man/"
$(Q)cp "$(ROOT_DIR)/docs/openttd.6" "$(BUNDLE_DIR)/man/"
$(Q)gzip -9 "$(BUNDLE_DIR)/man/openttd.6"
endif
$(Q)cp "$(ROOT_DIR)/media/openttd.32.xpm" "$(BUNDLE_DIR)/media/"
$(Q)cp "$(ROOT_DIR)/media/openttd."*.png "$(BUNDLE_DIR)/media/"
$(Q)cp "$(BIN_DIR)/scripts/"* "$(BUNDLE_DIR)/scripts/"
ifdef MENU_DIR
$(Q)cp "$(ROOT_DIR)/media/openttd.desktop" "$(BUNDLE_DIR)/media/"
$(Q)$(AWK) -f "$(ROOT_DIR)/media/openttd.desktop.translation.awk" "$(SRC_DIR)/lang/"*.txt | LC_ALL=C $(SORT) | $(AWK) -f "$(ROOT_DIR)/media/openttd.desktop.filter.awk" >> "$(BUNDLE_DIR)/media/openttd.desktop"
$(Q)sed s/=openttd/=$(BINARY_NAME)/g "$(BUNDLE_DIR)/media/openttd.desktop" > "$(ROOT_DIR)/media/openttd.desktop.install"
endif
ifeq ($(TTD), openttd.exe)
$(Q)unix2dos "$(BUNDLE_DIR)/docs/"* "$(BUNDLE_DIR)/README.md" "$(BUNDLE_DIR)/COPYING.md" "$(BUNDLE_DIR)/changelog.txt" "$(BUNDLE_DIR)/known-bugs.txt"
endif
### Packing the current bundle into several compressed file formats ###
#
# Zips & dmgs do not contain a root folder, i.e. they have files in the root of the zip/dmg.
# gzip, bzip2 and lha archives have a root folder, with the same name as the bundle.
#
# One can supply a custom name by adding BUNDLE_NAME:=<name> to the make command.
#
bundle_zip: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).zip'
$(Q)mkdir -p "$(BUNDLES_DIR)"
$(Q)cd "$(BUNDLE_DIR)" && zip -r $(shell if test -z "$(VERBOSE)"; then echo '-q'; fi) "$(BUNDLES_DIR)/$(BUNDLE_NAME).zip" .
bundle_7z: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).7z'
$(Q)mkdir -p "$(BUNDLES_DIR)"
$(Q)cd "$(BUNDLE_DIR)" && 7z a "$(BUNDLES_DIR)/$(BUNDLE_NAME).7z" .
bundle_gzip: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.gz'
$(Q)mkdir -p "$(BUNDLES_DIR)/.gzip/$(BUNDLE_NAME)"
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.gzip/$(BUNDLE_NAME)/"
$(Q)cd "$(BUNDLES_DIR)/.gzip" && tar -zc$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.gz" "$(BUNDLE_NAME)"
$(Q)rm -rf "$(BUNDLES_DIR)/.gzip"
bundle_bzip2: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.bz2'
$(Q)mkdir -p "$(BUNDLES_DIR)/.bzip2/$(BUNDLE_NAME)"
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.bzip2/$(BUNDLE_NAME)/"
$(Q)cd "$(BUNDLES_DIR)/.bzip2" && tar -jc$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.bz2" "$(BUNDLE_NAME)"
$(Q)rm -rf "$(BUNDLES_DIR)/.bzip2"
bundle_lzma: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.lzma'
$(Q)mkdir -p "$(BUNDLES_DIR)/.lzma/$(BUNDLE_NAME)"
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.lzma/$(BUNDLE_NAME)/"
$(Q)cd "$(BUNDLES_DIR)/.lzma" && tar --lzma -c$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.lzma" "$(BUNDLE_NAME)"
$(Q)rm -rf "$(BUNDLES_DIR)/.lzma"
bundle_xz: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).tar.xz'
$(Q)mkdir -p "$(BUNDLES_DIR)/.xz/$(BUNDLE_NAME)"
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.xz/$(BUNDLE_NAME)/"
$(Q)cd "$(BUNDLES_DIR)/.xz" && tar --xz -c$(shell if test -n "$(VERBOSE)"; then echo 'v'; fi)f "$(BUNDLES_DIR)/$(BUNDLE_NAME).tar.xz" "$(BUNDLE_NAME)"
$(Q)rm -rf "$(BUNDLES_DIR)/.xz"
bundle_lha: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).lha'
$(Q)mkdir -p "$(BUNDLES_DIR)/.lha/$(BUNDLE_NAME)"
$(Q)cp -R "$(BUNDLE_DIR)/"* "$(BUNDLES_DIR)/.lha/$(BUNDLE_NAME)/"
$(Q)cd "$(BUNDLES_DIR)/.lha" && lha ao6 "$(BUNDLES_DIR)/$(BUNDLE_NAME).lha" "$(BUNDLE_NAME)"
$(Q)rm -rf "$(BUNDLES_DIR)/.lha"
bundle_dmg: bundle
@echo '[BUNDLE] Creating $(BUNDLE_NAME).dmg'
$(Q)mkdir -p "$(BUNDLES_DIR)/OpenTTD $(VERSION)"
$(Q)cp -R "$(BUNDLE_DIR)/" "$(BUNDLES_DIR)/OpenTTD $(VERSION)"
$(Q)hdiutil create -ov -format UDZO -srcfolder "$(BUNDLES_DIR)/OpenTTD $(VERSION)" "$(BUNDLES_DIR)/$(BUNDLE_NAME).dmg"
$(Q)rm -fr "$(BUNDLES_DIR)/OpenTTD $(VERSION)"
bundle_exe: all
@echo '[BUNDLE] Creating $(BUNDLE_NAME).exe'
$(Q)mkdir -p "$(BUNDLES_DIR)"
$(Q)unix2dos "$(ROOT_DIR)/docs/"* "$(ROOT_DIR)/README.md" "$(ROOT_DIR)/COPYING.md" "$(ROOT_DIR)/changelog.txt" "$(ROOT_DIR)/known-bugs.txt"
$(Q)cd $(ROOT_DIR)/os/windows/installer && makensis.exe //DVERSION_INCLUDE=version_$(PLATFORM).txt install.nsi
$(Q)mv $(ROOT_DIR)/os/windows/installer/*$(PLATFORM).exe "$(BUNDLES_DIR)/$(BUNDLE_NAME).exe"
ifdef OSXAPP
install:
@echo '[INSTALL] Cannot install the OSX Application Bundle'
else
install: bundle
@echo '[INSTALL] Installing OpenTTD'
$(Q)install -d "$(INSTALL_BINARY_DIR)"
$(Q)install -d "$(INSTALL_ICON_DIR)"
$(Q)install -d "$(INSTALL_DATA_DIR)/ai"
$(Q)install -d "$(INSTALL_DATA_DIR)/game"
$(Q)install -d "$(INSTALL_DATA_DIR)/baseset"
$(Q)install -d "$(INSTALL_DATA_DIR)/lang"
$(Q)install -d "$(INSTALL_DATA_DIR)/scripts"
ifeq ($(TTD), openttd.exe)
$(Q)install -m 755 "$(BUNDLE_DIR)/$(TTD)" "$(INSTALL_BINARY_DIR)/${BINARY_NAME}.exe"
else
$(Q)install -m 755 "$(BUNDLE_DIR)/$(TTD)" "$(INSTALL_BINARY_DIR)/${BINARY_NAME}"
endif
$(Q)install -m 644 "$(BUNDLE_DIR)/lang/"* "$(INSTALL_DATA_DIR)/lang"
$(Q)install -m 644 "$(BUNDLE_DIR)/ai/"* "$(INSTALL_DATA_DIR)/ai"
$(Q)install -m 644 "$(BUNDLE_DIR)/game/"* "$(INSTALL_DATA_DIR)/game"
$(Q)install -m 644 "$(BUNDLE_DIR)/baseset/"* "$(INSTALL_DATA_DIR)/baseset"
$(Q)install -m 644 "$(BUNDLE_DIR)/scripts/"* "$(INSTALL_DATA_DIR)/scripts"
ifndef DO_NOT_INSTALL_DOCS
$(Q)install -d "$(INSTALL_DOC_DIR)"
$(Q)install -m 644 "$(BUNDLE_DIR)/docs/"* "$(BUNDLE_DIR)/README.md" "$(BUNDLE_DIR)/known-bugs.txt" "$(INSTALL_DOC_DIR)"
endif
ifndef DO_NOT_INSTALL_CHANGELOG
$(Q)install -d "$(INSTALL_DOC_DIR)"
$(Q)install -m 644 "$(BUNDLE_DIR)/changelog.txt" "$(INSTALL_DOC_DIR)"
endif
ifndef DO_NOT_INSTALL_LICENSE
$(Q)install -d "$(INSTALL_DOC_DIR)"
$(Q)install -m 644 "$(BUNDLE_DIR)/COPYING.md" "$(INSTALL_DOC_DIR)"
endif
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.32.xpm" "$(INSTALL_ICON_DIR)/${BINARY_NAME}.32.xpm"
ifdef ICON_THEME_DIR
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/16x16/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.16.png" "$(INSTALL_ICON_THEME_DIR)/16x16/apps/${BINARY_NAME}.png"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/32x32/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.32.png" "$(INSTALL_ICON_THEME_DIR)/32x32/apps/${BINARY_NAME}.png"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/48x48/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.48.png" "$(INSTALL_ICON_THEME_DIR)/48x48/apps/${BINARY_NAME}.png"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/64x64/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.64.png" "$(INSTALL_ICON_THEME_DIR)/64x64/apps/${BINARY_NAME}.png"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/128x128/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.128.png" "$(INSTALL_ICON_THEME_DIR)/128x128/apps/${BINARY_NAME}.png"
$(Q)install -d "$(INSTALL_ICON_THEME_DIR)/256x256/apps"
$(Q)install -m 644 "$(BUNDLE_DIR)/media/openttd.256.png" "$(INSTALL_ICON_THEME_DIR)/256x256/apps/${BINARY_NAME}.png"
else
$(Q)install -m 644 "$(BUNDLE_DIR)/media/"*.png "$(INSTALL_ICON_DIR)"
endif
ifdef MAN_DIR
ifndef DO_NOT_INSTALL_MAN
$(Q)install -d "$(INSTALL_MAN_DIR)"
$(Q)install -m 644 "$(BUNDLE_DIR)/man/openttd.6.gz" "$(INSTALL_MAN_DIR)/${BINARY_NAME}.6.gz"
endif
endif
ifdef MENU_DIR
$(Q)install -d "$(INSTALL_MENU_DIR)"
$(Q)install -m 644 "$(ROOT_DIR)/media/openttd.desktop.install" "$(INSTALL_MENU_DIR)/${BINARY_NAME}.desktop"
endif
endif # OSXAPP

View File

@@ -1,116 +0,0 @@
# This file is part of OpenTTD.
# OpenTTD 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, version 2.
# OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
#
# Building requires GRFCodec.
#
# Recent versions (including sources) can be found at:
# http://www.openttd.org/download-grfcodec
#
# The mercurial repository can be found at:
# http://hg.openttdcoop.org/grfcodec
#
ROOT_DIR = !!ROOT_DIR!!
GRF_DIR = $(ROOT_DIR)/media/extra_grf
BASESET_DIR = $(ROOT_DIR)/media/baseset
LANG_DIR = $(ROOT_DIR)/src/lang
BIN_DIR = !!BIN_DIR!!/baseset
OBJS_DIR = !!GRF_OBJS_DIR!!
OS = !!OS!!
STAGE = !!STAGE!!
# Check if we want to show what we are doing
ifdef VERBOSE
Q =
E = @true
else
Q = @
E = @echo
endif
GRFCODEC := !!GRFCODEC!!
NFORENUM := !!NFORENUM!!
CC_BUILD := !!CC_BUILD!!
MD5SUM := $(shell [ "$(OS)" = "OSX" ] && echo "md5 -r" || echo "md5sum")
# Some "should not be changed" settings.
NFO_FILES := $(GRF_DIR)/*.nfo $(GRF_DIR)/rivers/*.nfo
PNG_FILES := $(GRF_DIR)/*.png $(GRF_DIR)/rivers/*.png
# List of target files.
OBT_FILES := $(BIN_DIR)/orig_dos.obg
OBT_FILES += $(BIN_DIR)/orig_dos_de.obg
OBT_FILES += $(BIN_DIR)/orig_win.obg
OBT_FILES += $(BIN_DIR)/orig_dos.obs
OBT_FILES += $(BIN_DIR)/orig_win.obs
OBT_FILES += $(BIN_DIR)/no_sound.obs
OBT_FILES += $(BIN_DIR)/orig_dos.obm
OBT_FILES += $(BIN_DIR)/orig_win.obm
OBT_FILES += $(BIN_DIR)/no_music.obm
OBT_FILES += $(BIN_DIR)/orig_tto.obm
# Build the GRF.
all: $(OBT_FILES)
ifdef GRFCODEC
all: $(BIN_DIR)/openttd.grf $(BIN_DIR)/orig_extra.grf
endif
$(OBJS_DIR)/langfiles.tmp: $(LANG_DIR)/*.txt
$(E) '$(STAGE) Collecting baseset translations'
$(Q) cat $^ > $@
$(BIN_DIR)/%.obg: $(BASESET_DIR)/%.obg $(BIN_DIR)/orig_extra.grf $(OBJS_DIR)/langfiles.tmp $(BASESET_DIR)/translations.awk
$(E) '$(STAGE) Updating $(notdir $@)'
$(Q) sed 's/^ORIG_EXTRA.GRF = *[0-9a-f]*$$/ORIG_EXTRA.GRF = '`$(MD5SUM) $(BIN_DIR)/orig_extra.grf | sed 's@ .*@@'`'/' $< > $@.tmp
$(Q) awk -v langfiles='$(OBJS_DIR)/langfiles.tmp' -f $(BASESET_DIR)/translations.awk $@.tmp >$@
$(Q) rm $@.tmp
$(BIN_DIR)/%.obs: $(BASESET_DIR)/%.obs $(OBJS_DIR)/langfiles.tmp $(BASESET_DIR)/translations.awk
$(E) '$(STAGE) Updating $(notdir $@)'
$(Q) awk -v langfiles='$(OBJS_DIR)/langfiles.tmp' -f $(BASESET_DIR)/translations.awk $< >$@
$(BIN_DIR)/%.obm: $(BASESET_DIR)/%.obm $(OBJS_DIR)/langfiles.tmp $(BASESET_DIR)/translations.awk
$(E) '$(STAGE) Updating $(notdir $@)'
$(Q) awk -v langfiles='$(OBJS_DIR)/langfiles.tmp' -f $(BASESET_DIR)/translations.awk $< >$@
# Guard against trying to run GRFCODEC/NFORENUM without either being set.
ifdef GRFCODEC
ifdef NFORENUM
# Compile extra grf
$(BIN_DIR)/openttd.grf: $(PNG_FILES) $(NFO_FILES) $(GRF_DIR)/assemble_nfo.awk
$(E) '$(STAGE) Assembling openttd.nfo'
$(Q)-mkdir -p $(OBJS_DIR)/sprites
$(Q)-cp $(PNG_FILES) $(OBJS_DIR)/sprites 2> /dev/null
$(Q) awk -f $(GRF_DIR)/assemble_nfo.awk $(GRF_DIR)/openttd.nfo > $(OBJS_DIR)/sprites/openttd.nfo
$(Q) $(NFORENUM) -s $(OBJS_DIR)/sprites/openttd.nfo
$(E) '$(STAGE) Compiling openttd.grf'
$(Q) $(GRFCODEC) -n -s -e -p1 $(OBJS_DIR)/openttd.grf
$(Q)cp $(OBJS_DIR)/openttd.grf $(BIN_DIR)/openttd.grf
# The copy operation of PNG_FILES is duplicated from the target 'openttd.grf', thus those targets may not run in parallel.
$(BIN_DIR)/orig_extra.grf: $(PNG_FILES) $(NFO_FILES) $(GRF_DIR)/assemble_nfo.awk | $(BIN_DIR)/openttd.grf
$(E) '$(STAGE) Assembling orig_extra.nfo'
$(Q)-mkdir -p $(OBJS_DIR)/sprites
$(Q)-cp $(PNG_FILES) $(OBJS_DIR)/sprites 2> /dev/null
$(Q) awk -f $(GRF_DIR)/assemble_nfo.awk $(GRF_DIR)/orig_extra.nfo > $(OBJS_DIR)/sprites/orig_extra.nfo
$(Q) $(NFORENUM) -s $(OBJS_DIR)/sprites/orig_extra.nfo
$(E) '$(STAGE) Compiling orig_extra.grf'
$(Q) $(GRFCODEC) -n -s -e -p1 $(OBJS_DIR)/orig_extra.grf
$(Q)cp $(OBJS_DIR)/orig_extra.grf $(BIN_DIR)/orig_extra.grf
endif
endif
# Clean up temporary files.
clean:
$(Q)rm -f *.bak *.grf $(OBT_FILES)
# Clean up temporary files
mrproper: clean
$(Q)rm -fr sprites
.PHONY: all mrproper depend clean

View File

@@ -1,185 +0,0 @@
# This file is part of OpenTTD.
# OpenTTD 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, version 2.
# OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
# Check if we want to show what we are doing
ifdef VERBOSE
Q =
else
Q = @
endif
include Makefile.am
CONFIG_CACHE_PWD = !!CONFIG_CACHE_PWD!!
CONFIG_CACHE_SOURCE_LIST = !!CONFIG_CACHE_SOURCE_LIST!!
BIN_DIR = !!BIN_DIR!!
ICON_THEME_DIR = !!ICON_THEME_DIR!!
MAN_DIR = !!MAN_DIR!!
MENU_DIR = !!MENU_DIR!!
SRC_DIR = !!SRC_DIR!!
ROOT_DIR = !!ROOT_DIR!!
BUNDLE_DIR = "$(ROOT_DIR)/bundle"
BUNDLES_DIR = "$(ROOT_DIR)/bundles"
INSTALL_DIR = !!INSTALL_DIR!!
INSTALL_BINARY_DIR = "$(INSTALL_DIR)/"!!BINARY_DIR!!
INSTALL_MAN_DIR = "$(INSTALL_DIR)/$(MAN_DIR)"
INSTALL_MENU_DIR = "$(INSTALL_DIR)/$(MENU_DIR)"
INSTALL_ICON_DIR = "$(INSTALL_DIR)/"!!ICON_DIR!!
INSTALL_ICON_THEME_DIR = "$(INSTALL_DIR)/$(ICON_THEME_DIR)"
INSTALL_DATA_DIR = "$(INSTALL_DIR)/"!!DATA_DIR!!
INSTALL_DOC_DIR = "$(INSTALL_DIR)/"!!DOC_DIR!!
SOURCE_LIST = !!SOURCE_LIST!!
CONFIGURE_FILES = !!CONFIGURE_FILES!!
BINARY_NAME = !!BINARY_NAME!!
STRIP = !!STRIP!!
TTD = !!TTD!!
TTDS = $(SRC_DIRS:%=%/$(TTD))
OS = !!OS!!
OSXAPP = !!OSXAPP!!
LIPO = !!LIPO!!
AWK = !!AWK!!
SORT = !!SORT!!
DISTCC = !!DISTCC!!
RES := $(shell if [ ! -f $(CONFIG_CACHE_PWD) ] || [ "`pwd`" != "`cat $(CONFIG_CACHE_PWD)`" ]; then echo "`pwd`" > $(CONFIG_CACHE_PWD); fi )
RES := $(shell if [ ! -f $(CONFIG_CACHE_SOURCE_LIST) ] || [ -n "`cmp $(CONFIG_CACHE_SOURCE_LIST) $(SOURCE_LIST) 2>/dev/null`" ]; then cp $(SOURCE_LIST) $(CONFIG_CACHE_SOURCE_LIST); fi )
all: config.pwd config.cache
ifdef DISTCC
@if [ -z "`echo '$(MFLAGS)' | grep '\-j'`" ]; then echo; echo "WARNING: you enabled distcc support, but you don't seem to be using the -jN parameter"; echo; fi
endif
@for dir in $(DIRS); do \
$(MAKE) -C $$dir all || exit 1; \
done
ifdef LIPO
# Lipo is an OSX thing. If it is defined, it means we are building for universal,
# and so we have have to combine the binaries into one big binary
# Remove the last binary made by the last compiled target
$(Q)rm -f $(BIN_DIR)/$(TTD)
# Make all the binaries into one
$(Q)$(LIPO) -create -output $(BIN_DIR)/$(TTD) $(TTDS)
endif
help:
@echo "Available make commands:"
@echo ""
@echo "Compilation:"
@echo " all compile the executable and the lang files"
@echo " lang compile the lang files only"
@echo "Clean up:"
@echo " clean remove the files generated during compilation"
@echo " mrproper remove the files generated during configuration and compilation"
@echo "Run after compilation:"
@echo " run execute openttd after the compilation"
@echo " run-gdb execute openttd in debug mode after the compilation"
@echo " run-prof execute openttd in profiling mode after the compilation"
@echo "Installation:"
@echo " install install the compiled files and the data-files after the compilation"
@echo " bundle create the base for an installation bundle"
@echo " bundle_zip create the zip installation bundle"
@echo " bundle_gzip create the gzip installation bundle"
@echo " bundle_bzip2 create the bzip2 installation bundle"
@echo " bundle_lha create the lha installation bundle"
@echo " bundle_dmg create the dmg installation bundle"
config.pwd: $(CONFIG_CACHE_PWD)
$(MAKE) reconfigure
config.cache: $(CONFIG_CACHE_SOURCE_LIST) $(CONFIGURE_FILES)
$(MAKE) reconfigure
reconfigure:
ifeq ($(shell if test -f config.cache; then echo 1; fi), 1)
@echo "----------------"
@echo "The system detected that source.list or any configure file is altered."
@echo " Going to reconfigure with last known settings..."
@echo "----------------"
# Make sure we don't lock config.cache
@$(shell cat config.cache | sed 's@\\ @\\\\ @g') || exit 1
@echo "----------------"
@echo "Reconfig done. Please re-execute make."
@echo "----------------"
else
@echo "----------------"
@echo "Have not found a configuration, please run configure first."
@echo "----------------"
@exit 1
endif
clean:
@for dir in $(DIRS); do \
$(MAKE) -C $$dir clean; \
done
$(Q)rm -rf $(BUNDLE_TARGET)
lang:
@for dir in $(LANG_DIRS); do \
$(MAKE) -C $$dir all; \
done
mrproper:
@for dir in $(DIRS); do \
$(MAKE) -C $$dir mrproper; \
done
# Don't be tempted to merge these two for loops. Doing that breaks make
# --dry-run, since make has this "feature" that it always runs commands
# containing $(MAKE), even when --dry-run is passed. The objective is of
# course to also get a dry-run of submakes, but make is not smart enough
# to see that a for loop runs both a submake and an actual command.
@for dir in $(DIRS); do \
rm -f $$dir/Makefile; \
done
$(Q)rm -rf objs
$(Q)rm -f Makefile Makefile.am Makefile.bundle
$(Q)rm -f media/openttd.desktop media/openttd.desktop.install
$(Q)rm -f $(CONFIG_CACHE_SOURCE_LIST) config.cache config.pwd config.log $(CONFIG_CACHE_PWD)
# directories for bundle generation
$(Q)rm -rf $(BUNDLE_DIR)
$(Q)rm -rf $(BUNDLES_DIR)
# output of profiling
$(Q)rm -f $(BIN_DIR)/gmon.out
# output of generating 'API' documentation
$(Q)rm -rf $(ROOT_DIR)/docs/source
$(Q)rm -rf $(ROOT_DIR)/docs/aidocs
$(Q)rm -rf $(ROOT_DIR)/docs/gamedocs
# directories created by OpenTTD on regression testing
$(Q)rm -rf $(BIN_DIR)/ai/regression/content_download $(BIN_DIR)/ai/regression/save $(BIN_DIR)/ai/regression/scenario
distclean: mrproper
maintainer-clean: distclean
$(Q)rm -f $(BIN_DIR)/baseset/openttd.grf $(BIN_DIR)/baseset/orig_extra.grf $(BIN_DIR)/baseset/*.obg $(BIN_DIR)/baseset/*.obs $(BIN_DIR)/baseset/*.obm
depend:
@for dir in $(SRC_DIRS); do \
$(MAKE) -C $$dir depend; \
done
run: all
$(Q)cd !!BIN_DIR!! && ./!!TTD!! $(OPENTTD_ARGS)
run-gdb: all
$(Q)cd !!BIN_DIR!! && gdb --ex run --args ./!!TTD!! $(OPENTTD_ARGS)
run-prof: all
$(Q)cd !!BIN_DIR!! && ./!!TTD!! $(OPENTTD_ARGS) && gprof !!TTD!! | less
regression: all
$(Q)cd !!BIN_DIR!! && sh ai/regression/run.sh
test: regression
%.o:
@for dir in $(SRC_DIRS); do \
$(MAKE) -C $$dir $(@:src/%=%); \
done
%.lng:
@for dir in $(LANG_DIRS); do \
$(MAKE) -C $$dir $@; \
done
.PHONY: test distclean mrproper clean
include Makefile.bundle

View File

@@ -1,87 +0,0 @@
# This file is part of OpenTTD.
# OpenTTD 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, version 2.
# OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
STRGEN = !!STRGEN!!
SRC_DIR = !!SRC_DIR!!
LANG_DIR = !!LANG_DIR!!
BIN_DIR = !!BIN_DIR!!
LANGS_SRC = $(shell ls $(LANG_DIR)/*.txt)
LANGS = $(LANGS_SRC:$(LANG_DIR)/%.txt=%.lng)
CXX_BUILD = !!CXX_BUILD!!
CFLAGS_BUILD = !!CFLAGS_BUILD!!
CXXFLAGS_BUILD= !!CXXFLAGS_BUILD!!
LDFLAGS_BUILD = !!LDFLAGS_BUILD!!
STRGEN_FLAGS = !!STRGEN_FLAGS!!
STAGE = !!STAGE!!
LANG_SUPPRESS = !!LANG_SUPPRESS!!
LANG_OBJS_DIR = !!LANG_OBJS_DIR!!
ifeq ($(LANG_SUPPRESS), yes)
LANG_ERRORS = >/dev/null 2>&1
endif
# Check if we want to show what we are doing
ifdef VERBOSE
Q =
E = @true
else
Q = @
E = @echo
endif
RES := $(shell mkdir -p $(BIN_DIR)/lang )
all: table/strings.h $(LANGS)
strgen_base.o: $(SRC_DIR)/strgen/strgen_base.cpp $(SRC_DIR)/strgen/strgen.h $(SRC_DIR)/table/control_codes.h $(SRC_DIR)/table/strgen_tables.h $(SRC_DIR)/safeguards.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
strgen.o: $(SRC_DIR)/strgen/strgen.cpp $(SRC_DIR)/strgen/strgen.h $(SRC_DIR)/table/control_codes.h $(SRC_DIR)/table/strgen_tables.h $(SRC_DIR)/safeguards.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
string.o: $(SRC_DIR)/string.cpp $(SRC_DIR)/safeguards.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp $(SRC_DIR)/safeguards.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
getoptdata.o: $(SRC_DIR)/misc/getoptdata.cpp $(SRC_DIR)/misc/getoptdata.h $(SRC_DIR)/safeguards.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/misc/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
lang/english.txt: $(LANG_DIR)/english.txt
$(Q)mkdir -p lang
$(Q)cp $(LANG_DIR)/english.txt lang/english.txt
$(STRGEN): alloc_func.o string.o strgen_base.o strgen.o getoptdata.o
$(E) '$(STAGE) Compiling and Linking $@'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $^ -o $@
table/strings.h: lang/english.txt $(STRGEN)
$(E) '$(STAGE) Generating $@'
@mkdir -p table
$(Q)./$(STRGEN) -s $(LANG_DIR) -d table
$(LANGS): %.lng: $(LANG_DIR)/%.txt $(STRGEN) lang/english.txt
$(E) '$(STAGE) Compiling language $(*F)'
$(Q)./$(STRGEN) $(STRGEN_FLAGS) -s $(LANG_DIR) -d $(LANG_OBJS_DIR) $< $(LANG_ERRORS) && cp $@ $(BIN_DIR)/lang || true # Do not fail all languages when one fails
depend:
clean:
$(E) '$(STAGE) Cleaning up language files'
$(Q)rm -f strgen_base.o strgen.o string.o alloc_func.o getoptdata.o table/strings.h $(STRGEN) $(LANGS) $(LANGS:%=$(BIN_DIR)/lang/%) lang/english.*
mrproper: clean
$(Q)rm -rf $(BIN_DIR)/lang
%.lng:
@echo '$(STAGE) No such language: $(@:%.lng=%)'
.PHONY: all mrproper depend clean

View File

@@ -1,45 +0,0 @@
# This file is part of OpenTTD.
# OpenTTD 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, version 2.
# OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
#
# Makefile for creating bundles of MSVC's binaries in the same way as we make
# the zip bundles for ALL other OSes.
#
# Usage: make -f Makefile.msvc PLATFORM=[Win32|x64] BUNDLE_NAME=openttd-<version>-win[32|64]
# or make -f Makefile.msvc PLATFORM=[Win32|x64] BUNDLE_NAME=OTTD-win[32|64]-nightly-<revision>
#
# Check if we want to show what we are doing
ifdef VERBOSE
Q =
else
Q = @
endif
AWK = "awk"
ROOT_DIR := $(shell pwd)
BIN_DIR = "$(ROOT_DIR)/bin"
SRC_DIR = "$(ROOT_DIR)/src"
BUNDLE_DIR = "$(ROOT_DIR)/bundle"
BUNDLES_DIR = "$(ROOT_DIR)/bundles"
TTD = openttd.exe
PDB = openttd.pdb
MODE = Release
TARGET := $(shell echo $(PLATFORM) | sed "s@win64@x64@;s@win32@Win32@")
all:
$(Q)cp objs/$(TARGET)/$(MODE)/$(TTD) $(BIN_DIR)/$(TTD)
include Makefile.bundle.in
bundle_pdb:
@echo '[BUNDLE] Creating $(BUNDLE_NAME).pdb.xz'
$(Q)mkdir -p "$(BUNDLES_DIR)"
$(Q)cp objs/$(TARGET)/Release/$(PDB) $(BUNDLES_DIR)/$(BUNDLE_NAME).pdb
$(Q)xz -9 $(BUNDLES_DIR)/$(BUNDLE_NAME).pdb
regression: all
$(Q)cp bin/$(TTD) bin/openttd
$(Q)cd bin && sh ai/regression/run.sh

View File

@@ -1,63 +0,0 @@
# This file is part of OpenTTD.
# OpenTTD 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, version 2.
# OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
SETTINGSGEN = !!SETTINGSGEN!!
SRC_DIR = !!SRC_DIR!!
CXX_BUILD = !!CXX_BUILD!!
CFLAGS_BUILD = !!CFLAGS_BUILD!!
CXXFLAGS_BUILD = !!CXXFLAGS_BUILD!!
LDFLAGS_BUILD = !!LDFLAGS_BUILD!!
STAGE = !!STAGE!!
SETTING_OBJS_DIR = !!SETTING_OBJS_DIR!!
# Check if we want to show what we are doing
ifdef VERBOSE
Q =
E = @true
else
Q = @
E = @echo
endif
all: table/settings.h
settingsgen.o: $(SRC_DIR)/settingsgen/settingsgen.cpp $(SRC_DIR)/string_func.h $(SRC_DIR)/strings_type.h $(SRC_DIR)/misc/getoptdata.h $(SRC_DIR)/ini_type.h $(SRC_DIR)/core/smallvec_type.hpp $(SRC_DIR)/safeguards.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
alloc_func.o: $(SRC_DIR)/core/alloc_func.cpp $(SRC_DIR)/safeguards.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
getoptdata.o: $(SRC_DIR)/misc/getoptdata.cpp $(SRC_DIR)/misc/getoptdata.h $(SRC_DIR)/safeguards.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/misc/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
string.o: $(SRC_DIR)/string.cpp $(SRC_DIR)/safeguards.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
ini_load.o: $(SRC_DIR)/ini_load.cpp $(SRC_DIR)/core/alloc_func.hpp $(SRC_DIR)/core/mem_func.hpp $(SRC_DIR)/ini_type.h $(SRC_DIR)/string_func.h $(SRC_DIR)/safeguards.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
$(SETTINGSGEN): alloc_func.o string.o ini_load.o settingsgen.o getoptdata.o
$(E) '$(STAGE) Compiling and Linking $@'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $^ -o $@
table/settings.h: $(SETTINGSGEN) $(SRC_DIR)/table/settings.h.preamble $(SRC_DIR)/table/settings.h.postamble $(SRC_DIR)/table/*.ini
$(E) '$(STAGE) Generating $@'
@mkdir -p table
$(Q)./$(SETTINGSGEN) -o table/settings.h -b $(SRC_DIR)/table/settings.h.preamble -a $(SRC_DIR)/table/settings.h.postamble $(SRC_DIR)/table/*.ini
depend:
clean:
$(E) '$(STAGE) Cleaning up settings files'
$(Q)rm -f settingsgen.o alloc_func.o getoptdata.o string.o ini_load.o $(SETTINGSGEN) table/settings.h
mrproper: clean
.PHONY: all mrproper depend clean

View File

@@ -1,294 +0,0 @@
# This file is part of OpenTTD.
# OpenTTD 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, version 2.
# OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
CC_HOST = !!CC_HOST!!
CXX_HOST = !!CXX_HOST!!
CC_BUILD = !!CC_BUILD!!
CXX_BUILD = !!CXX_BUILD!!
WINDRES = !!WINDRES!!
STRIP = !!STRIP!!
CFLAGS = !!CFLAGS!!
CFLAGS_BUILD = !!CFLAGS_BUILD!!
CXXFLAGS = !!CXXFLAGS!!
CXXFLAGS_BUILD = !!CXXFLAGS_BUILD!!
LIBS = !!LIBS!!
LDFLAGS = !!LDFLAGS!!
LDFLAGS_BUILD = !!LDFLAGS_BUILD!!
ROOT_DIR = !!ROOT_DIR!!
BIN_DIR = !!BIN_DIR!!
LANG_DIR = !!LANG_DIR!!
SRC_OBJS_DIR = !!SRC_OBJS_DIR!!
LANG_OBJS_DIR = !!LANG_OBJS_DIR!!
SETTING_OBJS_DIR= !!SETTING_OBJS_DIR!!
SRC_DIR = !!SRC_DIR!!
SCRIPT_SRC_DIR = !!SCRIPT_SRC_DIR!!
MEDIA_DIR = !!MEDIA_DIR!!
TTD = !!TTD!!
STRGEN = !!STRGEN!!
DEPEND = !!DEPEND!!
OS = !!OS!!
STAGE = !!STAGE!!
MAKEDEPEND = !!MAKEDEPEND!!
CFLAGS_MAKEDEP = !!CFLAGS_MAKEDEP!!
SORT = !!SORT!!
AWK = !!AWK!!
CONFIG_CACHE_COMPILER = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_COMPILER!!
CONFIG_CACHE_LINKER = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_LINKER!!
CONFIG_CACHE_SOURCE = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_SOURCE!!
CONFIG_CACHE_VERSION = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_VERSION!!
OBJS_C := !!OBJS_C!!
OBJS_CPP := !!OBJS_CPP!!
OBJS_MM := !!OBJS_MM!!
OBJS_RC := !!OBJS_RC!!
OBJS := $(OBJS_C) $(OBJS_CPP) $(OBJS_MM) $(OBJS_RC)
SRCS := !!SRCS!!
# All C-files depend on those 3 files
FILE_DEP := $(CONFIG_CACHE_COMPILER)
# Create all dirs and subdirs
RES := $(shell mkdir -p $(BIN_DIR) $(sort $(dir $(OBJS))))
CFLAGS += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR) -I $(SETTING_OBJS_DIR)
CFLAGS_MAKEDEP += -I $(SRC_OBJS_DIR) -I $(LANG_OBJS_DIR) -I $(SETTING_OBJS_DIR)
ifdef SCRIPT_SRC_DIR
CFLAGS_MAKEDEP += -I $(SCRIPT_SRC_DIR)
endif
# Check if we want to show what we are doing
ifdef VERBOSE
Q =
E = @true
else
Q = @
E = @echo
endif
# Our default target
all: $(BIN_DIR)/$(TTD)
# This are 2 rules that are pointing back to STRGEN stuff.
# There is not really a need to have them here, but in case
# some weirdo wants to run 'make' in the 'src' dir and expects
# the languages to be recompiled, this catches that case and
# takes care of it nicely.
$(LANG_OBJS_DIR)/$(STRGEN):
$(MAKE) -C $(LANG_OBJS_DIR) $(STRGEN)
$(LANG_OBJS_DIR)/table/strings.h: $(LANG_DIR)/english.txt $(LANG_OBJS_DIR)/$(STRGEN)
$(MAKE) -C $(LANG_OBJS_DIR) table/strings.h
# Always run version detection, so we always have an accurate modified
# flag
VERSIONS := $(shell AWK="$(AWK)" "$(ROOT_DIR)/findversion.sh")
MODIFIED := $(shell echo "$(VERSIONS)" | cut -f 3 -d' ')
# Use autodetected revisions
VERSION := $(shell echo "$(VERSIONS)" | cut -f 1 -d' ')
ISODATE := $(shell echo "$(VERSIONS)" | cut -f 2 -d' ')
GITHASH := $(shell echo "$(VERSIONS)" | cut -f 4 -d' ')
ISTAG := $(shell echo "$(VERSIONS)" | cut -f 5 -d' ')
ISSTABLETAG := $(shell echo "$(VERSIONS)" | cut -f 6 -d' ')
# Make sure we have something in VERSION and ISODATE
ifeq ($(VERSION),)
VERSION := norev000
endif
ifeq ($(ISODATE),)
ISODATE := 00000000
endif
# This helps to recompile if flags change
RES := $(shell if [ "`cat $(CONFIG_CACHE_COMPILER) 2>/dev/null`" != "$(CFLAGS) $(CXXFLAGS)" ]; then echo "$(CFLAGS) $(CXXFLAGS)" > $(CONFIG_CACHE_COMPILER); fi )
RES := $(shell if [ "`cat $(CONFIG_CACHE_LINKER) 2>/dev/null`" != "$(LDFLAGS) $(LIBS)" ]; then echo "$(LDFLAGS) $(LIBS)" > $(CONFIG_CACHE_LINKER); fi )
# If there is a change in the source-file-list, make sure we recheck the deps
RES := $(shell if [ "`cat $(CONFIG_CACHE_SOURCE) 2>/dev/null`" != "$(SRCS)" ]; then echo "$(SRCS)" > $(CONFIG_CACHE_SOURCE); fi )
# If there is a change in the revision, make sure we recompile rev.cpp
RES := $(shell if [ "`cat $(CONFIG_CACHE_VERSION) 2>/dev/null`" != "$(VERSION) $(MODIFIED)" ]; then echo "$(VERSION) $(MODIFIED)" > $(CONFIG_CACHE_VERSION); fi )
ifndef MAKEDEPEND
# The slow, but always correct, dep-check
DEP_MASK := %.d
DEPS := $(OBJS:%.o=%.d)
# Only include the deps if we are compiling everything
ifeq ($(filter %.o clean mrproper, $(MAKECMDGOALS)),)
-include $(DEPS)
else
# In case we want to compile a single target, include the .d file for it
ifneq ($(filter %.o, $(MAKECMDGOALS)),)
SINGLE_DEP := $(filter %.o, $(MAKECMDGOALS))
-include $(SINGLE_DEP:%.o=%.d)
endif
endif
# Find the deps via GCC. Rarely wrong, but a bit slow
$(OBJS_C:%.o=%.d): %.d: $(SRC_DIR)/%.c $(FILE_DEP)
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.c=%.c)'
$(Q)$(CC_HOST) $(CFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
$(OBJS_CPP:%.o=%.d): %.d: $(SRC_DIR)/%.cpp $(FILE_DEP)
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
$(OBJS_MM:%.o=%.d): %.d: $(SRC_DIR)/%.mm $(FILE_DEP)
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.mm=%.mm)'
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
$(OBJS_RC:%.o=%.d): %.d: $(SRC_DIR)/%.rc $(FILE_DEP)
$(E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.rc=%.rc)'
$(Q)touch $@
else
# The much faster, but can be wrong, dep-check
DEP_MASK :=
DEPS := Makefile.dep
# Only include the deps if we are not cleaning
ifeq ($(filter depend clean mrproper, $(MAKECMDGOALS)),)
-include Makefile.dep
endif
ifeq ("$(SRC_OBJS_DIR)/$(DEPEND)","$(MAKEDEPEND)")
DEP := $(MAKEDEPEND)
$(SRC_OBJS_DIR)/$(DEPEND): $(SRC_DIR)/depend/depend.cpp
$(E) '$(STAGE) Compiling and linking $(DEPEND)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) -o $@ $<
endif
# Macro for invoking a command on groups of 100 words at a time
# (analogous to xargs(1)). The macro invokes itself recursively
# until the list of words is depleted.
#
# Usage: $(call xargs,COMMAND,LIST)
#
# COMMAND should be a shell command to which the words will be
# appended as arguments in groups of 100.
define xargs
$(1) $(wordlist 1,100,$(2))
$(if $(word 101,$(2)),$(call xargs,$(1),$(wordlist 101,$(words $(2)),$(2))))
endef
# Make sure that only 'make depend' ALWAYS triggers a recheck
ifeq ($(filter depend, $(MAKECMDGOALS)),)
Makefile.dep: $(FILE_DEP) $(SRCS:%=$(SRC_DIR)/%) $(CONFIG_CACHE_SOURCE) $(DEP)
else
Makefile.dep: $(FILE_DEP) $(SRCS:%=$(SRC_DIR)/%) $(DEP) FORCE
endif
$(E) '$(STAGE) DEP CHECK (all files)'
$(Q)rm -f Makefile.dep.tmp
$(Q)touch Makefile.dep.tmp
# Calculate the deps via makedepend
$(call xargs,$(Q)$(MAKEDEPEND) -f$(SRC_OBJS_DIR)/Makefile.dep.tmp -o.o -Y -v -a -- $(CFLAGS_MAKEDEP) -- 2>/dev/null,$(SRCS:%=$(SRC_DIR)/%))
# Remove all comments and includes that don't start with $(SRC_DIR)
# Remove $(SRC_DIR) from object-file-name
@$(AWK) ' \
/^# DO NOT/ { print $$0 ; next} \
/^#/ {next} \
/: / { \
left = NF - 1; \
for (n = 2; n <= NF; n++) { \
if (match($$n, "^$(ROOT_DIR)") == 0) { \
$$n = ""; \
left--; \
} \
} \
gsub("$(SRC_DIR)/", "", $$1); \
if (left > 0) { \
print $$0; \
$$1 = "Makefile.dep:"; \
print $$0; \
} \
next \
} \
{ \
print $$0 \
} \
' < Makefile.dep.tmp | sed 's@ *@ @g;s@ $$@@' | LC_ALL=C $(SORT) > Makefile.dep
$(Q)rm -f Makefile.dep.tmp Makefile.dep.tmp.bak
endif
# Avoid problems with deps if a .h/.hpp/.hpp.sq file is deleted without the deps
# being updated. Now the Makefile continues, the deps are recreated
# and all will be fine.
%.h %.hpp %.hpp.sq:
@true
# Compile all the files according to the targets
$(OBJS_C): %.o: $(SRC_DIR)/%.c $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.c=%.c)'
$(Q)$(CC_HOST) $(CFLAGS) -c -o $@ $<
$(filter-out %sse2.o, $(filter-out %ssse3.o, $(filter-out %sse4.o, $(OBJS_CPP)))): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -c -o $@ $<
$(filter %sse2.o, $(OBJS_CPP)): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -c -msse2 -o $@ $<
$(filter %ssse3.o, $(OBJS_CPP)): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -c -mssse3 -o $@ $<
$(filter %sse4.o, $(OBJS_CPP)): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -c -msse4.1 -o $@ $<
$(OBJS_MM): %.o: $(SRC_DIR)/%.mm $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.mm=%.mm)'
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -c -o $@ $<
$(OBJS_RC): %.o: $(SRC_DIR)/%.rc $(FILE_DEP)
$(E) '$(STAGE) Compiling resource $(<:$(SRC_DIR)/%.rc=%.rc)'
$(Q)$(WINDRES) -o $@ $<
$(BIN_DIR)/$(TTD): $(TTD)
$(Q)cp $(TTD) $(BIN_DIR)/$(TTD)
ifeq ($(OS), UNIX)
$(Q)cp $(MEDIA_DIR)/openttd.32.bmp $(BIN_DIR)/baseset/
endif
ifeq ($(OS), OSX)
$(Q)cp $(ROOT_DIR)/os/macosx/splash.png $(BIN_DIR)/baseset/
endif
$(TTD): $(OBJS) $(CONFIG_CACHE_LINKER)
$(E) '$(STAGE) Linking $@'
$(Q)+$(CXX_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
ifdef STRIP
$(Q)$(STRIP) $@
endif
# Revision files
$(SRC_DIR)/rev.cpp: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/rev.cpp.in
$(Q)cat $(SRC_DIR)/rev.cpp.in | sed "s@\!\!ISODATE\!\!@$(ISODATE)@g;s@!!VERSION!!@$(VERSION)@g;s@!!MODIFIED!!@$(MODIFIED)@g;s@!!DATE!!@`date +%d.%m.%y`@g;s@!!GITHASH!!@$(GITHASH)@g;s@!!ISTAG!!@$(ISTAG)@g;s@!!ISSTABLETAG!!@$(ISSTABLETAG)@g" > $(SRC_DIR)/rev.cpp
$(SRC_DIR)/os/windows/ottdres.rc: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/os/windows/ottdres.rc.in
$(Q)cat $(SRC_DIR)/os/windows/ottdres.rc.in | sed "s@\!\!ISODATE\!\!@$(ISODATE)@g;s@!!VERSION!!@$(VERSION)@g;s@!!DATE!!@`date +%d.%m.%y`@g;s@!!GITHASH!!@$(GITHASH)@g;s@!!ISTAG!!@$(ISTAG)@g;s@!!ISSTABLETAG!!@$(ISSTABLETAG)@g" > $(SRC_DIR)/os/windows/ottdres.rc
FORCE:
depend: $(DEPS)
clean:
$(E) '$(STAGE) Cleaning up object files'
$(Q)rm -f $(DEPS) $(OBJS) $(TTD) $(DEPEND) $(TTD:%=$(BIN_DIR)/%) $(BIN_DIR)/baseset/openttd.32.bmp $(CONFIG_CACHE_COMPILER) $(CONFIG_CACHE_LINKER) $(CONFIG_CACHE_SOURCE)
mrproper: clean
$(Q)rm -f $(SRC_DIR)/rev.cpp $(SRC_DIR)/os/windows/ottdres.rc
%.o:
@echo '$(STAGE) No such source-file: $(@:%.o=%).[c|cpp|mm|rc]'
.PHONY: all mrproper depend clean FORCE

213
README.md
View File

@@ -1,213 +0,0 @@
# OpenTTD
## Table of contents
- 1.0) [About](#10-about)
- 1.1) [Downloading OpenTTD](#11-downloading-openttd)
- 1.2) [OpenTTD gameplay manual](#12-openttd-gameplay-manual)
- 1.3) [Supported platforms](#13-supported-platforms)
- 1.4) [Installing and running OpenTTD](#14-installing-and-running-openttd)
- 1.5) [Add-on content / mods](#15-add-on-content--mods)
- 1.6) [OpenTTD directories](#16-openttd-directories)
- 1.7) [Compiling OpenTTD](#17-compiling-openttd)
- 2.0) [Contact and community](#20-contact-and-community)
- 2.1) [Contributing to OpenTTD](#21-contributing-to-openttd)
- 2.2) [Reporting bugs](#22-reporting-bugs)
- 2.3) [Translating](#23-translating)
- 3.0) [Licensing](#30-licensing)
- 4.0) [Credits](#40-credits)
## 1.0) About
OpenTTD is a transport simulation game based upon the popular game Transport Tycoon Deluxe, written by Chris Sawyer.
It attempts to mimic the original game as closely as possible while extending it with new features.
OpenTTD is licensed under the GNU General Public License version 2.0, but includes some 3rd party software under different licenses.
See the section ["Licensing"](#30-licensing) below for details.
## 1.1) Downloading OpenTTD
OpenTTD can be downloaded from the [official OpenTTD website](https://www.openttd.org/).
Both 'stable' and 'nightly' versions are available for download:
- most people should choose the 'stable' version, as this has been more extensively tested
- the 'nightly' version includes the latest changes and features, but may sometimes be less reliable
On some platforms OpenTTD will also be available via your OS package manager or a similar service.
## 1.2) OpenTTD gameplay manual
OpenTTD has a [community-maintained wiki](https://wiki.openttd.org/), including a gameplay manual and tips.
## 1.3) Supported platforms
OpenTTD has been ported to several platforms and operating systems.
The currently working platforms are:
- FreeBSD (SDL)
- Haiku (SDL)
- Linux (SDL)
- macOS (universal) (Cocoa video and sound drivers)
- OpenBSD (SDL)
- OS/2 (SDL)
- Windows (Win32 GDI (faster) or SDL)
### 1.3.1) Legacy support
Platforms, languages and compilers change.
We'll keep support going on old platforms as long as someone is interested in supporting them, except where it means the project can't move forward to keep up with language and compiler features.
We guarantee that every revision of OpenTTD will be able to load savegames from every older revision (excepting where the savegame is corrupt).
Please report a bug if you find a save that doesn't load.
## 1.4) Installing and running OpenTTD
OpenTTD is usually straightforward to install, but for more help the wiki [includes an installation guide](https://wiki.openttd.org/Installation).
OpenTTD needs some additional graphics and sound files to run.
For some platforms these will be downloaded during the installation process if required.
For some platforms, you will need to refer to [the installation guide](https://wiki.openttd.org/Installation).
### 1.4.1) Free graphics and sound files
The free data files, split into OpenGFX for graphics, OpenSFX for sounds and
OpenMSX for music can be found at:
- https://www.openttd.org/download-opengfx for OpenGFX
- https://www.openttd.org/download-opensfx for OpenSFX
- https://www.openttd.org/download-openmsx for OpenMSX
Please follow the readme of these packages about the installation procedure.
The Windows installer can optionally download and install these packages.
### 1.4.2) Original Transport Tycoon Deluxe graphics and sound files
If you want to play with the original Transport Tycoon Deluxe data files you have to copy the data files from the CD-ROM into the baseset/ directory.
It does not matter whether you copy them from the DOS or Windows version of Transport Tycoon Deluxe.
The Windows install can optionally copy these files.
You need to copy the following files:
- sample.cat
- trg1r.grf or TRG1.GRF
- trgcr.grf or TRGC.GRF
- trghr.grf or TRGH.GRF
- trgir.grf or TRGI.GRF
- trgtr.grf or TRGT.GRF
### 1.4.3) Original Transport Tycoon Deluxe music
If you want the Transport Tycoon Deluxe music, copy the appropriate files from the original game into the baseset folder.
- TTD for Windows: All files in the gm/ folder (gm_tt00.gm up to gm_tt21.gm)
- TTD for DOS: The GM.CAT file
- Transport Tycoon Original: The GM.CAT file, but rename it to GM-TTO.CAT
## 1.5) Add-on content / mods
OpenTTD features multiple types of add-on content, which modify gameplay in different ways.
Most types of add-on content can be downloaded within OpenTTD via the 'Check Online Content' button in the main menu.
Add-on content can also be installed manually, but that's more complicated; the [OpenTTD wiki](https://wiki.openttd.org/OpenTTD) may offer help with that, or the [OpenTTD directory structure guide](./docs/directory_structure.md).
### 1.5.1) AI opponents
OpenTTD comes without AI opponents, so if you want to play with AIs you have to download them.
The easiest way is via the 'Check Online Content' button in the main menu.
You can select some AIs that you think are compatible with your playing style.
AI help and discussions may also be found in the [AI section of the forum](https://www.tt-forums.net/viewforum.php?f=65).
### 1.5.2) Scenarios and height maps
Scenarios and heightmaps can be added via the 'Check Online Content' button in the main menu.
### 1.5.3) NewGRFs
A wide range of add-content is available as NewGRFs, including vehicles, industries, stations, landscape objects, town names and more.
NewGRFs can be added via the 'Check Online Content' button in the main menu.
See also the wiki [guide to NewGRFs](https://wiki.openttd.org/NewGRF) and [the forum graphics development section](https://www.tt-forums.net/viewforum.php?f=66).
### 1.5.4) Game scripts
Game scripts can provide additional challenges or changes to the standard OpenTTD gameplay, for example setting transport goals, or changing town growth behaviour.
Game scripts can be added via the 'Check Online Content' button in the main menu.
See also the wiki [guide to game scripts](https://wiki.openttd.org/Game_script) and [the forum graphics game script section](https://www.tt-forums.net/viewforum.php?f=65).
### 1.6) OpenTTD directories
OpenTTD uses its own directory structure to store game data, add-on content etc.
For more information, see the [directory structure guide](./docs/directory_structure.md).
### 1.7) Compiling OpenTTD
If you want to compile OpenTTD from source, instructions can be found in [COMPILING.md](./COMPILING.md).
## 2.0) Contact and Community
'Official' channels
- [OpenTTD website](https://www.openttd.org)
- IRC chat using #openttd on irc.oftc.net [more info about our irc channel](https://wiki.openttd.org/Irc)
- [OpenTTD on Github](https://github.com/openTTD/) for code repositories and for reporting issues
- [forum.openttd.org](https://forum.openttd.org/) - the primary community forum site for discussing OpenTTD and related games
- [OpenTTD wiki](https://wiki.openttd.org/) community-maintained wiki, including topics like gameplay guide, detailed explanation of some game mechanics, how to use add-on content (mods) and much more
'Unofficial' channels
- the OpenTTD wiki has a [page listing OpenTTD communities](https://wiki.openttd.org/Community) including some in languages other than English
### 2.1) Contributing to OpenTTD
We welcome contributors to OpenTTD. More information for contributors can be found in [CONTRIBUTING.md](./CONTRIBUTING.md)
### 2.2) Reporting bugs
Good bug reports are very helpful. We have a [guide to reporting bugs](./CONTRIBUTING.md#bug-reports) to help with this.
Desyncs in multiplayer are complex to debug and report (some software development skils are required).
Instructions can be found in [debugging and reporting desyncs](./docs/debugging_desyncs.md).
### 2.3) Translating
OpenTTD is translated into many languages. Translations are added and updated via the [online translation tool](https://translator.openttd.org).
## 3.0) Licensing
OpenTTD is licensed under the GNU General Public License version 2.0.
For the complete license text, see the file '[COPYING.md](./COPYING.md)'.
This license applies to all files in this distribution, except as noted below.
The squirrel implementation in `src/3rdparty/squirrel` is licensed under the Zlib license.
See `src/3rdparty/squirrel/COPYRIGHT` for the complete license text.
The md5 implementation in `src/3rdparty/md5` is licensed under the Zlib license.
See the comments in the source files in `src/3rdparty/md5` for the complete license text.
The implementations of Posix `getaddrinfo` and `getnameinfo` for OS/2 in `src/3rdparty/os2` are distributed partly under the GNU Lesser General Public License 2.1, and partly under the (3-clause) BSD license.
The exact licensing terms can be found in `src/3rdparty/os2/getaddrinfo.c` resp. `src/3rdparty/os2/getnameinfo.c`.
## 4.0 Credits
See [CREDITS.md](./CREDITS.md)

247
ai/ai.c Normal file
View File

@@ -0,0 +1,247 @@
/* $Id$ */
#include "../stdafx.h"
#include "../openttd.h"
#include "../variables.h"
#include "../command.h"
#include "../network.h"
#include "ai.h"
#include "default/default.h"
/**
* Dequeues commands put in the queue via AI_PutCommandInQueue.
*/
static void AI_DequeueCommands(PlayerID player)
{
AICommand *com, *entry_com;
entry_com = _ai_player[player].queue;
/* It happens that DoCommandP issues a new DoCommandAI which adds a new command
* to this very same queue (don't argue about this, if it currently doesn't
* happen I can tell you it will happen with AIScript -- TrueLight). If we
* do not make the queue NULL, that commands will be dequeued immediatly.
* Therefor we safe the entry-point to entry_com, and make the queue NULL, so
* the new queue can be safely built up. */
_ai_player[player].queue = NULL;
_ai_player[player].queue_tail = NULL;
/* Dequeue all commands */
while ((com = entry_com) != NULL) {
_current_player = player;
_cmd_text = com->text;
DoCommandP(com->tile, com->p1, com->p2, com->callback, com->procc);
/* Free item */
entry_com = com->next;
free(com->text);
free(com);
}
}
/**
* Needed for SP; we need to delay DoCommand with 1 tick, because else events
* will make infinite loops (AIScript).
*/
static void AI_PutCommandInQueue(PlayerID player, TileIndex tile, uint32 p1, uint32 p2, uint procc, CommandCallback* callback)
{
AICommand *com;
if (_ai_player[player].queue_tail == NULL) {
/* There is no item in the queue yet, create the queue */
_ai_player[player].queue = malloc(sizeof(AICommand));
_ai_player[player].queue_tail = _ai_player[player].queue;
} else {
/* Add an item at the end */
_ai_player[player].queue_tail->next = malloc(sizeof(AICommand));
_ai_player[player].queue_tail = _ai_player[player].queue_tail->next;
}
/* This is our new item */
com = _ai_player[player].queue_tail;
/* Assign the info */
com->tile = tile;
com->p1 = p1;
com->p2 = p2;
com->procc = procc;
com->callback = callback;
com->next = NULL;
com->text = NULL;
/* Copy the cmd_text, if needed */
if (_cmd_text != NULL) {
com->text = strdup(_cmd_text);
_cmd_text = NULL;
}
}
/**
* Executes a raw DoCommand for the AI.
*/
int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback)
{
PlayerID old_lp;
int32 res = 0;
const char* tmp_cmdtext;
/* If you enable DC_EXEC with DC_QUERY_COST you are a really strange
* person.. should we check for those funny jokes?
*/
/* The test already resets _cmd_text, so backup the pointer */
tmp_cmdtext = _cmd_text;
/* First, do a test-run to see if we can do this */
res = DoCommand(tile, p1, p2, flags & ~DC_EXEC, procc);
/* The command failed, or you didn't want to execute, or you are quering, return */
if (CmdFailed(res) || !(flags & DC_EXEC) || (flags & DC_QUERY_COST)) {
return res;
}
/* Restore _cmd_text */
_cmd_text = tmp_cmdtext;
/* If we did a DC_EXEC, and the command did not return an error, execute it
* over the network */
if (flags & DC_AUTO) procc |= CMD_AUTO;
if (flags & DC_NO_WATER) procc |= CMD_NO_WATER;
/* NetworkSend_Command needs _local_player to be set correctly, so
* adjust it, and put it back right after the function */
old_lp = _local_player;
_local_player = _current_player;
#ifdef ENABLE_NETWORK
/* Send the command */
if (_networking) {
/* Network is easy, send it to his handler */
NetworkSend_Command(tile, p1, p2, procc, callback);
} else {
#else
{
#endif
/* If we execute BuildCommands directly in SP, we have a big problem with events
* so we need to delay is for 1 tick */
AI_PutCommandInQueue(_current_player, tile, p1, p2, procc, callback);
}
/* Set _local_player back */
_local_player = old_lp;
return res;
}
int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
{
return AI_DoCommandCc(tile, p1, p2, flags, procc, NULL);
}
/**
* Run 1 tick of the AI. Don't overdo it, keep it realistic.
*/
static void AI_RunTick(PlayerID player)
{
extern void AiNewDoGameLoop(Player *p);
Player *p = GetPlayer(player);
_current_player = player;
if (_patches.ainew_active) {
AiNewDoGameLoop(p);
} else {
/* Enable all kind of cheats the old AI needs in order to operate correctly... */
_is_old_ai_player = true;
AiDoGameLoop(p);
_is_old_ai_player = false;
}
}
/**
* The gameloop for AIs.
* Handles one tick for all the AIs.
*/
void AI_RunGameLoop(void)
{
/* Don't do anything if ai is disabled */
if (!_ai.enabled) return;
/* Don't do anything if we are a network-client, or the AI has been disabled */
if (_networking && (!_network_server || !_patches.ai_in_multiplayer)) return;
/* New tick */
_ai.tick++;
/* Make sure the AI follows the difficulty rule.. */
assert(_opt.diff.competitor_speed <= 4);
if ((_ai.tick & ((1 << (4 - _opt.diff.competitor_speed)) - 1)) != 0) return;
/* Check for AI-client (so joining a network with an AI) */
if (!_networking || _network_server) {
/* Check if we want to run AIs (server or SP only) */
const Player* p;
FOR_ALL_PLAYERS(p) {
if (p->is_active && p->is_ai) {
/* This should always be true, else something went wrong... */
assert(_ai_player[p->index].active);
/* Run the script */
AI_DequeueCommands(p->index);
AI_RunTick(p->index);
}
}
}
_current_player = OWNER_NONE;
}
/**
* A new AI sees the day of light. You can do here what ever you think is needed.
*/
void AI_StartNewAI(PlayerID player)
{
assert(IsValidPlayer(player));
/* Called if a new AI is booted */
_ai_player[player].active = true;
}
/**
* This AI player died. Give it some chance to make a final puf.
*/
void AI_PlayerDied(PlayerID player)
{
/* Called if this AI died */
_ai_player[player].active = false;
}
/**
* Initialize some AI-related stuff.
*/
void AI_Initialize(void)
{
/* First, make sure all AIs are DEAD! */
AI_Uninitialize();
memset(&_ai, 0, sizeof(_ai));
memset(&_ai_player, 0, sizeof(_ai_player));
_ai.enabled = true;
}
/**
* Deinitializer for AI-related stuff.
*/
void AI_Uninitialize(void)
{
const Player* p;
FOR_ALL_PLAYERS(p) {
if (p->is_active && p->is_ai) AI_PlayerDied(p->index);
}
}

111
ai/ai.h Normal file
View File

@@ -0,0 +1,111 @@
#ifndef AI_H
#define AI_H
#include "../functions.h"
#include "../network.h"
#include "../player.h"
#include "../command.h"
/* How DoCommands look like for an AI */
typedef struct AICommand {
uint32 tile;
uint32 p1;
uint32 p2;
uint32 procc;
CommandCallback* callback;
char *text;
uint uid;
struct AICommand *next;
} AICommand;
/* The struct for an AIScript Player */
typedef struct AIPlayer {
bool active; ///< Is this AI active?
AICommand *queue; ///< The commands that he has in his queue
AICommand *queue_tail; ///< The tail of this queue
} AIPlayer;
/* The struct to keep some data about the AI in general */
typedef struct AIStruct {
/* General */
bool enabled; ///< Is AI enabled?
uint tick; ///< The current tick (something like _frame_counter, only for AIs)
} AIStruct;
VARDEF AIStruct _ai;
VARDEF AIPlayer _ai_player[MAX_PLAYERS];
// ai.c
void AI_StartNewAI(PlayerID player);
void AI_PlayerDied(PlayerID player);
void AI_RunGameLoop(void);
void AI_Initialize(void);
void AI_Uninitialize(void);
int32 AI_DoCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
int32 AI_DoCommandCc(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc, CommandCallback* callback);
/** Is it allowed to start a new AI.
* This function checks some boundries to see if we should launch a new AI.
* @return True if we can start a new AI.
*/
static inline bool AI_AllowNewAI(void)
{
/* If disabled, no AI */
if (!_ai.enabled)
return false;
/* If in network, but no server, no AI */
if (_networking && !_network_server)
return false;
/* If in network, and server, possible AI */
if (_networking && _network_server) {
/* Do we want AIs in multiplayer? */
if (!_patches.ai_in_multiplayer)
return false;
/* Only the NewAI is allowed... sadly enough the old AI just doesn't support this
* system, because all commands are delayed by at least 1 tick, which causes
* a big problem, because it uses variables that are only set AFTER the command
* is really executed... */
if (!_patches.ainew_active)
return false;
}
return true;
}
#define AI_CHANCE16(a,b) ((uint16) AI_Random() <= (uint16)((65536 * a) / b))
#define AI_CHANCE16R(a,b,r) ((uint16)(r = AI_Random()) <= (uint16)((65536 * a) / b))
/**
* The random-function that should be used by ALL AIs.
*/
static inline uint AI_RandomRange(uint max)
{
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
* but we pick InteractiveRandomRange if we are a network_server or network-client.
*/
if (_networking)
return InteractiveRandomRange(max);
else
return RandomRange(max);
}
/**
* The random-function that should be used by ALL AIs.
*/
static inline uint32 AI_Random(void)
{
/* We pick RandomRange if we are in SP (so when saved, we do the same over and over)
* but we pick InteractiveRandomRange if we are a network_server or network-client.
*/
if (_networking)
return InteractiveRandom();
else
return Random();
}
#endif /* AI_H */

3941
ai/default/default.c Normal file

File diff suppressed because it is too large Load Diff

8
ai/default/default.h Normal file
View File

@@ -0,0 +1,8 @@
/* $Id$ */
#ifndef DEFAULT_H
#define DEFAULT_H
void AiDoGameLoop(Player*);
#endif

324
ai/trolly/build.c Normal file
View File

@@ -0,0 +1,324 @@
/* $Id$ */
#include "../../stdafx.h"
#include "../../openttd.h"
#include "../../debug.h"
#include "../../functions.h"
#include "../../map.h"
#include "../../road_map.h"
#include "../../tile.h"
#include "../../vehicle.h"
#include "../../command.h"
#include "trolly.h"
#include "../../engine.h"
#include "../../station.h"
#include "../../variables.h"
#include "../../bridge.h"
#include "../ai.h"
// Build HQ
// Params:
// tile : tile where HQ is going to be build
bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile)
{
if (CmdFailed(AI_DoCommand(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ)))
return false;
AI_DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ);
return true;
}
// Build station
// Params:
// type : AI_TRAIN/AI_BUS/AI_TRUCK : indicates the type of station
// tile : tile where station is going to be build
// length : in case of AI_TRAIN: length of station
// numtracks : in case of AI_TRAIN: tracks of station
// direction : the direction of the station
// flag : flag passed to DoCommand (normally 0 to get the cost or DC_EXEC to build it)
int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag)
{
if (type == AI_TRAIN)
return AI_DoCommand(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
if (type == AI_BUS)
return AI_DoCommand(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
return AI_DoCommand(tile, direction, RS_TRUCK, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
}
// Builds a brdige. The second best out of the ones available for this player
// Params:
// tile_a : starting point
// tile_b : end point
// flag : flag passed to DoCommand
int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag)
{
int bridge_type, bridge_len, type, type2;
// Find a good bridgetype (the best money can buy)
bridge_len = GetBridgeLength(tile_a, tile_b);
type = type2 = 0;
for (bridge_type = MAX_BRIDGES-1; bridge_type >= 0; bridge_type--) {
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
type2 = type;
type = bridge_type;
// We found two bridges, exit
if (type2 != 0) break;
}
}
// There is only one bridge that can be built
if (type2 == 0 && type != 0) type2 = type;
// Now, simply, build the bridge!
if (p->ainew.tbt == AI_TRAIN) {
return AI_DoCommand(tile_a, tile_b, (0x00 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
} else {
return AI_DoCommand(tile_a, tile_b, (0x80 << 8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
}
}
// Build the route part by part
// Basicly what this function do, is build that amount of parts of the route
// that go in the same direction. It sets 'part' to the last part of the route builded.
// The return value is the cost for the builded parts
//
// Params:
// PathFinderInfo : Pointer to the PathFinderInfo used for AiPathFinder
// part : Which part we need to build
//
// TODO: skip already builded road-pieces (e.g.: cityroad)
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag)
{
int part = PathFinderInfo->position;
byte *route_extra = PathFinderInfo->route_extra;
TileIndex *route = PathFinderInfo->route;
int dir;
int old_dir = -1;
int cost = 0;
int res;
// We need to calculate the direction with the parent of the parent.. so we skip
// the first pieces and the last piece
if (part < 1) part = 1;
// When we are done, stop it
if (part >= PathFinderInfo->route_length - 1) {
PathFinderInfo->position = -2;
return 0;
}
if (PathFinderInfo->rail_or_road) {
// Tunnel code
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
cost += AI_DoCommand(route[part], 0, 0, flag, CMD_BUILD_TUNNEL);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be built!");
return 0;
}
return cost;
}
// Bridge code
if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
cost += AiNew_Build_Bridge(p, route[part], route[part-1], flag);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be built!");
return 0;
}
return cost;
}
// Build normal rail
// Keep it doing till we go an other way
if (route_extra[part - 1] == 0 && route_extra[part] == 0) {
while (route_extra[part] == 0) {
// Get the current direction
dir = AiNew_GetRailDirection(route[part-1], route[part], route[part+1]);
// Is it the same as the last one?
if (old_dir != -1 && old_dir != dir) break;
old_dir = dir;
// Build the tile
res = AI_DoCommand(route[part], 0, dir, flag, CMD_BUILD_SINGLE_RAIL);
if (CmdFailed(res)) {
// Problem.. let's just abort it all!
p->ainew.state = AI_STATE_NOTHING;
return 0;
}
cost += res;
// Go to the next tile
part++;
// Check if it is still in range..
if (part >= PathFinderInfo->route_length - 1) break;
}
part--;
}
// We want to return the last position, so we go back one
PathFinderInfo->position = part;
} else {
// Tunnel code
if ((AI_PATHFINDER_FLAG_TUNNEL & route_extra[part]) != 0) {
cost += AI_DoCommand(route[part], 0x200, 0, flag, CMD_BUILD_TUNNEL);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: tunnel could not be built!");
return 0;
}
return cost;
}
// Bridge code
if ((AI_PATHFINDER_FLAG_BRIDGE & route_extra[part]) != 0) {
cost += AiNew_Build_Bridge(p, route[part], route[part+1], flag);
PathFinderInfo->position++;
// TODO: problems!
if (CmdFailed(cost)) {
DEBUG(ai,0)("[AiNew - BuildPath] We have a serious problem: bridge could not be built!");
return 0;
}
return cost;
}
// Build normal road
// Keep it doing till we go an other way
// EnsureNoVehicle makes sure we don't build on a tile where a vehicle is. This way
// it will wait till the vehicle is gone..
if (route_extra[part-1] == 0 && route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
while (route_extra[part] == 0 && (flag != DC_EXEC || EnsureNoVehicle(route[part]))) {
// Get the current direction
dir = AiNew_GetRoadDirection(route[part-1], route[part], route[part+1]);
// Is it the same as the last one?
if (old_dir != -1 && old_dir != dir) break;
old_dir = dir;
// There is already some road, and it is a bridge.. don't build!!!
if (!IsTileType(route[part], MP_TUNNELBRIDGE)) {
// Build the tile
res = AI_DoCommand(route[part], dir, 0, flag | DC_NO_WATER, CMD_BUILD_ROAD);
// Currently, we ignore CMD_ERRORs!
if (CmdFailed(res) && flag == DC_EXEC && !IsTileType(route[part], MP_STREET) && !EnsureNoVehicle(route[part])) {
// Problem.. let's just abort it all!
DEBUG(ai,0)("Darn, the route could not be built.. aborting!");
p->ainew.state = AI_STATE_NOTHING;
return 0;
}
if (!CmdFailed(res)) cost += res;
}
// Go to the next tile
part++;
// Check if it is still in range..
if (part >= PathFinderInfo->route_length - 1) break;
}
part--;
// We want to return the last position, so we go back one
}
if (!EnsureNoVehicle(route[part]) && flag == DC_EXEC) part--;
PathFinderInfo->position = part;
}
return cost;
}
// This functions tries to find the best vehicle for this type of cargo
// It returns INVALID_ENGINE if not suitable engine is found
EngineID AiNew_PickVehicle(Player *p)
{
if (p->ainew.tbt == AI_TRAIN) {
// Not supported yet
return INVALID_ENGINE;
} else {
EngineID best_veh_index = INVALID_ENGINE;
int32 best_veh_rating = 0;
EngineID start = ROAD_ENGINES_INDEX;
EngineID end = ROAD_ENGINES_INDEX + NUM_ROAD_ENGINES;
EngineID i;
/* Loop through all road vehicles */
for (i = start; i != end; i++) {
const RoadVehicleInfo *rvi = RoadVehInfo(i);
const Engine* e = GetEngine(i);
int32 rating;
int32 ret;
/* Skip vehicles which can't take our cargo type */
if (rvi->cargo_type != p->ainew.cargo && !CanRefitTo(i, p->ainew.cargo)) continue;
// Is it availiable?
// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
if (!HASBIT(e->player_avail, _current_player) || e->reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
/* Rate and compare the engine by speed & capacity */
rating = rvi->max_speed * rvi->capacity;
if (rating <= best_veh_rating) continue;
// Can we build it?
ret = AI_DoCommand(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
if (CmdFailed(ret)) continue;
best_veh_rating = rating;
best_veh_index = i;
}
return best_veh_index;
}
}
void CcAI(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
Player* p = GetPlayer(_current_player);
if (success) {
p->ainew.state = AI_STATE_GIVE_ORDERS;
p->ainew.veh_id = _new_vehicle_id;
if (GetVehicle(p->ainew.veh_id)->cargo_type != p->ainew.cargo) {
/* Cargo type doesn't match, so refit it */
if (CmdFailed(DoCommand(tile, p->ainew.veh_id, p->ainew.cargo, DC_EXEC, CMD_REFIT_ROAD_VEH))) {
/* Refit failed, so sell the vehicle */
DoCommand(tile, p->ainew.veh_id, 0, DC_EXEC, CMD_SELL_ROAD_VEH);
p->ainew.state = AI_STATE_NOTHING;
}
}
} else {
/* XXX this should be handled more gracefully */
p->ainew.state = AI_STATE_NOTHING;
}
}
// Builds the best vehicle possible
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag)
{
EngineID i = AiNew_PickVehicle(p);
if (i == INVALID_ENGINE) return CMD_ERROR;
if (p->ainew.tbt == AI_TRAIN) return CMD_ERROR;
if (flag & DC_EXEC) {
return AI_DoCommandCc(tile, i, 0, flag, CMD_BUILD_ROAD_VEH, CcAI);
} else {
return AI_DoCommand(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
}
}
int AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag)
{
int ret, ret2;
if (p->ainew.tbt == AI_TRAIN) {
return AI_DoCommand(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
} else {
ret = AI_DoCommand(tile, direction, 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_DEPOT);
if (CmdFailed(ret)) return ret;
// Try to build the road from the depot
ret2 = AI_DoCommand(tile + TileOffsByDiagDir(direction), DiagDirToRoadBits(ReverseDiagDir(direction)), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
// If it fails, ignore it..
if (CmdFailed(ret2)) return ret;
return ret + ret2;
}
}

510
ai/trolly/pathfinder.c Normal file
View File

@@ -0,0 +1,510 @@
/* $Id$ */
#include "../../stdafx.h"
#include "../../openttd.h"
#include "../../bridge_map.h"
#include "../../debug.h"
#include "../../functions.h"
#include "../../map.h"
#include "../../tile.h"
#include "../../command.h"
#include "trolly.h"
#include "../../depot.h"
#include "../../tunnel_map.h"
#include "../../bridge.h"
#include "../ai.h"
#define TEST_STATION_NO_DIR 0xFF
// Tests if a station can be build on the given spot
// TODO: make it train compatible
static bool TestCanBuildStationHere(TileIndex tile, byte dir)
{
Player *p = GetPlayer(_current_player);
if (dir == TEST_STATION_NO_DIR) {
int32 ret;
// TODO: currently we only allow spots that can be access from al 4 directions...
// should be fixed!!!
for (dir = 0; dir < 4; dir++) {
ret = AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST);
if (!CmdFailed(ret)) return true;
}
return false;
}
// return true if command succeeded, so the inverse of CmdFailed()
return !CmdFailed(AiNew_Build_Station(p, p->ainew.tbt, tile, 1, 1, dir, DC_QUERY_COST));
}
static bool IsRoad(TileIndex tile)
{
return
// MP_STREET, but not a road depot?
(IsTileType(tile, MP_STREET) && !IsTileDepotType(tile, TRANSPORT_ROAD)) ||
(IsTileType(tile, MP_TUNNELBRIDGE) && (
(IsTunnel(tile) && GetTunnelTransportType(tile) == TRANSPORT_ROAD) ||
(IsBridge(tile) && GetBridgeTransportType(tile) == TRANSPORT_ROAD)
));
}
// Checks if a tile 'a' is between the tiles 'b' and 'c'
#define TILES_BETWEEN(a, b, c) (TileX(a) >= TileX(b) && TileX(a) <= TileX(c) && TileY(a) >= TileY(b) && TileY(a) <= TileY(c))
// Check if the current tile is in our end-area
static int32 AyStar_AiPathFinder_EndNodeCheck(AyStar *aystar, OpenListNode *current)
{
const Ai_PathFinderInfo* PathFinderInfo = aystar->user_target;
// It is not allowed to have a station on the end of a bridge or tunnel ;)
if (current->path.node.user_data[0] != 0) return AYSTAR_DONE;
if (TILES_BETWEEN(current->path.node.tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br))
if (IsTileType(current->path.node.tile, MP_CLEAR) || IsTileType(current->path.node.tile, MP_TREES))
if (current->path.parent == NULL || TestCanBuildStationHere(current->path.node.tile, AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile)))
return AYSTAR_FOUND_END_NODE;
return AYSTAR_DONE;
}
// Calculates the hash
// Currently it is a 10 bit hash, so the hash array has a max depth of 6 bits (so 64)
static uint AiPathFinder_Hash(uint key1, uint key2)
{
return (TileX(key1) & 0x1F) + ((TileY(key1) & 0x1F) << 5);
}
// Clear the memory of all the things
static void AyStar_AiPathFinder_Free(AyStar *aystar)
{
AyStarMain_Free(aystar);
free(aystar);
}
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current);
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current);
// This creates the AiPathFinder
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo)
{
PathNode start_node;
uint x;
uint y;
// Create AyStar
AyStar *result = malloc(sizeof(AyStar));
init_AyStar(result, AiPathFinder_Hash, 1 << 10);
// Set the function pointers
result->CalculateG = AyStar_AiPathFinder_CalculateG;
result->CalculateH = AyStar_AiPathFinder_CalculateH;
result->EndNodeCheck = AyStar_AiPathFinder_EndNodeCheck;
result->FoundEndNode = AyStar_AiPathFinder_FoundEndNode;
result->GetNeighbours = AyStar_AiPathFinder_GetNeighbours;
result->free = AyStar_AiPathFinder_Free;
// Set some information
result->loops_per_tick = AI_PATHFINDER_LOOPS_PER_TICK;
result->max_path_cost = 0;
result->max_search_nodes = AI_PATHFINDER_MAX_SEARCH_NODES;
// Set the user_data to the PathFinderInfo
result->user_target = PathFinderInfo;
// Set the start node
start_node.parent = NULL;
start_node.node.direction = 0;
start_node.node.user_data[0] = 0;
// Now we add all the starting tiles
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
start_node.node.tile = TileXY(x, y);
result->addstart(result, &start_node.node, 0);
}
}
return result;
}
// To reuse AyStar we sometimes have to clean all the memory
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo)
{
PathNode start_node;
uint x;
uint y;
aystar->clear(aystar);
// Set the user_data to the PathFinderInfo
aystar->user_target = PathFinderInfo;
// Set the start node
start_node.parent = NULL;
start_node.node.direction = 0;
start_node.node.user_data[0] = 0;
start_node.node.tile = PathFinderInfo->start_tile_tl;
// Now we add all the starting tiles
for (x = TileX(PathFinderInfo->start_tile_tl); x <= TileX(PathFinderInfo->start_tile_br); x++) {
for (y = TileY(PathFinderInfo->start_tile_tl); y <= TileY(PathFinderInfo->start_tile_br); y++) {
TileIndex tile = TileXY(x, y);
if (!IsTileType(tile, MP_CLEAR) && !IsTileType(tile, MP_TREES)) continue;
if (!TestCanBuildStationHere(tile, TEST_STATION_NO_DIR)) continue;
start_node.node.tile = tile;
aystar->addstart(aystar, &start_node.node, 0);
}
}
}
// The h-value, simple calculation
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
{
const Ai_PathFinderInfo* PathFinderInfo = aystar->user_target;
int r, r2;
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION) {
// The station is pointing to a direction, add a tile towards that direction, so the H-value is more accurate
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl + TileOffsByDiagDir(PathFinderInfo->end_direction));
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDiagDir(PathFinderInfo->end_direction));
} else {
// No direction, so just get the fastest route to the station
r = DistanceManhattan(current->tile, PathFinderInfo->end_tile_tl);
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br);
}
// See if the bottomright is faster than the topleft..
if (r2 < r) r = r2;
return r * AI_PATHFINDER_H_MULTIPLER;
}
// We found the end.. let's get the route back and put it in an array
static void AyStar_AiPathFinder_FoundEndNode(AyStar *aystar, OpenListNode *current)
{
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
uint i = 0;
PathNode *parent = &current->path;
do {
PathFinderInfo->route_extra[i] = parent->node.user_data[0];
PathFinderInfo->route[i++] = parent->node.tile;
if (i > lengthof(PathFinderInfo->route)) {
// We ran out of space for the PathFinder
DEBUG(ai, 0)("[AiPathFinder] Ran out of space in the route[] array!!!");
PathFinderInfo->route_length = -1; // -1 indicates out of space
return;
}
parent = parent->parent;
} while (parent != NULL);
PathFinderInfo->route_length = i;
DEBUG(ai, 1)("[Ai-PathFinding] Found route of %d nodes long in %d nodes of searching", i, Hash_Size(&aystar->ClosedListHash));
}
// What tiles are around us.
static void AyStar_AiPathFinder_GetNeighbours(AyStar *aystar, OpenListNode *current)
{
uint i;
int ret;
int dir;
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
aystar->num_neighbours = 0;
// Go through all surrounding tiles and check if they are within the limits
for (i = 0; i < 4; i++) {
TileIndex ctile = current->path.node.tile; // Current tile
TileIndex atile = ctile + TileOffsByDiagDir(i); // Adjacent tile
if (TileX(atile) > 1 && TileX(atile) < MapMaxX() - 1 &&
TileY(atile) > 1 && TileY(atile) < MapMaxY() - 1) {
// We also directly test if the current tile can connect to this tile..
// We do this simply by just building the tile!
// If the next step is a bridge, we have to enter it the right way
if (!PathFinderInfo->rail_or_road && IsRoad(atile)) {
if (IsTileType(atile, MP_TUNNELBRIDGE)) {
if (IsTunnel(atile)) {
if (GetTunnelDirection(atile) != i) continue;
} else {
if ((_m[atile].m5 & 1U) != DiagDirToAxis(i)) continue;
}
}
}
// But also if we are on a bridge, we can only move a certain direction
if (!PathFinderInfo->rail_or_road && IsRoad(ctile)) {
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
// An existing bridge/tunnel... let's test the direction ;)
if ((_m[ctile].m5 & 1U) != (i & 1)) continue;
}
}
if ((AI_PATHFINDER_FLAG_BRIDGE & current->path.node.user_data[0]) != 0 ||
(AI_PATHFINDER_FLAG_TUNNEL & current->path.node.user_data[0]) != 0) {
// We are a bridge/tunnel, how cool!!
// This means we can only point forward.. get the direction from the user_data
if (i != (current->path.node.user_data[0] >> 8)) continue;
}
dir = 0;
// First, check if we have a parent
if (current->path.parent == NULL && current->path.node.user_data[0] == 0) {
// If not, this means we are at the starting station
if (PathFinderInfo->start_direction != AI_PATHFINDER_NO_DIRECTION) {
// We do need a direction?
if (AiNew_GetDirection(ctile, atile) != PathFinderInfo->start_direction) {
// We are not pointing the right way, invalid tile
continue;
}
}
} else if (current->path.node.user_data[0] == 0) {
if (PathFinderInfo->rail_or_road) {
// Rail check
dir = AiNew_GetRailDirection(current->path.parent->node.tile, ctile, atile);
ret = AI_DoCommand(ctile, 0, dir, DC_AUTO | DC_NO_WATER, CMD_BUILD_SINGLE_RAIL);
if (CmdFailed(ret)) continue;
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
if (current->path.parent->parent != NULL) {
// Check if we don't make a 90degree curve
int dir1 = AiNew_GetRailDirection(current->path.parent->parent->node.tile, current->path.parent->node.tile, ctile);
if (_illegal_curves[dir1] == dir || _illegal_curves[dir] == dir1) {
continue;
}
}
#endif
} else {
// Road check
dir = AiNew_GetRoadDirection(current->path.parent->node.tile, ctile, atile);
if (IsRoad(ctile)) {
if (IsTileType(ctile, MP_TUNNELBRIDGE)) {
// We have a bridge, how nicely! We should mark it...
dir = 0;
} else {
// It already has road.. check if we miss any bits!
if ((_m[ctile].m5 & dir) != dir) {
// We do miss some pieces :(
dir &= ~_m[ctile].m5;
} else {
dir = 0;
}
}
}
// Only destruct things if it is MP_CLEAR of MP_TREES
if (dir != 0) {
ret = AI_DoCommand(ctile, dir, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
if (CmdFailed(ret)) continue;
}
}
}
// The tile can be connected
aystar->neighbours[aystar->num_neighbours].tile = atile;
aystar->neighbours[aystar->num_neighbours].user_data[0] = 0;
aystar->neighbours[aystar->num_neighbours++].direction = 0;
}
}
// Next step, check for bridges and tunnels
if (current->path.parent != NULL && current->path.node.user_data[0] == 0) {
// First we get the dir from this tile and his parent
DiagDirection dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
// It means we can only walk with the track, so the bridge has to be in the same direction
TileIndex tile = current->path.node.tile;
TileIndex new_tile = tile;
Slope tileh = GetTileSlope(tile, NULL);
// Bridges can only be build on land that is not flat
// And if there is a road or rail blocking
if (tileh != SLOPE_FLAT ||
(PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_STREET)) ||
(!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDiagDir(dir), MP_RAILWAY))) {
for (;;) {
new_tile += TileOffsByDiagDir(dir);
// Precheck, is the length allowed?
if (!CheckBridge_Stuff(0, GetBridgeLength(tile, new_tile))) break;
// Check if we hit the station-tile.. we don't like that!
if (TILES_BETWEEN(new_tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) break;
// Try building the bridge..
ret = AI_DoCommand(tile, new_tile, (0 << 8) + (MAX_BRIDGES / 2), DC_AUTO, CMD_BUILD_BRIDGE);
if (CmdFailed(ret)) continue;
// We can build a bridge here.. add him to the neighbours
aystar->neighbours[aystar->num_neighbours].tile = new_tile;
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_BRIDGE + (dir << 8);
aystar->neighbours[aystar->num_neighbours++].direction = 0;
// We can only have 12 neighbours, and we need 1 left for tunnels
if (aystar->num_neighbours == 11) break;
}
}
// Next, check for tunnels!
// Tunnels can only be built on slopes corresponding to the direction
// For now, we check both sides for this tile.. terraforming gives fuzzy result
if ((dir == DIAGDIR_NE && tileh == SLOPE_NE) ||
(dir == DIAGDIR_SE && tileh == SLOPE_SE) ||
(dir == DIAGDIR_SW && tileh == SLOPE_SW) ||
(dir == DIAGDIR_NW && tileh == SLOPE_NW)) {
// Now simply check if a tunnel can be build
ret = AI_DoCommand(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
tileh = GetTileSlope(_build_tunnel_endtile, NULL);
if (!CmdFailed(ret) && (tileh == SLOPE_SW || tileh == SLOPE_SE || tileh == SLOPE_NW || tileh == SLOPE_NE)) {
aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
aystar->neighbours[aystar->num_neighbours++].direction = 0;
}
}
}
}
extern uint GetRailFoundation(Slope tileh, TrackBits bits); // XXX function declaration in .c
extern uint GetRoadFoundation(Slope tileh, uint bits); // XXX function declaration in .c
extern uint GetBridgeFoundation(Slope tileh, Axis); // XXX function declaration in .c
enum {
BRIDGE_NO_FOUNDATION = 1 << 0 | 1 << 3 | 1 << 6 | 1 << 9 | 1 << 12,
};
// The most important function: it calculates the g-value
static int32 AyStar_AiPathFinder_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
{
Ai_PathFinderInfo *PathFinderInfo = (Ai_PathFinderInfo*)aystar->user_target;
int r, res = 0;
Slope tileh = GetTileSlope(current->tile, NULL);
Slope parent_tileh = GetTileSlope(parent->path.node.tile, NULL);
// Check if we hit the end-tile
if (TILES_BETWEEN(current->tile, PathFinderInfo->end_tile_tl, PathFinderInfo->end_tile_br)) {
// We are at the end-tile, check if we had a direction or something...
if (PathFinderInfo->end_direction != AI_PATHFINDER_NO_DIRECTION && AiNew_GetDirection(current->tile, parent->path.node.tile) != PathFinderInfo->end_direction) {
// We are not pointing the right way, invalid tile
return AYSTAR_INVALID_NODE;
}
// If it was valid, drop out.. we don't build on the endtile
return 0;
}
// Give everything a small penalty
res += AI_PATHFINDER_PENALTY;
if (!PathFinderInfo->rail_or_road) {
// Road has the lovely advantage it can use other road... check if
// the current tile is road, and if so, give a good bonus
if (IsRoad(current->tile)) {
res -= AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS;
}
}
// We should give a penalty when the tile is going up or down.. this is one way to do so!
// Too bad we have to count it from the parent.. but that is not so bad.
// We also dislike long routes on slopes, since they do not look too realistic
// when there is a flat land all around, they are more expensive to build, and
// especially they essentially block the ability to connect or cross the road
// from one side.
if (parent_tileh != SLOPE_FLAT && parent->path.parent != NULL) {
// Skip if the tile was from a bridge or tunnel
if (parent->path.node.user_data[0] == 0 && current->user_data[0] == 0) {
if (PathFinderInfo->rail_or_road) {
r = GetRailFoundation(parent_tileh, 1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
// Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information..
if (r >= 15 || (r == 0 && HASBIT(BRIDGE_NO_FOUNDATION, tileh))) {
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
} else {
res += AI_PATHFINDER_FOUNDATION_PENALTY;
}
} else {
if (!IsRoad(parent->path.node.tile) || !IsTileType(parent->path.node.tile, MP_TUNNELBRIDGE)) {
r = GetRoadFoundation(parent_tileh, AiNew_GetRoadDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
if (r >= 15 || r == 0) {
res += AI_PATHFINDER_TILE_GOES_UP_PENALTY;
} else {
res += AI_PATHFINDER_FOUNDATION_PENALTY;
}
}
}
}
}
// Are we part of a tunnel?
if ((AI_PATHFINDER_FLAG_TUNNEL & current->user_data[0]) != 0) {
// Tunnels are very expensive when build on long routes..
// Ironicly, we are using BridgeCode here ;)
r = AI_PATHFINDER_TUNNEL_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
res += r + (r >> 8);
}
// Are we part of a bridge?
if ((AI_PATHFINDER_FLAG_BRIDGE & current->user_data[0]) != 0) {
// That means for every length a penalty
res += AI_PATHFINDER_BRIDGE_PENALTY * GetBridgeLength(current->tile, parent->path.node.tile);
// Check if we are going up or down, first for the starting point
// In user_data[0] is at the 8th bit the direction
if (!HASBIT(BRIDGE_NO_FOUNDATION, parent_tileh)) {
if (GetBridgeFoundation(parent_tileh, (current->user_data[0] >> 8) & 1) < 15) {
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
}
}
// Second for the end point
if (!HASBIT(BRIDGE_NO_FOUNDATION, tileh)) {
if (GetBridgeFoundation(tileh, (current->user_data[0] >> 8) & 1) < 15) {
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
}
}
if (parent_tileh == SLOPE_FLAT) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
if (tileh == SLOPE_FLAT) res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
}
// To prevent the AI from taking the fastest way in tiles, but not the fastest way
// in speed, we have to give a good penalty to direction changing
// This way, we get almost the fastest way in tiles, and a very good speed on the track
if (!PathFinderInfo->rail_or_road) {
if (parent->path.parent != NULL &&
AiNew_GetDirection(current->tile, parent->path.node.tile) != AiNew_GetDirection(parent->path.node.tile, parent->path.parent->node.tile)) {
// When road exists, we don't like turning, but its free, so don't be to piggy about it
if (IsRoad(parent->path.node.tile)) {
res += AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY;
} else {
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
}
}
} else {
// For rail we have 1 exeption: diagonal rail..
// So we fetch 2 raildirection. That of the current one, and of the one before that
if (parent->path.parent != NULL && parent->path.parent->parent != NULL) {
int dir1 = AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile);
int dir2 = AiNew_GetRailDirection(parent->path.parent->parent->node.tile, parent->path.parent->node.tile, parent->path.node.tile);
// First, see if we are on diagonal path, that is better than straight path
if (dir1 > 1) res -= AI_PATHFINDER_DIAGONAL_BONUS;
// First see if they are different
if (dir1 != dir2) {
// dir 2 and 3 are 1 diagonal track, and 4 and 5.
if (!(((dir1 == 2 || dir1 == 3) && (dir2 == 2 || dir2 == 3)) || ((dir1 == 4 || dir1 == 5) && (dir2 == 4 || dir2 == 5)))) {
// It is not, so we changed of direction
res += AI_PATHFINDER_DIRECTION_CHANGE_PENALTY;
}
if (parent->path.parent->parent->parent != NULL) {
int dir3 = AiNew_GetRailDirection(parent->path.parent->parent->parent->node.tile, parent->path.parent->parent->node.tile, parent->path.parent->node.tile);
// Check if we changed 3 tiles of direction in 3 tiles.. bad!!!
if ((dir1 == 0 || dir1 == 1) && dir2 > 1 && (dir3 == 0 || dir3 == 1)) {
res += AI_PATHFINDER_CURVE_PENALTY;
}
}
}
}
}
return (res < 0) ? 0 : res;
}

118
ai/trolly/shared.c Normal file
View File

@@ -0,0 +1,118 @@
/* $Id$ */
#include "../../stdafx.h"
#include "../../openttd.h"
#include "../../debug.h"
#include "../../map.h"
#include "trolly.h"
#include "../../vehicle.h"
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
{
// 0 = vert
// 1 = horz
// 2 = dig up-left
// 3 = dig down-right
// 4 = dig down-left
// 5 = dig up-right
uint x1 = TileX(tile_a);
uint x2 = TileX(tile_b);
uint x3 = TileX(tile_c);
uint y1 = TileY(tile_a);
uint y2 = TileY(tile_b);
uint y3 = TileY(tile_c);
if (y1 == y2 && y2 == y3) return 0;
if (x1 == x2 && x2 == x3) return 1;
if (y2 > y1) return x2 > x3 ? 2 : 4;
if (x2 > x1) return y2 > y3 ? 2 : 5;
if (y1 > y2) return x2 > x3 ? 5 : 3;
if (x1 > x2) return y2 > y3 ? 4 : 3;
return 0;
}
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c)
{
int x1, x2, x3;
int y1, y2, y3;
int r;
x1 = TileX(tile_a);
x2 = TileX(tile_b);
x3 = TileX(tile_c);
y1 = TileY(tile_a);
y2 = TileY(tile_b);
y3 = TileY(tile_c);
r = 0;
if (x1 < x2) r += 8;
if (y1 < y2) r += 1;
if (x1 > x2) r += 2;
if (y1 > y2) r += 4;
if (x2 < x3) r += 2;
if (y2 < y3) r += 4;
if (x2 > x3) r += 8;
if (y2 > y3) r += 1;
return r;
}
// Get's the direction between 2 tiles seen from tile_a
DiagDirection AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b)
{
if (TileY(tile_a) < TileY(tile_b)) return DIAGDIR_SE;
if (TileY(tile_a) > TileY(tile_b)) return DIAGDIR_NW;
if (TileX(tile_a) < TileX(tile_b)) return DIAGDIR_SW;
return DIAGDIR_NE;
}
// This functions looks up if this vehicle is special for this AI
// and returns his flag
uint AiNew_GetSpecialVehicleFlag(Player* p, Vehicle* v)
{
uint i;
for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
if (p->ainew.special_vehicles[i].veh_id == v->index) {
return p->ainew.special_vehicles[i].flag;
}
}
// Not found :(
return 0;
}
bool AiNew_SetSpecialVehicleFlag(Player* p, Vehicle* v, uint flag)
{
int new_id = -1;
uint i;
for (i = 0; i < AI_MAX_SPECIAL_VEHICLES; i++) {
if (p->ainew.special_vehicles[i].veh_id == v->index) {
p->ainew.special_vehicles[i].flag |= flag;
return true;
}
if (new_id == -1 &&
p->ainew.special_vehicles[i].veh_id == 0 &&
p->ainew.special_vehicles[i].flag == 0) {
new_id = i;
}
}
// Out of special_vehicle spots :s
if (new_id == -1) {
DEBUG(ai, 1)("special_vehicles list is too small :(");
return false;
}
p->ainew.special_vehicles[new_id].veh_id = v->index;
p->ainew.special_vehicles[new_id].flag = flag;
return true;
}

1356
ai/trolly/trolly.c Normal file

File diff suppressed because it is too large Load Diff

262
ai/trolly/trolly.h Normal file
View File

@@ -0,0 +1,262 @@
/* $Id$ */
#ifndef AI_TROLLY_H
#define AI_TROLLY_H
#include "../../aystar.h"
#include "../../player.h"
/*
* These defines can be altered to change the behavoir of the AI
*
* WARNING:
* This can also alter the AI in a negative way. I will never claim these settings
* are perfect, but don't change them if you don't know what the effect is.
*/
// How many times it the H multiplied. The higher, the more it will go straight to the
// end point. The lower, how more it will find the route with the lowest cost.
// also: the lower, the longer it takes before route is calculated..
#define AI_PATHFINDER_H_MULTIPLER 100
// How many loops may AyStar do before it stops
// 0 = infinite
#define AI_PATHFINDER_LOOPS_PER_TICK 5
// How long may the AI search for one route?
// 0 = infinite
// This number is the number of tiles tested.
// It takes (AI_PATHFINDER_MAX_SEARCH_NODES / AI_PATHFINDER_LOOPS_PER_TICK) ticks
// to get here.. with 5000 / 10 = 500. 500 / 74 (one day) = 8 days till it aborts
// (that is: if the AI is on VERY FAST! :p
#define AI_PATHFINDER_MAX_SEARCH_NODES 5000
// If you enable this, the AI is not allowed to make 90degree turns
#define AI_PATHFINDER_NO_90DEGREES_TURN
// Below are defines for the g-calculation
// Standard penalty given to a tile
#define AI_PATHFINDER_PENALTY 150
// The penalty given to a tile that is going up
#define AI_PATHFINDER_TILE_GOES_UP_PENALTY 450
// The penalty given to a tile which would have to use fundation
#define AI_PATHFINDER_FOUNDATION_PENALTY 100
// Changing direction is a penalty, to prevent curved ways (with that: slow ways)
#define AI_PATHFINDER_DIRECTION_CHANGE_PENALTY 200
// Same penalty, only for when road already exists
#define AI_PATHFINDER_DIRECTION_CHANGE_ON_EXISTING_ROAD_PENALTY 50
// A diagonal track cost the same as a straigh, but a diagonal is faster... so give
// a bonus for using diagonal track
#ifdef AI_PATHFINDER_NO_90DEGREES_TURN
#define AI_PATHFINDER_DIAGONAL_BONUS 95
#else
#define AI_PATHFINDER_DIAGONAL_BONUS 75
#endif
// If a roadblock already exists, it gets a bonus
#define AI_PATHFINDER_ROAD_ALREADY_EXISTS_BONUS 140
// To prevent 3 direction changes in 3 tiles, this penalty is given in such situation
#define AI_PATHFINDER_CURVE_PENALTY 200
// Penalty a bridge gets per length
#define AI_PATHFINDER_BRIDGE_PENALTY 180
// The penalty for a bridge going up
#define AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY 1000
// Tunnels are expensive...
// Because of that, every tile the cost is increased with 1/8th of his value
// This is also true if you are building a tunnel yourself
#define AI_PATHFINDER_TUNNEL_PENALTY 350
/*
* Ai_New defines
*/
// How long may we search cities and industry for a new route?
#define AI_LOCATE_ROUTE_MAX_COUNTER 200
// How many days must there be between building the first station and the second station
// within one city. This number is in days and should be more than 4 months.
#define AI_CHECKCITY_DATE_BETWEEN 180
// How many cargo is needed for one station in a city?
#define AI_CHECKCITY_CARGO_PER_STATION 60
// How much cargo must there not be used in a city before we can build a new station?
#define AI_CHECKCITY_NEEDED_CARGO 50
// When there is already a station which takes the same good and the rating of that
// city is higher then this numer, we are not going to attempt to build anything
// there
#define AI_CHECKCITY_CARGO_RATING 50
// But, there is a chance of 1 out of this number, that we do ;)
#define AI_CHECKCITY_CARGO_RATING_CHANCE 5
// If a city is too small to contain a station, there is a small chance
// that we still do so.. just to make the city bigger!
#define AI_CHECKCITY_CITY_CHANCE 5
// This number indicates for every unit of cargo, how many tiles two stations maybe be away
// from eachother. In other words: if we have 120 units of cargo in one station, and 120 units
// of the cargo in the other station, both stations can be 96 units away from eachother, if the
// next number is 0.4.
#define AI_LOCATEROUTE_BUS_CARGO_DISTANCE 0.4
#define AI_LOCATEROUTE_TRUCK_CARGO_DISTANCE 0.7
// In whole tiles, the minimum distance for a truck route
#define AI_LOCATEROUTE_TRUCK_MIN_DISTANCE 30
// The amount of tiles in a square from -X to +X that is scanned for a station spot
// (so if this number is 10, 20x20 = 400 tiles are scanned for _the_ perfect spot
// Safe values are between 15 and 5
#define AI_FINDSTATION_TILE_RANGE 10
// Building on normal speed goes very fast. Idle this amount of ticks between every
// building part. It is calculated like this: (4 - competitor_speed) * num + 1
// where competitor_speed is between 0 (very slow) to 4 (very fast)
#define AI_BUILDPATH_PAUSE 10
// Minimum % of reliabilty a vehicle has to have before the AI buys it
#define AI_VEHICLE_MIN_RELIABILTY 60
// The minimum amount of money a player should always have
#define AI_MINIMUM_MONEY 15000
// If the most cheap route is build, how much is it going to cost..
// This is to prevent the AI from trying to build a route which can not be paid for
#define AI_MINIMUM_BUS_ROUTE_MONEY 25000
#define AI_MINIMUM_TRUCK_ROUTE_MONEY 35000
// The minimum amount of money before we are going to repay any money
#define AI_MINIMUM_LOAN_REPAY_MONEY 40000
// How many repays do we do if we have enough money to do so?
// Every repay is 10000
#define AI_LOAN_REPAY 2
// How much income must we have before paying back a loan? Month-based (and looked at the last month)
#define AI_MINIMUM_INCOME_FOR_LOAN 7000
// If there is <num> time as much cargo in the station then the vehicle can handle
// reuse the station instead of building a new one!
#define AI_STATION_REUSE_MULTIPLER 2
// No more than this amount of vehicles per station..
#define AI_CHECK_MAX_VEHICLE_PER_STATION 10
// How many thick between building 2 vehicles
#define AI_BUILD_VEHICLE_TIME_BETWEEN DAY_TICKS
// How many days must there between vehicle checks
// The more often, the less non-money-making lines there will be
// but the unfair it may seem to a human player
#define AI_DAYS_BETWEEN_VEHICLE_CHECKS 30
// How money profit does a vehicle needs to make to stay in order
// This is the profit of this year + profit of last year
// But also for vehicles that are just one year old. In other words:
// Vehicles of 2 years do easier meet this setting then vehicles
// of one year. This is a very good thing. New vehicles are filtered,
// while old vehicles stay longer, because we do get less in return.
#define AI_MINIMUM_ROUTE_PROFIT 1000
// A vehicle is considered lost when he his cargo is more than 180 days old
#define AI_VEHICLE_LOST_DAYS 180
// How many times may the AI try to find a route before it gives up
#define AI_MAX_TRIES_FOR_SAME_ROUTE 8
/*
* End of defines
*/
// This stops 90degrees curves
static const byte _illegal_curves[6] = {
255, 255, // Horz and vert, don't have the effect
5, // upleft and upright are not valid
4, // downright and downleft are not valid
2, // downleft and upleft are not valid
3, // upright and downright are not valid
};
enum {
AI_STATE_STARTUP = 0,
AI_STATE_FIRST_TIME,
AI_STATE_NOTHING,
AI_STATE_WAKE_UP,
AI_STATE_LOCATE_ROUTE,
AI_STATE_FIND_STATION,
AI_STATE_FIND_PATH,
AI_STATE_FIND_DEPOT,
AI_STATE_VERIFY_ROUTE,
AI_STATE_BUILD_STATION,
AI_STATE_BUILD_PATH,
AI_STATE_BUILD_DEPOT,
AI_STATE_BUILD_VEHICLE,
AI_STATE_WAIT_FOR_BUILD,
AI_STATE_GIVE_ORDERS,
AI_STATE_START_VEHICLE,
AI_STATE_REPAY_MONEY,
AI_STATE_CHECK_ALL_VEHICLES,
AI_STATE_ACTION_DONE,
AI_STATE_STOP, // Temporary function to stop the AI
};
// Used for tbt (train/bus/truck)
enum {
AI_TRAIN = 0,
AI_BUS,
AI_TRUCK,
};
enum {
AI_ACTION_NONE = 0,
AI_ACTION_BUS_ROUTE,
AI_ACTION_TRUCK_ROUTE,
AI_ACTION_REPAY_LOAN,
AI_ACTION_CHECK_ALL_VEHICLES,
};
// Used for from_type/to_type
enum {
AI_NO_TYPE = 0,
AI_CITY,
AI_INDUSTRY,
};
// Flags for in the vehicle
enum {
AI_VEHICLEFLAG_SELL = 1,
// Remember, flags must be in power of 2
};
#define AI_NO_CARGO 0xFF // Means that there is no cargo defined yet (used for industry)
#define AI_NEED_CARGO 0xFE // Used when the AI needs to find out a cargo for the route
#define AI_STATION_RANGE TileXY(MapMaxX(), MapMaxY())
#define AI_PATHFINDER_NO_DIRECTION (byte)-1
// Flags used in user_data
#define AI_PATHFINDER_FLAG_BRIDGE 1
#define AI_PATHFINDER_FLAG_TUNNEL 2
typedef void AiNew_StateFunction(Player *p);
// ai_new.c
void AiNewDoGameLoop(Player *p);
// ai_pathfinder.c
AyStar *new_AyStar_AiPathFinder(int max_tiles_around, Ai_PathFinderInfo *PathFinderInfo);
void clean_AyStar_AiPathFinder(AyStar *aystar, Ai_PathFinderInfo *PathFinderInfo);
// ai_shared.c
int AiNew_GetRailDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
int AiNew_GetRoadDirection(TileIndex tile_a, TileIndex tile_b, TileIndex tile_c);
DiagDirection AiNew_GetDirection(TileIndex tile_a, TileIndex tile_b);
bool AiNew_SetSpecialVehicleFlag(Player *p, Vehicle *v, uint flag);
uint AiNew_GetSpecialVehicleFlag(Player *p, Vehicle *v);
// ai_build.c
bool AiNew_Build_CompanyHQ(Player *p, TileIndex tile);
int AiNew_Build_Station(Player *p, byte type, TileIndex tile, byte length, byte numtracks, byte direction, byte flag);
int AiNew_Build_Bridge(Player *p, TileIndex tile_a, TileIndex tile_b, byte flag);
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
EngineID AiNew_PickVehicle(Player *p);
int AiNew_Build_Vehicle(Player *p, TileIndex tile, byte flag);
int AiNew_Build_Depot(Player* p, TileIndex tile, DiagDirection direction, byte flag);
#endif /* AI_TROLLY_H */

26
aircraft.h Normal file
View File

@@ -0,0 +1,26 @@
/* $Id$ */
#ifndef AIRCRAFT_H
#define AIRCRAFT_H
#include "station_map.h"
#include "vehicle.h"
static inline bool IsAircraftInHangar(const Vehicle* v)
{
assert(v->type == VEH_Aircraft);
return v->vehstatus & VS_HIDDEN && IsHangarTile(v->tile);
}
static inline bool IsAircraftInHangarStopped(const Vehicle* v)
{
return IsAircraftInHangar(v) && v->vehstatus & VS_STOPPED;
}
uint16 AircraftDefaultCargoCapacity(CargoID cid, EngineID engine_type);
void CcCloneAircraft(bool success, TileIndex tile, uint32 p1, uint32 p2);
void HandleAircraftEnterHangar(Vehicle *v);
#endif /* AIRCRAFT_H */

2146
aircraft_cmd.c Normal file

File diff suppressed because it is too large Load Diff

350
aircraft_gui.c Normal file
View File

@@ -0,0 +1,350 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "aircraft.h"
#include "debug.h"
#include "functions.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "map.h"
#include "window.h"
#include "gui.h"
#include "vehicle.h"
#include "gfx.h"
#include "command.h"
#include "engine.h"
#include "viewport.h"
#include "player.h"
#include "depot.h"
#include "vehicle_gui.h"
#include "newgrf_engine.h"
void CcCloneAircraft(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
if (success) ShowAircraftViewWindow(GetVehicle(_new_vehicle_id));
}
static void AircraftDetailsWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT: {
const Vehicle *v = GetVehicle(w->window_number);
SetWindowWidgetDisabledState(w, 2, v->owner != _local_player);
/* Disable service-scroller when interval is set to disabled */
SetWindowWidgetDisabledState(w, 5, !_patches.servint_aircraft);
SetWindowWidgetDisabledState(w, 6, !_patches.servint_aircraft);
SetDParam(0, v->string_id);
SetDParam(1, v->unitnumber);
DrawWindowWidgets(w);
/* Draw running cost */
{
int year = v->age / 366;
SetDParam(1, year);
SetDParam(0, (v->age + 365 < v->max_age) ? STR_AGE : STR_AGE_RED);
SetDParam(2, v->max_age / 366);
SetDParam(3, _price.aircraft_running * AircraftVehInfo(v->engine_type)->running_cost >> 8);
DrawString(2, 15, STR_A00D_AGE_RUNNING_COST_YR, 0);
}
/* Draw max speed */
{
SetDParam(0, v->max_speed * 128 / 10);
DrawString(2, 25, STR_A00E_MAX_SPEED, 0);
}
/* Draw profit */
{
SetDParam(0, v->profit_this_year);
SetDParam(1, v->profit_last_year);
DrawString(2, 35, STR_A00F_PROFIT_THIS_YEAR_LAST_YEAR, 0);
}
/* Draw breakdown & reliability */
{
SetDParam(0, v->reliability * 100 >> 16);
SetDParam(1, v->breakdowns_since_last_service);
DrawString(2, 45, STR_A010_RELIABILITY_BREAKDOWNS, 0);
}
/* Draw service interval text */
{
SetDParam(0, v->service_interval);
SetDParam(1, v->date_of_last_service);
DrawString(13, 103, _patches.servint_ispercent?STR_SERVICING_INTERVAL_PERCENT:STR_883C_SERVICING_INTERVAL_DAYS, 0);
}
DrawAircraftImage(v, 3, 57, INVALID_VEHICLE);
{
const Vehicle *u;
int y = 57;
do {
if (v->subtype <= 2) {
SetDParam(0, GetCustomEngineName(v->engine_type));
SetDParam(1, v->build_year);
SetDParam(2, v->value);
DrawString(60, y, STR_A011_BUILT_VALUE, 0);
y += 10;
SetDParam(0, v->cargo_type);
SetDParam(1, v->cargo_cap);
u = v->next;
SetDParam(2, u->cargo_type);
SetDParam(3, u->cargo_cap);
DrawString(60, y, (u->cargo_cap != 0) ? STR_A019_CAPACITY : STR_A01A_CAPACITY, 0);
y += 14;
}
if (v->cargo_count != 0) {
/* Cargo names (fix pluralness) */
SetDParam(0, v->cargo_type);
SetDParam(1, v->cargo_count);
SetDParam(2, v->cargo_source);
DrawString(60, y, STR_8813_FROM, 0);
y += 10;
}
} while ( (v=v->next) != NULL);
}
} break;
case WE_CLICK: {
int mod;
const Vehicle *v;
switch (e->we.click.widget) {
case 2: /* rename */
v = GetVehicle(w->window_number);
SetDParam(0, v->unitnumber);
ShowQueryString(v->string_id, STR_A030_NAME_AIRCRAFT, 31, 150, w->window_class, w->window_number, CS_ALPHANUMERAL);
break;
case 5: /* increase int */
mod = _ctrl_pressed? 5 : 10;
goto do_change_service_int;
case 6: /* decrease int */
mod = _ctrl_pressed?- 5 : -10;
do_change_service_int:
v = GetVehicle(w->window_number);
mod = GetServiceIntervalClamped(mod + v->service_interval);
if (mod == v->service_interval) return;
DoCommandP(v->tile, v->index, mod, NULL, CMD_CHANGE_SERVICE_INT | CMD_MSG(STR_018A_CAN_T_CHANGE_SERVICING));
break;
}
} break;
case WE_ON_EDIT_TEXT:
if (e->we.edittext.str[0] != '\0') {
_cmd_text = e->we.edittext.str;
DoCommandP(0, w->window_number, 0, NULL,
CMD_NAME_VEHICLE | CMD_MSG(STR_A031_CAN_T_NAME_AIRCRAFT));
}
break;
}
}
static const Widget _aircraft_details_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
{ WWT_CAPTION, RESIZE_NONE, 14, 11, 349, 0, 13, STR_A00C_DETAILS, STR_018C_WINDOW_TITLE_DRAG_THIS },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 350, 389, 0, 13, STR_01AA_NAME, STR_A032_NAME_AIRCRAFT },
{ WWT_PANEL, RESIZE_NONE, 14, 0, 389, 14, 55, 0x0, STR_NULL },
{ WWT_PANEL, RESIZE_NONE, 14, 0, 389, 56, 101, 0x0, STR_NULL },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 10, 102, 107, STR_0188, STR_884D_INCREASE_SERVICING_INTERVAL },
{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 0, 10, 108, 113, STR_0189, STR_884E_DECREASE_SERVICING_INTERVAL },
{ WWT_PANEL, RESIZE_NONE, 14, 11, 389, 102, 113, 0x0, STR_NULL },
{ WIDGETS_END},
};
static const WindowDesc _aircraft_details_desc = {
WDP_AUTO, WDP_AUTO, 390, 114,
WC_VEHICLE_DETAILS, WC_VEHICLE_VIEW,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
_aircraft_details_widgets,
AircraftDetailsWndProc
};
static void ShowAircraftDetailsWindow(const Vehicle *v)
{
Window *w;
VehicleID veh = v->index;
DeleteWindowById(WC_VEHICLE_ORDERS, veh);
DeleteWindowById(WC_VEHICLE_DETAILS, veh);
w = AllocateWindowDescFront(&_aircraft_details_desc, veh);
w->caption_color = v->owner;
// w->vscroll.cap = 6;
// w->traindetails_d.tab = 0;
}
static const Widget _aircraft_view_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
{ WWT_CAPTION, RESIZE_RIGHT, 14, 11, 237, 0, 13, STR_A00A, STR_018C_WINDOW_TITLE_DRAG_THIS },
{ WWT_STICKYBOX, RESIZE_LR, 14, 238, 249, 0, 13, 0x0, STR_STICKY_BUTTON },
{ WWT_PANEL, RESIZE_RB, 14, 0, 231, 14, 103, 0x0, STR_NULL },
{ WWT_INSET, RESIZE_RB, 14, 2, 229, 16, 101, 0x0, STR_NULL },
{ WWT_PUSHBTN, RESIZE_RTB, 14, 0, 237, 104, 115, 0x0, STR_A027_CURRENT_AIRCRAFT_ACTION },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 14, 31, SPR_CENTRE_VIEW_VEHICLE, STR_A029_CENTER_MAIN_VIEW_ON_AIRCRAFT },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 32, 49, SPR_SEND_AIRCRAFT_TODEPOT,STR_A02A_SEND_AIRCRAFT_TO_HANGAR },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 50, 67, SPR_REFIT_VEHICLE, STR_A03B_REFIT_AIRCRAFT_TO_CARRY },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 68, 85, SPR_SHOW_ORDERS, STR_A028_SHOW_AIRCRAFT_S_ORDERS },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 86, 103, SPR_SHOW_VEHICLE_DETAILS, STR_A02B_SHOW_AIRCRAFT_DETAILS },
{ WWT_PUSHIMGBTN, RESIZE_LR, 14, 232, 249, 32, 49, SPR_CLONE_AIRCRAFT, STR_CLONE_AIRCRAFT_INFO },
{ WWT_PANEL, RESIZE_LRB, 14, 232, 249, 104, 103, 0x0, STR_NULL },
{ WWT_RESIZEBOX, RESIZE_LRTB, 14, 238, 249, 104, 115, 0x0, STR_NULL },
{ WIDGETS_END},
};
static void AircraftViewWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT: {
const Vehicle *v = GetVehicle(w->window_number);
StringID str;
bool is_localplayer = v->owner == _local_player;
SetWindowWidgetDisabledState(w, 7, !is_localplayer);
SetWindowWidgetDisabledState(w, 8, !IsAircraftInHangarStopped(v) || !is_localplayer);
SetWindowWidgetDisabledState(w, 11, !is_localplayer);
/* draw widgets & caption */
SetDParam(0, v->string_id);
SetDParam(1, v->unitnumber);
DrawWindowWidgets(w);
if (v->vehstatus & VS_CRASHED) {
str = STR_8863_CRASHED;
} else if (v->vehstatus & VS_STOPPED) {
str = STR_8861_STOPPED;
} else {
switch (v->current_order.type) {
case OT_GOTO_STATION: {
SetDParam(0, v->current_order.dest);
SetDParam(1, v->cur_speed * 128 / 10);
str = STR_HEADING_FOR_STATION + _patches.vehicle_speed;
} break;
case OT_GOTO_DEPOT: {
/* Aircrafts always go to a station, even if you say depot */
SetDParam(0, v->current_order.dest);
SetDParam(1, v->cur_speed * 128 / 10);
if (HASBIT(v->current_order.flags, OFB_HALT_IN_DEPOT) && !HASBIT(v->current_order.flags, OFB_PART_OF_ORDERS)) {
str = STR_HEADING_FOR_HANGAR + _patches.vehicle_speed;
} else {
str = STR_HEADING_FOR_HANGAR_SERVICE + _patches.vehicle_speed;
}
} break;
case OT_LOADING:
str = STR_882F_LOADING_UNLOADING;
break;
default:
if (v->num_orders == 0) {
str = STR_NO_ORDERS + _patches.vehicle_speed;
SetDParam(0, v->cur_speed * 128 / 10);
} else {
str = STR_EMPTY;
}
break;
}
}
/* draw the flag plus orders */
DrawSprite(v->vehstatus & VS_STOPPED ? SPR_FLAG_VEH_STOPPED : SPR_FLAG_VEH_RUNNING, 2, w->widget[5].top + 1);
DrawStringCenteredTruncated(w->widget[5].left + 8, w->widget[5].right, w->widget[5].top + 1, str, 0);
DrawWindowViewport(w);
} break;
case WE_CLICK: {
const Vehicle *v = GetVehicle(w->window_number);
switch (e->we.click.widget) {
case 5: /* start stop */
DoCommandP(v->tile, v->index, 0, NULL, CMD_START_STOP_AIRCRAFT | CMD_MSG(STR_A016_CAN_T_STOP_START_AIRCRAFT));
break;
case 6: /* center main view */
ScrollMainWindowTo(v->x_pos, v->y_pos);
break;
case 7: /* goto hangar */
DoCommandP(v->tile, v->index, _ctrl_pressed ? DEPOT_SERVICE : 0, NULL, CMD_SEND_AIRCRAFT_TO_HANGAR | CMD_MSG(STR_A012_CAN_T_SEND_AIRCRAFT_TO));
break;
case 8: /* refit */
ShowVehicleRefitWindow(v, INVALID_VEH_ORDER_ID);
break;
case 9: /* show orders */
ShowOrdersWindow(v);
break;
case 10: /* show details */
ShowAircraftDetailsWindow(v);
break;
case 11:
/* clone vehicle */
DoCommandP(v->tile, v->index, _ctrl_pressed ? 1 : 0, CcCloneAircraft, CMD_CLONE_VEHICLE | CMD_MSG(STR_A008_CAN_T_BUILD_AIRCRAFT));
break;
}
} break;
case WE_RESIZE:
w->viewport->width += e->we.sizing.diff.x;
w->viewport->height += e->we.sizing.diff.y;
w->viewport->virtual_width += e->we.sizing.diff.x;
w->viewport->virtual_height += e->we.sizing.diff.y;
break;
case WE_DESTROY:
DeleteWindowById(WC_VEHICLE_ORDERS, w->window_number);
DeleteWindowById(WC_VEHICLE_REFIT, w->window_number);
DeleteWindowById(WC_VEHICLE_DETAILS, w->window_number);
break;
case WE_MOUSELOOP: {
const Vehicle *v = GetVehicle(w->window_number);
bool plane_stopped = IsAircraftInHangarStopped(v);
/* Widget 7 (send to hangar) must be hidden if the plane is already stopped in hangar.
* Widget 11 (clone) should then be shown, since cloning is allowed only while in hangar and stopped.
* This sytem allows to have two buttons, on top of each other*/
if (plane_stopped != IsWindowWidgetHidden(w, 7) || plane_stopped == IsWindowWidgetHidden(w, 11)) {
SetWindowWidgetHiddenState(w, 7, plane_stopped); // send to hangar
SetWindowWidgetHiddenState(w, 11, !plane_stopped); // clone
SetWindowDirty(w);
}
} break;
}
}
static const WindowDesc _aircraft_view_desc = {
WDP_AUTO, WDP_AUTO, 250, 116,
WC_VEHICLE_VIEW ,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS | WDF_STICKY_BUTTON | WDF_RESIZABLE,
_aircraft_view_widgets,
AircraftViewWndProc
};
void ShowAircraftViewWindow(const Vehicle *v)
{
Window *w = AllocateWindowDescFront(&_aircraft_view_desc, v->index);
if (w != NULL) {
w->caption_color = v->owner;
AssignWindowViewport(w, 3, 17, 0xE2, 0x54, w->window_number | (1 << 31), 0);
}
}

489
airport.c Normal file
View File

@@ -0,0 +1,489 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "debug.h"
#include "map.h"
#include "airport.h"
#include "macros.h"
#include "variables.h"
#include "airport_movement.h"
#include "date.h"
/* Uncomment this to print out a full report of the airport-structure
* You should either use
* - true: full-report, print out every state and choice with string-names
* OR
* - false: give a summarized report which only shows current and next position */
//#define DEBUG_AIRPORT false
static AirportFTAClass *CountryAirport;
static AirportFTAClass *CityAirport;
static AirportFTAClass *Oilrig;
static AirportFTAClass *Heliport;
static AirportFTAClass *MetropolitanAirport;
static AirportFTAClass *InternationalAirport;
static AirportFTAClass *CommuterAirport;
static AirportFTAClass *HeliDepot;
static AirportFTAClass *IntercontinentalAirport;
static AirportFTAClass *HeliStation;
static void AirportFTAClass_Constructor(AirportFTAClass *apc,
const byte *terminals, const byte *helipads,
const byte entry_point, const byte acc_planes,
const AirportFTAbuildup *apFA,
const TileIndexDiffC *depots, const byte nof_depots,
uint size_x, uint size_y
);
static void AirportFTAClass_Destructor(AirportFTAClass *apc);
static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA);
static void AirportBuildAutomata(AirportFTAClass *apc, const AirportFTAbuildup *apFA);
static byte AirportGetTerminalCount(const byte *terminals, byte *groups);
static byte AirportTestFTA(const AirportFTAClass *apc);
#ifdef DEBUG_AIRPORT
static void AirportPrintOut(const AirportFTAClass *apc, bool full_report);
#endif /* DEBUG_AIRPORT */
void InitializeAirports(void)
{
// country airport
CountryAirport = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
CountryAirport,
_airport_terminal_country,
NULL,
16,
ALL,
_airport_fta_country,
_airport_depots_country,
lengthof(_airport_depots_country),
4, 3
);
// city airport
CityAirport = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
CityAirport,
_airport_terminal_city,
NULL,
19,
ALL,
_airport_fta_city,
_airport_depots_city,
lengthof(_airport_depots_city),
6, 6
);
// metropolitan airport
MetropolitanAirport = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
MetropolitanAirport,
_airport_terminal_metropolitan,
NULL,
20,
ALL,
_airport_fta_metropolitan,
_airport_depots_metropolitan,
lengthof(_airport_depots_metropolitan),
6, 6
);
// international airport
InternationalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
InternationalAirport,
_airport_terminal_international,
_airport_helipad_international,
37,
ALL,
_airport_fta_international,
_airport_depots_international,
lengthof(_airport_depots_international),
7, 7
);
// intercontintental airport
IntercontinentalAirport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
IntercontinentalAirport,
_airport_terminal_intercontinental,
_airport_helipad_intercontinental,
43,
ALL,
_airport_fta_intercontinental,
_airport_depots_intercontinental,
lengthof(_airport_depots_intercontinental),
9,11
);
// heliport, oilrig
Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
Heliport,
NULL,
_airport_helipad_heliport_oilrig,
7,
HELICOPTERS_ONLY,
_airport_fta_heliport_oilrig,
NULL,
0,
1, 1
);
Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine
// commuter airport
CommuterAirport = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
CommuterAirport,
_airport_terminal_commuter,
_airport_helipad_commuter,
22,
ALL,
_airport_fta_commuter,
_airport_depots_commuter,
lengthof(_airport_depots_commuter),
5,4
);
// helidepot airport
HeliDepot = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
HeliDepot,
NULL,
_airport_helipad_helidepot,
4,
HELICOPTERS_ONLY,
_airport_fta_helidepot,
_airport_depots_helidepot,
lengthof(_airport_depots_helidepot),
2,2
);
// helistation airport
HeliStation = malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
HeliStation,
NULL,
_airport_helipad_helistation,
25,
HELICOPTERS_ONLY,
_airport_fta_helistation,
_airport_depots_helistation,
lengthof(_airport_depots_helistation),
4,2
);
}
void UnInitializeAirports(void)
{
AirportFTAClass_Destructor(CountryAirport);
AirportFTAClass_Destructor(CityAirport);
AirportFTAClass_Destructor(Heliport);
AirportFTAClass_Destructor(MetropolitanAirport);
AirportFTAClass_Destructor(InternationalAirport);
AirportFTAClass_Destructor(CommuterAirport);
AirportFTAClass_Destructor(HeliDepot);
AirportFTAClass_Destructor(IntercontinentalAirport);
AirportFTAClass_Destructor(HeliStation);
}
static void AirportFTAClass_Constructor(AirportFTAClass *apc,
const byte *terminals, const byte *helipads,
const byte entry_point, const byte acc_planes,
const AirportFTAbuildup *apFA,
const TileIndexDiffC *depots, const byte nof_depots,
uint size_x, uint size_y
)
{
byte nofterminals, nofhelipads;
byte nofterminalgroups, nofhelipadgroups;
apc->size_x = size_x;
apc->size_y = size_y;
/* Set up the terminal and helipad count for an airport.
* TODO: If there are more than 10 terminals or 4 helipads, internal variables
* need to be changed, so don't allow that for now */
nofterminals = AirportGetTerminalCount(terminals, &nofterminalgroups);
if (nofterminals > MAX_TERMINALS) {
DEBUG(misc, 0) ("[Ap] Currently only maximum of %d terminals are supported (you wanted %d)", MAX_TERMINALS, nofterminals);
assert(nofterminals <= MAX_TERMINALS);
}
apc->terminals = terminals;
nofhelipads = AirportGetTerminalCount(helipads, &nofhelipadgroups);
if (nofhelipads > MAX_HELIPADS) {
DEBUG(misc, 0) ("[Ap] Currently only maximum of %d helipads are supported (you wanted %d)", MAX_HELIPADS, nofhelipads);
assert(nofhelipads <= MAX_HELIPADS);
}
apc->helipads = helipads;
/* Get the number of elements from the source table. We also double check this
* with the entry point which must be within bounds and use this information
* later on to build and validate the state machine */
apc->nofelements = AirportGetNofElements(apFA);
if (entry_point >= apc->nofelements) {
DEBUG(misc, 0) ("[Ap] Entry (%d) must be within the airport (maximum %d)", entry_point, apc->nofelements);
assert(entry_point < apc->nofelements);
}
apc->acc_planes = acc_planes;
apc->entry_point = entry_point;
apc->airport_depots = depots;
apc->nof_depots = nof_depots;
/* Build the state machine itself */
AirportBuildAutomata(apc, apFA);
DEBUG(misc, 1) ("[Ap] #count %3d; #term %2d (%dgrp); #helipad %2d (%dgrp); entry %3d",
apc->nofelements, nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, apc->entry_point);
/* Test if everything went allright. This is only a rude static test checking
* the symantic correctness. By no means does passing the test mean that the
* airport is working correctly or will not deadlock for example */
{ byte ret = AirportTestFTA(apc);
if (ret != MAX_ELEMENTS) DEBUG(misc, 0) ("[Ap] ERROR with element: %d", ret - 1);
assert(ret == MAX_ELEMENTS);
}
#ifdef DEBUG_AIRPORT
AirportPrintOut(apc, DEBUG_AIRPORT);
#endif
}
static void AirportFTAClass_Destructor(AirportFTAClass *apc)
{
int i;
AirportFTA *current, *next;
for (i = 0; i < apc->nofelements; i++) {
current = apc->layout[i].next;
while (current != NULL) {
next = current->next;
free(current);
current = next;
};
}
free(apc->layout);
free(apc);
}
/** Get the number of elements of a source Airport state automata
* Since it is actually just a big array of AirportFTA types, we only
* know one element from the other by differing 'position' identifiers */
static uint16 AirportGetNofElements(const AirportFTAbuildup *apFA)
{
int i;
uint16 nofelements = 0;
int temp = apFA[0].position;
for (i = 0; i < MAX_ELEMENTS; i++) {
if (temp != apFA[i].position) {
nofelements++;
temp = apFA[i].position;
}
if (apFA[i].position == MAX_ELEMENTS) break;
}
return nofelements;
}
/* We calculate the terminal/helipod count based on the data passed to us
* This data (terminals) contains an index as a first element as to how many
* groups there are, and then the number of terminals for each group */
static byte AirportGetTerminalCount(const byte *terminals, byte *groups)
{
byte i;
byte nof_terminals = 0;
*groups = 0;
if (terminals != NULL) {
i = terminals[0];
*groups = i;
while (i-- > 0) {
terminals++;
assert(*terminals != 0); // no empty groups please
nof_terminals += *terminals;
}
}
return nof_terminals;
}
static void AirportBuildAutomata(AirportFTAClass *apc, const AirportFTAbuildup *apFA)
{
AirportFTA *current;
AirportFTA *FAutomata = malloc(sizeof(AirportFTA) * apc->nofelements);
uint16 internalcounter = 0;
uint16 i;
apc->layout = FAutomata;
for (i = 0; i < apc->nofelements; i++) {
current = &apc->layout[i];
current->position = apFA[internalcounter].position;
current->heading = apFA[internalcounter].heading;
current->block = apFA[internalcounter].block;
current->next_position = apFA[internalcounter].next;
// outgoing nodes from the same position, create linked list
while (current->position == apFA[internalcounter + 1].position) {
AirportFTA *newNode = malloc(sizeof(AirportFTA));
newNode->position = apFA[internalcounter + 1].position;
newNode->heading = apFA[internalcounter + 1].heading;
newNode->block = apFA[internalcounter + 1].block;
newNode->next_position = apFA[internalcounter + 1].next;
// create link
current->next = newNode;
current = current->next;
internalcounter++;
} // while
current->next = NULL;
internalcounter++;
}
}
static byte AirportTestFTA(const AirportFTAClass *apc)
{
byte position, i, next_position;
AirportFTA *current, *first;
next_position = 0;
for (i = 0; i < apc->nofelements; i++) {
position = apc->layout[i].position;
if (position != next_position) return i;
current = first = &apc->layout[i];
for (; current != NULL; current = current->next) {
/* A heading must always be valid. The only exceptions are
* - multiple choices as start, identified by a special value of 255
* - terminal group which is identified by a special value of 255 */
if (current->heading > MAX_HEADINGS) {
if (current->heading != 255) return i;
if (current == first && current->next == NULL) return i;
if (current != first && current->next_position > apc->terminals[0]) return i;
}
/* If there is only one choice, it must be at the end */
if (current->heading == 0 && current->next != NULL) return i;
/* Obviously the elements of the linked list must have the same identifier */
if (position != current->position) return i;
/* A next position must be within bounds */
if (current->next_position >= apc->nofelements) return i;
}
next_position++;
}
return MAX_ELEMENTS;
}
#ifdef DEBUG_AIRPORT
static const char* const _airport_heading_strings[] = {
"TO_ALL",
"HANGAR",
"TERM1",
"TERM2",
"TERM3",
"TERM4",
"TERM5",
"TERM6",
"HELIPAD1",
"HELIPAD2",
"TAKEOFF",
"STARTTAKEOFF",
"ENDTAKEOFF",
"HELITAKEOFF",
"FLYING",
"LANDING",
"ENDLANDING",
"HELILANDING",
"HELIENDLANDING",
"TERM7",
"TERM8",
"HELIPAD3",
"HELIPAD4",
"DUMMY" // extra heading for 255
};
static uint AirportBlockToString(uint32 block)
{
uint i = 0;
if (block & 0xffff0000) { block >>= 16; i += 16; }
if (block & 0x0000ff00) { block >>= 8; i += 8; }
if (block & 0x000000f0) { block >>= 4; i += 4; }
if (block & 0x0000000c) { block >>= 2; i += 2; }
if (block & 0x00000002) { i += 1; }
return i;
}
static void AirportPrintOut(const AirportFTAClass *apc, bool full_report)
{
uint16 i;
if (!full_report) printf("(P = Current Position; NP = Next Position)\n");
for (i = 0; i < apc->nofelements; i++) {
AirportFTA *current = &apc->layout[i];
for (; current != NULL; current = current->next) {
if (full_report) {
byte heading = (current->heading == 255) ? MAX_HEADINGS + 1 : current->heading;
printf("\tPos:%2d NPos:%2d Heading:%15s Block:%2d\n", current->position,
current->next_position, _airport_heading_strings[heading],
AirportBlockToString(current->block));
} else {
printf("P:%2d NP:%2d", current->position, current->next_position);
}
}
printf("\n");
}
}
#endif
const AirportFTAClass *GetAirport(const byte airport_type)
{
//FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
// needs constant change if more airports are added
switch (airport_type) {
default: NOT_REACHED();
case AT_SMALL: return CountryAirport;
case AT_LARGE: return CityAirport;
case AT_METROPOLITAN: return MetropolitanAirport;
case AT_HELIPORT: return Heliport;
case AT_OILRIG: return Oilrig;
case AT_INTERNATIONAL: return InternationalAirport;
case AT_COMMUTER: return CommuterAirport;
case AT_HELIDEPOT: return HeliDepot;
case AT_INTERCON: return IntercontinentalAirport;
case AT_HELISTATION: return HeliStation;
}
}
const AirportMovingData *GetAirportMovingData(byte airport_type, byte position)
{
assert(airport_type < lengthof(_airport_moving_datas));
assert(position < GetAirport(airport_type)->nofelements);
return &_airport_moving_datas[airport_type][position];
}
uint32 GetValidAirports(void)
{
uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
if (_cur_year >= 1980) SETBIT(bytemask, 3); // metropolitan airport
if (_cur_year >= 1990) SETBIT(bytemask, 4); // international airport
if (_cur_year >= 1983) SETBIT(bytemask, 5); // commuter airport
if (_cur_year >= 1976) SETBIT(bytemask, 6); // helidepot
if (_cur_year >= 2002) SETBIT(bytemask, 7); // intercontinental airport
if (_cur_year >= 1980) SETBIT(bytemask, 8); // helistation
return bytemask;
}

163
airport.h Normal file
View File

@@ -0,0 +1,163 @@
/* $Id$ */
#ifndef AIRPORT_H
#define AIRPORT_H
enum {MAX_TERMINALS = 10};
enum {MAX_HELIPADS = 4};
enum {MAX_ELEMENTS = 255};
enum {MAX_HEADINGS = 22};
// Airport types
enum {
AT_SMALL = 0,
AT_LARGE = 1,
AT_HELIPORT = 2,
AT_METROPOLITAN = 3,
AT_INTERNATIONAL = 4,
AT_COMMUTER = 5,
AT_HELIDEPOT = 6,
AT_INTERCON = 7,
AT_HELISTATION = 8,
AT_OILRIG = 15
};
// do not change unless you change v->subtype too. This aligns perfectly with its current setting
enum {
AIRCRAFT_ONLY = 0,
ALL = 1,
HELICOPTERS_ONLY = 2,
};
enum {
AMED_NOSPDCLAMP = 1 << 0,
AMED_TAKEOFF = 1 << 1,
AMED_SLOWTURN = 1 << 2,
AMED_LAND = 1 << 3,
AMED_EXACTPOS = 1 << 4,
AMED_BRAKE = 1 << 5,
AMED_HELI_RAISE = 1 << 6,
AMED_HELI_LOWER = 1 << 7,
};
/* Movement States on Airports (headings target) */
enum {
TO_ALL = 0,
HANGAR = 1,
TERM1 = 2,
TERM2 = 3,
TERM3 = 4,
TERM4 = 5,
TERM5 = 6,
TERM6 = 7,
HELIPAD1 = 8,
HELIPAD2 = 9,
TAKEOFF = 10,
STARTTAKEOFF = 11,
ENDTAKEOFF = 12,
HELITAKEOFF = 13,
FLYING = 14,
LANDING = 15,
ENDLANDING = 16,
HELILANDING = 17,
HELIENDLANDING = 18,
TERM7 = 19,
TERM8 = 20,
HELIPAD3 = 21,
HELIPAD4 = 22
};
// this maps the terminal to its corresponding state and block flag
// currently set for 10 terms, 4 helipads
static const byte _airport_terminal_state[] = {2, 3, 4, 5, 6, 7, 19, 20, 0, 0, 8, 9, 21, 22};
static const byte _airport_terminal_flag[] = {0, 1, 2, 3, 4, 5, 22, 23, 0, 0, 6, 7, 24, 25};
/* Movement Blocks on Airports */
// blocks (eg_airport_flags)
enum {
TERM1_block = 1 << 0,
TERM2_block = 1 << 1,
TERM3_block = 1 << 2,
TERM4_block = 1 << 3,
TERM5_block = 1 << 4,
TERM6_block = 1 << 5,
HELIPAD1_block = 1 << 6,
HELIPAD2_block = 1 << 7,
RUNWAY_IN_OUT_block = 1 << 8,
RUNWAY_IN_block = 1 << 8,
AIRPORT_BUSY_block = 1 << 8,
RUNWAY_OUT_block = 1 << 9,
TAXIWAY_BUSY_block = 1 << 10,
OUT_WAY_block = 1 << 11,
IN_WAY_block = 1 << 12,
AIRPORT_ENTRANCE_block = 1 << 13,
TERM_GROUP1_block = 1 << 14,
TERM_GROUP2_block = 1 << 15,
HANGAR2_AREA_block = 1 << 16,
TERM_GROUP2_ENTER1_block = 1 << 17,
TERM_GROUP2_ENTER2_block = 1 << 18,
TERM_GROUP2_EXIT1_block = 1 << 19,
TERM_GROUP2_EXIT2_block = 1 << 20,
PRE_HELIPAD_block = 1 << 21,
// blocks for new airports
TERM7_block = 1 << 22,
TERM8_block = 1 << 23,
TERM9_block = 1 << 24,
HELIPAD3_block = 1 << 24,
TERM10_block = 1 << 25,
HELIPAD4_block = 1 << 25,
HANGAR1_AREA_block = 1 << 26,
OUT_WAY2_block = 1 << 27,
IN_WAY2_block = 1 << 28,
RUNWAY_IN2_block = 1 << 29,
RUNWAY_OUT2_block = 1 << 10, // note re-uses TAXIWAY_BUSY
HELIPAD_GROUP_block = 1 << 13, // note re-uses AIRPORT_ENTRANCE
OUT_WAY_block2 = 1 << 31,
// end of new blocks
NOTHING_block = 1 << 30
};
typedef struct AirportMovingData {
int x,y;
byte flag;
byte direction;
} AirportMovingData;
// Finite sTate mAchine --> FTA
typedef struct AirportFTAClass {
byte nofelements; // number of positions the airport consists of
const byte *terminals;
const byte *helipads;
byte entry_point; // when an airplane arrives at this airport, enter it at position entry_point
byte acc_planes; // accept airplanes or helicopters or both
const TileIndexDiffC *airport_depots; // gives the position of the depots on the airports
byte nof_depots; // number of depots this airport has
struct AirportFTA *layout; // state machine for airport
byte size_x;
byte size_y;
} AirportFTAClass;
// internal structure used in openttd - Finite sTate mAchine --> FTA
typedef struct AirportFTA {
byte position; // the position that an airplane is at
byte next_position; // next position from this position
uint32 block; // 32 bit blocks (st->airport_flags), should be enough for the most complex airports
byte heading; // heading (current orders), guiding an airplane to its target on an airport
struct AirportFTA *next; // possible extra movement choices from this position
} AirportFTA;
void InitializeAirports(void);
void UnInitializeAirports(void);
const AirportFTAClass *GetAirport(const byte airport_type);
const AirportMovingData *GetAirportMovingData(byte airport_type, byte position);
/** Get buildable airport bitmask.
* @return get all buildable airports at this given time, bitmasked.
* Bit 0 means the small airport is buildable, etc.
* @todo set availability of airports by year, instead of airplane
*/
uint32 GetValidAirports(void);
#endif /* AIRPORT_H */

286
airport_gui.c Normal file
View File

@@ -0,0 +1,286 @@
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "functions.h"
#include "map.h"
#include "window.h"
#include "gui.h"
#include "viewport.h"
#include "gfx.h"
#include "sound.h"
#include "command.h"
#include "vehicle.h"
#include "station.h"
#include "airport.h"
#include "depot.h"
static byte _selected_airport_type;
static void ShowBuildAirportPicker(void);
void CcBuildAirport(bool success, TileIndex tile, uint32 p1, uint32 p2)
{
if (success) {
SndPlayTileFx(SND_1F_SPLAT, tile);
ResetObjectToPlace();
}
}
static void PlaceAirport(TileIndex tile)
{
DoCommandP(tile, _selected_airport_type, 0, CcBuildAirport, CMD_BUILD_AIRPORT | CMD_AUTO | CMD_NO_WATER | CMD_MSG(STR_A001_CAN_T_BUILD_AIRPORT_HERE));
}
static void PlaceAir_DemolishArea(TileIndex tile)
{
VpStartPlaceSizing(tile, 4);
}
enum {
ATW_AIRPORT = 3,
ATW_DEMOLISH = 4
};
static void BuildAirClick_Airport(Window *w)
{
if (HandlePlacePushButton(w, ATW_AIRPORT, SPR_CURSOR_AIRPORT, 1, PlaceAirport)) ShowBuildAirportPicker();
}
static void BuildAirClick_Demolish(Window *w)
{
HandlePlacePushButton(w, ATW_DEMOLISH, ANIMCURSOR_DEMOLISH, 1, PlaceAir_DemolishArea);
}
static void BuildAirClick_Landscaping(Window *w)
{
ShowTerraformToolbar();
}
typedef void OnButtonClick(Window *w);
static OnButtonClick * const _build_air_button_proc[] = {
BuildAirClick_Airport,
BuildAirClick_Demolish,
BuildAirClick_Landscaping,
};
static void BuildAirToolbWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT:
DrawWindowWidgets(w);
break;
case WE_CLICK:
if (e->we.click.widget - 3 >= 0)
_build_air_button_proc[e->we.click.widget - 3](w);
break;
case WE_KEYPRESS: {
switch (e->we.keypress.keycode) {
case '1': BuildAirClick_Airport(w); break;
case '2': BuildAirClick_Demolish(w); break;
case 'l': BuildAirClick_Landscaping(w); break;
default: return;
}
} break;
case WE_PLACE_OBJ:
_place_proc(e->we.place.tile);
break;
case WE_PLACE_DRAG:
VpSelectTilesWithMethod(e->we.place.pt.x, e->we.place.pt.y, e->we.place.userdata);
break;
case WE_PLACE_MOUSEUP:
if (e->we.place.pt.x != -1) {
DoCommandP(e->we.place.tile, e->we.place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
}
break;
case WE_ABORT_PLACE_OBJ:
RaiseWindowButtons(w);
w = FindWindowById(WC_BUILD_STATION, 0);
if (w != 0)
WP(w,def_d).close = true;
break;
case WE_DESTROY:
if (_patches.link_terraform_toolbar) DeleteWindowById(WC_SCEN_LAND_GEN, 0);
break;
}
}
static const Widget _air_toolbar_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 73, 0, 13, STR_A000_AIRPORTS, STR_018C_WINDOW_TITLE_DRAG_THIS },
{ WWT_STICKYBOX, RESIZE_NONE, 7, 74, 85, 0, 13, 0x0, STR_STICKY_BUTTON },
{ WWT_IMGBTN, RESIZE_NONE, 7, 0, 41, 14, 35, SPR_IMG_AIRPORT, STR_A01E_BUILD_AIRPORT },
{ WWT_IMGBTN, RESIZE_NONE, 7, 42, 63, 14, 35, SPR_IMG_DYNAMITE, STR_018D_DEMOLISH_BUILDINGS_ETC },
{ WWT_IMGBTN, RESIZE_NONE, 7, 64, 85, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP },
{ WIDGETS_END},
};
static const WindowDesc _air_toolbar_desc = {
WDP_ALIGN_TBR, 22, 86, 36,
WC_BUILD_TOOLBAR, 0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
_air_toolbar_widgets,
BuildAirToolbWndProc
};
void ShowBuildAirToolbar(void)
{
if (!IsValidPlayer(_current_player)) return;
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
AllocateWindowDescFront(&_air_toolbar_desc, 0);
if (_patches.link_terraform_toolbar) ShowTerraformToolbar();
}
static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_CREATE:
SetWindowWidgetLoweredState(w, 16, !_station_show_coverage);
SetWindowWidgetLoweredState(w, 17, _station_show_coverage);
LowerWindowWidget(w, _selected_airport_type + 7);
break;
case WE_PAINT: {
int i; // airport enabling loop
int rad = 4; // default catchment radious
uint32 avail_airports;
const AirportFTAClass *airport;
if (WP(w,def_d).close) return;
avail_airports = GetValidAirports();
RaiseWindowWidget(w, _selected_airport_type + 7);
if (!HASBIT(avail_airports, 0) && _selected_airport_type == AT_SMALL) _selected_airport_type = AT_LARGE;
if (!HASBIT(avail_airports, 1) && _selected_airport_type == AT_LARGE) _selected_airport_type = AT_SMALL;
LowerWindowWidget(w, _selected_airport_type + 7);
/* 'Country Airport' starts at widget 7, and if its bit is set, it is
* available, so take its opposite value to set the disabled state.
* There are 9 buildable airports
* XXX TODO : all airports should be held in arrays, with all relevant data.
* This should be part of newgrf-airports, i suppose
*/
for (i = 0; i < 9; i++) SetWindowWidgetDisabledState(w, i + 7, !HASBIT(avail_airports, i));
// select default the coverage area to 'Off' (16)
airport = GetAirport(_selected_airport_type);
SetTileSelectSize(airport->size_x, airport->size_y);
if (_patches.modified_catchment) {
switch (_selected_airport_type) {
case AT_OILRIG: rad = CA_AIR_OILPAD; break;
case AT_HELIPORT: rad = CA_AIR_HELIPORT; break;
case AT_SMALL: rad = CA_AIR_SMALL; break;
case AT_LARGE: rad = CA_AIR_LARGE; break;
case AT_METROPOLITAN: rad = CA_AIR_METRO; break;
case AT_INTERNATIONAL: rad = CA_AIR_INTER; break;
case AT_COMMUTER: rad = CA_AIR_COMMUTER; break;
case AT_HELIDEPOT: rad = CA_AIR_HELIDEPOT; break;
case AT_INTERCON: rad = CA_AIR_INTERCON; break;
case AT_HELISTATION: rad = CA_AIR_HELISTATION; break;
}
}
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
DrawWindowWidgets(w);
// strings such as 'Size' and 'Coverage Area'
// 'Coverage Area'
DrawStationCoverageAreaText(2, 206, (uint)-1, rad);
break;
}
case WE_CLICK: {
switch (e->we.click.widget) {
case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 14: case 15:
RaiseWindowWidget(w, _selected_airport_type + 7);
_selected_airport_type = e->we.click.widget - 7;
LowerWindowWidget(w, _selected_airport_type + 7);
SndPlayFx(SND_15_BEEP);
SetWindowDirty(w);
break;
case 16: case 17:
_station_show_coverage = e->we.click.widget - 16;
SetWindowWidgetLoweredState(w, 16, !_station_show_coverage);
SetWindowWidgetLoweredState(w, 17, _station_show_coverage);
SndPlayFx(SND_15_BEEP);
SetWindowDirty(w);
break;
}
} break;
case WE_MOUSELOOP: {
if (WP(w,def_d).close) {
DeleteWindow(w);
return;
}
CheckRedrawStationCoverage(w);
} break;
case WE_DESTROY:
if (!WP(w,def_d).close) ResetObjectToPlace();
break;
}
}
static const Widget _build_airport_picker_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 147, 0, 13, STR_3001_AIRPORT_SELECTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 52, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 53, 89, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 90, 127, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 128, 177, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 178, 239, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 27, 38, STR_SMALL_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 65, 76, STR_CITY_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 141, 152, STR_HELIPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 77, 88, STR_METRO_AIRPORT , STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 103, 114, STR_INTERNATIONAL_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 39, 50, STR_COMMUTER_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 165, 176, STR_HELIDEPOT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 115, 126, STR_INTERCONTINENTAL_AIRPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 2, 145, 153, 164, STR_HELISTATION, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 14, 73, 191, 202, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
{ WWT_TEXTBTN, RESIZE_NONE, 14, 74, 133, 191, 202, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 14, 27, STR_SMALL_AIRPORTS, STR_NULL},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 52, 65, STR_LARGE_AIRPORTS, STR_NULL},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 90, 103, STR_HUB_AIRPORTS, STR_NULL},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 128, 141, STR_HELIPORTS, STR_NULL},
{ WWT_LABEL, RESIZE_NONE, 7, 0, 147, 178, 191, STR_3066_COVERAGE_AREA_HIGHLIGHT, STR_NULL},
{ WIDGETS_END},
};
static const WindowDesc _build_airport_desc = {
WDP_AUTO, WDP_AUTO, 148, 240,
WC_BUILD_STATION, WC_BUILD_TOOLBAR,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_build_airport_picker_widgets,
BuildAirportPickerWndProc
};
static void ShowBuildAirportPicker(void)
{
AllocateWindowDesc(&_build_airport_desc);
}
void InitializeAirportGui(void)
{
_selected_airport_type = AT_SMALL;
}

794
airport_movement.h Normal file
View File

@@ -0,0 +1,794 @@
/* $Id$ */
#ifndef AIRPORT_MOVEMENT_H
#define AIRPORT_MOVEMENT_H
// state machine input struct (from external file, etc.)
// Finite sTate mAchine --> FTA
typedef struct AirportFTAbuildup {
byte position; // the position that an airplane is at
byte heading; // the current orders (eg. TAKEOFF, HANGAR, ENDLANDING, etc.)
uint32 block; // the block this position is on on the airport (st->airport_flags)
byte next; // next position from this position
} AirportFTAbuildup;
///////////////////////////////////////////////////////////////////////
/////*********Movement Positions on Airports********************///////
// Country Airfield (small) 4x3
static const AirportMovingData _airport_moving_data_country[22] = {
{ 53, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
{ 53, 27, 0, 0 }, // 01 Taxi to right outside depot
{ 32, 23, AMED_EXACTPOS, 7 }, // 02 Terminal 1
{ 10, 23, AMED_EXACTPOS, 7 }, // 03 Terminal 2
{ 43, 37, 0, 0 }, // 04 Going towards terminal 2
{ 24, 37, 0, 0 }, // 05 Going towards terminal 2
{ 53, 37, 0, 0 }, // 06 Going for takeoff
{ 61, 40, AMED_EXACTPOS, 1 }, // 07 Taxi to start of runway (takeoff)
{ 3, 40, AMED_NOSPDCLAMP, 0 }, // 08 Accelerate to end of runway
{ -79, 40, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 09 Take off
{ 177, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 10 Fly to landing position in air
{ 56, 40, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 11 Going down for land
{ 3, 40, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 12 Just landed, brake until end of runway
{ 7, 40, 0, 0 }, // 13 Just landed, turn around and taxi 1 square
{ 53, 40, 0, 0 }, // 14 Taxi from runway to crossing
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 15 Fly around waiting for a landing spot (north-east)
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Fly around waiting for a landing spot (north-west)
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 17 Fly around waiting for a landing spot (south-west)
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Fly around waiting for a landing spot (south)
{ 44, 37, AMED_HELI_RAISE, 0 }, // 19 Helicopter takeoff
{ 44, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 In position above landing spot helicopter
{ 44, 40, AMED_HELI_LOWER, 0 }, // 21 Helicopter landing
};
// Commuter Airfield (small) 5x4
static const AirportMovingData _airport_moving_data_commuter[37] = {
{ 69, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
{ 72, 22, 0, 0 }, // 01 Taxi to right outside depot
{ 8, 22, AMED_EXACTPOS, 5 }, // 01 Taxi to right outside depot
{ 24, 36, AMED_EXACTPOS, 3 }, // 03 Terminal 1
{ 40, 36, AMED_EXACTPOS, 3 }, // 04 Terminal 2
{ 56, 36, AMED_EXACTPOS, 3 }, // 05 Terminal 3
{ 40, 8, AMED_EXACTPOS, 1 }, // 06 Helipad 1
{ 56, 8, AMED_EXACTPOS, 1 }, // 07 Helipad 2
{ 24, 22, 0, 5 }, // 08 Taxiing
{ 40, 22, 0, 5 }, // 09 Taxiing
{ 56, 22, 0, 5 }, // 10 Taxiing
{ 72, 40, 0, 3 }, // 11 Airport OUTWAY
{ 72, 54, AMED_EXACTPOS, 1 }, // 12 Accelerate to end of runway
{ 7, 54, AMED_NOSPDCLAMP, 0 }, // 13 Release control of runway, for smoother movement
{ 5, 54, AMED_NOSPDCLAMP, 0 }, // 14 End of runway
{ -79, 54, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 15 Take off
{ 145, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Fly to landing position in air
{ 73, 54, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 17 Going down for land
{ 3, 54, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 18 Just landed, brake until end of runway
{ 12, 54, 0, 7 }, // 19 Just landed, turn around and taxi
{ 8, 32, 0, 7 }, // 20 Taxi from runway to crossing
{ -31, 149, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (north-east)
{ 1, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 22 Fly around waiting for a landing spot (north-west)
{ 193, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 Fly around waiting for a landing spot (south-west)
{ 225, 81, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 24 Fly around waiting for a landing spot (south)
// Helicopter
{ 80, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Bufferspace before helipad
{ 80, 0, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 26 Bufferspace before helipad
{ 32, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 27 Get in position for Helipad1
{ 48, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 28 Get in position for Helipad2
{ 32, 8, AMED_HELI_LOWER, 0 }, // 29 Land at Helipad1
{ 48, 8, AMED_HELI_LOWER, 0 }, // 30 Land at Helipad2
{ 32, 8, AMED_HELI_RAISE, 0 }, // 31 Takeoff Helipad1
{ 48, 8, AMED_HELI_RAISE, 0 }, // 32 Takeoff Helipad2
{ 64, 22, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 33 Go to position for Hangarentrance in air
{ 64, 22, AMED_HELI_LOWER, 0 }, // 34 Land in front of hangar
{ 40, 8, AMED_EXACTPOS, 0 }, // pre-helitakeoff helipad 1
{ 56, 8, AMED_EXACTPOS, 0 }, // pre-helitakeoff helipad 2
};
// City Airport (large) 6x6
static const AirportMovingData _airport_moving_data_town[25] = {
{ 85, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
{ 85, 27, 0, 0 }, // 01 Taxi to right outside depot
{ 26, 41, AMED_EXACTPOS, 5 }, // 02 Terminal 1
{ 56, 20, AMED_EXACTPOS, 3 }, // 03 Terminal 2
{ 38, 8, AMED_EXACTPOS, 5 }, // 04 Terminal 3
{ 65, 6, 0, 0 }, // 05 Taxi to right in infront of terminal 2/3
{ 80, 27, 0, 0 }, // 06 Taxiway terminals 2-3
{ 44, 63, 0, 0 }, // 07 Taxi to Airport center
{ 58, 71, 0, 0 }, // 08 Towards takeoff
{ 72, 85, 0, 0 }, // 09 Taxi to runway (takeoff)
{ 89, 85, AMED_EXACTPOS, 1 }, // 10 Taxi to start of runway (takeoff)
{ 3, 85, AMED_NOSPDCLAMP, 0 }, // 11 Accelerate to end of runway
{ -79, 85, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 12 Take off
{ 177, 85, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 13 Fly to landing position in air
{ 89, 85, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 14 Going down for land
{ 3, 85, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 15 Just landed, brake until end of runway
{ 20, 87, 0, 0 }, // 16 Just landed, turn around and taxi 1 square
{ 36, 71, 0, 0 }, // 17 Taxi from runway to crossing
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Fly around waiting for a landing spot (north-east)
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 19 Fly around waiting for a landing spot (north-west)
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 Fly around waiting for a landing spot (south-west)
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (south)
{ 44, 63, AMED_HELI_RAISE, 0 }, // 22 Helicopter takeoff
{ 28, 74, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 In position above landing spot helicopter
{ 28, 74, AMED_HELI_LOWER, 0 }, // 24 Helicopter landing
};
// Metropolitan Airport (metropolitan) - 2 runways
static const AirportMovingData _airport_moving_data_metropolitan[27] = {
{ 85, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar
{ 85, 27, 0, 0 }, // 01 Taxi to right outside depot
{ 26, 41, AMED_EXACTPOS, 5 }, // 02 Terminal 1
{ 56, 20, AMED_EXACTPOS, 3 }, // 03 Terminal 2
{ 38, 8, AMED_EXACTPOS, 5 }, // 04 Terminal 3
{ 65, 6, 0, 0 }, // 05 Taxi to right in infront of terminal 2/3
{ 70, 33, 0, 0 }, // 06 Taxiway terminals 2-3
{ 44, 58, 0, 0 }, // 07 Taxi to Airport center
{ 72, 58, 0, 0 }, // 08 Towards takeoff
{ 72, 69, 0, 0 }, // 09 Taxi to runway (takeoff)
{ 89, 69, AMED_EXACTPOS, 1 }, // 10 Taxi to start of runway (takeoff)
{ 3, 69, AMED_NOSPDCLAMP, 0 }, // 11 Accelerate to end of runway
{ -79, 69, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 12 Take off
{ 177, 85, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 13 Fly to landing position in air
{ 89, 85, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 14 Going down for land
{ 3, 85, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 15 Just landed, brake until end of runway
{ 21, 85, 0, 0 }, // 16 Just landed, turn around and taxi 1 square
{ 21, 69, 0, 0 }, // 17 On Runway-out taxiing to In-Way
{ 21, 54, AMED_EXACTPOS, 5 }, // 18 Taxi from runway to crossing
{ -31, 193, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 19 Fly around waiting for a landing spot (north-east)
{ 1, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 20 Fly around waiting for a landing spot (north-west)
{ 257, 1, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 21 Fly around waiting for a landing spot (south-west)
{ 273, 49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 22 Fly around waiting for a landing spot (south)
{ 44, 58, 0, 0 }, // 23 Helicopter takeoff spot on ground (to clear airport sooner)
{ 44, 63, AMED_HELI_RAISE, 0 }, // 24 Helicopter takeoff
{ 15, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Get in position above landing spot helicopter
{ 15, 54, AMED_HELI_LOWER, 0 }, // 26 Helicopter landing
};
// International Airport (international) - 2 runways, 6 terminals, dedicated helipod
static const AirportMovingData _airport_moving_data_international[51] = {
{ 7, 55, AMED_EXACTPOS, 3 }, // 00 In Hangar 1
{ 100, 21, AMED_EXACTPOS, 3 }, // 01 In Hangar 2
{ 7, 70, 0, 0 }, // 02 Taxi to right outside depot
{ 100, 36, 0, 0 }, // 03 Taxi to right outside depot
{ 38, 70, AMED_EXACTPOS, 5 }, // 04 Terminal 1
{ 38, 54, AMED_EXACTPOS, 5 }, // 05 Terminal 2
{ 38, 38, AMED_EXACTPOS, 5 }, // 06 Terminal 3
{ 70, 70, AMED_EXACTPOS, 1 }, // 07 Terminal 4
{ 70, 54, AMED_EXACTPOS, 1 }, // 08 Terminal 5
{ 70, 38, AMED_EXACTPOS, 1 }, // 09 Terminal 6
{ 104, 71, AMED_EXACTPOS, 1 }, // 10 Helipad 1
{ 104, 55, AMED_EXACTPOS, 1 }, // 11 Helipad 2
{ 22, 87, 0, 0 }, // 12 Towards Terminals 4/5/6, Helipad 1/2
{ 60, 87, 0, 0 }, // 13 Towards Terminals 4/5/6, Helipad 1/2
{ 66, 87, 0, 0 }, // 14 Towards Terminals 4/5/6, Helipad 1/2
{ 86, 87, AMED_EXACTPOS, 7 }, // 15 Towards Terminals 4/5/6, Helipad 1/2
{ 86, 70, 0, 0 }, // 16 In Front of Terminal 4 / Helipad 1
{ 86, 54, 0, 0 }, // 17 In Front of Terminal 5 / Helipad 2
{ 86, 38, 0, 0 }, // 18 In Front of Terminal 6
{ 86, 22, 0, 0 }, // 19 Towards Terminals Takeoff (Taxiway)
{ 66, 22, 0, 0 }, // 20 Towards Terminals Takeoff (Taxiway)
{ 60, 22, 0, 0 }, // 21 Towards Terminals Takeoff (Taxiway)
{ 38, 22, 0, 0 }, // 22 Towards Terminals Takeoff (Taxiway)
{ 22, 70, 0, 0 }, // 23 In Front of Terminal 1
{ 22, 58, 0, 0 }, // 24 In Front of Terminal 2
{ 22, 38, 0, 0 }, // 25 In Front of Terminal 3
{ 22, 22, AMED_EXACTPOS, 7 }, // 26 Going for Takeoff
{ 22, 6, 0, 0 }, // 27 On Runway-out, prepare for takeoff
{ 3, 6, AMED_EXACTPOS, 5 }, // 28 Accelerate to end of runway
{ 60, 6, AMED_NOSPDCLAMP, 0 }, // 29 Release control of runway, for smoother movement
{ 105, 6, AMED_NOSPDCLAMP, 0 }, // 30 End of runway
{ 190, 6, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 31 Take off
{ 193, 104, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 32 Fly to landing position in air
{ 105, 104, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 33 Going down for land
{ 3, 104, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 34 Just landed, brake until end of runway
{ 12, 104, 0, 0 }, // 35 Just landed, turn around and taxi 1 square
{ 7, 84, 0, 0 }, // 36 Taxi from runway to crossing
{ -31, 209, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 37 Fly around waiting for a landing spot (north-east)
{ 1, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 38 Fly around waiting for a landing spot (north-west)
{ 273, 6, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 39 Fly around waiting for a landing spot (south-west)
{ 305, 81, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 40 Fly around waiting for a landing spot (south)
// Helicopter
{ 128, 80, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 41 Bufferspace before helipad
{ 128, 80, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 42 Bufferspace before helipad
{ 96, 71, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 43 Get in position for Helipad1
{ 96, 55, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 44 Get in position for Helipad2
{ 96, 71, AMED_HELI_LOWER, 0 }, // 45 Land at Helipad1
{ 96, 55, AMED_HELI_LOWER, 0 }, // 46 Land at Helipad2
{ 104, 71, AMED_HELI_RAISE, 0 }, // 47 Takeoff Helipad1
{ 104, 55, AMED_HELI_RAISE, 0 }, // 48 Takeoff Helipad2
{ 104, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 49 Go to position for Hangarentrance in air
{ 104, 32, AMED_HELI_LOWER, 0} // 50 Land in HANGAR2_AREA to go to hangar
};
// Intercontinental Airport - 4 runways, 8 terminals, 2 dedicated helipads
static const AirportMovingData _airport_moving_data_intercontinental[77] = {
{ 7, 87, AMED_EXACTPOS, 3 }, // 00 In Hangar 1
{ 135, 72, AMED_EXACTPOS, 3 }, // 01 In Hangar 2
{ 7, 104, 0, 0 }, // 02 Taxi to right outside depot 1
{ 135, 88, 0, 0 }, // 03 Taxi to right outside depot 2
{ 56, 120, AMED_EXACTPOS, 6 }, // 04 Terminal 1
{ 56, 104, AMED_EXACTPOS, 5 }, // 05 Terminal 2
{ 56, 88, AMED_EXACTPOS, 5 }, // 06 Terminal 3
{ 56, 72, AMED_EXACTPOS, 5 }, // 07 Terminal 4
{ 88, 120, AMED_EXACTPOS, 0 }, // 08 Terminal 5
{ 88, 104, AMED_EXACTPOS, 1 }, // 09 Terminal 6
{ 88, 88, AMED_EXACTPOS, 1 }, // 10 Terminal 7
{ 88, 72, AMED_EXACTPOS, 1 }, // 11 Terminal 8
{ 88, 56, AMED_EXACTPOS, 3 }, // 12 Helipad 1
{ 72, 56, AMED_EXACTPOS, 1 }, // 13 Helipad 2
{ 40, 136, 0, 0 }, // 14 Term group 2 enter 1 a
{ 56, 136, 0, 0 }, // 15 Term group 2 enter 1 b
{ 88, 136, 0, 0 }, // 16 Term group 2 enter 2 a
{ 104, 136, 0, 0 }, // 17 Term group 2 enter 2 b
{ 104, 120, 0, 0 }, // 18 Term group 2 - opp term 5
{ 104, 104, 0, 0 }, // 19 Term group 2 - opp term 6 & exit2
{ 104, 88, 0, 0 }, // 20 Term group 2 - opp term 7 & hangar area 2
{ 104, 72, 0, 0 }, // 21 Term group 2 - opp term 8
{ 104, 56, 0, 0 }, // 22 Taxi Term group 2 exit a
{ 104, 40, 0, 0 }, // 23 Taxi Term group 2 exit b
{ 56, 40, 0, 0 }, // 24 Term group 2 exit 2a
{ 40, 40, 0, 0 }, // 25 Term group 2 exit 2b
{ 40, 120, 0, 0 }, // 26 Term group 1 - opp term 1
{ 40, 104, 0, 0 }, // 27 Term group 1 - opp term 2 & hangar area 1
{ 40, 88, 0, 0 }, // 28 Term group 1 - opp term 3
{ 40, 72, 0, 0 }, // 29 Term group 1 - opp term 4
{ 18, 72, 0, 7 }, // 30 Outway 1
{ 8, 40, 0, 7 }, // 31 Airport OUTWAY
{ 8, 24, AMED_EXACTPOS, 5 }, // 32 Accelerate to end of runway
{ 119, 24, AMED_NOSPDCLAMP, 0 }, // 33 Release control of runway, for smoother movement
{ 117, 24, AMED_NOSPDCLAMP, 0 }, // 34 End of runway
{ 197, 24, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 35 Take off
{ 254, 84, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 36 Flying to landing position in air
{ 117, 168, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 37 Going down for land
{ 3, 168, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 38 Just landed, brake until end of runway
{ 8, 168, 0, 0 }, // 39 Just landed, turn around and taxi
{ 8, 144, 0, 7 }, // 40 Taxi from runway
{ 8, 128, 0, 7 }, // 41 Taxi from runway
{ 8, 120, AMED_EXACTPOS, 5 }, // 42 Airport entrance
{ 56, 344, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 43 Fly around waiting for a landing spot (north-east)
{ -200, 88, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 44 Fly around waiting for a landing spot (north-west)
{ 56, -168, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 45 Fly around waiting for a landing spot (south-west)
{ 312, 88, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 46 Fly around waiting for a landing spot (south)
// Helicopter
{ 96, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 47 Bufferspace before helipad
{ 96, 40, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 48 Bufferspace before helipad
{ 82, 54, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 49 Get in position for Helipad1
{ 64, 56, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 50 Get in position for Helipad2
{ 81, 55, AMED_HELI_LOWER, 0 }, // 51 Land at Helipad1
{ 64, 56, AMED_HELI_LOWER, 0 }, // 52 Land at Helipad2
{ 80, 56, AMED_HELI_RAISE, 0 }, // 53 Takeoff Helipad1
{ 64, 56, AMED_HELI_RAISE, 0 }, // 54 Takeoff Helipad2
{ 136, 96, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 55 Go to position for Hangarentrance in air
{ 136, 96, AMED_HELI_LOWER, 0 }, // 56 Land in front of hangar2
{ 126, 104, 0, 3 }, // 57 Outway 2
{ 136, 136, 0, 1 }, // 58 Airport OUTWAY 2
{ 136, 152, AMED_EXACTPOS, 5 }, // 59 Accelerate to end of runway2
{ 16, 152, AMED_NOSPDCLAMP, 0 }, // 60 Release control of runway2, for smoother movement
{ 20, 152, AMED_NOSPDCLAMP, 0 }, // 61 End of runway2
{ -56, 152, AMED_NOSPDCLAMP | AMED_TAKEOFF, 0 }, // 62 Take off2
{ 24, 8, AMED_NOSPDCLAMP | AMED_LAND, 0 }, // 63 Going down for land2
{ 136, 8, AMED_NOSPDCLAMP | AMED_BRAKE, 0 }, // 64 Just landed, brake until end of runway2in
{ 136, 8, 0, 0 }, // 65 Just landed, turn around and taxi
{ 136, 24, 0, 3 }, // 66 Taxi from runway 2in
{ 136, 40, 0, 3 }, // 67 Taxi from runway 2in
{ 136, 56, AMED_EXACTPOS, 1 }, // 68 Airport entrance2
{ -56, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 69 Fly to landing position in air2
{ 88, 40, 0, 0 }, // 70 Taxi Term group 2 exit - opp heli1
{ 72, 40, 0, 0 }, // 71 Taxi Term group 2 exit - opp heli2
{ 88, 57, AMED_EXACTPOS, 3 }, // 72 pre-helitakeoff helipad 1
{ 71, 56, AMED_EXACTPOS, 1 }, // 73 pre-helitakeoff helipad 2
{ 8, 120, AMED_HELI_RAISE, 0 }, // 74 Helitakeoff outside depot 1
{ 136, 104, AMED_HELI_RAISE, 0 }, // 75 Helitakeoff outside depot 2
{ 197, 168, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0} // 76 Fly to landing position in air1
};
// Heliport (heliport)
static const AirportMovingData _airport_moving_data_heliport[9] = {
{ 5, 9, AMED_EXACTPOS, 1 }, // 0 - At heliport terminal
{ 2, 9, AMED_HELI_RAISE, 0 }, // 1 - Take off (play sound)
{ -3, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 - In position above landing spot helicopter
{ -3, 9, AMED_HELI_LOWER, 0 }, // 3 - Land
{ 2, 9, 0, 0 }, // 4 - Goto terminal on ground
{ -31, 59, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - Circle #1 (north-east)
{ -31, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - Circle #2 (north-west)
{ 49, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 7 - Circle #3 (south-west)
{ 70, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 8 - Circle #4 (south)
};
// HeliDepot 2x2 (heliport)
static const AirportMovingData _airport_moving_data_helidepot[18] = {
{ 24, 4, AMED_EXACTPOS, 1 }, // 0 - At depot
{ 24, 28, 0, 0 }, // 1 Taxi to right outside depot
{ 5, 38, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 Flying
{ -15, -15, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 3 - Circle #1 (north-east)
{ -15, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 4 - Circle #2 (north-west)
{ 49, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - Circle #3 (south-west)
{ 49, -15, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - Circle #4 (south-east)
{ 8, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 7 - PreHelipad
{ 8, 32, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 8 - Helipad
{ 8, 16, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 9 - Land
{ 8, 16, AMED_HELI_LOWER, 7 }, // 10 - Land
{ 8, 24, AMED_HELI_RAISE, 0 }, // 11 - Take off (play sound)
{ 32, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 7 }, // 12 Air to above hangar area
{ 32, 24, AMED_HELI_LOWER, 7 }, // 13 Taxi to right outside depot
{ 8, 24, AMED_EXACTPOS, 7 }, // 14 - on helipad1
{ 24, 28, AMED_HELI_RAISE, 0 }, // 15 Takeoff right outside depot
{ 8, 24, AMED_HELI_RAISE, 5 }, // 16 - Take off (play sound)
{ 8, 24, AMED_SLOWTURN | AMED_EXACTPOS, 2 }, // 17 - turn on helipad1 for takeoff
};
// HeliDepot 2x2 (heliport)
static const AirportMovingData _airport_moving_data_helistation[33] = {
{ 8, 3, AMED_EXACTPOS, 3 }, // 00 In Hangar2
{ 8, 22, 0, 0 }, // 01 outside hangar 2
{ 116, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 02 Fly to landing position in air
{ 14, 22, AMED_HELI_RAISE, 0 }, // 03 Helitakeoff outside hangar1(play sound)
{ 24, 22, 0, 0 }, // 04 taxiing
{ 40, 22, 0, 0 }, // 05 taxiing
{ 40, 8, AMED_EXACTPOS, 1 }, // 06 Helipad 1
{ 56, 8, AMED_EXACTPOS, 1 }, // 07 Helipad 2
{ 56, 24, AMED_EXACTPOS, 1 }, // 08 Helipad 3
{ 40, 8, AMED_EXACTPOS, 0 }, // 09 pre-helitakeoff helipad 1
{ 56, 8, AMED_EXACTPOS, 0 }, // 10 pre-helitakeoff helipad 2
{ 56, 24, AMED_EXACTPOS, 0 }, // 11 pre-helitakeoff helipad 3
{ 32, 8, AMED_HELI_RAISE, 0 }, // 12 Takeoff Helipad1
{ 48, 8, AMED_HELI_RAISE, 0 }, // 13 Takeoff Helipad2
{ 48, 24, AMED_HELI_RAISE, 0 }, // 14 Takeoff Helipad3
{ 84, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 15 Bufferspace before helipad
{ 68, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 16 Bufferspace before helipad
{ 32, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 17 Get in position for Helipad1
{ 48, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 18 Get in position for Helipad2
{ 48, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 1 }, // 19 Get in position for Helipad3
{ 40, 8, AMED_HELI_LOWER, 0 }, // 20 Land at Helipad1
{ 48, 8, AMED_HELI_LOWER, 0 }, // 21 Land at Helipad2
{ 48, 24, AMED_HELI_LOWER, 0 }, // 22 Land at Helipad3
{ 0, 22, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 23 Go to position for Hangarentrance in air
{ 0, 22, AMED_HELI_LOWER, 0 }, // 24 Land in front of hangar
{ 148, -8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 25 Fly around waiting for a landing spot (south-east)
{ 148, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 26 Fly around waiting for a landing spot (south-west)
{ 132, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 27 Fly around waiting for a landing spot (south-west)
{ 100, 24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 28 Fly around waiting for a landing spot (north-east)
{ 84, 8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 29 Fly around waiting for a landing spot (south-east)
{ 84, -8, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 30 Fly around waiting for a landing spot (south-west)
{ 100, -24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 31 Fly around waiting for a landing spot (north-west)
{ 132, -24, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 32 Fly around waiting for a landing spot (north-east)
};
// Oilrig
static const AirportMovingData _airport_moving_data_oilrig[9] = {
{ 31, 9, AMED_EXACTPOS, 1 }, // 0 - At oilrig terminal
{ 28, 9, AMED_HELI_RAISE, 0 }, // 1 - Take off (play sound)
{ 23, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 2 - In position above landing spot helicopter
{ 23, 9, AMED_HELI_LOWER, 0 }, // 3 - Land
{ 28, 9, 0, 0 }, // 4 - Goto terminal on ground
{ -31, 69, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 5 - circle #1 (north-east)
{ -31, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 6 - circle #2 (north-west)
{ 69, -49, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 7 - circle #3 (south-west)
{ 70, 9, AMED_NOSPDCLAMP | AMED_SLOWTURN, 0 }, // 8 - circle #4 (south)
};
///////////////////////////////////////////////////////////////////////
/////**********Movement Machine on Airports*********************///////
/* First element of terminals array tells us how many depots there are (to know size of array)
* this may be changed later when airports are moved to external file */
static const TileIndexDiffC _airport_depots_country[] = {{3, 0}};
static const byte _airport_terminal_country[] = {1, 2};
static const AirportFTAbuildup _airport_fta_country[] = {
{ 0, HANGAR, NOTHING_block, 1 },
{ 1, 255, AIRPORT_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM1, TERM1_block, 2 }, { 1, TERM2, 0, 4 }, { 1, HELITAKEOFF, 0, 19 }, { 1, 0, 0, 6 },
{ 2, TERM1, TERM1_block, 1 },
{ 3, TERM2, TERM2_block, 5 },
{ 4, 255, AIRPORT_BUSY_block, 0 }, { 4, TERM2, 0, 5 }, { 4, HANGAR, 0, 1 }, { 4, TAKEOFF, 0, 6 }, { 4, HELITAKEOFF, 0, 1 },
{ 5, 255, AIRPORT_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, 0, 0, 4 },
{ 6, 0, AIRPORT_BUSY_block, 7 },
// takeoff
{ 7, TAKEOFF, AIRPORT_BUSY_block, 8 },
{ 8, STARTTAKEOFF, NOTHING_block, 9 },
{ 9, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 10, FLYING, NOTHING_block, 15 }, { 10, LANDING, 0, 11 }, { 10, HELILANDING, 0, 20 },
{ 11, LANDING, AIRPORT_BUSY_block, 12 },
{ 12, 0, AIRPORT_BUSY_block, 13 },
{ 13, ENDLANDING, AIRPORT_BUSY_block, 14 }, { 13, TERM2, 0, 5 }, { 13, 0, 0, 14 },
{ 14, 0, AIRPORT_BUSY_block, 1 },
// In air
{ 15, 0, NOTHING_block, 16 },
{ 16, 0, NOTHING_block, 17 },
{ 17, 0, NOTHING_block, 18 },
{ 18, 0, NOTHING_block, 10 },
{ 19, HELITAKEOFF, NOTHING_block, 0 },
{ 20, HELILANDING, AIRPORT_BUSY_block, 21 },
{ 21, HELIENDLANDING, AIRPORT_BUSY_block, 1 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
static const TileIndexDiffC _airport_depots_commuter[] = { { 4, 0 } };
static const byte _airport_terminal_commuter[] = { 1, 3 };
static const byte _airport_helipad_commuter[] = { 1, 2 };
static const AirportFTAbuildup _airport_fta_commuter[] = {
{ 0, HANGAR, NOTHING_block, 1 }, { 0, HELITAKEOFF, HELIPAD2_block, 1 }, { 0, 0, 0, 1 },
{ 1, 255, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TAKEOFF, 0, 11 }, { 1, TERM1, TAXIWAY_BUSY_block, 10 }, { 1, TERM2, TAXIWAY_BUSY_block, 10 }, { 1, TERM3, TAXIWAY_BUSY_block, 10 }, { 1, HELIPAD1, TAXIWAY_BUSY_block, 10 }, { 1, HELIPAD2, TAXIWAY_BUSY_block, 10 }, { 1, HELITAKEOFF, TAXIWAY_BUSY_block, 10 }, { 1, 0, 0, 0 },
{ 2, 255, AIRPORT_ENTRANCE_block, 2 }, { 2, HANGAR, 0, 8 }, { 2, TERM1, 0, 8 }, { 2, TERM2, 0, 8 }, { 2, TERM3, 0, 8 }, { 2, HELIPAD1, 0, 8 }, { 2, HELIPAD2, 0, 8 }, { 2, HELITAKEOFF, 0, 8 }, { 2, 0, 0, 2 },
{ 3, TERM1, TERM1_block, 8 }, { 3, HANGAR, 0, 8 }, { 3, TAKEOFF, 0, 8 }, { 3, 0, 0, 3 },
{ 4, TERM2, TERM2_block, 9 }, { 4, HANGAR, 0, 9 }, { 4, TAKEOFF, 0, 9 }, { 4, 0, 0, 4 },
{ 5, TERM3, TERM3_block, 10 }, { 5, HANGAR, 0, 10 }, { 5, TAKEOFF, 0, 10 }, { 5, 0, 0, 5 },
{ 6, HELIPAD1, HELIPAD1_block, 6 }, { 6, HANGAR, TAXIWAY_BUSY_block, 9 }, { 6, HELITAKEOFF, 0, 35 },
{ 7, HELIPAD2, HELIPAD2_block, 7 }, { 7, HANGAR, TAXIWAY_BUSY_block, 10 }, { 7, HELITAKEOFF, 0, 36 },
{ 8, 255, TAXIWAY_BUSY_block, 8 }, { 8, TAKEOFF, TAXIWAY_BUSY_block, 9 }, { 8, HANGAR, TAXIWAY_BUSY_block, 9 }, { 8, TERM1, TERM1_block, 3 }, { 8, 0, TAXIWAY_BUSY_block, 9 },
{ 9, 255, TAXIWAY_BUSY_block, 9 }, { 9, TAKEOFF, TAXIWAY_BUSY_block, 10 }, { 9, HANGAR, TAXIWAY_BUSY_block, 10 }, { 9, TERM2, TERM2_block, 4 }, { 9, HELIPAD1, HELIPAD1_block, 6 }, { 9, HELITAKEOFF, HELIPAD1_block, 6 }, { 9, TERM1, TAXIWAY_BUSY_block, 8 }, { 9, 0, TAXIWAY_BUSY_block, 10 },
{ 10, 255, TAXIWAY_BUSY_block, 10 }, { 10, TERM3, TERM3_block, 5 }, { 10, HELIPAD1, 0, 9 }, { 10, HELIPAD2, HELIPAD2_block, 7 }, { 10, HELITAKEOFF, HELIPAD2_block, 7 }, { 10, TAKEOFF, TAXIWAY_BUSY_block, 1 }, { 10, HANGAR, TAXIWAY_BUSY_block, 1 }, { 10, 0, TAXIWAY_BUSY_block, 9 },
{ 11, 0, OUT_WAY_block, 12 },
// takeoff
{ 12, TAKEOFF, RUNWAY_IN_OUT_block, 13 },
{ 13, 0, RUNWAY_IN_OUT_block, 14 },
{ 14, STARTTAKEOFF, RUNWAY_IN_OUT_block, 15 },
{ 15, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 16, FLYING, NOTHING_block, 21 }, { 16, LANDING, IN_WAY_block, 17 }, { 16, HELILANDING, 0, 25 },
{ 17, LANDING, RUNWAY_IN_OUT_block, 18 },
{ 18, 0, RUNWAY_IN_OUT_block, 19 },
{ 19, 0, RUNWAY_IN_OUT_block, 20 },
{ 20, ENDLANDING, IN_WAY_block, 2 },
// In Air
{ 21, 0, NOTHING_block, 22 },
{ 22, 0, NOTHING_block, 23 },
{ 23, 0, NOTHING_block, 24 },
{ 24, 0, NOTHING_block, 16 },
// Helicopter -- stay in air in special place as a buffer to choose from helipads
{ 25, HELILANDING, PRE_HELIPAD_block, 26 },
{ 26, HELIENDLANDING, PRE_HELIPAD_block, 26 }, { 26, HELIPAD1, 0, 27 }, { 26, HELIPAD2, 0, 28 }, { 26, HANGAR, 0, 33 },
{ 27, 0, NOTHING_block, 29 }, //helipad1 approach
{ 28, 0, NOTHING_block, 30 },
// landing
{ 29, 255, NOTHING_block, 0 }, { 29, HELIPAD1, HELIPAD1_block, 6 },
{ 30, 255, NOTHING_block, 0 }, { 30, HELIPAD2, HELIPAD2_block, 7 },
// Helicopter -- takeoff
{ 31, HELITAKEOFF, NOTHING_block, 0 },
{ 32, HELITAKEOFF, NOTHING_block, 0 },
{ 33, 0, TAXIWAY_BUSY_block, 34 }, // need to go to hangar when waiting in air
{ 34, 0, TAXIWAY_BUSY_block, 1 },
{ 35, 0, HELIPAD1_block, 31 },
{ 36, 0, HELIPAD2_block, 32 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
static const TileIndexDiffC _airport_depots_city[] = { { 5, 0 } };
static const byte _airport_terminal_city[] = { 1, 3 };
static const AirportFTAbuildup _airport_fta_city[] = {
{ 0, HANGAR, NOTHING_block, 1 }, { 0, TAKEOFF, OUT_WAY_block, 1 }, { 0, 0, 0, 1 },
{ 1, 255, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM2, 0, 6 }, { 1, TERM3, 0, 6 }, { 1, 0, 0, 7 }, // for all else, go to 7
{ 2, TERM1, TERM1_block, 7 }, { 2, TAKEOFF, OUT_WAY_block, 7 }, { 2, 0, 0, 7 },
{ 3, TERM2, TERM2_block, 5 }, { 3, TAKEOFF, OUT_WAY_block, 5 }, { 3, 0, 0, 5 },
{ 4, TERM3, TERM3_block, 5 }, { 4, TAKEOFF, OUT_WAY_block, 5 }, { 4, 0, 0, 5 },
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TERM3, TERM3_block, 4 }, { 5, 0, 0, 6 },
{ 6, 255, TAXIWAY_BUSY_block, 0 }, { 6, TERM2, 0, 5 }, { 6, TERM3, 0, 5 }, { 6, HANGAR, 0, 1 }, { 6, 0, 0, 7 },
{ 7, 255, TAXIWAY_BUSY_block, 0 }, { 7, TERM1, TERM1_block, 2 }, { 7, TAKEOFF, OUT_WAY_block, 8 }, { 7, HELITAKEOFF, 0, 22 }, { 7, HANGAR, 0, 1 }, { 7, 0, 0, 6 },
{ 8, 0, OUT_WAY_block, 9 },
{ 9, 0, RUNWAY_IN_OUT_block, 10 },
// takeoff
{ 10, TAKEOFF, RUNWAY_IN_OUT_block, 11 },
{ 11, STARTTAKEOFF, NOTHING_block, 12 },
{ 12, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 13, FLYING, NOTHING_block, 18 }, { 13, LANDING, 0, 14 }, { 13, HELILANDING, 0, 23 },
{ 14, LANDING, RUNWAY_IN_OUT_block, 15 },
{ 15, 0, RUNWAY_IN_OUT_block, 16 },
{ 16, 0, RUNWAY_IN_OUT_block, 17 },
{ 17, ENDLANDING, IN_WAY_block, 7 },
// In Air
{ 18, 0, NOTHING_block, 19 },
{ 19, 0, NOTHING_block, 20 },
{ 20, 0, NOTHING_block, 21 },
{ 21, 0, NOTHING_block, 13 },
// helicopter
{ 22, HELITAKEOFF, NOTHING_block, 0 },
{ 23, HELILANDING, IN_WAY_block, 24 },
{ 24, HELIENDLANDING, IN_WAY_block, 17 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
static const TileIndexDiffC _airport_depots_metropolitan[] = { { 5, 0 } };
static const byte _airport_terminal_metropolitan[] = { 1, 3 };
static const AirportFTAbuildup _airport_fta_metropolitan[] = {
{ 0, HANGAR, NOTHING_block, 1 },
{ 1, 255, TAXIWAY_BUSY_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, TERM2, 0, 6 }, { 1, TERM3, 0, 6 }, { 1, 0, 0, 7 }, // for all else, go to 7
{ 2, TERM1, TERM1_block, 7 },
{ 3, TERM2, TERM2_block, 5 },
{ 4, TERM3, TERM3_block, 5 },
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, TERM2, TERM2_block, 3 }, { 5, TERM3, TERM3_block, 4 }, { 5, 0, 0, 6 },
{ 6, 255, TAXIWAY_BUSY_block, 0 }, { 6, TERM2, 0, 5 }, { 6, TERM3, 0, 5 }, { 6, HANGAR, 0, 1 }, { 6, 0, 0, 7 },
{ 7, 255, TAXIWAY_BUSY_block, 0 }, { 7, TERM1, TERM1_block, 2 }, { 7, TAKEOFF, 0, 8 }, { 7, HELITAKEOFF, 0, 23 }, { 7, HANGAR, 0, 1 }, { 7, 0, 0, 6 },
{ 8, 0, OUT_WAY_block, 9 },
{ 9, 0, RUNWAY_OUT_block, 10 },
// takeoff
{ 10, TAKEOFF, RUNWAY_OUT_block, 11 },
{ 11, STARTTAKEOFF, NOTHING_block, 12 },
{ 12, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 13, FLYING, NOTHING_block, 19 }, { 13, LANDING, 0, 14 }, { 13, HELILANDING, 0, 25 },
{ 14, LANDING, RUNWAY_IN_block, 15 },
{ 15, 0, RUNWAY_IN_block, 16 },
{ 16, 255, RUNWAY_IN_block, 0 }, { 16, ENDLANDING, IN_WAY_block, 17 },
{ 17, 255, RUNWAY_OUT_block, 0 }, { 17, ENDLANDING, IN_WAY_block, 18 },
{ 18, ENDLANDING, IN_WAY_block, 7 },
// In Air
{ 19, 0, NOTHING_block, 20 },
{ 20, 0, NOTHING_block, 21 },
{ 21, 0, NOTHING_block, 22 },
{ 22, 0, NOTHING_block, 13 },
// helicopter
{ 23, 0, NOTHING_block, 24 },
{ 24, HELITAKEOFF, NOTHING_block, 0 },
{ 25, HELILANDING, IN_WAY_block, 26 },
{ 26, HELIENDLANDING, IN_WAY_block, 18 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
static const TileIndexDiffC _airport_depots_international[] = { { 0, 3 }, { 6, 1 } };
static const byte _airport_terminal_international[] = { 2, 3, 3 };
static const byte _airport_helipad_international[] = { 1, 2 };
static const AirportFTAbuildup _airport_fta_international[] = {
{ 0, HANGAR, NOTHING_block, 2 }, { 0, 255, TERM_GROUP1_block, 0 }, { 0, 255, TERM_GROUP2_ENTER1_block, 1 }, { 0, HELITAKEOFF, HELIPAD1_block, 2 }, { 0, 0, 0, 2 },
{ 1, HANGAR, NOTHING_block, 3 }, { 1, 255, HANGAR2_AREA_block, 1 }, { 1, HELITAKEOFF, HELIPAD2_block, 3 }, { 1, 0, 0, 3 },
{ 2, 255, AIRPORT_ENTRANCE_block, 0 }, { 2, HANGAR, 0, 0 }, { 2, TERM4, 0, 12 }, { 2, TERM5, 0, 12 }, { 2, TERM6, 0, 12 }, { 2, HELIPAD1, 0, 12 }, { 2, HELIPAD2, 0, 12 }, { 2, HELITAKEOFF, 0, 12 }, { 2, 0, 0, 23 },
{ 3, 255, HANGAR2_AREA_block, 0 }, { 3, HANGAR, 0, 1 }, { 3, 0, 0, 18 },
{ 4, TERM1, TERM1_block, 23 }, { 4, HANGAR, AIRPORT_ENTRANCE_block, 23 }, { 4, 0, 0, 23 },
{ 5, TERM2, TERM2_block, 24 }, { 5, HANGAR, AIRPORT_ENTRANCE_block, 24 }, { 5, 0, 0, 24 },
{ 6, TERM3, TERM3_block, 25 }, { 6, HANGAR, AIRPORT_ENTRANCE_block, 25 }, { 6, 0, 0, 25 },
{ 7, TERM4, TERM4_block, 16 }, { 7, HANGAR, HANGAR2_AREA_block, 16 }, { 7, 0, 0, 16 },
{ 8, TERM5, TERM5_block, 17 }, { 8, HANGAR, HANGAR2_AREA_block, 17 }, { 8, 0, 0, 17 },
{ 9, TERM6, TERM6_block, 18 }, { 9, HANGAR, HANGAR2_AREA_block, 18 }, { 9, 0, 0, 18 },
{ 10, HELIPAD1, HELIPAD1_block, 10 }, { 10, HANGAR, HANGAR2_AREA_block, 16 }, { 10, HELITAKEOFF, 0, 47 },
{ 11, HELIPAD2, HELIPAD2_block, 11 }, { 11, HANGAR, HANGAR2_AREA_block, 17 }, { 11, HELITAKEOFF, 0, 48 },
{ 12, 0, TERM_GROUP2_ENTER1_block, 13 },
{ 13, 0, TERM_GROUP2_ENTER1_block, 14 },
{ 14, 0, TERM_GROUP2_ENTER2_block, 15 },
{ 15, 0, TERM_GROUP2_ENTER2_block, 16 },
{ 16, 255, TERM_GROUP2_block, 0 }, { 16, TERM4, TERM4_block, 7 }, { 16, HELIPAD1, HELIPAD1_block, 10 }, { 16, HELITAKEOFF, HELIPAD1_block, 10 }, { 16, 0, 0, 17 },
{ 17, 255, TERM_GROUP2_block, 0 }, { 17, TERM5, TERM5_block, 8 }, { 17, TERM4, 0, 16 }, { 17, HELIPAD1, 0, 16 }, { 17, HELIPAD2, HELIPAD2_block, 11 }, { 17, HELITAKEOFF, HELIPAD2_block, 11 }, { 17, 0, 0, 18 },
{ 18, 255, TERM_GROUP2_block, 0 }, { 18, TERM6, TERM6_block, 9 }, { 18, TAKEOFF, 0, 19 }, { 18, HANGAR, HANGAR2_AREA_block, 3 }, { 18, 0, 0, 17 },
{ 19, 0, TERM_GROUP2_EXIT1_block, 20 },
{ 20, 0, TERM_GROUP2_EXIT1_block, 21 },
{ 21, 0, TERM_GROUP2_EXIT2_block, 22 },
{ 22, 0, TERM_GROUP2_EXIT2_block, 26 },
{ 23, 255, TERM_GROUP1_block, 0 }, { 23, TERM1, TERM1_block, 4 }, { 23, HANGAR, AIRPORT_ENTRANCE_block, 2 }, { 23, 0, 0, 24 },
{ 24, 255, TERM_GROUP1_block, 0 }, { 24, TERM2, TERM2_block, 5 }, { 24, TERM1, 0, 23 }, { 24, HANGAR, 0, 23 }, { 24, 0, 0, 25 },
{ 25, 255, TERM_GROUP1_block, 0 }, { 25, TERM3, TERM3_block, 6 }, { 25, TAKEOFF, 0, 26 }, { 25, 0, 0, 24 },
{ 26, 255, TAXIWAY_BUSY_block, 0 }, { 26, TAKEOFF, 0, 27 }, { 26, 0, 0, 25 },
{ 27, 0, OUT_WAY_block, 28 },
// takeoff
{ 28, TAKEOFF, OUT_WAY_block, 29 },
{ 29, 0, RUNWAY_OUT_block, 30 },
{ 30, STARTTAKEOFF, NOTHING_block, 31 },
{ 31, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 32, FLYING, NOTHING_block, 37 }, { 32, LANDING, 0, 33 }, { 32, HELILANDING, 0, 41 },
{ 33, LANDING, RUNWAY_IN_block, 34 },
{ 34, 0, RUNWAY_IN_block, 35 },
{ 35, 0, RUNWAY_IN_block, 36 },
{ 36, ENDLANDING, IN_WAY_block, 36 }, { 36, 255, TERM_GROUP1_block, 0 }, { 36, 255, TERM_GROUP2_ENTER1_block, 1 }, { 36, TERM4, 0, 12 }, { 36, TERM5, 0, 12 }, { 36, TERM6, 0, 12 }, { 36, 0, 0, 2 },
// In Air
{ 37, 0, NOTHING_block, 38 },
{ 38, 0, NOTHING_block, 39 },
{ 39, 0, NOTHING_block, 40 },
{ 40, 0, NOTHING_block, 32 },
// Helicopter -- stay in air in special place as a buffer to choose from helipads
{ 41, HELILANDING, PRE_HELIPAD_block, 42 },
{ 42, HELIENDLANDING, PRE_HELIPAD_block, 42 }, { 42, HELIPAD1, 0, 43 }, { 42, HELIPAD2, 0, 44 }, { 42, HANGAR, 0, 49 },
{ 43, 0, NOTHING_block, 45 },
{ 44, 0, NOTHING_block, 46 },
// landing
{ 45, 255, NOTHING_block, 0 }, { 45, HELIPAD1, HELIPAD1_block, 10 },
{ 46, 255, NOTHING_block, 0 }, { 46, HELIPAD2, HELIPAD2_block, 11 },
// Helicopter -- takeoff
{ 47, HELITAKEOFF, NOTHING_block, 0 },
{ 48, HELITAKEOFF, NOTHING_block, 0 },
{ 49, 0, HANGAR2_AREA_block, 50 }, // need to go to hangar when waiting in air
{ 50, 0, HANGAR2_AREA_block, 3 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
// intercontinental
static const TileIndexDiffC _airport_depots_intercontinental[] = { { 0, 5 }, { 8, 4 } };
static const byte _airport_terminal_intercontinental[] = { 2, 4, 4 };
static const byte _airport_helipad_intercontinental[] = { 1, 2 };
static const AirportFTAbuildup _airport_fta_intercontinental[] = {
{ 0, HANGAR, NOTHING_block, 2 }, { 0, 255, HANGAR1_AREA_block | TERM_GROUP1_block, 0 }, { 0, 255, HANGAR1_AREA_block | TERM_GROUP1_block, 1 }, { 0, TAKEOFF, HANGAR1_AREA_block | TERM_GROUP1_block, 2 }, { 0, 0, 0, 2 },
{ 1, HANGAR, NOTHING_block, 3 }, { 1, 255, HANGAR2_AREA_block, 1 }, { 1, 255, HANGAR2_AREA_block, 0 }, { 1, 0, 0, 3 },
{ 2, 255, HANGAR1_AREA_block, 0 }, { 2, 255, TERM_GROUP1_block, 0 }, { 2, 255, TERM_GROUP1_block, 1 }, { 2, HANGAR, 0, 0 }, { 2, TAKEOFF, TERM_GROUP1_block, 27 }, { 2, TERM5, 0, 26 }, { 2, TERM6, 0, 26 }, { 2, TERM7, 0, 26 }, { 2, TERM8, 0, 26 }, { 2, HELIPAD1, 0, 26 }, { 2, HELIPAD2, 0, 26 }, { 2, HELITAKEOFF, 0, 74 }, { 2, 0, 0, 27 },
{ 3, 255, HANGAR2_AREA_block, 0 }, { 3, HANGAR, 0, 1 }, { 3, HELITAKEOFF, 0, 75 }, { 3, 0, 0, 20 },
{ 4, TERM1, TERM1_block, 26 }, { 4, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 26 }, { 4, 0, 0, 26 },
{ 5, TERM2, TERM2_block, 27 }, { 5, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 27 }, { 5, 0, 0, 27 },
{ 6, TERM3, TERM3_block, 28 }, { 6, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 28 }, { 6, 0, 0, 28 },
{ 7, TERM4, TERM4_block, 29 }, { 7, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 29 }, { 7, 0, 0, 29 },
{ 8, TERM5, TERM5_block, 18 }, { 8, HANGAR, HANGAR2_AREA_block, 18 }, { 8, 0, 0, 18 },
{ 9, TERM6, TERM6_block, 19 }, { 9, HANGAR, HANGAR2_AREA_block, 19 }, { 9, 0, 0, 19 },
{ 10, TERM7, TERM7_block, 20 }, { 10, HANGAR, HANGAR2_AREA_block, 20 }, { 10, 0, 0, 20 },
{ 11, TERM8, TERM8_block, 21 }, { 11, HANGAR, HANGAR2_AREA_block, 21 }, { 11, 0, 0, 21 },
{ 12, HELIPAD1, HELIPAD1_block, 12 }, { 12, HANGAR, 0, 70 }, { 12, HELITAKEOFF, 0, 72 },
{ 13, HELIPAD2, HELIPAD2_block, 13 }, { 13, HANGAR, 0, 71 }, { 13, HELITAKEOFF, 0, 73 },
{ 14, 0, TERM_GROUP2_ENTER1_block, 15 },
{ 15, 0, TERM_GROUP2_ENTER1_block, 16 },
{ 16, 0, TERM_GROUP2_ENTER2_block, 17 },
{ 17, 0, TERM_GROUP2_ENTER2_block, 18 },
{ 18, 255, TERM_GROUP2_block, 0 }, { 18, TERM5, TERM5_block, 8 }, { 18, TAKEOFF, 0, 19 }, { 18, HELITAKEOFF, HELIPAD1_block, 19 }, { 18, 0, TERM_GROUP2_EXIT1_block, 19 },
{ 19, 255, TERM_GROUP2_block, 0 }, { 19, TERM6, TERM6_block, 9 }, { 19, TERM5, 0, 18 }, { 19, TAKEOFF, 0, 57 }, { 19, HELITAKEOFF, HELIPAD1_block, 20 }, { 19, 0, TERM_GROUP2_EXIT1_block, 20 }, // add exit to runway out 2
{ 20, 255, TERM_GROUP2_block, 0 }, { 20, TERM7, TERM7_block, 10 }, { 20, TERM5, 0, 19 }, { 20, TERM6, 0, 19 }, { 20, HANGAR, HANGAR2_AREA_block, 3 }, { 20, TAKEOFF, 0, 19 }, { 20, 0, TERM_GROUP2_EXIT1_block, 21 },
{ 21, 255, TERM_GROUP2_block, 0 }, { 21, TERM8, TERM8_block, 11 }, { 21, HANGAR, HANGAR2_AREA_block, 20 }, { 21, TERM5, 0, 20 }, { 21, TERM6, 0, 20 }, { 21, TERM7, 0, 20 }, { 21, TAKEOFF, 0, 20 }, { 21, 0, TERM_GROUP2_EXIT1_block, 22 },
{ 22, 255, TERM_GROUP2_block, 0 }, { 22, HANGAR, 0, 21 }, { 22, TERM5, 0, 21 }, { 22, TERM6, 0, 21 }, { 22, TERM7, 0, 21 }, { 22, TERM8, 0, 21 }, { 22, TAKEOFF, 0, 21 }, { 22, 0, 0, 23 },
{ 23, 0, TERM_GROUP2_EXIT1_block, 70 },
{ 24, 0, TERM_GROUP2_EXIT2_block, 25 },
{ 25, 255, TERM_GROUP2_EXIT2_block, 0 }, { 25, HANGAR, HANGAR1_AREA_block | TERM_GROUP1_block, 29 }, { 25, 0, 0, 29 },
{ 26, 255, TERM_GROUP1_block, 0 }, { 26, TERM1, TERM1_block, 4 }, { 26, HANGAR, HANGAR1_AREA_block, 27 }, { 26, TERM5, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM6, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM7, TERM_GROUP2_ENTER1_block, 14 }, { 26, TERM8, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELIPAD1, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELIPAD2, TERM_GROUP2_ENTER1_block, 14 }, { 26, HELITAKEOFF, TERM_GROUP2_ENTER1_block, 14 }, { 26, 0, 0, 27 },
{ 27, 255, TERM_GROUP1_block, 0 }, { 27, TERM2, TERM2_block, 5 }, { 27, HANGAR, HANGAR1_AREA_block, 2 }, { 27, TERM1, 0, 26 }, { 27, TERM5, 0, 26 }, { 27, TERM6, 0, 26 }, { 27, TERM7, 0, 26 }, { 27, TERM8, 0, 26 }, { 27, HELIPAD1, 0, 14 }, { 27, HELIPAD2, 0, 14 }, { 27, 0, 0, 28 },
{ 28, 255, TERM_GROUP1_block, 0 }, { 28, TERM3, TERM3_block, 6 }, { 28, HANGAR, HANGAR1_AREA_block, 27 }, { 28, TERM1, 0, 27 }, { 28, TERM2, 0, 27 }, { 28, TERM4, 0, 29 }, { 28, TERM5, 0, 14 }, { 28, TERM6, 0, 14 }, { 28, TERM7, 0, 14 }, { 28, TERM8, 0, 14 }, { 28, HELIPAD1, 0, 14 }, { 28, HELIPAD2, 0, 14 }, { 28, 0, 0, 29 },
{ 29, 255, TERM_GROUP1_block, 0 }, { 29, TERM4, TERM4_block, 7 }, { 29, HANGAR, HANGAR1_AREA_block, 27 }, { 29, TAKEOFF, 0, 30 }, { 29, 0, 0, 28 },
{ 30, 0, OUT_WAY_block2, 31 },
{ 31, 0, OUT_WAY_block, 32 },
// takeoff
{ 32, TAKEOFF, RUNWAY_OUT_block, 33 },
{ 33, 0, RUNWAY_OUT_block, 34 },
{ 34, STARTTAKEOFF, NOTHING_block, 35 },
{ 35, ENDTAKEOFF, NOTHING_block, 0 },
// landing
{ 36, 0, 0, 0 },
{ 37, LANDING, RUNWAY_IN_block, 38 },
{ 38, 0, RUNWAY_IN_block, 39 },
{ 39, 0, RUNWAY_IN_block, 40 },
{ 40, ENDLANDING, RUNWAY_IN_block, 41 },
{ 41, 0, IN_WAY_block, 42 },
{ 42, 255, IN_WAY_block, 0 }, { 42, 255, TERM_GROUP1_block, 0 }, { 42, 255, TERM_GROUP1_block, 1 }, { 42, HANGAR, 0, 2 }, { 42, 0, 0, 26 },
// In Air
{ 43, 0, 0, 44 },
{ 44, FLYING, 0, 45 }, { 44, HELILANDING, 0, 47 }, { 44, LANDING, 0, 69 }, { 44, 0, 0, 45 },
{ 45, 0, 0, 46 },
{ 46, FLYING, 0, 43 }, { 46, LANDING, 0, 76 }, { 46, 0, 0, 43 },
// Helicopter -- stay in air in special place as a buffer to choose from helipads
{ 47, HELILANDING, PRE_HELIPAD_block, 48 },
{ 48, HELIENDLANDING, PRE_HELIPAD_block, 48 }, { 48, HELIPAD1, 0, 49 }, { 48, HELIPAD2, 0, 50 }, { 48, HANGAR, 0, 55 },
{ 49, 0, NOTHING_block, 51 },
{ 50, 0, NOTHING_block, 52 },
// landing
{ 51, 255, NOTHING_block, 0 }, { 51, HELIPAD1, HELIPAD1_block, 12 }, { 51, HANGAR, 0, 55 }, { 51, 0, 0, 12 },
{ 52, 255, NOTHING_block, 0 }, { 52, HELIPAD2, HELIPAD2_block, 13 }, { 52, HANGAR, 0, 55 }, { 52, 0, 0, 13 },
// Helicopter -- takeoff
{ 53, HELITAKEOFF, NOTHING_block, 0 },
{ 54, HELITAKEOFF, NOTHING_block, 0 },
{ 55, 0, HANGAR2_AREA_block, 56 }, // need to go to hangar when waiting in air
{ 56, 0, HANGAR2_AREA_block, 3 },
// runway 2 out support
{ 57, 255, OUT_WAY2_block, 0 }, { 57, TAKEOFF, 0, 58 }, { 57, 0, 0, 58 },
{ 58, 0, OUT_WAY2_block, 59 },
{ 59, TAKEOFF, RUNWAY_OUT2_block, 60 }, // takeoff
{ 60, 0, RUNWAY_OUT2_block, 61 },
{ 61, STARTTAKEOFF, NOTHING_block, 62 },
{ 62, ENDTAKEOFF, NOTHING_block, 0 },
// runway 2 in support
{ 63, LANDING, RUNWAY_IN2_block, 64 },
{ 64, 0, RUNWAY_IN2_block, 65 },
{ 65, 0, RUNWAY_IN2_block, 66 },
{ 66, ENDLANDING, RUNWAY_IN2_block, 0 }, { 66, 255, 0, 1 }, { 66, 255, 0, 0 }, { 66, 0, 0, 67 },
{ 67, 0, IN_WAY2_block, 68 },
{ 68, 255, IN_WAY2_block, 0 }, { 68, 255, TERM_GROUP2_block, 1 }, { 68, 255, TERM_GROUP1_block, 0 }, { 68, HANGAR, HANGAR2_AREA_block, 22 }, { 68, 0, 0, 22 },
{ 69, 255, RUNWAY_IN2_block, 0 }, { 69, 0, RUNWAY_IN2_block, 63 },
{ 70, 255, TERM_GROUP2_EXIT1_block, 0 }, { 70, HELIPAD1, HELIPAD1_block, 12 }, { 70, HELITAKEOFF, HELIPAD1_block, 12 }, { 70, 0, 0, 71 },
{ 71, 255, TERM_GROUP2_EXIT1_block, 0 }, { 71, HELIPAD2, HELIPAD2_block, 13 }, { 71, HELITAKEOFF, HELIPAD1_block, 12 }, { 71, 0, 0, 24 },
{ 72, 0, HELIPAD1_block, 53 },
{ 73, 0, HELIPAD2_block, 54 },
{ 74, HELITAKEOFF, NOTHING_block, 0 },
{ 75, HELITAKEOFF, NOTHING_block, 0 },
{ 76, 255, RUNWAY_IN_block, 0 }, { 76, 0, RUNWAY_IN_block, 37 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
// heliports, oilrigs don't have depots
static const byte _airport_helipad_heliport_oilrig[] = { 1, 1 };
static const AirportFTAbuildup _airport_fta_heliport_oilrig[] = {
{ 0, HELIPAD1, HELIPAD1_block, 1 },
{ 1, HELITAKEOFF, NOTHING_block, 0 }, // takeoff
{ 2, 255, AIRPORT_BUSY_block, 0 }, { 2, HELILANDING, 0, 3 }, { 2, HELITAKEOFF, 0, 1 },
{ 3, HELILANDING, AIRPORT_BUSY_block, 4 },
{ 4, HELIENDLANDING, AIRPORT_BUSY_block, 4 }, { 4, HELIPAD1, HELIPAD1_block, 0 }, { 4, HELITAKEOFF, 0, 2 },
// In Air
{ 5, 0, NOTHING_block, 6 },
{ 6, 0, NOTHING_block, 7 },
{ 7, 0, NOTHING_block, 8 },
{ 8, FLYING, NOTHING_block, 5 }, { 8, HELILANDING, HELIPAD1_block, 2 }, // landing
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
// helidepots
static const TileIndexDiffC _airport_depots_helidepot[] = { { 1, 0 } };
static const byte _airport_helipad_helidepot[] = { 1, 1 };
static const AirportFTAbuildup _airport_fta_helidepot[] = {
{ 0, HANGAR, NOTHING_block, 1 },
{ 1, 255, HANGAR2_AREA_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, HELIPAD1, HELIPAD1_block, 14 }, { 1, HELITAKEOFF, 0, 15 }, { 1, 0, 0, 0 },
{ 2, FLYING, NOTHING_block, 3 }, { 2, HELILANDING, PRE_HELIPAD_block, 7 }, { 2, HANGAR, 0, 12 }, { 2, HELITAKEOFF, NOTHING_block, 16 },
// In Air
{ 3, 0, NOTHING_block, 4 },
{ 4, 0, NOTHING_block, 5 },
{ 5, 0, NOTHING_block, 6 },
{ 6, 0, NOTHING_block, 2 },
// Helicopter -- stay in air in special place as a buffer to choose from helipads
{ 7, HELILANDING, PRE_HELIPAD_block, 8 },
{ 8, HELIENDLANDING, PRE_HELIPAD_block, 8 }, { 8, HELIPAD1, 0, 9 }, { 8, HANGAR, 0, 12 }, { 8, 0, 0, 2 },
{ 9, 0, NOTHING_block, 10 },
// landing
{ 10, 255, NOTHING_block, 10 }, { 10, HELIPAD1, HELIPAD1_block, 14 }, { 10, HANGAR, 0, 1 }, { 10, 0, 0, 14 },
// Helicopter -- takeoff
{ 11, HELITAKEOFF, NOTHING_block, 0 },
{ 12, 0, HANGAR2_AREA_block, 13 }, // need to go to hangar when waiting in air
{ 13, 0, HANGAR2_AREA_block, 1 },
{ 14, HELIPAD1, HELIPAD1_block, 14 }, { 14, HANGAR, 0, 1 }, { 14, HELITAKEOFF, 0, 17 },
{ 15, HELITAKEOFF, NOTHING_block, 0 }, // takeoff outside depot
{ 16, HELITAKEOFF, 0, 14 },
{ 17, 0, NOTHING_block, 11 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
// helistation
static const TileIndexDiffC _airport_depots_helistation[] = { { 0, 0 } };
static const byte _airport_helipad_helistation[] = { 1, 3 };
static const AirportFTAbuildup _airport_fta_helistation[] = {
{ 0, HANGAR, NOTHING_block, 8 }, { 0, HELIPAD1, 0, 1 }, { 0, HELIPAD2, 0, 1 }, { 0, HELIPAD3, 0, 1 }, { 0, HELITAKEOFF, 0, 1 }, { 0, 0, 0, 0 },
{ 1, 255, HANGAR2_AREA_block, 0 }, { 1, HANGAR, 0, 0 }, { 1, HELITAKEOFF, 0, 3 }, { 1, 0, 0, 4 },
// landing
{ 2, FLYING, NOTHING_block, 28 }, { 2, HELILANDING, 0, 15 }, { 2, 0, 0, 28 },
// helicopter side
{ 3, HELITAKEOFF, NOTHING_block, 0 }, // helitakeoff outside hangar2
{ 4, 255, TAXIWAY_BUSY_block, 0 }, { 4, HANGAR, HANGAR2_AREA_block, 1 }, { 4, HELITAKEOFF, 0, 1 }, { 4, 0, 0, 5 },
{ 5, 255, TAXIWAY_BUSY_block, 0 }, { 5, HELIPAD1, HELIPAD1_block, 6 }, { 5, HELIPAD2, HELIPAD2_block, 7 }, { 5, HELIPAD3, HELIPAD3_block, 8 }, { 5, 0, 0, 4 },
{ 6, HELIPAD1, HELIPAD1_block, 5 }, { 6, HANGAR, HANGAR2_AREA_block, 5 }, { 6, HELITAKEOFF, 0, 9 }, { 6, 0, 0, 6 },
{ 7, HELIPAD2, HELIPAD2_block, 5 }, { 7, HANGAR, HANGAR2_AREA_block, 5 }, { 7, HELITAKEOFF, 0, 10 }, { 7, 0, 0, 7 },
{ 8, HELIPAD3, HELIPAD3_block, 5 }, { 8, HANGAR, HANGAR2_AREA_block, 5 }, { 8, HELITAKEOFF, 0, 11 }, { 8, 0, 0, 8 },
{ 9, 0, HELIPAD1_block, 12 },
{ 10, 0, HELIPAD2_block, 13 },
{ 11, 0, HELIPAD3_block, 14 },
{ 12, HELITAKEOFF, NOTHING_block, 0 },
{ 13, HELITAKEOFF, NOTHING_block, 0 },
{ 14, HELITAKEOFF, NOTHING_block, 0 },
// heli - in flight moves
{ 15, HELILANDING, PRE_HELIPAD_block, 16 },
{ 16, HELIENDLANDING, PRE_HELIPAD_block, 16 }, { 16, HELIPAD1, 0, 17 }, { 16, HELIPAD2, 0, 18 }, { 16, HELIPAD3, 0, 19 }, { 16, HANGAR, 0, 23 },
{ 17, 0, NOTHING_block, 20 },
{ 18, 0, NOTHING_block, 21 },
{ 19, 0, NOTHING_block, 22 },
// heli landing
{ 20, 255, NOTHING_block, 0 }, { 20, HELIPAD1, HELIPAD1_block, 6 }, { 20, HANGAR, 0, 23 }, { 20, 0, 0, 6 },
{ 21, 255, NOTHING_block, 0 }, { 21, HELIPAD2, HELIPAD2_block, 7 }, { 21, HANGAR, 0, 23 }, { 21, 0, 0, 7 },
{ 22, 255, NOTHING_block, 0 }, { 22, HELIPAD3, HELIPAD3_block, 8 }, { 22, HANGAR, 0, 23 }, { 22, 0, 0, 8 },
{ 23, 0, HANGAR2_AREA_block, 24 }, // need to go to helihangar when waiting in air
{ 24, 0, HANGAR2_AREA_block, 1 },
{ 25, 0, NOTHING_block, 26 },
{ 26, 0, NOTHING_block, 27 },
{ 27, 0, NOTHING_block, 2 },
{ 28, 0, NOTHING_block, 29 },
{ 29, 0, NOTHING_block, 30 },
{ 30, 0, NOTHING_block, 31 },
{ 31, 0, NOTHING_block, 32 },
{ 32, 0, NOTHING_block, 25 },
{ MAX_ELEMENTS, 0, 0, 0 } // end marker. DO NOT REMOVE
};
static const AirportMovingData * const _airport_moving_datas[] = {
_airport_moving_data_country, // Country Airfield (small) 4x3
_airport_moving_data_town, // City Airport (large) 6x6
_airport_moving_data_heliport, // Heliport
_airport_moving_data_metropolitan, // Metropolitain Airport (large) - 2 runways
_airport_moving_data_international, // International Airport (xlarge) - 2 runways
_airport_moving_data_commuter, // Commuter Airfield (small) 5x4
_airport_moving_data_helidepot, // Helidepot
_airport_moving_data_intercontinental, // Intercontinental Airport (xxlarge) - 4 runways
_airport_moving_data_helistation, // Helistation
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
_airport_moving_data_oilrig // Oilrig
};
#endif /* AIRPORT_MOVEMENT_H */

296
aystar.c Normal file
View File

@@ -0,0 +1,296 @@
/* $Id$ */
/*
* This file has the core function for AyStar
* AyStar is a fast pathfinding routine and is used for things like
* AI_pathfinding and Train_pathfinding.
* For more information about AyStar (A* Algorithm), you can look at
* http://en.wikipedia.org/wiki/A-star_search_algorithm
*/
/*
* Friendly reminder:
* Call (AyStar).free() when you are done with Aystar. It reserves a lot of memory
* And when not free'd, it can cause system-crashes.
* Also remember that when you stop an algorithm before it is finished, your
* should call clear() yourself!
*/
#include "stdafx.h"
#include "openttd.h"
#include "aystar.h"
int _aystar_stats_open_size;
int _aystar_stats_closed_size;
// This looks in the Hash if a node exists in ClosedList
// If so, it returns the PathNode, else NULL
static PathNode* AyStarMain_ClosedList_IsInList(AyStar *aystar, const AyStarNode *node)
{
return (PathNode*)Hash_Get(&aystar->ClosedListHash, node->tile, node->direction);
}
// This adds a node to the ClosedList
// It makes a copy of the data
static void AyStarMain_ClosedList_Add(AyStar *aystar, const PathNode *node)
{
// Add a node to the ClosedList
PathNode *new_node = malloc(sizeof(*new_node));
*new_node = *node;
Hash_Set(&aystar->ClosedListHash, node->node.tile, node->node.direction, new_node);
}
// Checks if a node is in the OpenList
// If so, it returns the OpenListNode, else NULL
static OpenListNode *AyStarMain_OpenList_IsInList(AyStar *aystar, const AyStarNode *node)
{
return (OpenListNode*)Hash_Get(&aystar->OpenListHash, node->tile, node->direction);
}
// Gets the best node from OpenList
// returns the best node, or NULL of none is found
// Also it deletes the node from the OpenList
static OpenListNode *AyStarMain_OpenList_Pop(AyStar *aystar)
{
// Return the item the Queue returns.. the best next OpenList item.
OpenListNode *res = (OpenListNode*)aystar->OpenListQueue.pop(&aystar->OpenListQueue);
if (res != NULL) {
Hash_Delete(&aystar->OpenListHash, res->path.node.tile, res->path.node.direction);
}
return res;
}
// Adds a node to the OpenList
// It makes a copy of node, and puts the pointer of parent in the struct
static void AyStarMain_OpenList_Add(AyStar *aystar, PathNode *parent, const AyStarNode *node, int f, int g)
{
// Add a new Node to the OpenList
OpenListNode *new_node = malloc(sizeof(*new_node));
new_node->g = g;
new_node->path.parent = parent;
new_node->path.node = *node;
Hash_Set(&aystar->OpenListHash, node->tile, node->direction, new_node);
// Add it to the queue
aystar->OpenListQueue.push(&aystar->OpenListQueue, new_node, f);
}
/*
* Checks one tile and calculate his f-value
* return values:
* AYSTAR_DONE : indicates we are done
*/
int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
{
int new_f, new_g, new_h;
PathNode *closedlist_parent;
OpenListNode *check;
// Check the new node against the ClosedList
if (AyStarMain_ClosedList_IsInList(aystar, current) != NULL) return AYSTAR_DONE;
// Calculate the G-value for this node
new_g = aystar->CalculateG(aystar, current, parent);
// If the value was INVALID_NODE, we don't do anything with this node
if (new_g == AYSTAR_INVALID_NODE) return AYSTAR_DONE;
// There should not be given any other error-code..
assert(new_g >= 0);
// Add the parent g-value to the new g-value
new_g += parent->g;
if (aystar->max_path_cost != 0 && (uint)new_g > aystar->max_path_cost) return AYSTAR_DONE;
// Calculate the h-value
new_h = aystar->CalculateH(aystar, current, parent);
// There should not be given any error-code..
assert(new_h >= 0);
// The f-value if g + h
new_f = new_g + new_h;
// Get the pointer to the parent in the ClosedList (the currentone is to a copy of the one in the OpenList)
closedlist_parent = AyStarMain_ClosedList_IsInList(aystar, &parent->path.node);
// Check if this item is already in the OpenList
check = AyStarMain_OpenList_IsInList(aystar, current);
if (check != NULL) {
uint i;
// Yes, check if this g value is lower..
if (new_g > check->g) return AYSTAR_DONE;
aystar->OpenListQueue.del(&aystar->OpenListQueue, check, 0);
// It is lower, so change it to this item
check->g = new_g;
check->path.parent = closedlist_parent;
/* Copy user data, will probably have changed */
for (i = 0; i < lengthof(current->user_data); i++) {
check->path.node.user_data[i] = current->user_data[i];
}
// Readd him in the OpenListQueue
aystar->OpenListQueue.push(&aystar->OpenListQueue, check, new_f);
} else {
// A new node, add him to the OpenList
AyStarMain_OpenList_Add(aystar, closedlist_parent, current, new_f, new_g);
}
return AYSTAR_DONE;
}
/*
* This function is the core of AyStar. It handles one item and checks
* his neighbour items. If they are valid, they are added to be checked too.
* return values:
* AYSTAR_EMPTY_OPENLIST : indicates all items are tested, and no path
* has been found.
* AYSTAR_LIMIT_REACHED : Indicates that the max_nodes limit has been
* reached.
* AYSTAR_FOUND_END_NODE : indicates we found the end. Path_found now is true, and in path is the path found.
* AYSTAR_STILL_BUSY : indicates we have done this tile, did not found the path yet, and have items left to try.
*/
int AyStarMain_Loop(AyStar *aystar)
{
int i, r;
// Get the best node from OpenList
OpenListNode *current = AyStarMain_OpenList_Pop(aystar);
// If empty, drop an error
if (current == NULL) return AYSTAR_EMPTY_OPENLIST;
// Check for end node and if found, return that code
if (aystar->EndNodeCheck(aystar, current) == AYSTAR_FOUND_END_NODE) {
if (aystar->FoundEndNode != NULL)
aystar->FoundEndNode(aystar, current);
free(current);
return AYSTAR_FOUND_END_NODE;
}
// Add the node to the ClosedList
AyStarMain_ClosedList_Add(aystar, &current->path);
// Load the neighbours
aystar->GetNeighbours(aystar, current);
// Go through all neighbours
for (i = 0; i < aystar->num_neighbours; i++) {
// Check and add them to the OpenList if needed
r = aystar->checktile(aystar, &aystar->neighbours[i], current);
}
// Free the node
free(current);
if (aystar->max_search_nodes != 0 && Hash_Size(&aystar->ClosedListHash) >= aystar->max_search_nodes) {
/* We've expanded enough nodes */
return AYSTAR_LIMIT_REACHED;
} else {
// Return that we are still busy
return AYSTAR_STILL_BUSY;
}
}
/*
* This function frees the memory it allocated
*/
void AyStarMain_Free(AyStar *aystar)
{
aystar->OpenListQueue.free(&aystar->OpenListQueue, false);
/* 2nd argument above is false, below is true, to free the values only
* once */
delete_Hash(&aystar->OpenListHash, true);
delete_Hash(&aystar->ClosedListHash, true);
#ifdef AYSTAR_DEBUG
printf("[AyStar] Memory free'd\n");
#endif
}
/*
* This function make the memory go back to zero
* This function should be called when you are using the same instance again.
*/
void AyStarMain_Clear(AyStar *aystar)
{
// Clean the Queue, but not the elements within. That will be done by
// the hash.
aystar->OpenListQueue.clear(&aystar->OpenListQueue, false);
// Clean the hashes
clear_Hash(&aystar->OpenListHash, true);
clear_Hash(&aystar->ClosedListHash, true);
#ifdef AYSTAR_DEBUG
printf("[AyStar] Cleared AyStar\n");
#endif
}
/*
* This is the function you call to run AyStar.
* return values:
* AYSTAR_FOUND_END_NODE : indicates we found an end node.
* AYSTAR_NO_PATH : indicates that there was no path found.
* AYSTAR_STILL_BUSY : indicates we have done some checked, that we did not found the path yet, and that we still have items left to try.
* When the algorithm is done (when the return value is not AYSTAR_STILL_BUSY)
* aystar->clear() is called. Note that when you stop the algorithm halfway,
* you should still call clear() yourself!
*/
int AyStarMain_Main(AyStar *aystar) {
int r, i = 0;
// Loop through the OpenList
// Quit if result is no AYSTAR_STILL_BUSY or is more than loops_per_tick
while ((r = aystar->loop(aystar)) == AYSTAR_STILL_BUSY && (aystar->loops_per_tick == 0 || ++i < aystar->loops_per_tick)) { }
#ifdef AYSTAR_DEBUG
switch (r) {
case AYSTAR_FOUND_END_NODE: printf("[AyStar] Found path!\n"); break;
case AYSTAR_EMPTY_OPENLIST: printf("[AyStar] OpenList run dry, no path found\n"); break;
case AYSTAR_LIMIT_REACHED: printf("[AyStar] Exceeded search_nodes, no path found\n"); break;
default: break;
}
#endif
if (r != AYSTAR_STILL_BUSY) {
/* We're done, clean up */
_aystar_stats_open_size = aystar->OpenListHash.size;
_aystar_stats_closed_size = aystar->ClosedListHash.size;
aystar->clear(aystar);
}
switch (r) {
case AYSTAR_FOUND_END_NODE: return AYSTAR_FOUND_END_NODE;
case AYSTAR_EMPTY_OPENLIST:
case AYSTAR_LIMIT_REACHED: return AYSTAR_NO_PATH;
default: return AYSTAR_STILL_BUSY;
}
}
/*
* Adds a node from where to start an algorithm. Multiple nodes can be added
* if wanted. You should make sure that clear() is called before adding nodes
* if the AyStar has been used before (though the normal main loop calls
* clear() automatically when the algorithm finishes
* g is the cost for starting with this node.
*/
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g)
{
#ifdef AYSTAR_DEBUG
printf("[AyStar] Starting A* Algorithm from node (%d, %d, %d)\n",
TileX(start_node->tile), TileY(start_node->tile), start_node->direction);
#endif
AyStarMain_OpenList_Add(aystar, NULL, start_node, 0, g);
}
void init_AyStar(AyStar *aystar, Hash_HashProc hash, uint num_buckets)
{
// Allocated the Hash for the OpenList and ClosedList
init_Hash(&aystar->OpenListHash, hash, num_buckets);
init_Hash(&aystar->ClosedListHash, hash, num_buckets);
// Set up our sorting queue
// BinaryHeap allocates a block of 1024 nodes
// When thatone gets full it reserves an otherone, till this number
// That is why it can stay this high
init_BinaryHeap(&aystar->OpenListQueue, 102400);
aystar->addstart = AyStarMain_AddStartNode;
aystar->main = AyStarMain_Main;
aystar->loop = AyStarMain_Loop;
aystar->free = AyStarMain_Free;
aystar->clear = AyStarMain_Clear;
aystar->checktile = AyStarMain_CheckTile;
}

179
aystar.h Normal file
View File

@@ -0,0 +1,179 @@
/* $Id$ */
/*
* This file has the header for AyStar
* AyStar is a fast pathfinding routine and is used for things like
* AI_pathfinding and Train_pathfinding.
* For more information about AyStar (A* Algorithm), you can look at
* http://en.wikipedia.org/wiki/A-star_search_algorithm
*/
#ifndef AYSTAR_H
#define AYSTAR_H
#include "queue.h"
//#define AYSTAR_DEBUG
enum {
AYSTAR_FOUND_END_NODE,
AYSTAR_EMPTY_OPENLIST,
AYSTAR_STILL_BUSY,
AYSTAR_NO_PATH,
AYSTAR_LIMIT_REACHED,
AYSTAR_DONE
};
enum{
AYSTAR_INVALID_NODE = -1,
};
typedef struct AyStarNode AyStarNode;
struct AyStarNode {
TileIndex tile;
uint direction;
uint user_data[2];
};
// The resulting path has nodes looking like this.
typedef struct PathNode PathNode;
struct PathNode {
AyStarNode node;
// The parent of this item
PathNode *parent;
};
// For internal use only
// We do not save the h-value, because it is only needed to calculate the f-value.
// h-value should _always_ be the distance left to the end-tile.
typedef struct OpenListNode OpenListNode;
struct OpenListNode {
int g;
PathNode path;
};
typedef struct AyStar AyStar;
/*
* This function is called to check if the end-tile is found
* return values can be:
* AYSTAR_FOUND_END_NODE : indicates this is the end tile
* AYSTAR_DONE : indicates this is not the end tile (or direction was wrong)
*/
/*
* The 2nd parameter should be OpenListNode, and NOT AyStarNode. AyStarNode is
* part of OpenListNode and so it could be accessed without any problems.
* The good part about OpenListNode is, and how AIs use it, that you can
* access the parent of the current node, and so check if you, for example
* don't try to enter the file tile with a 90-degree curve. So please, leave
* this an OpenListNode, it works just fine -- TrueLight
*/
typedef int32 AyStar_EndNodeCheck(AyStar *aystar, OpenListNode *current);
/*
* This function is called to calculate the G-value for AyStar Algorithm.
* return values can be:
* AYSTAR_INVALID_NODE : indicates an item is not valid (e.g.: unwalkable)
* Any value >= 0 : the g-value for this tile
*/
typedef int32 AyStar_CalculateG(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
/*
* This function is called to calculate the H-value for AyStar Algorithm.
* Mostly, this must result the distance (Manhattan way) between the
* current point and the end point
* return values can be:
* Any value >= 0 : the h-value for this tile
*/
typedef int32 AyStar_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
/*
* This function request the tiles around the current tile and put them in tiles_around
* tiles_around is never resetted, so if you are not using directions, just leave it alone.
* Warning: never add more tiles_around than memory allocated for it.
*/
typedef void AyStar_GetNeighbours(AyStar *aystar, OpenListNode *current);
/*
* If the End Node is found, this function is called.
* It can do, for example, calculate the route and put that in an array
*/
typedef void AyStar_FoundEndNode(AyStar *aystar, OpenListNode *current);
// For internal use, see aystar.c
typedef void AyStar_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g);
typedef int AyStar_Main(AyStar *aystar);
typedef int AyStar_Loop(AyStar *aystar);
typedef int AyStar_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
typedef void AyStar_Free(AyStar *aystar);
typedef void AyStar_Clear(AyStar *aystar);
struct AyStar {
/* These fields should be filled before initting the AyStar, but not changed
* afterwards (except for user_data and user_path)! (free and init again to change them) */
/* These should point to the application specific routines that do the
* actual work */
AyStar_CalculateG *CalculateG;
AyStar_CalculateH *CalculateH;
AyStar_GetNeighbours *GetNeighbours;
AyStar_EndNodeCheck *EndNodeCheck;
AyStar_FoundEndNode *FoundEndNode;
/* These are completely untouched by AyStar, they can be accesed by
* the application specific routines to input and output data.
* user_path should typically contain data about the resulting path
* afterwards, user_target should typically contain information about
* what where looking for, and user_data can contain just about
* everything */
void *user_path;
void *user_target;
uint user_data[10];
/* How many loops are there called before AyStarMain_Main gives
* control back to the caller. 0 = until done */
byte loops_per_tick;
/* If the g-value goes over this number, it stops searching
* 0 = infinite */
uint max_path_cost;
/* The maximum amount of nodes that will be expanded, 0 = infinite */
uint max_search_nodes;
/* These should be filled with the neighbours of a tile by
* GetNeighbours */
AyStarNode neighbours[12];
byte num_neighbours;
/* These will contain the methods for manipulating the AyStar. Only
* main() should be called externally */
AyStar_AddStartNode *addstart;
AyStar_Main *main;
AyStar_Loop *loop;
AyStar_Free *free;
AyStar_Clear *clear;
AyStar_CheckTile *checktile;
/* These will contain the open and closed lists */
/* The actual closed list */
Hash ClosedListHash;
/* The open queue */
Queue OpenListQueue;
/* An extra hash to speed up the process of looking up an element in
* the open list */
Hash OpenListHash;
};
void AyStarMain_AddStartNode(AyStar *aystar, AyStarNode *start_node, uint g);
int AyStarMain_Main(AyStar *aystar);
int AyStarMain_Loop(AyStar *aystar);
int AyStarMain_CheckTile(AyStar *aystar, AyStarNode *current, OpenListNode *parent);
void AyStarMain_Free(AyStar *aystar);
void AyStarMain_Clear(AyStar *aystar);
/* Initialize an AyStar. You should fill all appropriate fields before
* callling init_AyStar (see the declaration of AyStar for which fields are
* internal */
void init_AyStar(AyStar *aystar, Hash_HashProc hash, uint num_buckets);
#endif /* AYSTAR_H */

View File

@@ -1,72 +0,0 @@
trigger:
- master
- release/*
pr:
- master
- release/*
jobs:
- job: windows
displayName: 'Windows'
pool:
vmImage: 'VS2017-Win2016'
strategy:
matrix:
Win32:
BuildPlatform: 'Win32'
Win64:
BuildPlatform: 'x64'
steps:
- template: azure-pipelines/templates/ci-git-rebase.yml
- template: azure-pipelines/templates/windows-dependencies.yml
- template: azure-pipelines/templates/ci-opengfx.yml
- template: azure-pipelines/templates/windows-build.yml
parameters:
BuildPlatform: $(BuildPlatform)
BuildConfiguration: Debug
- script: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86
cd projects
call regression.bat
displayName: 'Test'
- job: linux
displayName: 'Linux'
pool:
vmImage: 'ubuntu-16.04'
strategy:
matrix:
linux-amd64-clang-3.9:
Tag: 'linux-amd64-clang-3.9'
linux-amd64-gcc-6:
Tag: 'linux-amd64-gcc-6'
linux-i386-gcc-6:
Tag: 'linux-i386-gcc-6'
steps:
- template: azure-pipelines/templates/ci-git-rebase.yml
# The dockers already have the dependencies installed
# The dockers already have OpenGFX installed
- template: azure-pipelines/templates/linux-build.yml
parameters:
Image: compile-farm-ci
Tag: $(Tag)
- job: macos
displayName: 'MacOS'
pool:
vmImage: 'macOS-10.14'
variables:
MACOSX_DEPLOYMENT_TARGET: 10.9
steps:
- template: azure-pipelines/templates/ci-git-rebase.yml
- template: azure-pipelines/templates/osx-dependencies.yml
- template: azure-pipelines/templates/ci-opengfx.yml
- template: azure-pipelines/templates/osx-build.yml
- script: 'make regression'
displayName: 'Test'

View File

@@ -1,10 +0,0 @@
trigger:
branches:
include:
- refs/tags/*
pr: none
jobs:
- template: azure-pipelines/templates/release.yml
parameters:
IsStableRelease: true

View File

@@ -1,7 +0,0 @@
trigger: none
pr: none
jobs:
- template: azure-pipelines/templates/release.yml
parameters:
IsStableRelease: false

View File

@@ -1,16 +0,0 @@
#!/bin/sh
tag=$(git name-rev --name-only --tags --no-undefined HEAD 2>/dev/null | sed 's@\^0$@@')
# If we are a tag, show the part of the changelog till (but excluding) the last stable
if [ -n "$tag" ]; then
grep='^[0-9]\+\.[0-9]\+\.[0-9]\+[^-]'
next=$(cat changelog.txt | grep '^[0-9]' | awk 'BEGIN { show="false" } // { if (show=="true") print $0; if ($1=="'$tag'") show="true"} ' | grep "$grep" | head -n1 | sed 's/ .*//')
cat changelog.txt | awk 'BEGIN { show="false" } /^[0-9]+.[0-9]+.[0-9]+/ { if ($1=="'$next'") show="false"; if ($1=="'$tag'") show="true";} // { if (show=="true") print $0 }'
exit 0
fi
# In all other cases, show the git log of the last 7 days
revdate=$(git log -1 --pretty=format:"%ci")
last_week=$(date -d "$revdate -7days" +"%Y-%m-%d %H:%M")
git log --after="${last_week}" --pretty=fuller

View File

@@ -1,86 +0,0 @@
#!/bin/sh
set -ex
if [ -z "$1" ]; then
echo "Usage: $0 <folder-with-bundles>"
exit 1
fi
FOLDER=$1
if [ ! -e .version ] || [ ! -e .release_date ]; then
echo "This script should be executed in the root of an extracted source tarball"
exit 1
fi
# Find the name based on the version
if [ -e .is_stable ]; then
isTesting=$(cat .version | grep "RC\|beta" || true)
if [ -z "${isTesting}" ]; then
NAME="stable"
else
NAME="testing"
fi
else
NAME=$(cat .version | cut -d- -f2 | cut -d- -f-2)
fi
# Convert the date to a YAML date
DATE=$(cat .release_date | tr ' ' T | sed 's/TUTC/:00-00:00/')
VERSION=$(cat .version)
BASE="openttd-${VERSION}"
echo "name: ${NAME}" > manifest.yaml
echo "date: ${DATE}" >> manifest.yaml
echo "base: ${BASE}-" >> manifest.yaml
error=""
FILES=
DEV_FILES=
for filename in $(ls ${FOLDER} | grep -v ".txt$\|.md$\|sum$" | sort); do
case ${filename} in
*docs* |\
*source* |\
*dbg.deb |\
*pdb.xz )
DEV_FILES="${DEV_FILES} ${filename}"
;;
*)
FILES="${FILES} ${filename}"
;;
esac
done
# output_files key filename...
output_files() {
if [ "$#" -lt 2 ]; then return; fi
key=$1
echo "${key}:" >> manifest.yaml
shift
while [ "$#" -gt 0 ]; do
filename=$1
if [ ! -e ${FOLDER}/${filename}.md5sum ] || [ ! -e ${FOLDER}/${filename}.sha1sum ] || [ ! -e ${FOLDER}/${filename}.sha256sum ]; then
echo "ERROR: missing checksum file for ${filename}" 1>&2
error="y"
continue
fi
echo "- id: ${filename}" >> manifest.yaml
echo " size: $(stat -c"%s" ${FOLDER}/${filename})" >> manifest.yaml
echo " md5sum: $(cat ${FOLDER}/${filename}.md5sum | cut -d\ -f1)" >> manifest.yaml
echo " sha1sum: $(cat ${FOLDER}/${filename}.sha1sum | cut -d\ -f1)" >> manifest.yaml
echo " sha256sum: $(cat ${FOLDER}/${filename}.sha256sum | cut -d\ -f1)" >> manifest.yaml
shift
done
}
output_files files ${FILES}
output_files dev_files ${DEV_FILES}
if [ -n "${error}" ]; then
echo "ERROR: exiting due to earlier errors" 1>&2
exit 1
fi

View File

@@ -1,10 +0,0 @@
steps:
# Rebase to target branch for every PR. This means users don't have to
# rebase every time target branch changes. As long as the PR applies cleanly, we
# will validate it.
- bash: |
git config user.email 'info@openttd.org'
git config user.name 'OpenTTD CI'
git rebase origin/${SYSTEM_PULLREQUEST_TARGETBRANCH}
displayName: 'Rebase to target branch'
condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))

View File

@@ -1,8 +0,0 @@
steps:
- bash: |
set -ex
cd bin/baseset
curl -L https://binaries.openttd.org/extra/opengfx/0.5.2/opengfx-0.5.2-all.zip > opengfx-0.5.2-all.zip
unzip opengfx-0.5.2-all.zip
rm -f opengfx-0.5.2-all.zip
displayName: 'Install OpenGFX'

View File

@@ -1,36 +0,0 @@
parameters:
Image: ''
Tag: ''
ContainerCommand: ''
steps:
# 'envVars' in the 'Docker@1' task is a bit funky. When you want to use a
# variable, you have to quote it. But the quote is also sent directly to
# Docker and ends up in the variable, which you don't want. To work around
# this, we set the correct variable first (which becomes an env-variable), and
# pass that env-variable through to Docker. We cannot use the normal
# 'variables' entry, as we are a template. So that results in this bit of
# Bash code. Not because it is pretty, but it is the only way we found that
# works.
- bash: |
echo "##vso[task.setvariable variable=TARGET_BRANCH]${SYSTEM_PULLREQUEST_TARGETBRANCH}"
echo "Target branch is ${SYSTEM_PULLREQUEST_TARGETBRANCH}"
displayName: "Set target branch"
condition: and(succeeded(), eq(variables['Build.Reason'], 'PullRequest'))
- task: Docker@1
${{ if eq(parameters.Image, 'compile-farm') }}:
displayName: 'Build'
${{ if eq(parameters.Image, 'compile-farm-ci') }}:
displayName: 'Build and test'
# Run the commit-checker only if it is a Pull Request
condition: and(succeeded(), or(not(contains(variables['Agent.JobName'], 'commit-checker')), eq(variables['Build.Reason'], 'PullRequest')))
inputs:
command: 'Run an image'
imageName: openttd/${{ parameters.Image }}:${{ parameters.Tag }}
volumes: '$(Build.SourcesDirectory):$(Build.SourcesDirectory)'
workingDirectory: '$(Build.SourcesDirectory)'
containerCommand: ${{ parameters.ContainerCommand }}
runInBackground: false
envVars: |
TARGET_BRANCH

View File

@@ -1,5 +0,0 @@
steps:
# Because we run the compile in a docker (under root), we are not owner
# of the 'bundles' folder. Fix that by executing a chown on it.
- bash: sudo chown -R $(id -u):$(id -g) bundles
displayName: 'Claim bundles folder back'

View File

@@ -1,5 +0,0 @@
steps:
- script: './configure PKG_CONFIG_PATH=/usr/local/lib/pkgconfig --enable-static'
displayName: 'Configure'
- script: 'make -j2'
displayName: 'Build'

View File

@@ -1,12 +0,0 @@
steps:
- script: |
set -ex
HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config lzo xz libpng freetype
# Remove the dynamic libraries of these libraries, to ensure we use
# the static versions. That is important, as it is unlikely any
# end-user has these brew libraries installed.
rm /usr/local/Cellar/lzo/*/lib/*.dylib
rm /usr/local/Cellar/xz/*/lib/*.dylib
rm /usr/local/Cellar/libpng/*/lib/*.dylib
rm /usr/local/Cellar/freetype/*/lib/*.dylib
displayName: 'Install dependencies'

View File

@@ -1,19 +0,0 @@
parameters:
CalculateChecksums: true
steps:
- ${{ if eq(parameters.CalculateChecksums, true) }}:
- bash: |
set -ex
cd bundles
for i in $(ls); do
openssl dgst -r -md5 -hex $i > $i.md5sum
openssl dgst -r -sha1 -hex $i > $i.sha1sum
openssl dgst -r -sha256 -hex $i > $i.sha256sum
done
displayName: 'Calculate checksums'
- task: PublishBuildArtifacts@1
displayName: 'Publish bundles'
inputs:
PathtoPublish: bundles/
ArtifactName: bundles

View File

@@ -1,20 +0,0 @@
# Fetch the source tarball as prepared by an earlier job. In there is the
# version predefined. This ensures we are all going to compile the same
# source with the same version.
steps:
- checkout: none
- task: DownloadBuildArtifacts@0
displayName: 'Download source'
inputs:
downloadType: specific
itemPattern: 'bundles/openttd-*-source.tar.xz'
downloadPath: '$(Build.ArtifactStagingDirectory)'
- bash: tar --xz -xf ../a/bundles/openttd-*-source.tar.xz --strip-components=1
displayName: 'Extracting source'
- bash: |
set -e
VERSION=$(cat .version)
echo "${VERSION}"
echo "##vso[build.updatebuildnumber]${VERSION}"
displayName: 'Change BuildNumber to version'

View File

@@ -1,20 +0,0 @@
parameters:
IsStableRelease: false
steps:
- task: DownloadBuildArtifacts@0
displayName: 'Download all bundles'
inputs:
downloadType: specific
itemPattern: 'bundles/*'
downloadPath: '$(Build.ArtifactStagingDirectory)'
- ${{ if eq(parameters.IsStableRelease, true) }}:
- script: |
touch .is_stable
displayName: 'Mark as stable release'
- script: |
set -ex
./azure-pipelines/manifest.sh ../a/bundles/
mkdir -p bundles
mv manifest.yaml bundles/
displayName: 'Create manifest.yaml'

View File

@@ -1,35 +0,0 @@
# Set the revisions, and remove the VCS files.
# This ensures everything else picks up on the predefined versions, and not
# that because of some build process the version all of a sudden changes.
steps:
- script: |
set -ex
if [ -n "${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}" ]; then
# We are triggered from a GitHub Pull Request
git checkout -B pr${SYSTEM_PULLREQUEST_PULLREQUESTNUMBER}
elif [ "${BUILD_SOURCEBRANCHNAME}" = "merge" ] || [ "${BUILD_SOURCEBRANCHNAME}" = "head" ]; then
# We are manually triggered based on a GitHub Pull Request
PULLREQUESTNUMBER=$(echo ${BUILD_SOURCEBRANCH} | cut -d/ -f3)
git checkout -B pr${PULLREQUESTNUMBER}
else
git checkout -B ${BUILD_SOURCEBRANCHNAME}
fi
./findversion.sh > .ottdrev
./azure-pipelines/changelog.sh > .changelog
TZ='UTC' date +"%Y-%m-%d %H:%M UTC" > .release_date
cat .ottdrev | cut -f 1 -d$'\t' > .version
echo "Release Date: $(cat .release_date)"
echo "Revision: $(cat .ottdrev)"
echo "Version: $(cat .version)"
displayName: 'Create version files'
- script: |
set -e
VERSION=$(cat .version)
echo "${VERSION}"
echo "##vso[build.updatebuildnumber]${VERSION}"
displayName: 'Change BuildNumber to version'
- script: find . -iname .hg -or -iname .git -or -iname .svn | xargs rm -rf
displayName: 'Remove VCS information'

View File

@@ -1,184 +0,0 @@
parameters:
# If this is false, not all targets are triggered. For example:
# The NSIS installer for Windows and the creation of debs only work for
# releases. Not for any other type of binary. So they are skilled if this
# is set to false.
IsStableRelease: false
jobs:
- job: source
displayName: 'Source'
pool:
vmImage: 'ubuntu-16.04'
steps:
- template: release-prepare-source.yml
- script: |
set -ex
# Rename the folder to openttd-NNN-source
mkdir openttd-$(Build.BuildNumber)
find . -maxdepth 1 -not -name . -not -name openttd-$(Build.BuildNumber) -exec mv {} openttd-$(Build.BuildNumber)/ \;
# Copy back release_date, as it is needed for the template 'release-bundles'
cp openttd-$(Build.BuildNumber)/.release_date .release_date
mkdir bundles
tar --xz -cf bundles/openttd-$(Build.BuildNumber)-source.tar.xz openttd-$(Build.BuildNumber)
zip -9 -r -q bundles/openttd-$(Build.BuildNumber)-source.zip openttd-$(Build.BuildNumber)
displayName: 'Create bundle'
- template: release-bundles.yml
- job: meta
displayName: 'Metadata'
pool:
vmImage: 'ubuntu-16.04'
dependsOn: source
steps:
- template: release-fetch-source.yml
- script: |
set -ex
mkdir -p bundles
cp .changelog bundles/changelog.txt
cp .release_date bundles/released.txt
cp README.md bundles/README.md
displayName: 'Copy meta files'
- template: release-bundles.yml
parameters:
CalculateChecksums: false
- job: docs
displayName: 'Docs'
pool:
vmImage: 'ubuntu-16.04'
dependsOn: source
steps:
- template: release-fetch-source.yml
- template: linux-build.yml
parameters:
Image: compile-farm
ContainerCommand: '$(Build.BuildNumber)'
Tag: docs
- template: linux-claim-bundles.yml
- template: release-bundles.yml
- job: windows
displayName: 'Windows'
pool:
vmImage: 'VS2017-Win2016'
dependsOn: source
strategy:
matrix:
Win32:
BuildPlatform: 'Win32'
BundlePlatform: 'win32'
Win64:
BuildPlatform: 'x64'
BundlePlatform: 'win64'
steps:
- template: release-fetch-source.yml
- template: windows-dependencies.yml
- template: windows-dependency-zip.yml
- ${{ if eq(parameters.IsStableRelease, true) }}:
- template: windows-dependency-nsis.yml
- template: windows-build.yml
parameters:
BuildPlatform: $(BuildPlatform)
BuildConfiguration: Release
- bash: |
set -ex
make -f Makefile.msvc bundle_pdb bundle_zip PLATFORM=$(BundlePlatform) BUNDLE_NAME=openttd-$(Build.BuildNumber)-windows-$(BundlePlatform)
displayName: 'Create bundles'
- ${{ if eq(parameters.IsStableRelease, true) }}:
- bash: |
set -ex
# NSIS will be part of the Hosted image in the next update. Till then, we set the PATH ourself
export PATH="${PATH}:/c/Program Files (x86)/NSIS"
make -f Makefile.msvc bundle_exe PLATFORM=$(BundlePlatform) BUNDLE_NAME=openttd-$(Build.BuildNumber)-windows-$(BundlePlatform)
displayName: 'Create installer bundle'
- template: release-bundles.yml
- ${{ if eq(parameters.IsStableRelease, true) }}:
- job: linux_stable
displayName: 'Linux'
pool:
vmImage: 'ubuntu-16.04'
dependsOn: source
strategy:
matrix:
linux-ubuntu-xenial-i386-gcc:
Tag: 'linux-ubuntu-xenial-i386-gcc'
linux-ubuntu-xenial-amd64-gcc:
Tag: 'linux-ubuntu-xenial-amd64-gcc'
linux-ubuntu-bionic-i386-gcc:
Tag: 'linux-ubuntu-bionic-i386-gcc'
linux-ubuntu-bionic-amd64-gcc:
Tag: 'linux-ubuntu-bionic-amd64-gcc'
linux-debian-stretch-i386-gcc:
Tag: 'linux-debian-stretch-i386-gcc'
linux-debian-stretch-amd64-gcc:
Tag: 'linux-debian-stretch-amd64-gcc'
linux-debian-buster-i386-gcc:
Tag: 'linux-debian-buster-i386-gcc'
linux-debian-buster-amd64-gcc:
Tag: 'linux-debian-buster-amd64-gcc'
steps:
- template: release-fetch-source.yml
- template: linux-build.yml
parameters:
Image: compile-farm
ContainerCommand: '$(Build.BuildNumber)'
Tag: $(Tag)
- template: linux-claim-bundles.yml
- template: release-bundles.yml
- job: macos
displayName: 'MacOS'
pool:
vmImage: 'macOS-10.14'
dependsOn: source
variables:
MACOSX_DEPLOYMENT_TARGET: 10.9
steps:
- template: release-fetch-source.yml
- template: osx-dependencies.yml
- template: osx-build.yml
- script: 'make bundle_zip bundle_dmg BUNDLE_NAME=openttd-$(Build.BuildNumber)-macosx'
displayName: 'Create bundles'
- template: release-bundles.yml
- job: manifest
displayName: 'Manifest'
pool:
vmImage: 'ubuntu-16.04'
dependsOn:
- source
- docs
- windows
- ${{ if eq(parameters.IsStableRelease, true) }}:
- linux_stable
- macos
# "Skipped" is not a status, and is not succeeded. So it seems to be
# considered failed. So we trigger if all the earlier jobs are done (which
# might be succeeded, failed, or skipped), and run this job. This is not
# optimal, but given the rules, it is the only way to get this to work (as
# some jobs might be skipped).
condition: succeededOrFailed()
steps:
- template: release-fetch-source.yml
- template: release-manifest.yml
${{ if eq(parameters.IsStableRelease, true) }}:
parameters:
IsStableRelease: true
- template: release-bundles.yml
parameters:
CalculateChecksums: false

View File

@@ -1,11 +0,0 @@
parameters:
BuildPlatform: ''
steps:
- task: VSBuild@1
displayName: 'Build'
inputs:
solution: 'projects/openttd_vs141.sln'
platform: ${{ parameters.BuildPlatform }}
configuration: ${{ parameters.BuildConfiguration }}
maximumCpuCount: true

View File

@@ -1,14 +0,0 @@
steps:
- bash: |
set -ex
curl -L https://github.com/OpenTTD/CompileFarm/releases/download/latest/windows-dependencies.zip > windows-dependencies.zip
unzip windows-dependencies.zip
rm -f windows-dependencies.zip
mv windows-dependencies/installed /c/vcpkg/
rm -rf windows-dependencies
displayName: 'Install dependencies'
workingDirectory: $(Build.ArtifactStagingDirectory)
- script: c:\vcpkg\vcpkg.exe integrate install
displayName: 'Integrate vcpkg'

View File

@@ -1,26 +0,0 @@
parameters:
condition: true
steps:
- bash: |
set -ex
mkdir nsis-plugin; cd nsis-plugin
curl -L https://devs.openttd.org/~truebrain/nsis-plugins/Nsis7z.zip > Nsis7z.zip
unzip Nsis7z.zip
cp -R Plugins/* "/c/Program Files (x86)/NSIS/Plugins/"
cd ..; rm -rf nsis-plugin
mkdir nsis-plugin; cd nsis-plugin
curl -L https://devs.openttd.org/~truebrain/nsis-plugins/NsisGetVersion.zip > NsisGetVersion.zip
unzip NsisGetVersion.zip
cp -R Plugins/* "/c/Program Files (x86)/NSIS/Plugins/x86-ansi/"
cd ..; rm -rf nsis-plugin
mkdir nsis-plugin; cd nsis-plugin
curl -L https://devs.openttd.org/~truebrain/nsis-plugins/NsisFindProc.zip > NsisFindProc.zip
unzip NsisFindProc.zip
cp -R *.dll "/c/Program Files (x86)/NSIS/Plugins/x86-ansi/"
cd ..; rm -rf nsis-plugin
displayName: 'Install NSIS with the 7z, GetVersion, and FindProc plugins'
condition: and(succeeded(), ${{ parameters.condition }})

View File

@@ -1,5 +0,0 @@
steps:
- bash: |
set -ex
choco install zip
displayName: 'Install zip'

View File

@@ -1,381 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("0.7 API compatibility in effect:");
AILog.Info(" - AITown::GetLastMonthProduction's behaviour has slightly changed.");
AILog.Info(" - AISubsidy::GetDestination returns STATION_INVALID for awarded subsidies.");
AILog.Info(" - AISubsidy::GetSource returns STATION_INVALID for awarded subsidies.");
AISign.GetMaxSignID <- function()
{
local list = AISignList();
local max_id = 0;
foreach (id, d in list) {
if (id > max_id) max_id = id;
}
return max_id;
}
AITile.GetHeight <- function(tile)
{
if (!AIMap.IsValidTile(tile)) return -1;
return AITile.GetCornerHeight(tile, AITile.CORNER_N);
}
AIOrder.ChangeOrder <- function(vehicle_id, order_position, order_flags)
{
return AIOrder.SetOrderFlags(vehicle_id, order_position, order_flags);
}
AIWaypoint.WAYPOINT_INVALID <- 0xFFFF;
AISubsidy.SourceIsTown <- function(subsidy_id)
{
if (!AISubsidy.IsValidSubsidy(subsidy_id) || AISubsidy.IsAwarded(subsidy_id)) return false;
return AISubsidy.GetSourceType(subsidy_id) == AISubsidy.SPT_TOWN;
}
AISubsidy.GetSource <- function(subsidy_id)
{
if (!AISubsidy.IsValidSubsidy(subsidy_id)) return AIBaseStation.STATION_INVALID;
if (AISubsidy.IsAwarded(subsidy_id)) {
return AIBaseStation.STATION_INVALID;
}
return AISubsidy.GetSourceIndex(subsidy_id);
}
AISubsidy.DestinationIsTown <- function(subsidy_id)
{
if (!AISubsidy.IsValidSubsidy(subsidy_id) || AISubsidy.IsAwarded(subsidy_id)) return false;
return AISubsidy.GetDestinationType(subsidy_id) == AISubsidy.SPT_TOWN;
}
AISubsidy.GetDestination <- function(subsidy_id)
{
if (!AISubsidy.IsValidSubsidy(subsidy_id)) return AIBaseStation.STATION_INVALID;
if (AISubsidy.IsAwarded(subsidy_id)) {
return AIBaseStation.STATION_INVALID;
}
return AISubsidy.GetDestinationIndex(subsidy_id);
}
AITown.GetMaxProduction <- function(town_id, cargo_id)
{
return AITown.GetLastMonthProduction(town_id, cargo_id);
}
AIRail.RemoveRailWaypoint <- function(tile)
{
return AIRail.RemoveRailWaypointTileRect(tile, tile, true);
}
AIRail.RemoveRailStationTileRect <- function(tile, tile2)
{
return AIRail.RemoveRailStationTileRectangle(tile, tile2, false);
}
AIVehicle.SkipToVehicleOrder <- function(vehicle_id, order_position)
{
return AIOrder.SkipToOrder(vehicle_id, order_position);
}
AIEngine.IsValidEngine <- function(engine_id)
{
return AIEngine.IsBuildable(engine_id);
}
AIEngine._GetName <- AIEngine.GetName;
AIEngine.GetName <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return null;
return AIEngine._GetName(engine_id);
}
AIEngine._GetCargoType <- AIEngine.GetCargoType;
AIEngine.GetCargoType <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return 255;
return AIEngine._GetCargoType(engine_id);
}
AIEngine._CanRefitCargo <- AIEngine.CanRefitCargo;
AIEngine.CanRefitCargo <- function(engine_id, cargo_id)
{
if (!AIEngine.IsBuildable(engine_id)) return false;
return AIEngine._CanRefitCargo(engine_id, cargo_id);
}
AIEngine._CanPullCargo <- AIEngine.CanPullCargo;
AIEngine.CanPullCargo <- function(engine_id, cargo_id)
{
if (!AIEngine.IsBuildable(engine_id)) return false;
return AIEngine._CanPullCargo(engine_id, cargo_id);
}
AIEngine._GetCapacity <- AIEngine.GetCapacity;
AIEngine.GetCapacity <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetCapacity(engine_id);
}
AIEngine._GetReliability <- AIEngine.GetReliability;
AIEngine.GetReliability <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetReliability(engine_id);
}
AIEngine._GetMaxSpeed <- AIEngine.GetMaxSpeed;
AIEngine.GetMaxSpeed <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetMaxSpeed(engine_id);
}
AIEngine._GetPrice <- AIEngine.GetPrice;
AIEngine.GetPrice <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetPrice(engine_id);
}
AIEngine._GetMaxAge <- AIEngine.GetMaxAge;
AIEngine.GetMaxAge <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetMaxAge(engine_id);
}
AIEngine._GetRunningCost <- AIEngine.GetRunningCost;
AIEngine.GetRunningCost <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetRunningCost(engine_id);
}
AIEngine._GetPower <- AIEngine.GetPower;
AIEngine.GetPower <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetPower(engine_id);
}
AIEngine._GetWeight <- AIEngine.GetWeight;
AIEngine.GetWeight <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetWeight(engine_id);
}
AIEngine._GetMaxTractiveEffort <- AIEngine.GetMaxTractiveEffort;
AIEngine.GetMaxTractiveEffort <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetMaxTractiveEffort(engine_id);
}
AIEngine._GetDesignDate <- AIEngine.GetDesignDate;
AIEngine.GetDesignDate <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetDesignDate(engine_id);
}
AIEngine._GetVehicleType <- AIEngine.GetVehicleType;
AIEngine.GetVehicleType <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return AIVehicle.VT_INVALID;
return AIEngine._GetVehicleType(engine_id);
}
AIEngine._IsWagon <- AIEngine.IsWagon;
AIEngine.IsWagon <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return false;
return AIEngine._IsWagon(engine_id);
}
AIEngine._CanRunOnRail <- AIEngine.CanRunOnRail;
AIEngine.CanRunOnRail <- function(engine_id, track_rail_type)
{
if (!AIEngine.IsBuildable(engine_id)) return false;
return AIEngine._CanRunOnRail(engine_id, track_rail_type);
}
AIEngine._HasPowerOnRail <- AIEngine.HasPowerOnRail;
AIEngine.HasPowerOnRail <- function(engine_id, track_rail_type)
{
if (!AIEngine.IsBuildable(engine_id)) return false;
return AIEngine._HasPowerOnRail(engine_id, track_rail_type);
}
AIEngine._GetRoadType <- AIEngine.GetRoadType;
AIEngine.GetRoadType <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return AIRoad.ROADTYPE_INVALID;
return AIEngine._GetRoadType(engine_id);
}
AIEngine._GetRailType <- AIEngine.GetRailType;
AIEngine.GetRailType <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return AIRail.RAILTYPE_INVALID;
return AIEngine._GetRailType(engine_id);
}
AIEngine._IsArticulated <- AIEngine.IsArticulated;
AIEngine.IsArticulated <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return false;
return AIEngine._IsArticulated(engine_id);
}
AIEngine._GetPlaneType <- AIEngine.GetPlaneType;
AIEngine.GetPlaneType <- function(engine_id)
{
if (!AIEngine.IsBuildable(engine_id)) return -1;
return AIEngine._GetPlaneType(engine_id);
}
_AIWaypointList <- AIWaypointList;
class AIWaypointList extends _AIWaypointList {
constructor()
{
::_AIWaypointList.constructor(AIWaypoint.WAYPOINT_RAIL);
}
}
AIRoad._BuildRoadStation <- AIRoad.BuildRoadStation;
AIRoad.BuildRoadStation <- function(tile, front, road_veh_type, station_id)
{
if (AIRoad.IsRoadStationTile(tile) && AICompany.IsMine(AITile.GetOwner(tile))) return false;
return AIRoad._BuildRoadStation(tile, front, road_veh_type, station_id);
}
AIRoad._BuildDriveThroughRoadStation <- AIRoad.BuildDriveThroughRoadStation;
AIRoad.BuildDriveThroughRoadStation <- function(tile, front, road_veh_type, station_id)
{
if (AIRoad.IsRoadStationTile(tile) && AICompany.IsMine(AITile.GetOwner(tile))) return false;
return AIRoad._BuildDriveThroughRoadStation(tile, front, road_veh_type, station_id);
}
AIBridgeList.HasNext <-
AIBridgeList_Length.HasNext <-
AICargoList.HasNext <-
AICargoList_IndustryAccepting.HasNext <-
AICargoList_IndustryProducing.HasNext <-
AIDepotList.HasNext <-
AIEngineList.HasNext <-
AIGroupList.HasNext <-
AIIndustryList.HasNext <-
AIIndustryList_CargoAccepting.HasNext <-
AIIndustryList_CargoProducing.HasNext <-
AIIndustryTypeList.HasNext <-
AIList.HasNext <-
AIRailTypeList.HasNext <-
AISignList.HasNext <-
AIStationList.HasNext <-
AIStationList_Vehicle.HasNext <-
AISubsidyList.HasNext <-
AITileList.HasNext <-
AITileList_IndustryAccepting.HasNext <-
AITileList_IndustryProducing.HasNext <-
AITileList_StationType.HasNext <-
AITownList.HasNext <-
AIVehicleList.HasNext <-
AIVehicleList_DefaultGroup.HasNext <-
AIVehicleList_Group.HasNext <-
AIVehicleList_SharedOrders.HasNext <-
AIVehicleList_Station.HasNext <-
AIWaypointList.HasNext <-
AIWaypointList_Vehicle.HasNext <-
function()
{
return !this.IsEnd();
}
AIIndustry._IsCargoAccepted <- AIIndustry.IsCargoAccepted;
AIIndustry.IsCargoAccepted <- function(industry_id, cargo_id)
{
return AIIndustry._IsCargoAccepted(industry_id, cargo_id) != AIIndustry.CAS_NOT_ACCEPTED;
}
AIAbstractList <- AIList;
AIList.ChangeItem <- AIList.SetValue;
AIRail.ERR_NONUNIFORM_STATIONS_DISABLED <- 0xFFFF;
AICompany.GetCompanyValue <- function(company)
{
return AICompany.GetQuarterlyCompanyValue(company, AICompany.CURRENT_QUARTER);
}
AITown.GetLastMonthTransported <- AITown.GetLastMonthSupplied;
AIEvent.AI_ET_INVALID <- AIEvent.ET_INVALID;
AIEvent.AI_ET_TEST <- AIEvent.ET_TEST;
AIEvent.AI_ET_SUBSIDY_OFFER <- AIEvent.ET_SUBSIDY_OFFER;
AIEvent.AI_ET_SUBSIDY_OFFER_EXPIRED <- AIEvent.ET_SUBSIDY_OFFER_EXPIRED;
AIEvent.AI_ET_SUBSIDY_AWARDED <- AIEvent.ET_SUBSIDY_AWARDED;
AIEvent.AI_ET_SUBSIDY_EXPIRED <- AIEvent.ET_SUBSIDY_EXPIRED;
AIEvent.AI_ET_ENGINE_PREVIEW <- AIEvent.ET_ENGINE_PREVIEW;
AIEvent.AI_ET_COMPANY_NEW <- AIEvent.ET_COMPANY_NEW;
AIEvent.AI_ET_COMPANY_IN_TROUBLE <- AIEvent.ET_COMPANY_IN_TROUBLE;
AIEvent.AI_ET_COMPANY_MERGER <- AIEvent.ET_COMPANY_MERGER;
AIEvent.AI_ET_COMPANY_BANKRUPT <- AIEvent.ET_COMPANY_BANKRUPT;
AIEvent.AI_ET_VEHICLE_CRASHED <- AIEvent.ET_VEHICLE_CRASHED;
AIEvent.AI_ET_VEHICLE_LOST <- AIEvent.ET_VEHICLE_LOST;
AIEvent.AI_ET_VEHICLE_WAITING_IN_DEPOT <- AIEvent.ET_VEHICLE_WAITING_IN_DEPOT;
AIEvent.AI_ET_VEHICLE_UNPROFITABLE <- AIEvent.ET_VEHICLE_UNPROFITABLE;
AIEvent.AI_ET_INDUSTRY_OPEN <- AIEvent.ET_INDUSTRY_OPEN;
AIEvent.AI_ET_INDUSTRY_CLOSE <- AIEvent.ET_INDUSTRY_CLOSE;
AIEvent.AI_ET_ENGINE_AVAILABLE <- AIEvent.ET_ENGINE_AVAILABLE;
AIEvent.AI_ET_STATION_FIRST_VEHICLE <- AIEvent.ET_STATION_FIRST_VEHICLE;
AIEvent.AI_ET_DISASTER_ZEPPELINER_CRASHED <- AIEvent.ET_DISASTER_ZEPPELINER_CRASHED;
AIEvent.AI_ET_DISASTER_ZEPPELINER_CLEARED <- AIEvent.ET_DISASTER_ZEPPELINER_CLEARED;
AIOrder.AIOF_NONE <- AIOrder.OF_NONE
AIOrder.AIOF_NON_STOP_INTERMEDIATE <- AIOrder.OF_NON_STOP_INTERMEDIATE
AIOrder.AIOF_NON_STOP_DESTINATION <- AIOrder.OF_NON_STOP_DESTINATION
AIOrder.AIOF_UNLOAD <- AIOrder.OF_UNLOAD
AIOrder.AIOF_TRANSFER <- AIOrder.OF_TRANSFER
AIOrder.AIOF_NO_UNLOAD <- AIOrder.OF_NO_UNLOAD
AIOrder.AIOF_FULL_LOAD <- AIOrder.OF_FULL_LOAD
AIOrder.AIOF_FULL_LOAD_ANY <- AIOrder.OF_FULL_LOAD_ANY
AIOrder.AIOF_NO_LOAD <- AIOrder.OF_NO_LOAD
AIOrder.AIOF_SERVICE_IF_NEEDED <- AIOrder.OF_SERVICE_IF_NEEDED
AIOrder.AIOF_STOP_IN_DEPOT <- AIOrder.OF_STOP_IN_DEPOT
AIOrder.AIOF_GOTO_NEAREST_DEPOT <- AIOrder.OF_GOTO_NEAREST_DEPOT
AIOrder.AIOF_NON_STOP_FLAGS <- AIOrder.OF_NON_STOP_FLAGS
AIOrder.AIOF_UNLOAD_FLAGS <- AIOrder.OF_UNLOAD_FLAGS
AIOrder.AIOF_LOAD_FLAGS <- AIOrder.OF_LOAD_FLAGS
AIOrder.AIOF_DEPOT_FLAGS <- AIOrder.OF_DEPOT_FLAGS
AIOrder.AIOF_INVALID <- AIOrder.OF_INVALID
/* 1.9 adds a vehicle type parameter. */
AIBridge._GetName <- AIBridge.GetName;
AIBridge.GetName <- function(bridge_id)
{
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
}
/* 1.9 adds parent_group_id to CreateGroup function */
AIGroup._CreateGroup <- AIGroup.CreateGroup;
AIGroup.CreateGroup <- function(vehicle_type)
{
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
}

View File

@@ -1,133 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("1.0 API compatibility in effect.");
AIRoad._BuildRoadStation <- AIRoad.BuildRoadStation;
AIRoad.BuildRoadStation <- function(tile, front, road_veh_type, station_id)
{
if (AIRoad.IsRoadStationTile(tile) && AICompany.IsMine(AITile.GetOwner(tile))) return false;
return AIRoad._BuildRoadStation(tile, front, road_veh_type, station_id);
}
AIRoad._BuildDriveThroughRoadStation <- AIRoad.BuildDriveThroughRoadStation;
AIRoad.BuildDriveThroughRoadStation <- function(tile, front, road_veh_type, station_id)
{
if (AIRoad.IsRoadStationTile(tile) && AICompany.IsMine(AITile.GetOwner(tile))) return false;
return AIRoad._BuildDriveThroughRoadStation(tile, front, road_veh_type, station_id);
}
AIBridgeList.HasNext <-
AIBridgeList_Length.HasNext <-
AICargoList.HasNext <-
AICargoList_IndustryAccepting.HasNext <-
AICargoList_IndustryProducing.HasNext <-
AIDepotList.HasNext <-
AIEngineList.HasNext <-
AIGroupList.HasNext <-
AIIndustryList.HasNext <-
AIIndustryList_CargoAccepting.HasNext <-
AIIndustryList_CargoProducing.HasNext <-
AIIndustryTypeList.HasNext <-
AIList.HasNext <-
AIRailTypeList.HasNext <-
AISignList.HasNext <-
AIStationList.HasNext <-
AIStationList_Vehicle.HasNext <-
AISubsidyList.HasNext <-
AITileList.HasNext <-
AITileList_IndustryAccepting.HasNext <-
AITileList_IndustryProducing.HasNext <-
AITileList_StationType.HasNext <-
AITownList.HasNext <-
AIVehicleList.HasNext <-
AIVehicleList_DefaultGroup.HasNext <-
AIVehicleList_Depot.HasNext <-
AIVehicleList_Group.HasNext <-
AIVehicleList_SharedOrders.HasNext <-
AIVehicleList_Station.HasNext <-
AIWaypointList.HasNext <-
AIWaypointList_Vehicle.HasNext <-
function()
{
return !this.IsEnd();
}
AIIndustry._IsCargoAccepted <- AIIndustry.IsCargoAccepted;
AIIndustry.IsCargoAccepted <- function(industry_id, cargo_id)
{
return AIIndustry._IsCargoAccepted(industry_id, cargo_id) != AIIndustry.CAS_NOT_ACCEPTED;
}
AIAbstractList <- AIList;
AIList.ChangeItem <- AIList.SetValue;
AIRail.ERR_NONUNIFORM_STATIONS_DISABLED <- 0xFFFF;
AICompany.GetCompanyValue <- function(company)
{
return AICompany.GetQuarterlyCompanyValue(company, AICompany.CURRENT_QUARTER);
}
AITown.GetLastMonthTransported <- AITown.GetLastMonthSupplied;
AIEvent.AI_ET_INVALID <- AIEvent.ET_INVALID;
AIEvent.AI_ET_TEST <- AIEvent.ET_TEST;
AIEvent.AI_ET_SUBSIDY_OFFER <- AIEvent.ET_SUBSIDY_OFFER;
AIEvent.AI_ET_SUBSIDY_OFFER_EXPIRED <- AIEvent.ET_SUBSIDY_OFFER_EXPIRED;
AIEvent.AI_ET_SUBSIDY_AWARDED <- AIEvent.ET_SUBSIDY_AWARDED;
AIEvent.AI_ET_SUBSIDY_EXPIRED <- AIEvent.ET_SUBSIDY_EXPIRED;
AIEvent.AI_ET_ENGINE_PREVIEW <- AIEvent.ET_ENGINE_PREVIEW;
AIEvent.AI_ET_COMPANY_NEW <- AIEvent.ET_COMPANY_NEW;
AIEvent.AI_ET_COMPANY_IN_TROUBLE <- AIEvent.ET_COMPANY_IN_TROUBLE;
AIEvent.AI_ET_COMPANY_ASK_MERGER <- AIEvent.ET_COMPANY_ASK_MERGER;
AIEvent.AI_ET_COMPANY_MERGER <- AIEvent.ET_COMPANY_MERGER;
AIEvent.AI_ET_COMPANY_BANKRUPT <- AIEvent.ET_COMPANY_BANKRUPT;
AIEvent.AI_ET_VEHICLE_CRASHED <- AIEvent.ET_VEHICLE_CRASHED;
AIEvent.AI_ET_VEHICLE_LOST <- AIEvent.ET_VEHICLE_LOST;
AIEvent.AI_ET_VEHICLE_WAITING_IN_DEPOT <- AIEvent.ET_VEHICLE_WAITING_IN_DEPOT;
AIEvent.AI_ET_VEHICLE_UNPROFITABLE <- AIEvent.ET_VEHICLE_UNPROFITABLE;
AIEvent.AI_ET_INDUSTRY_OPEN <- AIEvent.ET_INDUSTRY_OPEN;
AIEvent.AI_ET_INDUSTRY_CLOSE <- AIEvent.ET_INDUSTRY_CLOSE;
AIEvent.AI_ET_ENGINE_AVAILABLE <- AIEvent.ET_ENGINE_AVAILABLE;
AIEvent.AI_ET_STATION_FIRST_VEHICLE <- AIEvent.ET_STATION_FIRST_VEHICLE;
AIEvent.AI_ET_DISASTER_ZEPPELINER_CRASHED <- AIEvent.ET_DISASTER_ZEPPELINER_CRASHED;
AIEvent.AI_ET_DISASTER_ZEPPELINER_CLEARED <- AIEvent.ET_DISASTER_ZEPPELINER_CLEARED;
AIOrder.AIOF_NONE <- AIOrder.OF_NONE
AIOrder.AIOF_NON_STOP_INTERMEDIATE <- AIOrder.OF_NON_STOP_INTERMEDIATE
AIOrder.AIOF_NON_STOP_DESTINATION <- AIOrder.OF_NON_STOP_DESTINATION
AIOrder.AIOF_UNLOAD <- AIOrder.OF_UNLOAD
AIOrder.AIOF_TRANSFER <- AIOrder.OF_TRANSFER
AIOrder.AIOF_NO_UNLOAD <- AIOrder.OF_NO_UNLOAD
AIOrder.AIOF_FULL_LOAD <- AIOrder.OF_FULL_LOAD
AIOrder.AIOF_FULL_LOAD_ANY <- AIOrder.OF_FULL_LOAD_ANY
AIOrder.AIOF_NO_LOAD <- AIOrder.OF_NO_LOAD
AIOrder.AIOF_SERVICE_IF_NEEDED <- AIOrder.OF_SERVICE_IF_NEEDED
AIOrder.AIOF_STOP_IN_DEPOT <- AIOrder.OF_STOP_IN_DEPOT
AIOrder.AIOF_GOTO_NEAREST_DEPOT <- AIOrder.OF_GOTO_NEAREST_DEPOT
AIOrder.AIOF_NON_STOP_FLAGS <- AIOrder.OF_NON_STOP_FLAGS
AIOrder.AIOF_UNLOAD_FLAGS <- AIOrder.OF_UNLOAD_FLAGS
AIOrder.AIOF_LOAD_FLAGS <- AIOrder.OF_LOAD_FLAGS
AIOrder.AIOF_DEPOT_FLAGS <- AIOrder.OF_DEPOT_FLAGS
AIOrder.AIOF_INVALID <- AIOrder.OF_INVALID
/* 1.9 adds a vehicle type parameter. */
AIBridge._GetName <- AIBridge.GetName;
AIBridge.GetName <- function(bridge_id)
{
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
}
/* 1.9 adds parent_group_id to CreateGroup function */
AIGroup._CreateGroup <- AIGroup.CreateGroup;
AIGroup.CreateGroup <- function(vehicle_type)
{
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
}

View File

@@ -1,70 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("1.1 API compatibility in effect.");
AICompany.GetCompanyValue <- function(company)
{
return AICompany.GetQuarterlyCompanyValue(company, AICompany.CURRENT_QUARTER);
}
AITown.GetLastMonthTransported <- AITown.GetLastMonthSupplied;
AIEvent.AI_ET_INVALID <- AIEvent.ET_INVALID;
AIEvent.AI_ET_TEST <- AIEvent.ET_TEST;
AIEvent.AI_ET_SUBSIDY_OFFER <- AIEvent.ET_SUBSIDY_OFFER;
AIEvent.AI_ET_SUBSIDY_OFFER_EXPIRED <- AIEvent.ET_SUBSIDY_OFFER_EXPIRED;
AIEvent.AI_ET_SUBSIDY_AWARDED <- AIEvent.ET_SUBSIDY_AWARDED;
AIEvent.AI_ET_SUBSIDY_EXPIRED <- AIEvent.ET_SUBSIDY_EXPIRED;
AIEvent.AI_ET_ENGINE_PREVIEW <- AIEvent.ET_ENGINE_PREVIEW;
AIEvent.AI_ET_COMPANY_NEW <- AIEvent.ET_COMPANY_NEW;
AIEvent.AI_ET_COMPANY_IN_TROUBLE <- AIEvent.ET_COMPANY_IN_TROUBLE;
AIEvent.AI_ET_COMPANY_ASK_MERGER <- AIEvent.ET_COMPANY_ASK_MERGER;
AIEvent.AI_ET_COMPANY_MERGER <- AIEvent.ET_COMPANY_MERGER;
AIEvent.AI_ET_COMPANY_BANKRUPT <- AIEvent.ET_COMPANY_BANKRUPT;
AIEvent.AI_ET_VEHICLE_CRASHED <- AIEvent.ET_VEHICLE_CRASHED;
AIEvent.AI_ET_VEHICLE_LOST <- AIEvent.ET_VEHICLE_LOST;
AIEvent.AI_ET_VEHICLE_WAITING_IN_DEPOT <- AIEvent.ET_VEHICLE_WAITING_IN_DEPOT;
AIEvent.AI_ET_VEHICLE_UNPROFITABLE <- AIEvent.ET_VEHICLE_UNPROFITABLE;
AIEvent.AI_ET_INDUSTRY_OPEN <- AIEvent.ET_INDUSTRY_OPEN;
AIEvent.AI_ET_INDUSTRY_CLOSE <- AIEvent.ET_INDUSTRY_CLOSE;
AIEvent.AI_ET_ENGINE_AVAILABLE <- AIEvent.ET_ENGINE_AVAILABLE;
AIEvent.AI_ET_STATION_FIRST_VEHICLE <- AIEvent.ET_STATION_FIRST_VEHICLE;
AIEvent.AI_ET_DISASTER_ZEPPELINER_CRASHED <- AIEvent.ET_DISASTER_ZEPPELINER_CRASHED;
AIEvent.AI_ET_DISASTER_ZEPPELINER_CLEARED <- AIEvent.ET_DISASTER_ZEPPELINER_CLEARED;
AIEvent.AI_ET_TOWN_FOUNDED <- AIEvent.ET_TOWN_FOUNDED;
AIOrder.AIOF_NONE <- AIOrder.OF_NONE
AIOrder.AIOF_NON_STOP_INTERMEDIATE <- AIOrder.OF_NON_STOP_INTERMEDIATE
AIOrder.AIOF_NON_STOP_DESTINATION <- AIOrder.OF_NON_STOP_DESTINATION
AIOrder.AIOF_UNLOAD <- AIOrder.OF_UNLOAD
AIOrder.AIOF_TRANSFER <- AIOrder.OF_TRANSFER
AIOrder.AIOF_NO_UNLOAD <- AIOrder.OF_NO_UNLOAD
AIOrder.AIOF_FULL_LOAD <- AIOrder.OF_FULL_LOAD
AIOrder.AIOF_FULL_LOAD_ANY <- AIOrder.OF_FULL_LOAD_ANY
AIOrder.AIOF_NO_LOAD <- AIOrder.OF_NO_LOAD
AIOrder.AIOF_SERVICE_IF_NEEDED <- AIOrder.OF_SERVICE_IF_NEEDED
AIOrder.AIOF_STOP_IN_DEPOT <- AIOrder.OF_STOP_IN_DEPOT
AIOrder.AIOF_GOTO_NEAREST_DEPOT <- AIOrder.OF_GOTO_NEAREST_DEPOT
AIOrder.AIOF_NON_STOP_FLAGS <- AIOrder.OF_NON_STOP_FLAGS
AIOrder.AIOF_UNLOAD_FLAGS <- AIOrder.OF_UNLOAD_FLAGS
AIOrder.AIOF_LOAD_FLAGS <- AIOrder.OF_LOAD_FLAGS
AIOrder.AIOF_DEPOT_FLAGS <- AIOrder.OF_DEPOT_FLAGS
AIOrder.AIOF_INVALID <- AIOrder.OF_INVALID
/* 1.9 adds a vehicle type parameter. */
AIBridge._GetName <- AIBridge.GetName;
AIBridge.GetName <- function(bridge_id)
{
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
}
/* 1.9 adds parent_group_id to CreateGroup function */
AIGroup._CreateGroup <- AIGroup.CreateGroup;
AIGroup.CreateGroup <- function(vehicle_type)
{
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
}

View File

@@ -1,6 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/

View File

@@ -1,22 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("1.2 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
AIBridge._GetName <- AIBridge.GetName;
AIBridge.GetName <- function(bridge_id)
{
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
}
/* 1.9 adds parent_group_id to CreateGroup function */
AIGroup._CreateGroup <- AIGroup.CreateGroup;
AIGroup.CreateGroup <- function(vehicle_type)
{
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
}

View File

@@ -1,22 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("1.3 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
AIBridge._GetName <- AIBridge.GetName;
AIBridge.GetName <- function(bridge_id)
{
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
}
/* 1.9 adds parent_group_id to CreateGroup function */
AIGroup._CreateGroup <- AIGroup.CreateGroup;
AIGroup.CreateGroup <- function(vehicle_type)
{
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
}

View File

@@ -1,22 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("1.4 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
AIBridge._GetName <- AIBridge.GetName;
AIBridge.GetName <- function(bridge_id)
{
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
}
/* 1.9 adds parent_group_id to CreateGroup function */
AIGroup._CreateGroup <- AIGroup.CreateGroup;
AIGroup.CreateGroup <- function(vehicle_type)
{
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
}

View File

@@ -1,22 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("1.5 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
AIBridge._GetName <- AIBridge.GetName;
AIBridge.GetName <- function(bridge_id)
{
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
}
/* 1.9 adds parent_group_id to CreateGroup function */
AIGroup._CreateGroup <- AIGroup.CreateGroup;
AIGroup.CreateGroup <- function(vehicle_type)
{
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
}

View File

@@ -1,22 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("1.6 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
AIBridge._GetName <- AIBridge.GetName;
AIBridge.GetName <- function(bridge_id)
{
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
}
/* 1.9 adds parent_group_id to CreateGroup function */
AIGroup._CreateGroup <- AIGroup.CreateGroup;
AIGroup.CreateGroup <- function(vehicle_type)
{
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
}

View File

@@ -1,22 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("1.7 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
AIBridge._GetName <- AIBridge.GetName;
AIBridge.GetName <- function(bridge_id)
{
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
}
/* 1.9 adds parent_group_id to CreateGroup function */
AIGroup._CreateGroup <- AIGroup.CreateGroup;
AIGroup.CreateGroup <- function(vehicle_type)
{
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
}

View File

@@ -1,22 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("1.8 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
AIBridge._GetName <- AIBridge.GetName;
AIBridge.GetName <- function(bridge_id)
{
return AIBridge._GetName(bridge_id, AIVehicle.VT_RAIL);
}
/* 1.9 adds parent_group_id to CreateGroup function */
AIGroup._CreateGroup <- AIGroup.CreateGroup;
AIGroup.CreateGroup <- function(vehicle_type)
{
return AIGroup._CreateGroup(vehicle_type, AIGroup.GROUP_INVALID);
}

View File

@@ -1,8 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
AILog.Info("1.9 API compatibility in effect.");

View File

@@ -1,67 +0,0 @@
#!/bin/sh
if ! [ -f ai/regression/completeness.sh ]; then
echo "Make sure you are in the root of OpenTTD before starting this script."
exit 1
fi
cat ai/regression/tst_*/main.nut | tr ';' '\n' | awk '
/^function/ {
for (local in locals) {
delete locals[local]
}
if (match($0, "function Regression::Start") || match($0, "function Regression::Stop")) next
locals["this"] = "AIControllerSquirrel"
}
/local/ {
gsub(".*local", "local")
if (match($4, "^AI")) {
sub("\\(.*", "", $4)
locals[$2] = $4
}
}
/Valuate/ {
gsub(".*Valuate\\(", "")
gsub("\\).*", "")
gsub(",.*", "")
gsub("\\.", "::")
print $0
}
/\./ {
for (local in locals) {
if (match($0, local ".")) {
fname = substr($0, index($0, local "."))
sub("\\(.*", "", fname)
sub("\\.", "::", fname)
sub(local, locals[local], fname)
print fname
if (match(locals[local], "List")) {
sub(locals[local], "AIAbstractList", fname)
print fname
}
}
}
# We want to remove everything before the FIRST occurrence of AI.
# If we do not remove any other occurrences of AI from the string
# we will remove everything before the LAST occurrence of AI, so
# do some little magic to make it work the way we want.
sub("AI", "AXXXXY")
gsub("AI", "AXXXXX")
sub(".*AXXXXY", "AI")
if (match($0, "^AI") && match($0, ".")) {
sub("\\(.*", "", $0)
sub("\\.", "::", $0)
print $0
}
}
' | sed 's/ //g' | sort | uniq > tmp.in_regression
grep 'DefSQ.*Method' ../src/script/api/ai/*.hpp.sq | grep -v 'AIError::' | grep -v 'AIAbstractList::Valuate' | grep -v '::GetClassName' | sed 's/^[^,]*, &//g;s/,[^,]*//g' | sort > tmp.in_api
diff -u tmp.in_regression tmp.in_api | grep -v '^+++' | grep '^+' | sed 's/^+//'
rm -f tmp.in_regression tmp.in_api

Binary file not shown.

View File

@@ -1,20 +0,0 @@
[misc]
display_opt = SHOW_TOWN_NAMES|SHOW_STATION_NAMES|SHOW_SIGNS|WAYPOINTS
language = english.lng
[gui]
autosave = off
[game_creation]
town_name = english
[ai_players]
none =
regression =
[vehicle]
road_side = right
plane_speed = 2
[construction]
max_bridge_length = 100

View File

@@ -1,13 +0,0 @@
class Regression extends AIInfo {
function GetAuthor() { return "OpenTTD NoAI Developers Team"; }
function GetName() { return "Regression"; }
function GetShortName() { return "REGR"; }
function GetDescription() { return "This runs regression-tests on some commands. On the same map the result should always be the same."; }
function GetVersion() { return 1; }
function GetAPIVersion() { return "1.10"; }
function GetDate() { return "2007-03-18"; }
function CreateInstance() { return "Regression"; }
}
RegisterAI(Regression());

View File

@@ -1,69 +0,0 @@
#!/bin/sh
if ! [ -f ai/regression/run.sh ]; then
echo "Make sure you are in the root of OpenTTD before starting this script."
exit 1
fi
if [ -f scripts/game_start.scr ]; then
mv scripts/game_start.scr scripts/game_start.scr.regression
fi
params=""
gdb=""
if [ "$1" != "-r" ]; then
params="-snull -mnull -vnull:ticks=30000"
fi
if [ "$1" = "-g" ]; then
gdb="gdb --ex run --args "
fi
if [ -d "ai/regression/tst_$1" ]; then
tests="ai/regression/tst_$1"
elif [ -d "ai/regression/tst_$2" ]; then
tests="ai/regression/tst_$2"
else
tests=ai/regression/tst_*
fi
ret=0
for tst in $tests; do
echo -n "Running $tst... "
# Make sure that only one info.nut is present for each test run. Otherwise openttd gets confused.
cp ai/regression/regression_info.nut $tst/info.nut
sav=$tst/test.sav
if ! [ -f $sav ]; then
sav=ai/regression/empty.sav
fi
if [ -n "$gdb" ]; then
$gdb ./openttd -x -c ai/regression/regression.cfg $params -g $sav
else
./openttd -x -c ai/regression/regression.cfg $params -g $sav -d script=2 -d misc=9 2>&1 | awk '{ gsub("0x(\\(nil\\)|0+)(x0)?", "0x00000000", $0); gsub("^dbg: \\[script\\]", "", $0); gsub("^ ", "ERROR: ", $0); gsub("ERROR: \\[1\\] ", "", $0); gsub("\\[P\\] ", "", $0); print $0; }' | grep -v '^dbg: \[.*\]' > $tst/tmp.regression
fi
if [ -z "$gdb" ]; then
res="`diff -ub $tst/result.txt $tst/tmp.regression`"
if [ -z "$res" ]; then
echo "passed!"
else
echo "failed! Difference:"
echo "$res"
ret=1
fi
fi
rm $tst/info.nut
if [ "$1" != "-k" ]; then
rm -f $tst/tmp.regression
fi
done
if [ -f scripts/game_start.scr.regression ]; then
mv scripts/game_start.scr.regression scripts/game_start.scr
fi
exit $ret

View File

@@ -1,152 +0,0 @@
Option Explicit
' This file is part of OpenTTD.
' OpenTTD 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, version 2.
' OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
Dim FSO
Set FSO = CreateObject("Scripting.FileSystemObject")
Function GetTestList()
Dim retests, i, tests, dir
Set retests = New RegExp
Set GetTestList = CreateObject("Scripting.Dictionary")
retests.Pattern = "ai/regression/tst_*"
retests.Global = True
For i = 0 To WScript.Arguments.Count - 1
Dim test
test = "ai/regression/tst_" & WScript.Arguments.Item(i)
If FSO.FolderExists(test) Then
retests.Pattern = test
Exit For
End If
Next
For Each dir In FSO.GetFolder("ai/regression/").SubFolders
Dim name
name = "ai/regression/" & dir.Name
If retests.Test(name) Then
GetTestList.Add name, name
End If
Next
End Function
Function GetParams()
GetParams = "-snull -mnull -vnull:ticks=30000"
If WScript.Arguments.Count = 0 Then Exit Function
If WScript.Arguments.Item(0) <> "-r" Then Exit Function
GetParams = ""
End Function
Sub FilterFile(filename)
Dim lines, filter, file
Set file = FSO.OpenTextFile(filename, 1)
If Not file.AtEndOfStream Then
lines = file.ReadAll
End If
file.Close
Set filter = New RegExp
filter.Global = True
filter.Multiline = True
filter.Pattern = "0x(\(nil\)|0+)(x0)?"
lines = filter.Replace(lines, "0x00000000")
filter.Pattern = "^dbg: \[script\]"
lines = filter.Replace(lines, "")
filter.Pattern = "^ "
lines = filter.Replace(lines, "ERROR: ")
filter.Pattern = "ERROR: \[1\] \[P\] "
lines = filter.Replace(lines, "")
filter.Pattern = "^dbg: .*\r\n"
lines = filter.Replace(lines, "")
Set file = FSO.OpenTextFile(filename, 2)
file.Write lines
file.Close
End Sub
Function CompareFiles(filename1, filename2)
Dim file, lines1, lines2
Set file = FSO.OpenTextFile(filename1, 1)
If Not file.AtEndOfStream Then
lines1 = file.ReadAll
End IF
file.Close
Set file = FSO.OpenTextFile(filename2, 1)
If Not file.AtEndOfStream Then
lines2 = file.ReadAll
End IF
file.Close
CompareFiles = (lines1 = lines2)
End Function
Function RunTest(test, params, ret)
Dim WshShell, oExec, sav, command
Set WshShell = CreateObject("WScript.Shell")
' Make sure that only one info.nut is present for each test run. Otherwise openttd gets confused.
FSO.CopyFile "ai/regression/regression_info.nut", test & "/info.nut"
sav = test & "/test.sav"
If Not FSO.FileExists(sav) Then
sav = "ai/regression/empty.sav"
End If
command = ".\openttd -x -c ai/regression/regression.cfg " & params & " -g " & sav & " -d script=2 -d misc=9"
' 2>&1 must be after >tmp.regression, else stderr is not redirected to the file
WshShell.Run "cmd /c " & command & " >"& test & "/tmp.regression 2>&1", 0, True
FilterFile test & "/tmp.regression"
If CompareFiles(test & "/result.txt", test & "/tmp.regression") Then
RunTest = "passed!"
Else
RunTest = "failed!"
ret = 1
End If
FSO.DeleteFile test & "/info.nut"
If WScript.Arguments.Count > 0 Then
If WScript.Arguments.Item(0) = "-k" Then
Exit Function
End If
End If
FSO.DeleteFile test & "/tmp.regression"
End Function
On Error Resume Next
WScript.StdOut.WriteLine ""
If Err.Number <> 0 Then
WScript.Echo "This script must be started with cscript."
WScript.Quit 1
End If
On Error Goto 0
If Not FSO.FileExists("ai/regression/run.vbs") Then
WScript.Echo "Make sure you are in the root of OpenTTD before starting this script."
WScript.Quit 1
End If
If FSO.FileExists("scripts/game_start.scr") Then
FSO.MoveFile "scripts/game_start.scr", "scripts/game_start.scr.regression"
End If
Dim params, test, ret
params = GetParams()
ret = 0
For Each test in GetTestList()
WScript.StdOut.Write "Running " & test & "... "
WScript.StdOut.WriteLine RunTest(test, params, ret)
Next
If FSO.FileExists("scripts/game_start.scr.regression") Then
FSO.MoveFile "scripts/game_start.scr.regression", "scripts/game_start.scr"
End If
WScript.Quit ret

File diff suppressed because it is too large Load Diff

View File

@@ -1,2 +0,0 @@
print(" Required this file");

File diff suppressed because it is too large Load Diff

View File

@@ -1,214 +0,0 @@
class Regression extends AIController {
function Start();
};
function Regression::StationList()
{
local list = AIStationList(AIStation.STATION_BUS_STOP + AIStation.STATION_TRUCK_STOP);
print("");
print("--StationList--");
print(" Count(): " + list.Count());
list.Valuate(AIStation.GetLocation);
print(" Location ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
list.Valuate(AIStation.GetCargoWaiting, 0);
print(" CargoWaiting(0) ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
list.Valuate(AIStation.GetCargoWaiting, 1);
print(" CargoWaiting(1) ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
};
function Regression::StationList_Cargo()
{
print("");
print("--StationList_Cargo--");
for (local mode = AIStationList_Cargo.CM_WAITING; mode <= AIStationList_Cargo.CM_PLANNED; ++mode) {
print(" " + mode);
for (local selector = AIStationList_Cargo.CS_BY_FROM; selector <= AIStationList_Cargo.CS_FROM_BY_VIA ; ++selector) {
print(" " + selector);
local list = AIStationList_Cargo(mode, selector, 6, 0, 7);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
}
}
};
function Regression::StationList_CargoPlanned()
{
print("");
print("--StationList_CargoPlanned--");
for (local selector = AIStationList_Cargo.CS_BY_FROM; selector <= AIStationList_Cargo.CS_FROM_BY_VIA; ++selector) {
print(" " + selector);
local list = AIStationList_CargoPlanned(selector, 6, 0, 7);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
}
};
function Regression::StationList_CargoPlannedByFrom()
{
print("");
print("--StationList_CargoPlannedByFrom--");
local list = AIStationList_CargoPlannedByFrom(2, 0);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
};
function Regression::StationList_CargoPlannedByVia()
{
print("");
print("--StationList_CargoPlannedByVia--");
local list = AIStationList_CargoPlannedByVia(2, 0);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
};
function Regression::StationList_CargoPlannedViaByFrom()
{
print("");
print("--StationList_CargoPlannedViaByFrom--");
local list = AIStationList_CargoPlannedViaByFrom(6, 0, 7);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
};
function Regression::StationList_CargoPlannedFromByVia()
{
print("");
print("--StationList_CargoPlannedFromByVia--");
local list = AIStationList_CargoPlannedFromByVia(6, 0, 7);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
};
function Regression::StationList_CargoWaiting()
{
print("");
print("--StationList_CargoWaiting--");
for (local selector = AIStationList_Cargo.CS_BY_FROM; selector <= AIStationList_Cargo.CS_FROM_BY_VIA; ++selector) {
print(" " + selector);
local list = AIStationList_CargoWaiting(selector, 6, 0, 7);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
}
};
function Regression::StationList_CargoWaitingByFrom()
{
print("");
print("--StationList_CargoWaitingByFrom--");
local list = AIStationList_CargoWaitingByFrom(2, 0);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
};
function Regression::StationList_CargoWaitingByVia()
{
print("");
print("--StationList_CargoWaitingByVia--");
local list = AIStationList_CargoWaitingByVia(2, 0);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
};
function Regression::StationList_CargoWaitingViaByFrom()
{
print("");
print("--StationList_CargoWaitingViaByFrom--");
local list = AIStationList_CargoWaitingViaByFrom(6, 0, 7);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
};
function Regression::StationList_CargoWaitingFromByVia()
{
print("");
print("--StationList_CargoWaitingFromByVia--");
local list = AIStationList_CargoWaitingFromByVia(2, 0, 2);
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
};
function Regression::StationList_Vehicle()
{
local list = AIStationList_Vehicle(12);
print("");
print("--StationList_Vehicle--");
print(" Count(): " + list.Count());
list.Valuate(AIStation.GetLocation);
print(" Location ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
list.Valuate(AIStation.GetCargoWaiting, 0);
print(" CargoWaiting(0) ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
list.Valuate(AIStation.GetCargoWaiting, 1);
print(" CargoWaiting(1) ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
list.Valuate(AIStation.GetCargoRating, 1);
print(" CargoRating(1) ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
list.Valuate(AIStation.GetDistanceManhattanToTile, 30000);
print(" DistanceManhattanToTile(30000) ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
list.Valuate(AIStation.GetDistanceSquareToTile, 30000);
print(" DistanceSquareToTile(30000) ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
list.Valuate(AIStation.IsWithinTownInfluence, 0);
print(" IsWithinTownInfluence(0) ListDump:");
for (local i = list.Begin(); !list.IsEnd(); i = list.Next()) {
print(" " + i + " => " + list.GetValue(i));
}
}
function Regression::Start()
{
StationList();
StationList_Cargo();
StationList_CargoPlanned();
StationList_CargoPlannedByFrom();
StationList_CargoPlannedByVia();
StationList_CargoPlannedViaByFrom();
StationList_CargoPlannedFromByVia();
StationList_CargoWaiting();
StationList_CargoWaitingByFrom();
StationList_CargoWaitingByVia();
StationList_CargoWaitingViaByFrom();
StationList_CargoWaitingFromByVia();
StationList_Vehicle();
}

View File

@@ -1,127 +0,0 @@
--StationList--
Count(): 5
Location ListDump:
6 => 42341
2 => 41831
7 => 41825
5 => 33421
4 => 33411
CargoWaiting(0) ListDump:
7 => 6
6 => 6
2 => 3
5 => 0
4 => 0
CargoWaiting(1) ListDump:
7 => 0
6 => 0
5 => 0
4 => 0
2 => 0
--StationList_Cargo--
0
0
6 => 6
1
6 => 2
2
2 => 4
7 => 2
3
1
0
7 => 18
6 => 16
2 => 7
1
6 => 8
2 => 3
2
2 => 16
6 => 14
7 => 11
3
6 => 10
2 => 8
--StationList_CargoPlanned--
0
7 => 18
6 => 16
2 => 7
1
6 => 8
2 => 3
2
2 => 16
6 => 14
7 => 11
3
6 => 10
2 => 8
--StationList_CargoPlannedByFrom--
7 => 8
6 => 8
2 => 7
--StationList_CargoPlannedByVia--
2 => 16
6 => 7
--StationList_CargoPlannedViaByFrom--
6 => 8
2 => 3
--StationList_CargoPlannedFromByVia--
6 => 10
2 => 8
--StationList_CargoWaiting--
0
6 => 6
1
6 => 2
2
2 => 4
7 => 2
3
--StationList_CargoWaitingByFrom--
2 => 3
--StationList_CargoWaitingByVia--
6 => 3
--StationList_CargoWaitingViaByFrom--
6 => 2
--StationList_CargoWaitingFromByVia--
6 => 3
--StationList_Vehicle--
Count(): 2
Location ListDump:
5 => 33421
4 => 33411
CargoWaiting(0) ListDump:
5 => 0
4 => 0
CargoWaiting(1) ListDump:
5 => 0
4 => 0
CargoRating(1) ListDump:
5 => -1
4 => -1
DistanceManhattanToTile(30000) ListDump:
5 => 106
4 => 96
DistanceSquareToTile(30000) ListDump:
5 => 8818
4 => 7058
IsWithinTownInfluence(0) ListDump:
5 => 0
4 => 0
ERROR: The script died unexpectedly.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,6 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/

View File

@@ -1,30 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
GSLog.Info("1.2 API compatibility in effect.");
GSTown._SetGrowthRate <- GSTown.SetGrowthRate;
GSTown.SetGrowthRate <- function(town_id, days_between_town_growth)
{
/* Growth rate 0 caused resetting the custom growth rate. While this was undocumented, it was used nevertheless (ofc). */
if (days_between_town_growth == 0) days_between_town_growth = GSTown.TOWN_GROWTH_NORMAL;
return GSTown._SetGrowthRate(town_id, days_between_town_growth);
}
/* 1.5 adds a game element reference to the news. */
GSNews._Create <- GSNews.Create;
GSNews.Create <- function(type, text, company)
{
return GSNews._Create(type, text, company, GSNews.NR_NONE, 0);
}
/* 1.9 adds a vehicle type parameter. */
GSBridge._GetName <- GSBridge.GetName;
GSBridge.GetName <- function(bridge_id)
{
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
}

View File

@@ -1,30 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
GSLog.Info("1.3 API compatibility in effect.");
GSTown._SetGrowthRate <- GSTown.SetGrowthRate;
GSTown.SetGrowthRate <- function(town_id, days_between_town_growth)
{
/* Growth rate 0 caused resetting the custom growth rate. While this was undocumented, it was used nevertheless (ofc). */
if (days_between_town_growth == 0) days_between_town_growth = GSTown.TOWN_GROWTH_NORMAL;
return GSTown._SetGrowthRate(town_id, days_between_town_growth);
}
/* 1.5 adds a game element reference to the news. */
GSNews._Create <- GSNews.Create;
GSNews.Create <- function(type, text, company)
{
return GSNews._Create(type, text, company, GSNews.NR_NONE, 0);
}
/* 1.9 adds a vehicle type parameter. */
GSBridge._GetName <- GSBridge.GetName;
GSBridge.GetName <- function(bridge_id)
{
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
}

View File

@@ -1,22 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
GSLog.Info("1.4 API compatibility in effect.");
/* 1.5 adds a game element reference to the news. */
GSNews._Create <- GSNews.Create;
GSNews.Create <- function(type, text, company)
{
return GSNews._Create(type, text, company, GSNews.NR_NONE, 0);
}
/* 1.9 adds a vehicle type parameter. */
GSBridge._GetName <- GSBridge.GetName;
GSBridge.GetName <- function(bridge_id)
{
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
}

View File

@@ -1,15 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
GSLog.Info("1.5 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
GSBridge._GetName <- GSBridge.GetName;
GSBridge.GetName <- function(bridge_id)
{
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
}

View File

@@ -1,15 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
GSLog.Info("1.6 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
GSBridge._GetName <- GSBridge.GetName;
GSBridge.GetName <- function(bridge_id)
{
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
}

View File

@@ -1,15 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
GSLog.Info("1.7 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
GSBridge._GetName <- GSBridge.GetName;
GSBridge.GetName <- function(bridge_id)
{
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
}

View File

@@ -1,15 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
GSLog.Info("1.8 API compatibility in effect.");
/* 1.9 adds a vehicle type parameter. */
GSBridge._GetName <- GSBridge.GetName;
GSBridge.GetName <- function(bridge_id)
{
return GSBridge._GetName(bridge_id, GSVehicle.VT_RAIL);
}

View File

@@ -1,8 +0,0 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
GSLog.Info("1.9 API compatibility in effect.");

View File

@@ -1,2 +0,0 @@
start_ai MyAI

View File

@@ -1,2 +0,0 @@
# Show a MOTD
say "Welcome..."

View File

@@ -1,22 +1,12 @@
/*
* This file is part of OpenTTD.
* OpenTTD 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, version 2.
* OpenTTD 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 OpenTTD. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file bmp.cpp Read and write support for bmps. */
/* $Id$ */
#include "stdafx.h"
#include "openttd.h"
#include "gfx.h"
#include "bmp.h"
#include "core/bitmath_func.hpp"
#include "core/alloc_func.hpp"
#include "core/mem_func.hpp"
#include "macros.h"
#include "safeguards.h"
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file)
{
void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file) {
buffer->pos = -1;
buffer->file = file;
buffer->read = 0;
@@ -25,24 +15,18 @@ void BmpInitializeBuffer(BmpBuffer *buffer, FILE *file)
static inline void AdvanceBuffer(BmpBuffer *buffer)
{
if (buffer->read < 0) return;
buffer->read = (int)fread(buffer->data, 1, BMP_BUFFER_SIZE, buffer->file);
buffer->pos = 0;
}
static inline bool EndOfBuffer(BmpBuffer *buffer)
{
if (buffer->read < 0) return false;
if (buffer->pos == buffer->read || buffer->pos < 0) AdvanceBuffer(buffer);
return buffer->pos == buffer->read;
}
static inline byte ReadByte(BmpBuffer *buffer)
{
if (buffer->read < 0) return 0;
if (buffer->pos == buffer->read || buffer->pos < 0) AdvanceBuffer(buffer);
buffer->real_pos++;
return buffer->data[buffer->pos++];
@@ -68,9 +52,7 @@ static inline void SkipBytes(BmpBuffer *buffer, int bytes)
static inline void SetStreamOffset(BmpBuffer *buffer, int offset)
{
if (fseek(buffer->file, offset, SEEK_SET) < 0) {
buffer->read = -1;
}
fseek(buffer->file, offset, SEEK_SET);
buffer->pos = -1;
buffer->real_pos = offset;
AdvanceBuffer(buffer);
@@ -138,63 +120,53 @@ static inline bool BmpRead4(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
*/
static inline bool BmpRead4Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{
uint i;
uint x = 0;
uint y = info->height - 1;
byte n, c, b;
byte *pixel = &data->bitmap[y * info->width];
while (y != 0 || x < info->width) {
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
byte n = ReadByte(buffer);
byte c = ReadByte(buffer);
n = ReadByte(buffer);
c = ReadByte(buffer);
if (n == 0) {
switch (c) {
case 0: // end of line
x = 0;
if (y == 0) return false;
pixel = &data->bitmap[--y * info->width];
break;
case 1: // end of bitmap
return true;
case 2: { // delta
if (EndOfBuffer(buffer)) return false;
byte dx = ReadByte(buffer);
byte dy = ReadByte(buffer);
/* Check for over- and underflow. */
if (x + dx >= info->width || x + dx < x || dy > y) return false;
x += dx;
y -= dy;
pixel = &data->bitmap[y * info->width + x];
break;
}
default: { // uncompressed
uint i = 0;
while (i++ < c) {
if (EndOfBuffer(buffer) || x >= info->width) return false;
byte b = ReadByte(buffer);
*pixel++ = GB(b, 4, 4);
case 0: // end of line
x = 0;
pixel = &data->bitmap[--y * info->width];
break;
case 1: // end of bitmap
x = info->width;
y = 0;
pixel = NULL;
break;
case 2: // delta
x += ReadByte(buffer);
i = ReadByte(buffer);
if (x >= info->width || (y == 0 && i > 0)) return false;
y -= i;
pixel = &data->bitmap[y * info->width + x];
break;
default: // uncompressed
i = 0;
while (i++ < c) {
if (EndOfBuffer(buffer) || x >= info->width) return false;
b = ReadByte(buffer);
*pixel++ = GB(b, 4, 4);
x++;
if (x < info->width && i++ < c) {
*pixel++ = GB(b, 0, 4);
x++;
if (i++ < c) {
if (x >= info->width) return false;
*pixel++ = GB(b, 0, 4);
x++;
}
}
/* Padding for 16 bit align */
SkipBytes(buffer, ((c + 1) / 2) % 2);
break;
}
/* Padding for 16 bit align */
SkipBytes(buffer, ((c + 1) / 2) % 2);
break;
}
} else {
/* Apparently it is common to encounter BMPs where the count of
* pixels to be written is higher than the remaining line width.
* Ignore the superfluous pixels instead of reporting an error. */
uint i = 0;
while (x < info->width && i++ < n) {
i = 0;
while (i++ < n) {
if (EndOfBuffer(buffer) || x >= info->width) return false;
*pixel++ = GB(c, 4, 4);
x++;
if (x < info->width && i++ < n) {
@@ -231,55 +203,43 @@ static inline bool BmpRead8(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
*/
static inline bool BmpRead8Rle(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{
uint i;
uint x = 0;
uint y = info->height - 1;
byte n, c;
byte *pixel = &data->bitmap[y * info->width];
while (y != 0 || x < info->width) {
if (EndOfBuffer(buffer)) return false; // the file is shorter than expected
byte n = ReadByte(buffer);
byte c = ReadByte(buffer);
n = ReadByte(buffer);
c = ReadByte(buffer);
if (n == 0) {
switch (c) {
case 0: // end of line
x = 0;
if (y == 0) return false;
pixel = &data->bitmap[--y * info->width];
break;
case 1: // end of bitmap
return true;
case 2: { // delta
if (EndOfBuffer(buffer)) return false;
byte dx = ReadByte(buffer);
byte dy = ReadByte(buffer);
/* Check for over- and underflow. */
if (x + dx >= info->width || x + dx < x || dy > y) return false;
x += dx;
y -= dy;
pixel = &data->bitmap[y * info->width + x];
break;
}
default: { // uncompressed
for (uint i = 0; i < c; i++) {
if (EndOfBuffer(buffer) || x >= info->width) return false;
*pixel++ = ReadByte(buffer);
x++;
}
/* Padding for 16 bit align */
SkipBytes(buffer, c % 2);
break;
}
case 0: // end of line
x = 0;
pixel = &data->bitmap[--y * info->width];
break;
case 1: // end of bitmap
x = info->width;
y = 0;
pixel = NULL;
break;
case 2: // delta
x += ReadByte(buffer);
i = ReadByte(buffer);
if (x >= info->width || (y == 0 && i > 0)) return false;
y -= i;
pixel = &data->bitmap[y * info->width + x];
break;
default: // uncompressed
if ((x += c) > info->width) return false;
for (i = 0; i < c; i++) *pixel++ = ReadByte(buffer);
/* Padding for 16 bit align */
SkipBytes(buffer, c % 2);
break;
}
} else {
/* Apparently it is common to encounter BMPs where the count of
* pixels to be written is higher than the remaining line width.
* Ignore the superfluous pixels instead of reporting an error. */
for (uint i = 0; x < info->width && i < n; i++) {
for (i = 0; i < n; i++) {
if (x >= info->width) return false;
*pixel++ = c;
x++;
}
@@ -317,8 +277,7 @@ static inline bool BmpRead24(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{
uint32 header_size;
assert(info != nullptr);
MemSetT(info, 0);
assert(info != NULL);
/* Reading BMP header */
if (ReadWord(buffer) != 0x4D42) return false; // signature should be 'BM'
@@ -361,15 +320,16 @@ bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
if (info->bpp <= 8) {
uint i;
/* Reads number of colours if available in info header */
/* Reads number of colors if available in info header */
if (header_size >= 16) {
SkipBytes(buffer, 12); // skip image size and resolution
info->palette_size = ReadDword(buffer); // number of colours in palette
info->palette_size = ReadDword(buffer); // number of colors in palette
SkipBytes(buffer, header_size - 16); // skip the end of info header
}
if (info->palette_size == 0) info->palette_size = 1 << info->bpp;
data->palette = CallocT<Colour>(info->palette_size);
data->palette = calloc(info->palette_size, sizeof(*(data->palette)));
if (data->palette == NULL) return false;
for (i = 0; i < info->palette_size; i++) {
data->palette[i].b = ReadByte(buffer);
@@ -388,9 +348,10 @@ bool BmpReadHeader(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
*/
bool BmpReadBitmap(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
{
assert(info != nullptr && data != nullptr);
assert(info != NULL && data != NULL);
data->bitmap = CallocT<byte>(info->width * info->height * ((info->bpp == 24) ? 3 : 1));
data->bitmap = calloc(info->width * info->height, ((info->bpp == 24) ? 3 : 1) * sizeof(byte));
if (data->bitmap == NULL) return false;
/* Load image */
SetStreamOffset(buffer, info->offset);
@@ -401,17 +362,17 @@ bool BmpReadBitmap(BmpBuffer *buffer, BmpInfo *info, BmpData *data)
case 4: return BmpRead4(buffer, info, data);
case 8: return BmpRead8(buffer, info, data);
case 24: return BmpRead24(buffer, info, data);
default: NOT_REACHED();
default: NOT_REACHED(); return false;
}
case 1: return BmpRead8Rle(buffer, info, data); // 8-bit RLE compression
case 2: return BmpRead4Rle(buffer, info, data); // 4-bit RLE compression
default: NOT_REACHED();
default: NOT_REACHED(); return false;
}
}
void BmpDestroyData(BmpData *data)
{
assert(data != nullptr);
assert(data != NULL);
free(data->palette);
free(data->bitmap);
}

Some files were not shown because too many files have changed in this diff Show More