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

Compare commits

..

1 Commits

Author SHA1 Message Date
Darkvater
783f82e7c4 (svn r2326) Release 0.4.0 2005-05-15 21:54:44 +00:00
1772 changed files with 206212 additions and 677327 deletions

44
.gitignore vendored
View File

@@ -1,44 +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_*.obg
!bin/baseset/orig_*.obs
!bin/baseset/no_sound.obs
!bin/baseset/no_music.obm
!bin/baseset/orig_*.obm
!bin/scripts
bin/scripts/*
!bin/scripts/*.example
!bin/scripts/readme.txt
bundle/*
bundles/*
docs/aidocs/*
docs/gamedocs/*
docs/source/*
media/openttd.desktop
media/openttd.desktop.install
objs/*
projects/Debug
projects/Release
projects/*.ncb
projects/*.suo
projects/*.sdf
projects/*.opensdf
projects/*.vcproj.*.user
projects/*.vcxproj.user
src/rev.cpp
src/os/windows/ottdres.rc
/Makefile*
!/Makefile.msvc
/config.*
!/config.lib
!*.in
*.tmp

View File

@@ -1,29 +0,0 @@
syntax: glob
.svn
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/*
Makefile
Makefile.am
Makefile.bundle
media/openttd.desktop
media/openttd.desktop.install
objs/*
projects/*.ncb
projects/*.suo
projects/*.sdf
projects/*.opensdf
projects/*.vcproj.*.user
projects/*.vcxproj.user
src/rev.cpp
src/os/windows/ottdres.rc

39
COPYING
View File

@@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 2, June 1991 Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc., Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
Preamble 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 freedom to share and change it. By contrast, the GNU General Public
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to the GNU Library General Public License instead.) You can apply it to
your programs, too. 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
@@ -55,8 +55,8 @@ 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. modification follow.
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 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
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on does not normally print such an announcement, your work based on
the Program is not required to print an announcement.) the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program, identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not distribution of the source code, even though third parties are not
compelled to copy the source along with the object code. 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 except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License. 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 certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License original copyright holder who places the Program under this License
@@ -255,7 +255,7 @@ 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 preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally. 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 FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@@ -277,9 +277,9 @@ 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 PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES. 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 possible use to the public, the best way to achieve this is to make it
@@ -303,9 +303,10 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License along You should have received a copy of the GNU General Public License
with this program; if not, write to the Free Software Foundation, Inc., along with this program; if not, write to the Free Software
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
@@ -335,5 +336,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General library. If this is what you want to do, use the GNU Library General
Public License instead of this License. Public License instead of this License.

236
Doxyfile
View File

@@ -1,236 +0,0 @@
# $Id$
# 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
#---------------------------------------------------------------------------
PROJECT_NAME = OpenTTD
OUTPUT_DIRECTORY = docs/source/
CREATE_SUBDIRS = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = YES
STRIP_FROM_PATH = ./
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 2
ALIASES =
OPTIMIZE_OUTPUT_FOR_C = YES
OPTIMIZE_OUTPUT_JAVA = NO
SUBGROUPING = YES
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = NO
EXTRACT_PRIVATE = YES
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
SORT_BRIEF_DOCS = NO
SORT_BY_SCOPE_NAME = NO
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = YES
SHOW_DIRECTORIES = YES
FILE_VERSION_FILTER =
#---------------------------------------------------------------------------
# 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_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = ./src/
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.h \
*.hpp
RECURSIVE = YES
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS = */3rdparty */.svn */script/api
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = YES
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# 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
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = YES
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = YES
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = YES
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = NO
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED = ENABLE_NETWORK WITH_ZLIB WITH_LZO WITH_LZMA WITH_SDL WITH_PNG WITH_FONTCONFIG WITH_FREETYPE WITH_ICU UNICODE _UNICODE _GNU_SOURCE FINAL=
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::additions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE = openttd.tag
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
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

1027
Makefile Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,227 +0,0 @@
# $Id$
# 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")
REV := $(shell echo "$(VERSIONS)" | cut -f 1 -d' ')
# Make sure we have something in REV
ifeq ($(REV),)
REV := norev000
endif
ifndef BUNDLE_NAME
BUNDLE_NAME = openttd-custom-$(REV)-$(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)" "$(REV)"
$(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.txt" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/COPYING" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/known-bugs.txt" "$(BUNDLE_DIR)/"
$(Q)cp "$(ROOT_DIR)/docs/multiplayer.txt" "$(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 | $(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.txt" "$(BUNDLE_DIR)/COPYING" "$(BUNDLE_DIR)/changelog.txt" "$(BUNDLE_DIR)/known-bugs.txt"
ifeq ($(OS), DOS)
$(Q)cp "$(ROOT_DIR)/os/dos/cwsdpmi.txt" "$(BUNDLE_DIR)/docs/"
ifndef STRIP
$(Q)cp "$(ROOT_DIR)/os/dos/cwsdpmi.exe" "$(TTD_DIR)/"
endif
endif
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 $(REV)"
$(Q)cp -R "$(BUNDLE_DIR)/" "$(BUNDLES_DIR)/OpenTTD $(REV)"
$(Q)hdiutil create -ov -format UDZO -srcfolder "$(BUNDLES_DIR)/OpenTTD $(REV)" "$(BUNDLES_DIR)/$(BUNDLE_NAME).dmg"
$(Q)rm -fr "$(BUNDLES_DIR)/OpenTTD $(REV)"
bundle_exe: all
@echo '[BUNDLE] Creating $(BUNDLE_NAME).exe'
$(Q)mkdir -p "$(BUNDLES_DIR)"
$(Q)unix2dos "$(ROOT_DIR)/docs/"*.txt "$(ROOT_DIR)/readme.txt" "$(ROOT_DIR)/COPYING" "$(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)/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)/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.txt" "$(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" "$(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,95 +0,0 @@
# $Id$
# 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 and NFORenum. Older versions of GRFCodec are
# known to miscompile the graphics.
#
# Recent nightlies (including sources) of both can be found at:
# http://www.openttd.org/download-grfcodec
# http://www.openttd.org/download-nforenum
#
# The mercurial repository of both can be found at:
# http://hg.openttdcoop.org/grfcodec
# http://hg.openttdcoop.org/nforenum
#
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
# Build the GRF.
ifdef GRFCODEC
all: $(BIN_DIR)/openttd.grf $(BIN_DIR)/orig_dos.obg $(BIN_DIR)/orig_dos_de.obg $(BIN_DIR)/orig_win.obg $(BIN_DIR)/orig_dos.obs $(BIN_DIR)/orig_win.obs $(BIN_DIR)/no_sound.obs $(BIN_DIR)/orig_win.obm $(BIN_DIR)/no_music.obm
else
all:
endif
# Make sure the sprites directory exists.
$(OBJS_DIR)/sprites:
$(Q)-mkdir "$@"
$(OBJS_DIR)/langfiles.tmp: $(LANG_DIR)/*.txt
$(E) '$(STAGE) Collecting baseset translations'
$(Q) cat $^ > $@
$(BIN_DIR)/%.obg: $(BASESET_DIR)/%.obg $(BIN_DIR)/openttd.grf $(OBJS_DIR)/langfiles.tmp $(BASESET_DIR)/translations.awk
$(E) '$(STAGE) Updating $(notdir $@)'
$(Q) sed 's/^OPENTTD.GRF = *[0-9a-f]*$$/OPENTTD.GRF = '`$(MD5SUM) $(BIN_DIR)/openttd.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 $< >$@
# Compile extra grf
$(BIN_DIR)/openttd.grf: $(PNG_FILES) $(NFO_FILES) $(OBJS_DIR)/sprites
$(E) '$(STAGE) Assembling openttd.nfo'
$(Q)-cp $(PNG_FILES) $(OBJS_DIR)/sprites 2> /dev/null
$(Q) $(CC_BUILD) -nostdinc -I$(GRF_DIR) -C -E - < "$(GRF_DIR)/openttd.nfo" | sed -e '/^#/d' -e '/^$$/d' > $(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
# Clean up temporary files.
clean:
$(Q)rm -f *.bak *.grf
# Clean up temporary files
mrproper: clean
$(Q)rm -fr sprites
.PHONY: all mrproper depend clean

View File

@@ -1,189 +0,0 @@
# $Id$
# 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 paramter"; 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 -f $(ROOT_DIR)/openttd.tag
$(Q)rm -rf $(ROOT_DIR)/docs/source
# output of generating AI API documentation
$(Q)rm -f $(SRC_DIR)/ai/api/openttd.tag
$(Q)rm -rf $(ROOT_DIR)/docs/aidocs
# 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/*.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,105 +0,0 @@
# $Id$
# 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!!
ENDIAN_CHECK = !!ENDIAN_CHECK!!
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
# Make sure endian_host.h is reachable as if it was in the src/ dir
CFLAGS_BUILD += -I $(LANG_OBJS_DIR)
ENDIAN_TARGETS := endian_host.h endian_target.h $(ENDIAN_CHECK)
# 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 endian_host.h $(SRC_DIR)/table/control_codes.h $(SRC_DIR)/table/strgen_tables.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 endian_host.h $(SRC_DIR)/table/control_codes.h $(SRC_DIR)/table/strgen_tables.h
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSTRGEN -c -o $@ $<
string.o: $(SRC_DIR)/string.cpp endian_host.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 endian_host.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
$(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
# The targets to compile the endian-code
endian_host.h: $(ENDIAN_CHECK)
$(E) '$(STAGE) Testing endianness for host'
$(Q)./$(ENDIAN_CHECK) > $@
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
$(E) '$(STAGE) Compiling and Linking $@'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $< -o $@
depend:
clean:
$(E) '$(STAGE) Cleaning up language files'
$(Q)rm -f strgen.o string.o alloc_func.o getoptdata.o table/strings.h $(STRGEN) $(LANGS) $(LANGS:%=$(BIN_DIR)/lang/%) lang/english.* $(ENDIAN_TARGETS)
mrproper: clean
$(Q)rm -rf $(BIN_DIR)/lang
%.lng:
@echo '$(STAGE) No such language: $(@:%.lng=%)'
.PHONY: all mrproper depend clean

View File

@@ -1,47 +0,0 @@
# $Id$
# 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,78 +0,0 @@
# $Id$
# 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!!
ENDIAN_CHECK = !!ENDIAN_CHECK!!
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!!
ENDIAN_TARGETS := endian_host.h endian_target.h $(ENDIAN_CHECK)
# 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
$(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 endian_host.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
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/misc/%.cpp=%.cpp)'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) -DSETTINGSGEN -c -o $@ $<
string.o: $(SRC_DIR)/string.cpp endian_host.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
$(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
# The targets to compile the endian-code
endian_host.h: $(ENDIAN_CHECK)
$(E) '$(STAGE) Testing endianness for host'
$(Q)./$(ENDIAN_CHECK) > $@
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
$(E) '$(STAGE) Compiling and Linking $@'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $< -o $@
depend:
clean:
$(E) '$(STAGE) Cleaning up settings files'
$(Q)rm -f settingsgen.o alloc_func.o getoptdata.o ini_load.o $(SETTINGSGEN) $(ENDIAN_TARGETS) table/settings.h
mrproper: clean
.PHONY: all mrproper depend clean

View File

@@ -1,303 +0,0 @@
# $Id$
# 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!!
ENDIAN_CHECK = !!ENDIAN_CHECK!!
DEPEND = !!DEPEND!!
ENDIAN_FORCE = !!ENDIAN_FORCE!!
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_ENDIAN = $(SRC_OBJS_DIR)/!!CONFIG_CACHE_ENDIAN!!
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) endian_target.h
# Create all dirs and subdirs
RES := $(shell mkdir -p $(BIN_DIR) $(sort $(dir $(OBJS))))
# Make sure endian_target.h is reasable as if it was in the src/ dir
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
ENDIAN_TARGETS := endian_target.h $(ENDIAN_CHECK)
# 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
REV := $(shell echo "$(VERSIONS)" | cut -f 1 -d' ')
REV_NR := $(shell echo "$(VERSIONS)" | cut -f 2 -d' ')
# Make sure we have something in REV and REV_NR
ifeq ($(REV),)
REV := norev000
endif
ifeq ($(REV_NR),)
REV_NR := 0
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 )
RES := $(shell if [ "`cat $(CONFIG_CACHE_ENDIAN) 2>/dev/null`" != "$(ENDIAN_FORCE)" ]; then echo "$(ENDIAN_FORCE)" > $(CONFIG_CACHE_ENDIAN); 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`" != "$(REV) $(MODIFIED)" ]; then echo "$(REV) $(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 $(ENDIAN_TARGETS) %.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)$(CC_HOST) $(CFLAGS) -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 $(ENDIAN_TARGETS) 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
# 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
$(Q)$(MAKEDEPEND) -f$(SRC_OBJS_DIR)/Makefile.dep.tmp -o.o -Y -v -- $(CFLAGS_MAKEDEP) -- $(SRCS:%=$(SRC_DIR)/%) 2>/dev/null
# Convert x:/... paths to /x/... for mingw
ifeq ($(OS), MINGW)
@cat Makefile.dep.tmp | sed 's@/\([a-zA-Z]\):\/@\/\1\/@g' > Makefile.dep.tmp.mingw
@cp Makefile.dep.tmp.mingw Makefile.dep.tmp
@rm -f Makefile.dep.tmp.mingw
endif
# 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@ $$@@' | $(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 $@ $<
$(OBJS_CPP): %.o: $(SRC_DIR)/%.cpp $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$(Q)$(CXX_HOST) $(CFLAGS) $(CXXFLAGS) -c -o $@ $<
$(OBJS_MM): %.o: $(SRC_DIR)/%.mm $(DEP_MASK) $(FILE_DEP)
$(E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.mm=%.mm)'
$(Q)$(CC_HOST) $(CFLAGS) -c -o $@ $<
$(OBJS_RC): %.o: $(SRC_DIR)/%.rc $(FILE_DEP)
$(E) '$(STAGE) Compiling resource $(<:$(SRC_DIR)/%.rc=%.rc)'
$(Q)$(WINDRES) -o $@ -I `basename $<` $<
$(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 $@'
ifeq ($(OS), PSP)
# Because of a bug in the PSP GCC tools, linking via CXX results
# in total chaos and more problems then you can handle. So we need
# CC to link OpenTTD for PSP
$(Q)+$(CC_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
else
$(Q)+$(CXX_HOST) $(LDFLAGS) $(OBJS) $(LIBS) -o $@
endif
ifdef STRIP
$(Q)$(STRIP) $@
endif
ifeq ($(OS), DOS)
$(E) '$(STAGE) Adding CWSDPMI stub to $@'
$(Q)$(ROOT_DIR)/os/dos/make_dos_binary_selfcontained.sh $(SRC_OBJS_DIR)/$@
endif
# The targets to compile the endian-code
endian_target.h: $(ENDIAN_CHECK) $(CONFIG_CACHE_ENDIAN)
$(E) '$(STAGE) Testing endianness for target'
$(Q)./$(ENDIAN_CHECK) $(ENDIAN_FORCE) > $@
$(ENDIAN_CHECK): $(SRC_DIR)/endian_check.cpp
$(E) '$(STAGE) Compiling and Linking $@'
$(Q)$(CXX_BUILD) $(CFLAGS_BUILD) $(CXXFLAGS_BUILD) $(LDFLAGS_BUILD) $< -o $@
# Revision files
$(SRC_DIR)/rev.cpp: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/rev.cpp.in
$(Q)cat $(SRC_DIR)/rev.cpp.in | sed "s@\!\!REVISION\!\!@$(REV_NR)@g;s@!!VERSION!!@$(REV)@g;s@!!MODIFIED!!@$(MODIFIED)@g;s@!!DATE!!@`date +%d.%m.%y`@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@\!\!REVISION\!\!@$(REV_NR)@g;s@!!VERSION!!@$(REV)@g;s@!!DATE!!@`date +%d.%m.%y`@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_ENDIAN) $(CONFIG_CACHE_SOURCE) $(ENDIAN_TARGETS)
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

8
StdAfx.c Normal file
View File

@@ -0,0 +1,8 @@
// stdafx.cpp : source file that includes just the standard includes
// ttd.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

3992
ai.c Normal file

File diff suppressed because it is too large Load Diff

259
ai.h Normal file
View File

@@ -0,0 +1,259 @@
#ifndef AI_H
#define AI_H
#include "aystar.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_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 TILE_XY(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(uint tile_a, uint tile_b, uint tile_c);
int AiNew_GetRoadDirection(uint tile_a, uint tile_b, uint tile_c);
int AiNew_GetDirection(uint tile_a, uint tile_b);
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, uint tile);
int AiNew_Build_Station(Player *p, byte type, uint tile, byte length, byte numtracks, byte direction, byte flag);
int AiNew_Build_Bridge(Player *p, uint tile_a, uint tile_b, byte flag);
int AiNew_Build_RoutePart(Player *p, Ai_PathFinderInfo *PathFinderInfo, byte flag);
int AiNew_PickVehicle(Player *p);
int AiNew_Build_Vehicle(Player *p, uint tile, byte flag);
int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag);
#endif

260
ai_build.c Normal file
View File

@@ -0,0 +1,260 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "map.h"
#include "tile.h"
#include "command.h"
#include "ai.h"
#include "engine.h"
#include "station.h"
// Build HQ
// Params:
// tile : tile where HQ is going to be build
bool AiNew_Build_CompanyHQ(Player *p, uint tile) {
if (CmdFailed(DoCommandByTile(tile, 0, 0, DC_AUTO | DC_NO_WATER, CMD_BUILD_COMPANY_HQ)))
return false;
DoCommandByTile(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, uint tile, byte length, byte numtracks, byte direction, byte flag) {
if (type == AI_TRAIN)
return DoCommandByTile(tile, direction + (numtracks << 8) + (length << 16), 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_RAILROAD_STATION);
if (type == AI_BUS)
return DoCommandByTile(tile, direction, RS_BUS, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD_STOP);
return DoCommandByTile(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, uint tile_a, uint 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 build..
if (type2 == 0 && type != 0) type2 = type;
// Now, simply, build the bridge!
if (p->ainew.tbt == AI_TRAIN)
return DoCommandByTile(tile_a, tile_b, (0<<8) + type2, flag | DC_AUTO, CMD_BUILD_BRIDGE);
return DoCommandByTile(tile_a, tile_b, (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 += DoCommandByTile(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 build!");
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 build!");
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 = DoCommandByTile(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 += DoCommandByTile(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 build!");
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 build!");
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 = DoCommandByTile(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 builded.. 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 vehicle_id or -1 if not found
int AiNew_PickVehicle(Player *p) {
if (p->ainew.tbt == AI_TRAIN) {
// Not supported yet
return -1;
} else {
int start, count, i, ret = CMD_ERROR;
start = _cargoc.ai_roadveh_start[p->ainew.cargo];
count = _cargoc.ai_roadveh_count[p->ainew.cargo];
// Let's check it backwards.. we simply want to best engine available..
for (i=start+count-1;i>=start;i--) {
// Is it availiable?
// Also, check if the reliability of the vehicle is above the AI_VEHICLE_MIN_RELIABILTY
if (!HASBIT(_engines[i].player_avail, _current_player) || _engines[i].reliability * 100 < AI_VEHICLE_MIN_RELIABILTY << 16) continue;
// Can we build it?
ret = DoCommandByTile(0, i, 0, DC_QUERY_COST, CMD_BUILD_ROAD_VEH);
if (!CmdFailed(ret)) break;
}
// We did not find a vehicle :(
if (CmdFailed(ret)) { return -1; }
return i;
}
}
// Builds the best vehicle possible
int AiNew_Build_Vehicle(Player *p, uint tile, byte flag) {
int i = AiNew_PickVehicle(p);
if (i == -1) return CMD_ERROR;
if (p->ainew.tbt == AI_TRAIN)
return CMD_ERROR;
return DoCommandByTile(tile, i, 0, flag, CMD_BUILD_ROAD_VEH);
}
int AiNew_Build_Depot(Player *p, uint tile, byte direction, byte flag)
{
static const byte _roadbits_by_dir[4] = {2,1,8,4};
int ret, ret2;
if (p->ainew.tbt == AI_TRAIN)
return DoCommandByTile(tile, 0, direction, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_TRAIN_DEPOT);
ret = DoCommandByTile(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 = DoCommandByTile(tile + TileOffsByDir(direction), _roadbits_by_dir[direction], 0, flag | DC_AUTO | DC_NO_WATER, CMD_BUILD_ROAD);
// If it fails, ignore it..
if (CmdFailed(ret2)) return ret;
return ret + ret2;
}

1322
ai_new.c Normal file

File diff suppressed because it is too large Load Diff

500
ai_pathfinder.c Normal file
View File

@@ -0,0 +1,500 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "map.h"
#include "tile.h"
#include "command.h"
#include "ai.h"
#include "depot.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(uint tile, byte dir)
{
Player *p = DEREF_PLAYER(_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) && (
// road tunnel?
((_map5[tile] & 0x80) == 0 && (_map5[tile] & 0x4) == 0x4) ||
// road bridge?
((_map5[tile] & 0x80) != 0 && (_map5[tile] & 0x2) == 0x2)
));
}
// 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)
{
Ai_PathFinderInfo *PathFinderInfo = (Ai_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 = TILE_XY(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++) {
if (!(IsTileType(TILE_XY(x, y), MP_CLEAR) || IsTileType(TILE_XY(x, y), MP_TREES))) continue;
if (!TestCanBuildStationHere(TILE_XY(x, y), TEST_STATION_NO_DIR)) continue;
start_node.node.tile = TILE_XY(x, y);
aystar->addstart(aystar, &start_node.node, 0);
}
}
}
// The h-value, simple calculation
static int32 AyStar_AiPathFinder_CalculateH(AyStar *aystar, AyStarNode *current, OpenListNode *parent)
{
Ai_PathFinderInfo *PathFinderInfo = (Ai_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 + TileOffsByDir(PathFinderInfo->end_direction));
r2 = DistanceManhattan(current->tile, PathFinderInfo->end_tile_br + TileOffsByDir(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 + TileOffsByDir(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)) {
// An existing bridge... let's test the direction ;)
if ((_map5[atile] & 1U) != (i & 1)) continue;
// This problem only is valid for tunnels:
// When the last tile was not yet a tunnel, check if we enter from the right side..
if ((_map5[atile] & 0x80) == 0) {
if (i != (_map5[atile] & 3U)) 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 ((_map5[ctile] & 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 = DoCommandByTile(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 ((_map5[ctile] & dir) != dir) {
// We do miss some pieces :(
dir &= ~_map5[ctile];
} else {
dir = 0;
}
}
}
// Only destruct things if it is MP_CLEAR of MP_TREES
if (dir != 0) {
ret = DoCommandByTile(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) {
TileInfo ti;
// First we get the dir from this tile and his parent
int dir = AiNew_GetDirection(current->path.parent->node.tile, current->path.node.tile);
// It means we can only walk with the track, so the bridge has to be in the same direction
TileIndex tile = current->path.node.tile;
TileIndex new_tile = tile;
FindLandscapeHeightByTile(&ti, tile);
// Bridges can only be build on land that is not flat
// And if there is a road or rail blocking
if (ti.tileh != 0 ||
(PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_STREET)) ||
(!PathFinderInfo->rail_or_road && IsTileType(tile + TileOffsByDir(dir), MP_RAILWAY))) {
for (;;) {
new_tile += TileOffsByDir(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 = DoCommandByTile(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 build with tileh of 3, 6, 9 or 12, depending on the direction
// For now, we check both sides for this tile.. terraforming gives fuzzy result
if ((dir == 0 && ti.tileh == 12) ||
(dir == 1 && ti.tileh == 6) ||
(dir == 2 && ti.tileh == 3) ||
(dir == 3 && ti.tileh == 9)) {
// Now simply check if a tunnel can be build
ret = DoCommandByTile(tile, (PathFinderInfo->rail_or_road?0:0x200), 0, DC_AUTO, CMD_BUILD_TUNNEL);
FindLandscapeHeightByTile(&ti, _build_tunnel_endtile);
if (!CmdFailed(ret) && (ti.tileh == 3 || ti.tileh == 6 || ti.tileh == 9 || ti.tileh == 12)) {
aystar->neighbours[aystar->num_neighbours].tile = _build_tunnel_endtile;
aystar->neighbours[aystar->num_neighbours].user_data[0] = AI_PATHFINDER_FLAG_TUNNEL + (dir << 8);
aystar->neighbours[aystar->num_neighbours++].direction = 0;
}
}
}
}
extern uint GetRailFoundation(uint tileh, uint bits);
extern uint GetRoadFoundation(uint tileh, uint bits);
extern uint GetBridgeFoundation(uint tileh, byte direction);
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;
TileInfo ti, parent_ti;
// Gather some information about the tile..
FindLandscapeHeightByTile(&ti, current->tile);
FindLandscapeHeightByTile(&parent_ti, parent->path.node.tile);
// 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_ti.tileh != 0 && 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_ti.tileh, 1 << AiNew_GetRailDirection(parent->path.parent->node.tile, parent->path.node.tile, current->tile));
// Maybe is BRIDGE_NO_FOUNDATION a bit strange here, but it contains just the right information..
if (r >= 15 || (r == 0 && (BRIDGE_NO_FOUNDATION & (1 << ti.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_ti.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 (!(BRIDGE_NO_FOUNDATION & (1 << parent_ti.tileh))) {
if (GetBridgeFoundation(parent_ti.tileh, (current->user_data[0] >> 8) & 1) < 15)
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
}
// Second for the end point
if (!(BRIDGE_NO_FOUNDATION & (1 << ti.tileh))) {
if (GetBridgeFoundation(ti.tileh, (current->user_data[0] >> 8) & 1) < 15)
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
}
if (parent_ti.tileh == 0)
res += AI_PATHFINDER_BRIDGE_GOES_UP_PENALTY;
if (ti.tileh == 0)
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;
}
}
}
}
}
// Res should never be below zero.. if so, make it zero!
if (res < 0) { res = 0; }
// Return our value
return res;
}

119
ai_shared.c Normal file
View File

@@ -0,0 +1,119 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "map.h"
#include "ai.h"
#include "vehicle.h"
int AiNew_GetRailDirection(uint tile_a, uint tile_b, uint tile_c) {
// 0 = vert
// 1 = horz
// 2 = dig up-left
// 3 = dig down-right
// 4 = dig down-left
// 5 = dig up-right
int x1, x2, x3;
int y1, y2, y3;
x1 = TileX(tile_a);
x2 = TileX(tile_b);
x3 = TileX(tile_c);
y1 = TileY(tile_a);
y2 = TileY(tile_b);
y3 = TileY(tile_c);
if (y1 == y2 && y2 == y3) return 0;
if (x1 == x2 && x2 == x3) return 1;
if (y2 > y1) {
if (x2 > x3) return 2;
else return 4;
}
if (x2 > x1) {
if (y2 > y3) return 2;
else return 5;
}
if (y1 > y2) {
if (x2 > x3) return 5;
else return 3;
}
if (x1 > x2) {
if (y2 > y3) return 4;
else return 3;
}
return 0;
}
int AiNew_GetRoadDirection(uint tile_a, uint tile_b, uint 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
int AiNew_GetDirection(uint tile_a, uint tile_b) {
if (TileY(tile_a) < TileY(tile_b)) return 1;
if (TileY(tile_a) > TileY(tile_b)) return 3;
if (TileX(tile_a) < TileX(tile_b)) return 2;
return 0;
}
// This functions looks up if this vehicle is special for this AI
// and returns his flag
uint AiNew_GetSpecialVehicleFlag(Player *p, Vehicle *v) {
int 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 i, new_id = -1;
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;
}

2083
aircraft_cmd.c Normal file

File diff suppressed because it is too large Load Diff

1113
aircraft_gui.c Normal file

File diff suppressed because it is too large Load Diff

361
airport.c Normal file
View File

@@ -0,0 +1,361 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "map.h"
#include "airport.h"
AirportFTAClass *CountryAirport;
AirportFTAClass *CityAirport;
AirportFTAClass *Heliport, *Oilrig;
AirportFTAClass *MetropolitanAirport;
AirportFTAClass *InternationalAirport;
static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
const byte *terminals, const byte *helipads,
const byte entry_point, const byte acc_planes,
const AirportFTAbuildup *FA,
const TileIndexDiffC *depots, const byte nof_depots);
static void AirportFTAClass_Destructor(AirportFTAClass *Airport);
static uint16 AirportGetNofElements(const AirportFTAbuildup *FA);
static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA);
static byte AirportTestFTA(const AirportFTAClass *Airport);
/*static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report);
static byte AirportBlockToString(uint32 block);*/
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)
);
// 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)
);
// 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)
);
// 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)
);
// heliport, oilrig
Heliport = (AirportFTAClass *)malloc(sizeof(AirportFTAClass));
AirportFTAClass_Constructor(
Heliport,
NULL,
_airport_helipad_heliport_oilrig,
7,
HELICOPTERS_ONLY,
_airport_fta_heliport_oilrig,
NULL,
0
);
Oilrig = Heliport; // exactly the same structure for heliport/oilrig, so share state machine
}
void UnInitializeAirports(void)
{
AirportFTAClass_Destructor(CountryAirport);
AirportFTAClass_Destructor(CityAirport);
AirportFTAClass_Destructor(Heliport);
AirportFTAClass_Destructor(MetropolitanAirport);
AirportFTAClass_Destructor(InternationalAirport);
}
static void AirportFTAClass_Constructor(AirportFTAClass *Airport,
const byte *terminals, const byte *helipads,
const byte entry_point, const byte acc_planes,
const AirportFTAbuildup *FA,
const TileIndexDiffC *depots, const byte nof_depots)
{
byte nofterminals, nofhelipads;
byte nofterminalgroups = 0;
byte nofhelipadgroups = 0;
const byte * curr;
int i;
nofterminals = nofhelipads = 0;
//now we read the number of terminals we have
if (terminals != NULL) {
i = terminals[0];
nofterminalgroups = i;
curr = terminals;
while (i-- > 0) {
curr++;
assert(*curr != 0); //we don't want to have an empty group
nofterminals += *curr;
}
}
Airport->terminals = terminals;
//read helipads
if (helipads != NULL) {
i = helipads[0];
nofhelipadgroups = i;
curr = helipads;
while (i-- > 0) {
curr++;
assert(*curr != 0); //no empty groups please
nofhelipads += *curr;
}
}
Airport->helipads = helipads;
// if there are more terminals than 6, internal variables have to be changed, so don't allow that
// same goes for helipads
if (nofterminals > MAX_TERMINALS) { printf("Currently only maximum of %2d terminals are supported (you wanted %2d)\n", MAX_TERMINALS, nofterminals);}
if (nofhelipads > MAX_HELIPADS) { printf("Currently only maximum of %2d helipads are supported (you wanted %2d)\n", MAX_HELIPADS, nofhelipads);}
// terminals/helipads are divided into groups. Groups are computed by dividing the number
// of terminals by the number of groups. Half in half. If #terminals is uneven, first group
// will get the less # of terminals
assert(nofterminals <= MAX_TERMINALS);
assert(nofhelipads <= MAX_HELIPADS);
Airport->nofelements = AirportGetNofElements(FA);
// check
if (entry_point >= Airport->nofelements) {printf("Entry point (%2d) must be within the airport positions (which is max %2d)\n", entry_point, Airport->nofelements);}
assert(entry_point < Airport->nofelements);
Airport->acc_planes = acc_planes;
Airport->entry_point = entry_point;
Airport->airport_depots = depots;
Airport->nof_depots = nof_depots;
// build the state machine
AirportBuildAutomata(Airport, FA);
DEBUG(misc, 1) ("#Elements %2d; #Terminals %2d in %d group(s); #Helipads %2d in %d group(s); Entry Point %d", Airport->nofelements,
nofterminals, nofterminalgroups, nofhelipads, nofhelipadgroups, Airport->entry_point);
{
byte _retval = AirportTestFTA(Airport);
if (_retval != MAX_ELEMENTS) {printf("ERROR with element: %d\n", _retval-1);}
assert(_retval == MAX_ELEMENTS);
}
// print out full information
// true -- full info including heading, block, etc
// false -- short info, only position and next position
//AirportPrintOut(Airport, false);
}
static void AirportFTAClass_Destructor(AirportFTAClass *Airport)
{
int i;
AirportFTA *current, *next;
for (i = 0; i < Airport->nofelements; i++) {
current = Airport->layout[i].next_in_chain;
while (current != NULL) {
next = current->next_in_chain;
free(current);
current = next;
};
}
free(Airport->layout);
free(Airport);
}
static uint16 AirportGetNofElements(const AirportFTAbuildup *FA)
{
int i;
uint16 nofelements = 0;
int temp = FA[0].position;
for (i = 0; i < MAX_ELEMENTS; i++) {
if (temp != FA[i].position) {
nofelements++;
temp = FA[i].position;
}
if (FA[i].position == MAX_ELEMENTS) {break;}
}
return nofelements;
}
static void AirportBuildAutomata(AirportFTAClass *Airport, const AirportFTAbuildup *FA)
{
AirportFTA *FAutomata;
AirportFTA *current;
uint16 internalcounter, i;
FAutomata = (AirportFTA *)malloc(sizeof(AirportFTA) * Airport->nofelements);
Airport->layout = FAutomata;
internalcounter = 0;
for (i = 0; i < Airport->nofelements; i++) {
current = &Airport->layout[i];
current->position = FA[internalcounter].position;
current->heading = FA[internalcounter].heading;
current->block = FA[internalcounter].block;
current->next_position = FA[internalcounter].next_in_chain;
// outgoing nodes from the same position, create linked list
while (current->position == FA[internalcounter+1].position) {
AirportFTA *newNode = (AirportFTA *)malloc(sizeof(AirportFTA));
newNode->position = FA[internalcounter+1].position;
newNode->heading = FA[internalcounter+1].heading;
newNode->block = FA[internalcounter+1].block;
newNode->next_position = FA[internalcounter+1].next_in_chain;
// create link
current->next_in_chain = newNode;
current = current->next_in_chain;
internalcounter++;
} // while
current->next_in_chain = NULL;
internalcounter++;
}
}
static byte AirportTestFTA(const AirportFTAClass *Airport)
{
byte position, i, next_element;
AirportFTA *temp;
next_element = 0;
for (i = 0; i < Airport->nofelements; i++) {
position = Airport->layout[i].position;
if (position != next_element) {return i;}
temp = &Airport->layout[i];
do {
if (temp->heading > MAX_HEADINGS && temp->heading != 255) {return i;}
if (temp->heading == 0 && temp->next_in_chain != 0) {return i;}
if (position != temp->position) {return i;}
if (temp->next_position >= Airport->nofelements) {return i;}
temp = temp->next_in_chain;
} while (temp != NULL);
next_element++;
}
return MAX_ELEMENTS;
}
static const char* const _airport_heading_strings[MAX_HEADINGS+2] = {
"TO_ALL",
"HANGAR",
"TERM1",
"TERM2",
"TERM3",
"TERM4",
"TERM5",
"TERM6",
"HELIPAD1",
"HELIPAD2",
"TAKEOFF",
"STARTTAKEOFF",
"ENDTAKEOFF",
"HELITAKEOFF",
"FLYING",
"LANDING",
"ENDLANDING",
"HELILANDING",
"HELIENDLANDING",
"DUMMY" // extra heading for 255
};
/*
static void AirportPrintOut(const AirportFTAClass *Airport, const bool full_report)
{
AirportFTA *temp;
uint16 i;
byte heading;
printf("(P = Current Position; NP = Next Position)\n");
for (i = 0; i < Airport->nofelements; i++) {
temp = &Airport->layout[i];
if (full_report) {
heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading;
printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position,
_airport_heading_strings[heading], AirportBlockToString(temp->block));
}
else { printf("P:%2d NP:%2d", temp->position, temp->next_position);}
while (temp->next_in_chain != NULL) {
temp = temp->next_in_chain;
if (full_report) {
heading = (temp->heading == 255) ? MAX_HEADINGS+1 : temp->heading;
printf("Pos:%2d NPos:%2d Heading:%15s Block:%2d\n", temp->position, temp->next_position,
_airport_heading_strings[heading], AirportBlockToString(temp->block));
}
else { printf("P:%2d NP:%2d", temp->position, temp->next_position);}
}
printf("\n");
}
}
static byte AirportBlockToString(uint32 block)
{
byte 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;
}*/
const AirportFTAClass* GetAirport(const byte airport_type)
{
AirportFTAClass *Airport = NULL;
//FIXME -- AircraftNextAirportPos_and_Order -> Needs something nicer, don't like this code
// needs constant change if more airports are added
switch (airport_type) {
case AT_SMALL: Airport = CountryAirport; break;
case AT_LARGE: Airport = CityAirport; break;
case AT_METROPOLITAN: Airport = MetropolitanAirport; break;
case AT_HELIPORT: Airport = Heliport; break;
case AT_OILRIG: Airport = Oilrig; break;
case AT_INTERNATIONAL: Airport = InternationalAirport; break;
default:
#ifdef DEBUG__
printf("Airport AircraftNextAirportPos_and_Order not yet implemented\n");
#endif
assert(airport_type <= AT_INTERNATIONAL);
}
return Airport;
}

67
airport.h Normal file
View File

@@ -0,0 +1,67 @@
#ifndef AIRPORT_H
#define AIRPORT_H
#include "airport_movement.h"
enum {MAX_TERMINALS = 6};
enum {MAX_HELIPADS = 2};
// Airport types
enum {
AT_SMALL = 0,
AT_LARGE = 1,
AT_HELIPORT = 2,
AT_METROPOLITAN = 3,
AT_INTERNATIONAL = 4,
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
};
// 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
} 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_in_chain; // possible extra movement choices from this position
} AirportFTA;
void InitializeAirports(void);
void UnInitializeAirports(void);
const AirportFTAClass* GetAirport(const byte airport_type);
/** 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
*/
static inline uint32 GetValidAirports(void)
{
uint32 bytemask = _avail_aircraft; /// sets the first 3 bytes, 0 - 2, @see AdjustAvailAircraft()
// 1980-1-1 is --> 21915
// 1990-1-1 is --> 25568
if (_date >= 21915) {SETBIT(bytemask, 3);} // metropilitan airport 1980
if (_date >= 25568) {SETBIT(bytemask, 4);} // international airport 1990
return bytemask;
}
#endif /* AIRPORT_H */

245
airport_gui.c Normal file
View File

@@ -0,0 +1,245 @@
#include "stdafx.h"
#include "ttd.h"
#include "table/sprites.h"
#include "table/strings.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, uint tile, uint32 p1, uint32 p2)
{
if (success) {
SndPlayTileFx(SND_1F_SPLAT, tile);
ResetObjectToPlace();
}
}
static void PlaceAirport(uint 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(uint tile)
{
VpStartPlaceSizing(tile, 4);
}
static void BuildAirClick_Airport(Window *w)
{
if (HandlePlacePushButton(w, 3, 0xAA4, 1, PlaceAirport)) ShowBuildAirportPicker();
}
static void BuildAirClick_Demolish(Window *w)
{
HandlePlacePushButton(w, 4, 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->click.widget - 3 >= 0)
_build_air_button_proc[e->click.widget - 3](w);
break;
case WE_KEYPRESS: {
switch (e->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->place.tile);
break;
case WE_PLACE_DRAG: {
VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, e->place.userdata);
return;
}
case WE_PLACE_MOUSEUP:
if (e->place.pt.x != -1) {
DoCommandP(e->place.tile, e->place.starttile, 0, CcPlaySound10, CMD_CLEAR_AREA | CMD_MSG(STR_00B5_CAN_T_CLEAR_THIS_AREA));
}
break;
case WE_ABORT_PLACE_OBJ:
UnclickWindowButtons(w);
SetWindowDirty(w);
w = FindWindowById(WC_BUILD_STATION, 0);
if (w != 0)
WP(w,def_d).close = true;
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_PANEL, RESIZE_NONE, 7, 0, 41, 14, 35, 0x2E8, STR_A01E_BUILD_AIRPORT},
{ WWT_PANEL, RESIZE_NONE, 7, 42, 63, 14, 35, 0x2BF, STR_018D_DEMOLISH_BUILDINGS_ETC},
{ WWT_PANEL, RESIZE_NONE, 7, 64, 85, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
{ WIDGETS_END},
};
static const WindowDesc _air_toolbar_desc = {
640-86, 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 (_current_player == OWNER_SPECTATOR) return;
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
AllocateWindowDescFront(&_air_toolbar_desc, 0);
}
static void BuildAirportPickerWndProc(Window *w, WindowEvent *e)
{
switch (e->event) {
case WE_PAINT: {
int sel;
int rad = 4; // default catchment radious
uint32 avail_airports;
if (WP(w,def_d).close) return;
sel = _selected_airport_type;
avail_airports = GetValidAirports();
if (!HASBIT(avail_airports, 0) && sel == AT_SMALL) sel = AT_LARGE;
if (!HASBIT(avail_airports, 1) && sel == AT_LARGE) sel = AT_SMALL;
/* 'Country Airport' starts at widget 3, and if its bit is set, it is available,
* so take its opposite value to set the disabled_state. There are only 5 available
* airports, so XOr with 0x1F (1 1111) */
w->disabled_state = (avail_airports ^ 0x1F) << 3;
_selected_airport_type = sel;
// select default the coverage area to 'Off' (8)
w->click_state = ((1<<3) << sel) | ((1<<8) << _station_show_coverage);
SetTileSelectSize(_airport_size_x[sel],_airport_size_y[sel]);
if (_patches.modified_catchment) {
switch (sel) {
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;
}
}
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
DrawWindowWidgets(w);
// strings such as 'Size' and 'Coverage Area'
DrawStringCentered(74, 16, STR_305B_SIZE, 0);
DrawStringCentered(74, 78, STR_3066_COVERAGE_AREA_HIGHLIGHT, 0);
DrawStationCoverageAreaText(2, 104, (uint)-1, rad);
break;
}
case WE_CLICK: {
switch(e->click.widget) {
case 3: case 4: case 5: case 6: case 7:
_selected_airport_type = e->click.widget - 3;
SndPlayFx(SND_15_BEEP);
SetWindowDirty(w);
break;
case 8: case 9:
_station_show_coverage = e->click.widget - 8;
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, 130, 0x0, STR_NULL},
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 73, 27, 38, STR_3059_SMALL, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 74, 145, 27, 38, STR_305A_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 63, 74, STR_306B_HELIPORT, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 39, 50, STR_305AA_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{WWT_NODISTXTBTN, RESIZE_NONE, 14, 2, 145, 51, 62, STR_305AB_LARGE, STR_3058_SELECT_SIZE_TYPE_OF_AIRPORT},
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 14, 73, 88, 98, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 74, 133, 88, 98, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
{ WIDGETS_END},
};
static const WindowDesc _build_airport_desc = {
-1, -1, 148, 131, // height, 130+1
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;
_last_built_aircraft_depot_tile = 0;
}

468
airport_movement.h Normal file
View File

@@ -0,0 +1,468 @@
#ifndef AIRPORT_MOVEMENT_H
#define AIRPORT_MOVEMENT_H
#include "stdafx.h"
#include "macros.h"
typedef struct AirportMovingData {
int x,y;
byte flag;
byte direction;
} AirportMovingData;
// 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_in_chain; // next position from this position
} AirportFTAbuildup;
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,
};
enum {MAX_ELEMENTS = 255};
enum {MAX_HEADINGS = 18};
///////////////////////////////////////////////////////////////////////
///////***********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
};
///////////////////////////////////////////////////////////////////////
///////**********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,
NOTHING_block = 1 << 30
};
///////////////////////////////////////////////////////////////////////
/////*********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
};
// 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
};
// 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)
};
// 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 depots 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_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
};
// 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
};
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
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
_airport_moving_data_oilrig // Oilrig
};
#endif /* AIRPORT_MOVEMENT_H */

278
aystar.c Normal file
View File

@@ -0,0 +1,278 @@
/*
* 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 "ttd.h"
#include "aystar.h"
// 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, 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, PathNode *node)
{
// Add a node to the ClosedList
PathNode *new_node = malloc(sizeof(PathNode));
*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, 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, AyStarNode *node, int f, int g)
{
// Add a new Node to the OpenList
OpenListNode* new_node = malloc(sizeof(OpenListNode));
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
if ((check = AyStarMain_OpenList_IsInList(aystar, current)) != 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
if (r == AYSTAR_FOUND_END_NODE)
printf("[AyStar] Found path!\n");
else if (r == AYSTAR_EMPTY_OPENLIST)
printf("[AyStar] OpenList run dry, no path found\n");
else if (r == AYSTAR_LIMIT_REACHED)
printf("[AyStar] Exceeded search_nodes, no path found\n");
#endif
if (r != AYSTAR_STILL_BUSY)
/* We're done, clean up */
aystar->clear(aystar);
// Check result-value
if (r == AYSTAR_FOUND_END_NODE) return AYSTAR_FOUND_END_NODE;
// Check if we have some left in the OpenList
if (r == AYSTAR_EMPTY_OPENLIST || r == AYSTAR_LIMIT_REACHED) return AYSTAR_NO_PATH;
// Return we are still busy
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;
}

177
aystar.h Normal file
View File

@@ -0,0 +1,177 @@
/*
* 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 {
uint 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

View File

@@ -1,369 +0,0 @@
/* $Id$ */
/*
* 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 compatability 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

View File

@@ -1,121 +0,0 @@
/* $Id$ */
/*
* 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 compatability 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

View File

@@ -1,58 +0,0 @@
/* $Id$ */
/*
* 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 compatability 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

View File

@@ -1,10 +0,0 @@
/* $Id$ */
/*
* 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 compatability in effect.");

View File

@@ -1,8 +0,0 @@
/* $Id$ */
/*
* 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,69 +0,0 @@
#!/bin/sh
# $Id$
if ! [ -f ai/regression/regression.nut ]; then
echo "Make sure you are in the root of OpenTTD before starting this script."
exit 1
fi
cat ai/regression/regression.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 occurence of AI.
# If we do not remove any other occurences of AI from the string
# we will remove everything before the LAST occurence 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/ai/api/*.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

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

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,15 +0,0 @@
/* $Id$ */
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 all commands. On the same map the result should always be the same."; }
function GetVersion() { return 1; }
function GetAPIVersion() { return "1.3"; }
function GetDate() { return "2007-03-18"; }
function CreateInstance() { return "Regression"; }
}
RegisterAI(Regression());

View File

@@ -1,4 +0,0 @@
/* $Id$ */
print(" Required this file");

View File

@@ -1,55 +0,0 @@
#!/bin/sh
# $Id$
if ! [ -f ai/regression/regression.nut ]; then
echo "Make sure you are in the root of OpenTTD before starting this script."
exit 1
fi
cp ai/regression/regression.nut ai/regression/main.nut
cp ai/regression/regression_info.nut ai/regression/info.nut
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 [ -n "$gdb" ]; then
$gdb ./openttd -x -c ai/regression/regression.cfg $params -g ai/regression/regression.sav
else
./openttd -x -c ai/regression/regression.cfg $params -g ai/regression/regression.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: \[.*\]' > tmp.regression
fi
ret=0
if [ -z "$gdb" ]; then
res="`diff -ub ai/regression/regression.txt tmp.regression`"
if [ -z "$res" ]; then
echo "Regression test passed!"
else
echo "Regression test failed! Difference:"
echo "$res"
ret=1
fi
echo ""
echo "Regression test done"
fi
rm -f ai/regression/main.nut ai/regression/info.nut
if [ -f scripts/game_start.scr.regression ]; then
mv scripts/game_start.scr.regression scripts/game_start.scr
fi
if [ "$1" != "-k" ]; then
rm -f tmp.regression
fi
exit $ret

View File

@@ -1,93 +0,0 @@
; $Id$
;
; This represents more or less nothingness
;
[metadata]
name = NoMusic
shortname = NULL
version = 0
fallback = true
description = A music pack without actual music.
description.af_ZA = 'n Musiek stel sonder enige musiek.
description.ar_EG = مجموعة موسيقى بدون موسيقى
description.be_BY = "Пусты" набор музычнага афармлення, не змяшчаючы ніякай музыкі.
description.bg_BG = Празен музикален пакет.
description.ca_ES = Un joc de música sense cap música.
description.cs_CZ = Prázná hudební sada.
description.cy_GB = Pecyn cerddoriaeth heb unrhyw gerddoriaeth ynddo.
description.da_DK = En musikpakke uden musik.
description.de_DE = Ein Musikset ohne Musik.
description.el_GR = Ένα πάκετο μουσικής χωρίς πραγματική μουσική.
description.en_AU = A music pack without actual music.
description.en_US = A music pack without actual music.
description.es_ES = Un conjunto de música vacío.
description.et_EE = Muusikakomplekt ilma igasuguse muusikata.
description.fi_FI = Musiikkipaketti, jossa ei ole musiikkia.
description.fr_FR = Un pack de musiques sans musiques.
description.gd_GB = Pacaid ciùil anns nach eil fonn sam bith.
description.gl_ES = Un conxunto de músicas sen ningunha música.
description.hr_HR = Muzički paket bez ikakve muzike.
description.hu_HU = Zenei alapcsomag zene nélkül.
description.id_ID = Paket musik tanpa musik sungguhan.
description.is_IS = Tónlistarpakki sem er í raun án tónlistar.
description.it_IT = Un pacchetto musicale non contenente alcuna musica.
description.ja_JP = 音楽が無いミュージックパック
description.ko_KR = 실제 음악이 없는 음악 목록입니다.
description.lt_LT = Muzikos pakas be muzikos.
description.nb_NO = En musikkpakke uten noe musikk.
description.nl_NL = Een muziekset zonder muziek.
description.nn_NO = Ei musikkpakke utan noko musikk.
description.pl_PL = Zestaw utworów muzycznych nie zawierający żadnej muzyki.
description.pt_PT = Um conjunto de música vazio.
description.ro_RO = Un set de muzică fără muzică inclusă.
description.ru_RU = "Пустой" набор музыкального оформления, не содержащий никакой музыки.
description.sk_SK = Sada hudby neobsahujúca hudbu.
description.sl_SI = Glasbeni paket z vključeno glasbo.
description.sr_RS = Prazan skup muzičkih numera.
description.sv_SE = Ett musikpaket utan någon musik.
description.ta_IN = இசை இல்லாத இசைத்தொகுப்பு.
description.th_TH = A music pack without actual music.
description.tr_TR = Müzik içermeyen boş bir müzik paketi.
description.vi_VN = Gói âm nhạc này không có nhạc nào.
description.zh_CN = 一个没有实际内容的音乐包.
description.zh_TW = 不含任何音樂的音樂集。
[files]
theme =
old_0 =
old_1 =
old_2 =
old_3 =
old_4 =
old_5 =
old_6 =
old_7 =
old_8 =
old_9 =
new_0 =
new_1 =
new_2 =
new_3 =
new_4 =
new_5 =
new_6 =
new_7 =
new_8 =
new_9 =
ezy_0 =
ezy_1 =
ezy_2 =
ezy_3 =
ezy_4 =
ezy_5 =
ezy_6 =
ezy_7 =
ezy_8 =
ezy_9 =
[md5s]
[names]
[origin]
default = This file was part of your OpenTTD installation.

View File

@@ -1,61 +0,0 @@
; $Id$
;
; This represents more or less nothingness
;
[metadata]
name = NoSound
shortname = NULL
version = 2
fallback = true
description = A sound pack without any sounds.
description.af_ZA = 'n Klank stel sonder enige klanke.
description.ar_EG = مجموعة صوت بدوت اصوات مضافة
description.be_BY = "Пусты" набор гукавога афармленьня, не змяшчаючы ніякіх гукаў.
description.bg_BG = Празен звуков пакет.
description.ca_ES = Un joc de sons sense cap so.
description.cs_CZ = Prázdná sada zvuků.
description.cy_GB = Pecyn sain heb unrhyw effeithiau sain ynddo.
description.da_DK = En lydpakke uden lyde.
description.de_DE = Basissounds ohne Sound.
description.el_GR = Ένα πάκετο ήχων χώρις ήχους.
description.en_AU = A sound pack without any sounds.
description.en_US = A sound pack without any sounds.
description.es_ES = Un conjunto de sonidos vacío.
description.et_EE = Ilma häälteta helipakk.
description.fi_FI = Äänipaketti, jossa ei ole ääniä.
description.fr_FR = Un pack de sons sans sons.
description.gd_GB = Pacaid fhuaimean anns nach eil fuaim sam bith.
description.gl_ES = Un conxunto de sons sen ningún son
description.hr_HR = Zvučni paket bez ikakvih zvukova.
description.hu_HU = Hang alapcsomag hangok nélkül.
description.id_ID = Paket efek suara tanpa suara apapun.
description.is_IS = Hljóðpakki án hljóðs.
description.it_IT = Un pacchetto sonoro non contenente alcun suono.
description.ja_JP = 音楽が無いミュージックパック
description.ko_KR = 아무런 효과음도 없는 효과음 팩입니다.
description.lt_LT = Garsų pakas be jokių garsų.
description.nb_NO = En lydpakke uten noen lyder.
description.nl_NL = Een geluidset zonder geluid.
description.nn_NO = Ei lydpakke utan nokon lydar.
description.pl_PL = Zestaw dźwięków nie zawierający żadnych dźwięków.
description.pt_PT = Um conjunto de sons vazio.
description.ro_RO = Un set de sunete fără nici un sunet inclus.
description.ru_RU = "Пустой" набор звукового оформления, не содержащий никаких звуков.
description.sk_SK = Zvuková sada neobsahujúca zvuky.
description.sl_SI = Zvočni paket brez zvoka.
description.sr_RS = Prazan skup zvukova.
description.sv_SE = Ett ljudpaket utan några ljud.
description.ta_IN = ஒலிகள் இல்லாத ஒலி தொகுப்பு.
description.th_TH = A sound pack without any sounds.
description.tr_TR = Ses içermeyen boş bir ses kümesi.
description.vi_VN = Gói âm thanh này không có âm thanh nào.
description.zh_CN = 一个空的音效包.
description.zh_TW = 不含任何音效的音效集。
[files]
samples =
[md5s]
[origin]
default = This file was part of your OpenTTD installation.

Binary file not shown.

Binary file not shown.

View File

@@ -1,74 +0,0 @@
; $Id$
;
; This represents the original graphics as on the non-German Transport
; Tycoon Deluxe DOS CD.
;
[metadata]
name = original_dos
shortname = TTDD
version = 1
palette = DOS
description = Original Transport Tycoon Deluxe DOS edition graphics.
description.af_ZA = Oorspronklike Transport Tycoon Deluxe DOS uitgawe grafieke.
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الرسومية نسخة الدوس
description.be_BY = Арыгінальная графіка з Transport Tycoon Deluxe для DOS.
description.bg_BG = Оригинални графики на Transport Tycoon Deluxe за DOS.
description.ca_ES = Gràfics originals de Transport Tycoon Deluxe per a DOS.
description.cs_CZ = Původní sada grafik Transport Tycoon Deluxe (verze pro DOS).
description.cy_GB = Graffeg gwreiddiol fersiwn DOS o Transport Tycoon Deluxe.
description.da_DK = Originalgrafik fra Transport Tycoon Deluxe DOS-version.
description.de_DE = Original Transport Tycoon Deluxe DOS Basisgrafiken.
description.el_GR = Αρχικά γραφικά από το Transport Tycoon Deluxe έκδοση DOS.
description.en_AU = Original Transport Tycoon Deluxe DOS edition graphics.
description.en_US = Original Transport Tycoon Deluxe DOS edition graphics.
description.es_ES = Gráficos originales de Transport Tycoon Deluxe versión DOS.
description.et_EE = Algse Transport Tycoon Deluxe DOSi versiooni graafika.
description.fi_FI = Alkuperäiset Transport Tycoon Deluxen DOS-version grafiikat.
description.fr_FR = Graphiques originaux de Transport Tycoon Deluxe (version DOS).
description.gd_GB = Grafaigeachd aig an deasachadh DOS tùsail aig Transport Tycoon Deluxe.
description.gl_ES = Graficos da edición orixinal de Transport Tycoon Deluxe para DOS.
description.hr_HR = Originalna grafika za Transport Tycoon Deluxe DOS izdanje.
description.hu_HU = Az eredeti Transport Tycoon Deluxe DOS verziójának grafikája.
description.id_ID = Grafik orisinil Transport Tycoon Deluxe versi DOS.
description.is_IS = Upprunalega grafíkin úr Transport Tycoon Deluxe DOS útgáfunni.
description.it_IT = Grafica originale di Transport Tycoon Deluxe, edizione DOS.
description.ja_JP = オリジナルDOS『トランスポートタイクンデラックス』版画像
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 도스 에디션의 그래픽입니다.
description.lt_LT = Originali Transport Tycoon Deluxe DOS leidimo grafika.
description.nb_NO = Original grafikk fra Transport Tycoon Deluxe for DOS.
description.nl_NL = Originele graphics van de Transport Tycoon Deluxe DOS-versie.
description.nn_NO = Original grafikk frå Transport Tycoon Deluxe for DOS.
description.pl_PL = Oryginalna edycja grafik dla Transport Tycoon Deluxe DOS.
description.pt_PT = Gráficos originais da edição DOS de Transport Tycoon Deluxe.
description.ro_RO = Setul grafic original al Transport Tycoon Deluxe pentru DOS.
description.ru_RU = Оригинальная графика из Transport Tycoon Deluxe для DOS.
description.sk_SK = Pôvodná grafika Transport Tycoon Deluxe (DOS).
description.sl_SI = Originalna grafika Transport Tycoon Deluxe za različico DOS.
description.sr_RS = Originalni skup grafika Transport Tycoon Deluxe DOS izdanja.
description.sv_SE = Originalgrafiken från Transport Tycoon Deluxe, DOS-utgåvan.
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் DOS பதிப்பு அசைவூட்டங்கள்.
description.th_TH = กราฟฟิกต้นตำหรับของ Transport Tycoon Deluxe DOS edition
description.tr_TR = Orijinal Transport Tycoon Deluxe DOS sürümü grafikleri.
description.vi_VN = Đồ họa gốc từ phiên bản Transport Tycoon Deluxe trên DOS
description.zh_CN = 运输大亨DOS豪华版原版图形包.
description.zh_TW = 原版 Transport Tycoon Deluxe DOS 版的圖形。
[files]
base = TRG1.GRF
logos = TRGI.GRF
arctic = TRGC.GRF
tropical = TRGH.GRF
toyland = TRGT.GRF
extra = OPENTTD.GRF
[md5s]
TRG1.GRF = 9311676280e5b14077a8ee41c1b42192
TRGI.GRF = da6a6c9dcc451eec88d79211437b76a8
TRGC.GRF = ed446637e034104c5559b32c18afe78d
TRGH.GRF = ee6616fb0e6ef6b24892c58c93d86fc9
TRGT.GRF = e30e8a398ae86c03dc534a8ac7dfb3b6
OPENTTD.GRF = c683a77e1a43aed7db29ef318b166dd9
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
OPENTTD.GRF = This file was part of your OpenTTD installation.

View File

@@ -1,62 +0,0 @@
; $Id$
;
; This represents the original sounds as on the Transport
; Tycoon Deluxe DOS CD.
;
[metadata]
name = original_dos
shortname = TTDO
version = 0
description = Original Transport Tycoon Deluxe DOS edition sounds.
description.af_ZA = Oorspronklike Transport Tycoon Deluxe DOS uitgawe klanke.
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الصوتية نسخة الدوس
description.be_BY = Арыгінальны набор гукавога афармленьня з гульні Transport Tycoon Deluxe для DOS.
description.bg_BG = Оригинални звуци на Transport Tycoon Deluxe за DOS.
description.ca_ES = Sons originals de Transport Tycoon Deluxe per a DOS.
description.cs_CZ = Původní sada zvuků Transport Tycoon Deluxe (verze pro DOS).
description.cy_GB = Effeithiau sain gwreiddiol fersiwn DOS o Transport Tycoon Deluxe.
description.da_DK = Originallyd fra Transport Tycoon Deluxe DOS-version.
description.de_DE = Original Transport Tycoon Deluxe DOS Basissounds.
description.el_GR = Αρχικοί ήχοι από το Transport Tycoon Deluxe έκδοση DOS.
description.en_AU = Original Transport Tycoon Deluxe DOS edition sounds.
description.en_US = Original Transport Tycoon Deluxe DOS edition sounds.
description.es_ES = Sonidos originales de Transport Tycoon Deluxe versión DOS.
description.et_EE = Algse Transport Tycoon Deluxe DOSi versiooni helid.
description.fi_FI = Alkuperäiset Transport Tycoon Deluxen DOS-version äänet.
description.fr_FR = Sons originaux de Transport Tycoon Deluxe (version DOS).
description.gd_GB = Fuaimean aig an deasachadh DOS tùsail aig Transport Tycoon Deluxe.
description.gl_ES = Sons da edición orixinal de Transport Tycoon Deluxe para DOS.
description.hr_HR = Originalni zvukovi za Transport Tycoon Deluxe DOS izdanje.
description.hu_HU = Az eredeti Transport Tycoon Deluxe DOS verziójának hangjai.
description.id_ID = Efek suara orisinil Transport Tycoon Deluxe versi DOS.
description.is_IS = Upprunalega hljóðið úr Transport Tycoon Deluxe DOS útgáfunni.
description.it_IT = Suoni originali di Transport Tycoon Deluxe, edizione DOS.
description.ja_JP = オリジナル DOS 『トランスポートタイクンデラックス』版音楽
description.ko_KR = 오리지널 트랜스포트 타이쿤 도스 에디션의 효과음입니다.
description.lt_LT = Originalūs Transport Tycoon Deluxe DOS leidimo garsai.
description.nb_NO = Originale lyder fra Transport Tycoon Deluxe for DOS.
description.nl_NL = Originele geluiden van de Transport Tycoon Deluxe DOS-versie.
description.nn_NO = Originale lydar frå Transport Tycoon Deluxe for DOS.
description.pl_PL = Oryginalna edycja dźwięków dla Transport Tycoon Deluxe DOS.
description.pt_PT = Sons originais da edição DOS de Transport Tycoon Deluxe.
description.ro_RO = Setul de sunete original al Transport Tycoon Deluxe pentru DOS.
description.ru_RU = Оригинальный набор звукового оформления из игры Transport Tycoon Deluxe для DOS.
description.sk_SK = Pôvodné zvuky Transport Tycoon Deluxe (DOS).
description.sl_SI = Originalni zvoki Transport Tycoon Deluxe različice DOS.
description.sr_RS = Originalni skup zvukova Transport Tycoon Deluxe DOS izdanja.
description.sv_SE = Originalljuden från Transport Tycoon Deluxe, DOS-utgåvan.
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் DOS பதிப்பு ஒலிகள்.
description.th_TH = เสียงต้นตำหรับของ Transport Tycoon Deluxe DOS edition
description.tr_TR = Orijinal Transport Tycoon Deluxe DOS sürümü sesleri.
description.vi_VN = Âm thanh gốc từ phiên bản Transport Tycoon Deluxe trên DOS
description.zh_CN = 运输大亨DOS豪华版原版音效包.
description.zh_TW = 原版 Transport Tycoon Deluxe DOS 版的音效。
[files]
samples = SAMPLE.CAT
[md5s]
SAMPLE.CAT = 422ea3dd074d2859bb51639a6e0e85da
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.

View File

@@ -1,74 +0,0 @@
; $Id$
;
; This represents the original graphics as on the German Transport
; Tycoon Deluxe DOS CD. It contains one broken sprite.
;
[metadata]
name = original_dos_de
shortname = TTDD
version = 0
palette = DOS
description = Original Transport Tycoon Deluxe DOS (German) edition graphics.
description.af_ZA = Oorspronklike Transport Tycoon Deluxe DOS (German) uitgawe grafieke.
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الالمانية نسخة الدوس
description.be_BY = Арыгінальная графіка з нямецкай версіі Transport Tycoon Deluxe для DOS.
description.bg_BG = Оригинални графики на Transport Tycoon Deluxe за DOS (немски) .
description.ca_ES = Gràfics originals de Transport Tycoon Deluxe per a DOS (Alemany).
description.cs_CZ = Původní sada grafik Transport Tycoon Deluxe (německá verze pro DOS).
description.cy_GB = Graffeg gwreiddiol fersiwn DOS (Almaenig) o Transport Tycoon Deluxe.
description.da_DK = Originalgrafik fra Transport Tycoon Deluxe DOS (Tysk) version.
description.de_DE = Original Transport Tycoon Deluxe DOS (Deutsch) Basisgrafiken.
description.el_GR = Αρχικά γραφικά από το Transport Tycoon Deluxe έκδοση DOS (Γερμανικό).
description.en_AU = Original Transport Tycoon Deluxe DOS (German) edition graphics.
description.en_US = Original Transport Tycoon Deluxe DOS (German) edition graphics.
description.es_ES = Gráficos originales de Transport Tycoon Deluxe versión DOS (Alemán).
description.et_EE = Algse Transport Tycoon Deluxe DOSi (Saksa) versiooni graafika.
description.fi_FI = Alkuperäiset Saksassa julkaistun Transport Tycoon Deluxen DOS-version grafiikat.
description.fr_FR = Graphiques originaux de Transport Tycoon Deluxe (version DOS allemande).
description.gd_GB = Grafaigeachd aig an deasachadh DOS (Gearmailteach) tùsail aig Transport Tycoon Deluxe.
description.gl_ES = Graficos da edición orixinal (alemá) de Transport Tycoon Deluxe para DOS.
description.hr_HR = Originalna grafika za Transport Tycoon Deluxe DOS (Njemački) izdanje.
description.hu_HU = Az eredeti Transport Tycoon Deluxe DOS (német) verziójának grafikája.
description.id_ID = Grafik orisinil Transport Tycoon Deluxe versi DOS (Jerman).
description.is_IS = Upprunalega grafíkin úr Transport Tycoon Deluxe DOS (þýsku) útgáfunni.
description.it_IT = Grafica originale di Transport Tycoon Deluxe (tedesco), edizione DOS.
description.ja_JP = オリジナルDOS『トランスポートタイクンデラックス』ドイツ語版 画像
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 도스 에디션(독일)의 그래픽입니다.
description.lt_LT = Originali Transport Tycoon Deluxe DOS (Vokiečių) leidimo grafika.
description.nb_NO = Original grafikk fra Transport Tycoon Deluxe for DOS (tysk).
description.nl_NL = Originele graphics van de Duitse Transport Tycoon Deluxe DOS-versie.
description.nn_NO = Original grafikk frå Transport Tycoon Deluxe for DOS (tysk).
description.pl_PL = Oryginalna edycja grafik dla Transport Tycoon Deluxe DOS (German).
description.pt_PT = Gráficos originais da edição DOS (Alemã) de Transport Tycoon Deluxe.
description.ro_RO = Setul grafic original al Transport Tycoon Deluxe pentru DOS (ediţia germană).
description.ru_RU = Оригинальная графика из немецкой версии Transport Tycoon Deluxe для DOS.
description.sk_SK = Pôvodná grafika Transport Tycoon Deluxe (DOS) (v jazyku nemčina).
description.sl_SI = Originalna grafika Transport Tycoon Deluxe za nemško različico DOS.
description.sr_RS = Originalni skup grafika nemačkog Transport Tycoon Deluxe DOS izdanja.
description.sv_SE = Originalgrafiken från Transport Tycoon Deluxe, DOS-utgåvan (tyska).
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் DOS (செருமன்) பதிப்பு அசைவூட்டங்கள்.
description.th_TH = กราฟฟิกต้นตำหรับของ Transport Tycoon Deluxe DOS (German) edition
description.tr_TR = Orijinal Transport Tycoon Deluxe DOS (Almanca) sürümü grafikleri.
description.vi_VN = Đồ họa gốc từ phiên bản Transport Tycoon Deluxe trên DOS (tiếng Đức)
description.zh_CN = 运输大亨DOS豪华德语版原版图形包.
description.zh_TW = 原版 Transport Tycoon Deluxe DOS 版 (德國版) 的圖形。
[files]
base = TRG1.GRF
logos = TRGI.GRF
arctic = TRGC.GRF
tropical = TRGH.GRF
toyland = TRGT.GRF
extra = OPENTTD.GRF
[md5s]
TRG1.GRF = 9311676280e5b14077a8ee41c1b42192
TRGI.GRF = da6a6c9dcc451eec88d79211437b76a8
TRGC.GRF = ed446637e034104c5559b32c18afe78d
TRGH.GRF = ee6616fb0e6ef6b24892c58c93d86fc9
TRGT.GRF = fcde1d7e8a74197d72a62695884b909e
OPENTTD.GRF = c683a77e1a43aed7db29ef318b166dd9
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
OPENTTD.GRF = This file was part of your OpenTTD installation.

View File

@@ -1,74 +0,0 @@
; $Id$
;
; This represents the original graphics as on the Transport
; Tycoon Deluxe for Windows CD.
;
[metadata]
name = original_windows
shortname = TTDW
version = 0
palette = Windows
description = Original Transport Tycoon Deluxe Windows edition graphics.
description.af_ZA = Oorspronklike Transport Tycoon Deluxe Windows uitgawe grafieke.
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الرسومية نسخة وندوز
description.be_BY = Арыгінальная графіка з Transport Tycoon Deluxe для Windows.
description.bg_BG = Оригинални графики на Transport Tycoon Deluxe за Windows.
description.ca_ES = Gràfics originals de Transport Tycoon Deluxe per a Windows.
description.cs_CZ = Původní sada grafik Transport Tycoon Deluxe (verze pro Windows).
description.cy_GB = Graffeg gwreiddiol fersiwn Windows o Transport Tycoon Deluxe.
description.da_DK = Originalgrafik fra Transport Tycoon Deluxe Windows-version.
description.de_DE = Original Transport Tycoon Deluxe Windows Basisgrafiken.
description.el_GR = Αρχικά γραφικά από το Transport Tycoon Deluxe έκδοση Windows.
description.en_AU = Original Transport Tycoon Deluxe Windows edition graphics.
description.en_US = Original Transport Tycoon Deluxe Windows edition graphics.
description.es_ES = Gráficos originales de Transport Tycoon Deluxe versión Windows.
description.et_EE = Algse Transport Tycoon Deluxe Windowsi versiooni graafika.
description.fi_FI = Alkuperäiset Transport Tycoon Deluxen Windows-version grafiikat.
description.fr_FR = Graphiques originaux de Transport Tycoon Deluxe (version Windows).
description.gd_GB = Grafaigeachd aig an deasachadh Windows tùsail aig Transport Tycoon Deluxe.
description.gl_ES = Graficos da edición orixinal de Transport Tycoon Deluxe para Windows.
description.hr_HR = Originalna grafika za Transport Tycoon Deluxe Windows izdanje.
description.hu_HU = Az eredeti Transport Tycoon Deluxe Windows verziójának grafikája.
description.id_ID = Grafik orisinil Transport Tycoon Deluxe versi Windows.
description.is_IS = Upprunalega grafíkin úr Transport Tycoon Deluxe Windows útgáfunni.
description.it_IT = Grafica originale di Transport Tycoon Deluxe, edizione Windows.
description.ja_JP = オリジナルウィンドーズ『トランスポートタイクンデラックス』版 画像
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 윈도우 에디션의 그래픽입니다.
description.lt_LT = Originali Transport Tycoon Deluxe Windows leidimo grafika.
description.nb_NO = Original grafikk fra Transport Tycoon Deluxe for Windows.
description.nl_NL = Originele graphics van de Transport Tycoon Deluxe Windows-versie.
description.nn_NO = Original grafikk frå Transport Tycoon Deluxe for Windows.
description.pl_PL = Oryginalna edycja grafik dla Transport Tycoon Deluxe Windows.
description.pt_PT = Gráficos originais da edição Windows de Transport Tycoon Deluxe.
description.ro_RO = Setul grafic original al Transport Tycoon Deluxe pentru Windows.
description.ru_RU = Оригинальная графика из Transport Tycoon Deluxe для Windows.
description.sk_SK = Pôvodná grafika Transport Tycoon Deluxe (Windows).
description.sl_SI = Originalna grafika Transport Tycoon Deluxe za različico oken(windows).
description.sr_RS = Originalni skup grafika Transport Tycoon Deluxe Windows izdanja.
description.sv_SE = Originalgrafiken från Transport Tycoon Deluxe, Windows-utgåvan.
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் விண்டோஸ் பதிப்பு அசைவூட்டங்கள்.
description.th_TH = กราฟฟิกต้ำตำหรับของ Transport Tycoon Deluxe Windows edition
description.tr_TR = Orijinal Transport Tycoon Deluxe Windows sürümü grafikleri.
description.vi_VN = Đồ họa gốc từ phiên bản Transport Tycoon Deluxe trên Windows
description.zh_CN = 运输大亨Windows豪华版原版图形包.
description.zh_TW = 原版 Transport Tycoon Deluxe Windows 版的圖形。
[files]
base = TRG1R.GRF
logos = TRGIR.GRF
arctic = TRGCR.GRF
tropical = TRGHR.GRF
toyland = TRGTR.GRF
extra = OPENTTD.GRF
[md5s]
TRG1R.GRF = b04ce593d8c5016e07473a743d7d3358
TRGIR.GRF = 0c2484ff6be49fc63a83be6ab5c38f32
TRGCR.GRF = 3668f410c761a050b5e7095a2b14879b
TRGHR.GRF = 06bf2b7a31766f048baac2ebe43457b1
TRGTR.GRF = de53650517fe661ceaa3138c6edb0eb8
OPENTTD.GRF = c683a77e1a43aed7db29ef318b166dd9
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.
OPENTTD.GRF = This file was part of your OpenTTD installation.

View File

@@ -1,137 +0,0 @@
; $Id$
;
; This represents the original music as on the Transport
; Tycoon Deluxe for Windows CD.
;
[metadata]
name = original_windows
shortname = TTDW
version = 1
description = Original Transport Tycoon Deluxe Windows edition music.
description.af_ZA = Oorspronklike Transport Tycoon Deluxe Windows uitgawe musiek.
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الموسيقية نسخة وندوز
description.be_BY = Арыгінальны набор музычнага афармленьня з гульні Transport Tycoon Deluxe для Windows.
description.bg_BG = Оригинална музика на Transport Tycoon Deluxe за Windows.
description.ca_ES = Música Original de Transport Tycoon Deluxe per a Windows.
description.cs_CZ = Původní hudba Transport Tycoon Deluxe (verze pro Windows).
description.cy_GB = Cerddoriaeth gwreiddiol fersion Windows o Transport Tycoon Deluxe.
description.da_DK = Originalmusik fra Transport Tycoon Deluxe Windows-version.
description.de_DE = Original Transport Tycoon Deluxe Windows Musikset.
description.el_GR = Αρχική μουσική από το Transport Tycoon Deluxe έκδοση Windows.
description.en_AU = Original Transport Tycoon Deluxe Windows edition music.
description.en_US = Original Transport Tycoon Deluxe Windows edition music.
description.es_ES = Música original de Transport Tycoon Deluxe versión Windows.
description.et_EE = Algse Transport Tycoon Deluxe Windowsi versiooni muusika.
description.fi_FI = Alkuperäinen Transport Tycoon Deluxen Windows-version musiikki.
description.fr_FR = Musiques originales de Transport Tycoon Deluxe (version Windows).
description.gd_GB = Ceòl aig an deasachadh Windows tùsail aig Transport Tycoon Deluxe.
description.gl_ES = Música da edición orixinal de Transport Tycoon Deluxe para Windows.
description.hr_HR = Originalna muzika za Transport Tycoon Deluxe Windows izdanje.
description.hu_HU = Az eredeti Transport Tycoon Deluxe Windows verziójának zenéje.
description.id_ID = Musik pengiring orisinil Transport Tycoon Deluxe versi Windows.
description.is_IS = Upprunalega tónlistin úr Transport Tycoon Deluxe Windows útgáfunni.
description.it_IT = Musica originale di Transport Tycoon Deluxe, edizione Windows.
description.ja_JP = オリジナルウィンドーズ『トランスポートタイクンデラックス』版音楽
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 윈도우 에디션의 음악입니다.
description.lt_LT = Originali Transport Tycoon Deluxe Windows leidimo muzika.
description.nb_NO = Original musikk fra Transport Tycoon Deluxe for Windows.
description.nl_NL = Originele muziek van de Transport Tycoon Deluxe Windows-versie.
description.nn_NO = Original musikk frå Transport Tycoon Deluxe for Windows.
description.pl_PL = Oryginalna edycja utworów muzycznych w Transport Tycoon Deluxe Windows.
description.pt_PT = Música original da edição Windows de Transport Tycoon Deluxe.
description.ro_RO = Setul de muzică original al Transport Tycoon Deluxe pentru Windows.
description.ru_RU = Оригинальный набор музыкального оформления из игры Transport Tycoon Deluxe для Windows.
description.sk_SK = Pôvodná hudba z Transport Tycoon Deluxe (Windows).
description.sl_SI = Originalna glasba Transport Tycoon Deluxe različice oken(windows).
description.sr_RS = Originalni skup muzičkih numera Transport Tycoon Deluxe Windows izdanja.
description.sv_SE = Originalmusiken från Transport Tycoon Deluxe, Windows-utgåvan.
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் விண்டோஸ் பதிப்பு இசை.
description.th_TH = เพลงต้นตำหรับชอง Transport Tycoon Deluxe Windows edition
description.tr_TR = Orijinal Transport Tycoon Deluxe Windows sürümü müzikleri.
description.vi_VN = Nhạc gốc từ phiên bản Transport Tycoon Deluxe trên Windows
description.zh_CN = Transport Tycoon Deluxe运输大亨Windows豪华版的原版音乐包
description.zh_TW = 原版 Transport Tycoon Deluxe Windows 版的音樂。
[files]
theme = GM_TT00.GM
old_0 = GM_TT02.GM
old_1 = GM_TT06.GM
old_2 = GM_TT03.GM
old_3 = GM_TT12.GM
old_4 = GM_TT08.GM
old_5 = GM_TT13.GM
old_6 = GM_TT14.GM
old_7 = GM_TT10.GM
old_8 =
old_9 =
new_0 = GM_TT04.GM
new_1 = GM_TT01.GM
new_2 = GM_TT05.GM
new_3 = GM_TT15.GM
new_4 = GM_TT11.GM
new_5 = GM_TT16.GM
new_6 = GM_TT09.GM
new_7 =
new_8 =
new_9 =
ezy_0 = GM_TT18.GM
ezy_1 = GM_TT19.GM
ezy_2 = GM_TT21.GM
ezy_3 = GM_TT17.GM
ezy_4 = GM_TT20.GM
ezy_5 = GM_TT07.GM
ezy_6 =
ezy_7 =
ezy_8 =
ezy_9 =
[md5s]
GM_TT00.GM = 45cfec1b9d8c7a0ad45e755833cbf221
GM_TT01.GM = ab14ed3392d848abd2a2e90a9d75d121
GM_TT02.GM = dd4f696e4be5987ce738257b08b50171
GM_TT03.GM = a1bfde23343df9e4063419bf29c166b8
GM_TT04.GM = 4e6943aa0c455203d76c79389054747d
GM_TT05.GM = cee281cb85a2e2343552d97640545a47
GM_TT06.GM = 26d1de5efa8675f94065784e9d539e49
GM_TT07.GM = 6f2691e17558f552ec4c565e4ab7139c
GM_TT08.GM = a42bf2cb3340a822f1a69646fc7a487d
GM_TT09.GM = eb35761a58a8df3c59ed8929cce13916
GM_TT10.GM = 42fecd686720a785d20a78590c466a82
GM_TT11.GM = 50ef1ef02e49d2112786dd45e69dc3ee
GM_TT12.GM = 4ce707a0e0e72419f0681dd9bd95271b
GM_TT13.GM = e765753be29d889ec818f38009103619
GM_TT14.GM = 270e2d63bd32b95a4d007ce15a6ce45f
GM_TT15.GM = 89e116a1c0c69f1845cc903a9bfbe460
GM_TT16.GM = f824e2371b3bedfe61aad4b9c62dd6be
GM_TT17.GM = 1b23eebb0796c1ab99cd97fa7082cf7b
GM_TT18.GM = 15650de3bad645d0e88c4f5c7a2df92a
GM_TT19.GM = 7aec079e15bd09588660b85545ac4dfc
GM_TT20.GM = 1509097889dee617aa1e9a1738a5a930
GM_TT21.GM = a8d0aaad02e1a762d8d54cf81da56bab
[names]
GM_TT00.GM = Tycoon DELUXE Theme
GM_TT01.GM = Snarl Up
GM_TT02.GM = Easy Driver
GM_TT03.GM = Little Red Diesel
GM_TT04.GM = City Groove
GM_TT05.GM = Aliens Ate My Railway
GM_TT06.GM = Stoke It
GM_TT07.GM = Don't Walk!
GM_TT08.GM = Sawyer's Tune
GM_TT09.GM = Fell Apart On Me
GM_TT10.GM = Can't Get There From Here
GM_TT11.GM = Hard Drivin'
GM_TT12.GM = Road Hog
GM_TT13.GM = Hold That Train!
GM_TT14.GM = Broomer's Oil Rag
GM_TT15.GM = Goss Groove
GM_TT16.GM = Small Town
GM_TT17.GM = Cruise Control
GM_TT18.GM = Stroll On
GM_TT19.GM = Funk Central
GM_TT20.GM = Jammit
GM_TT21.GM = Movin' On
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.

View File

@@ -1,62 +0,0 @@
; $Id$
;
; This represents the original sounds as on the Transport
; Tycoon Deluxe for Windows CD.
;
[metadata]
name = original_windows
shortname = TTDO
version = 0
description = Original Transport Tycoon Deluxe Windows edition sounds.
description.af_ZA = Oorspronklike Transport Tycoon Deluxe Windows uitgawe klanke.
description.ar_EG = النسخة الاصلية من ترانسبورت تايكون ديلوكس الصوتية نسخة وندوز
description.be_BY = Арыгінальны набор гукавога афармленьня з гульні Transport Tycoon Deluxe для Windows.
description.bg_BG = Оригинални звуци на Transport Tycoon Deluxe за Windows.
description.ca_ES = Sons originals de Transport Tycoon Deluxe per a Windows.
description.cs_CZ = Původní sada zvuků Transport Tycoon Deluxe (verze pro Windows).
description.cy_GB = Effeithiau sain gwreiddiol fersiwn Windows o Transport Tycoon Deluxe.
description.da_DK = Originallyd fra Transport Tycoon Deluxe Windows-version.
description.de_DE = Original Transport Tycoon Deluxe Windows Basissounds.
description.el_GR = Αρχικοί ήχοι από το Transport Tycoon Deluxe έκδοση Windows.
description.en_AU = Original Transport Tycoon Deluxe Windows edition sounds.
description.en_US = Original Transport Tycoon Deluxe Windows edition sounds.
description.es_ES = Sonidos originales de Transport Tycoon Deluxe versión Windows.
description.et_EE = Algse Transport Tycoon Deluxe Windowsi versiooni helid.
description.fi_FI = Alkuperäiset Transport Tycoon Deluxen Windows-version äänet.
description.fr_FR = Sons originaux de Transport Tycoon Deluxe (version Windows).
description.gd_GB = Fuaimean aig an deasachadh Windows tùsail aig Transport Tycoon Deluxe.
description.gl_ES = Sons da edición orixinal de Transport Tycoon Deluxe para Windows.
description.hr_HR = Originalni zvukovi za Transport Tycoon Deluxe Windows izdanje.
description.hu_HU = Az eredeti Transport Tycoon Deluxe Windows verziójának hangjai.
description.id_ID = Efek suara orisinil Transport Tycoon Deluxe versi Windows.
description.is_IS = Upprunalega hljóðið úr Transport Tycoon Deluxe Windows útgáfunni.
description.it_IT = Suoni originali di Transport Tycoon Deluxe, edizione Windows.
description.ja_JP = オリジナルウィンドーズ『トランスポートタイクンデラックス』版音楽
description.ko_KR = 오리지널 트랜스포트 타이쿤 디럭스 윈도우 에디션의 효과음입니다.
description.lt_LT = Originalūs Transport Tycoon Deluxe Windows leidimo garsai.
description.nb_NO = Originale lyder fra Transport Tycoon Deluxe for Windows.
description.nl_NL = Originele geluiden van de Transport Tycoon Deluxe Windows-versie.
description.nn_NO = Originale lydar frå Transport Tycoon Deluxe for Windows.
description.pl_PL = Oryginalna edycja dźwięków dla Transport Tycoon Deluxe Windows.
description.pt_PT = Sons originais da edição Windows de Transport Tycoon Deluxe.
description.ro_RO = Setul de sunete original al Transport Tycoon Deluxe pentru Windows.
description.ru_RU = Оригинальный набор звукового оформления из игры Transport Tycoon Deluxe для Windows.
description.sk_SK = Pôvodné zvuky Transport Tycoon Deluxe (Windows).
description.sl_SI = Originalni zvoki Transport Tycoon Deluxe različice oken(windows).
description.sr_RS = Originalni skup zvukova Transport Tycoon Deluxe Windows izdanja.
description.sv_SE = Originalljuden från Transport Tycoon Deluxe, Windows-utgåvan.
description.ta_IN = அசல் டிரான்ஸ்ஃபோர்ட் டைகூன் டீலக்ஸ் விண்டோஸ் பதிப்பு ஒலிகள்.
description.th_TH = เสียงต้นตำหรับของ Transport Tycoon Deluxe Windows edition
description.tr_TR = Orijinal Transport Tycoon Deluxe Windows sürümü sesleri.
description.vi_VN = Âm thanh gốc từ phiên bản Transport Tycoon Deluxe trên Windows
description.zh_CN = Transport Tycoon Deluxe Windows (运输大亨Windows豪华版)的原版音效包.
description.zh_TW = 原版 Transport Tycoon Deluxe Windows 版的音效。
[files]
samples = SAMPLE.CAT
[md5s]
SAMPLE.CAT = 9212e81e72badd4bbe1eaeae66458e10
[origin]
default = You can find it on your Transport Tycoon Deluxe CD-ROM.

View File

@@ -1,10 +0,0 @@
/* $Id$ */
/*
* 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 compatability in effect.");

View File

@@ -1,8 +0,0 @@
/* $Id$ */
/*
* 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,2 +0,0 @@
start_ai MyAI

View File

@@ -1,4 +0,0 @@
echo "Setting dedicated network server settings..."
# empty the server password
server_pw = "*"
server_name = "My example dedicated gameserver"

View File

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

View File

@@ -1,3 +0,0 @@
# set default server port, and have the dedicated server listen on all interfaces
server_ip = all
server_port = 3979

View File

@@ -1,2 +0,0 @@
# set the server port to the default value
server_port = 3979

166
bridge_gui.c Normal file
View File

@@ -0,0 +1,166 @@
#include "stdafx.h"
#include "ttd.h"
#include "table/strings.h"
#include "map.h"
#include "window.h"
#include "gui.h"
#include "viewport.h"
#include "gfx.h"
#include "command.h"
#include "sound.h"
static struct BridgeData {
int count;
TileIndex start_tile;
TileIndex end_tile;
byte type;
byte indexes[MAX_BRIDGES];
int32 costs[MAX_BRIDGES];
} _bridge;
extern const uint16 _bridge_type_price_mod[MAX_BRIDGES];
extern const PalSpriteID _bridge_sprites[MAX_BRIDGES];
extern const uint16 _bridge_speeds[MAX_BRIDGES];
extern const StringID _bridge_material[MAX_BRIDGES];
void CcBuildBridge(bool success, uint tile, uint32 p1, uint32 p2)
{
if (success) SndPlayTileFx(SND_27_BLACKSMITH_ANVIL, tile);
}
static void BuildBridge(Window *w, int i)
{
DeleteWindow(w);
DoCommandP(_bridge.end_tile, _bridge.start_tile, _bridge.indexes[i] | (_bridge.type << 8), CcBuildBridge,
CMD_BUILD_BRIDGE | CMD_AUTO | CMD_MSG(STR_5015_CAN_T_BUILD_BRIDGE_HERE));
}
static void BuildBridgeWndProc(Window *w, WindowEvent *e)
{
switch(e->event) {
case WE_PAINT: {
int i;
DrawWindowWidgets(w);
for(i=0; i < 4 && i + w->vscroll.pos < _bridge.count; i++) {
int ind = _bridge.indexes[i + w->vscroll.pos];
SetDParam(2, _bridge.costs[i + w->vscroll.pos]);
SetDParam(1, (_bridge_speeds[ind] >> 4) * 10);
SetDParam(0, _bridge_material[ind]);
DrawSprite(_bridge_sprites[ind], 3, 15 + i * 22);
DrawString(44, 15 + i*22 , STR_500D, 0);
}
} break;
case WE_KEYPRESS: {
uint i = e->keypress.keycode - '1';
if (i < 9 && i < (uint)_bridge.count) {
e->keypress.cont = false;
BuildBridge(w, i);
}
break;
}
case WE_CLICK:
if (e->click.widget == 2) {
uint ind = ((int)e->click.pt.y - 14) / 22;
if (ind < 4 && (ind += w->vscroll.pos) < (uint)_bridge.count)
BuildBridge(w, ind);
}
break;
}
}
static const Widget _build_bridge_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_100D_SELECT_RAIL_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WIDGETS_END},
};
static const WindowDesc _build_bridge_desc = {
-1, -1, 200, 102,
WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_build_bridge_widgets,
BuildBridgeWndProc
};
static const Widget _build_road_bridge_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 199, 0, 13, STR_1803_SELECT_ROAD_BRIDGE, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_MATRIX, RESIZE_NONE, 7, 0, 187, 14, 101, 0x401, STR_101F_BRIDGE_SELECTION_CLICK},
{ WWT_SCROLLBAR, RESIZE_NONE, 7, 188, 199, 14, 101, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
{ WIDGETS_END},
};
static const WindowDesc _build_road_bridge_desc = {
-1, -1, 200, 102,
WC_BUILD_BRIDGE,WC_BUILD_TOOLBAR,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_build_road_bridge_widgets,
BuildBridgeWndProc
};
void ShowBuildBridgeWindow(uint start, uint end, byte bridge_type)
{
int j = 0;
int32 ret;
uint16 errmsg;
DeleteWindowById(WC_BUILD_BRIDGE, 0);
_bridge.type = bridge_type;
_bridge.start_tile = start;
_bridge.end_tile = end;
errmsg = 0xFFFF;
// only query bridge building possibility once, result is the same for all bridges!
// returns CMD_ERROR on failure, and priCe on success
ret = DoCommandByTile(end, start, (bridge_type << 8), DC_AUTO | DC_QUERY_COST, CMD_BUILD_BRIDGE);
if (ret == CMD_ERROR) {
errmsg = _error_message;
}
// check which bridges can be built
else {
int bridge_len; // length of the middle parts of the bridge
int tot_bridge_len; // total length of bridge
// get absolute bridge length
bridge_len = GetBridgeLength(start, end);
tot_bridge_len = bridge_len + 2;
tot_bridge_len = CalcBridgeLenCostFactor(tot_bridge_len);
for (bridge_type = 0; bridge_type != MAX_BRIDGES; bridge_type++) { // loop for all bridgetypes
if (CheckBridge_Stuff(bridge_type, bridge_len)) {
// bridge is accepted, add to list
// add to terraforming & bulldozing costs the cost of the bridge itself (not computed with DC_QUERY_COST)
_bridge.costs[j] = ret + (((int64)tot_bridge_len * _price.build_bridge * _bridge_type_price_mod[bridge_type]) >> 8);
_bridge.indexes[j] = bridge_type;
j++;
}
}
}
_bridge.count = j;
if (j != 0) {
Window *w = AllocateWindowDesc((_bridge.type & 0x80) ? &_build_road_bridge_desc : &_build_bridge_desc);
w->vscroll.cap = 4;
w->vscroll.count = (byte)j;
} else {
ShowErrorMessage(errmsg, STR_5015_CAN_T_BUILD_BRIDGE_HERE, TileX(end) * 16, TileY(end) * 16);
}
}

74
callback_table.c Normal file
View File

@@ -0,0 +1,74 @@
#include "stdafx.h"
#include "ttd.h"
#include "functions.h"
// If you add a callback for DoCommandP, also add the callback in here
// see below for the full list!
// If you don't do it, it won't work across the network!!
/* aircraft_gui.c */
CommandCallback CcBuildAircraft;
/* airport_gui.c */
CommandCallback CcBuildAirport;
/* bridge_gui.c */
CommandCallback CcBuildBridge;
/* dock_gui.c */
CommandCallback CcBuildDocks;
CommandCallback CcBuildCanal;
/* main_gui.c */
CommandCallback CcPlaySound10;
CommandCallback CcPlaceSign;
CommandCallback CcTerraform;
//CommandCallback CcDemolish;
CommandCallback CcBuildTown;
/* rail_gui.c */
CommandCallback CcPlaySound1E;
CommandCallback CcRailDepot;
CommandCallback CcStation;
CommandCallback CcBuildRailTunnel;
/* road_gui.c */
CommandCallback CcPlaySound1D;
CommandCallback CcBuildRoadTunnel;
CommandCallback CcRoadDepot;
/* roadveh_gui.c */
CommandCallback CcBuildRoadVeh;
/* ship_gui.c */
CommandCallback CcBuildShip;
/* train_gui.c */
CommandCallback CcBuildWagon;
CommandCallback CcBuildLoco;
CommandCallback *_callback_table[] = {
/* 0x00 */ NULL,
/* 0x01 */ CcBuildAircraft,
/* 0x02 */ CcBuildAirport,
/* 0x03 */ CcBuildBridge,
/* 0x04 */ CcBuildCanal,
/* 0x05 */ CcBuildDocks,
/* 0x06 */ CcBuildLoco,
/* 0x07 */ CcBuildRoadVeh,
/* 0x08 */ CcBuildShip,
/* 0x09 */ CcBuildTown,
/* 0x0A */ CcBuildRoadTunnel,
/* 0x0B */ CcBuildRailTunnel,
/* 0x0C */ CcBuildWagon,
/* 0x0D */ CcRoadDepot,
/* 0x0E */ CcRailDepot,
/* 0x0F */ CcPlaceSign,
/* 0x10 */ CcPlaySound10,
/* 0x11 */ CcPlaySound1D,
/* 0x12 */ CcPlaySound1E,
/* 0x13 */ CcStation,
/* 0x14 */ CcTerraform
};
const int _callback_table_count = lengthof(_callback_table);

7
callback_table.h Normal file
View File

@@ -0,0 +1,7 @@
#ifndef CALLBACK_TABLE_H
#define CALLBACK_TABLE_H
extern CommandCallback *_callback_table[];
extern const int _callback_table_count;
#endif

File diff suppressed because it is too large Load Diff

864
clear_cmd.c Normal file
View File

@@ -0,0 +1,864 @@
#include "stdafx.h"
#include "ttd.h"
#include "table/strings.h"
#include "map.h"
#include "tile.h"
#include "viewport.h"
#include "command.h"
typedef struct TerraformerHeightMod {
TileIndex tile;
byte height;
} TerraformerHeightMod;
typedef struct TerraformerState {
int height[4];
uint32 flags;
int direction;
int modheight_count;
int tile_table_count;
int32 cost;
TileIndex *tile_table;
TerraformerHeightMod *modheight;
} TerraformerState;
static int TerraformAllowTileProcess(TerraformerState *ts, TileIndex tile)
{
TileIndex *t;
int count;
if (TileX(tile) == MapMaxX() || TileY(tile) == MapMaxY())
return -1;
t = ts->tile_table;
for(count = ts->tile_table_count; count != 0; count--,t++) {
if (*t == tile)
return 0;
}
return 1;
}
static int TerraformGetHeightOfTile(TerraformerState *ts, TileIndex tile)
{
TerraformerHeightMod *mod = ts->modheight;
int count;
for(count = ts->modheight_count; count != 0; count--, mod++) {
if (mod->tile == tile)
return mod->height;
}
return TileHeight(tile);
}
static void TerraformAddDirtyTile(TerraformerState *ts, TileIndex tile)
{
int count;
TileIndex *t;
count = ts->tile_table_count;
if (count >= 625)
return;
for(t = ts->tile_table; count != 0; count--,t++) {
if (*t == tile)
return;
}
ts->tile_table[ts->tile_table_count++] = tile;
}
static void TerraformAddDirtyTileAround(TerraformerState *ts, TileIndex tile)
{
TerraformAddDirtyTile(ts, tile+TILE_XY(0,-1));
TerraformAddDirtyTile(ts, tile+TILE_XY(-1,-1));
TerraformAddDirtyTile(ts, tile+TILE_XY(-1,0));
TerraformAddDirtyTile(ts, tile);
}
static int TerraformProc(TerraformerState *ts, uint tile, int mode)
{
int r;
int32 ret;
assert(tile < MapSize());
if ((r=TerraformAllowTileProcess(ts, tile)) <= 0)
return r;
if (IsTileType(tile, MP_RAILWAY)) {
static const byte _railway_modes[4] = {8, 0x10, 4, 0x20};
static const byte _railway_dangslopes[4] = {0xd, 0xe, 7, 0xb};
static const byte _railway_dangslopes2[4] = {0x2, 0x1, 0x8, 0x4};
// Nothing could be built at the steep slope - this avoids a bug
// when you have a single diagonal track in one corner on a
// basement and then you raise/lower the other corner.
int tileh = GetTileSlope(tile, NULL) & 0xF;
if (tileh == _railway_dangslopes[mode] ||
tileh == _railway_dangslopes2[mode]) {
_terraform_err_tile = tile;
_error_message = STR_1008_MUST_REMOVE_RAILROAD_TRACK;
return -1;
}
// If we have a single diagonal track there, the other side of
// tile can be terraformed.
if ((_map5[tile]&~0x40) == _railway_modes[mode])
return 0;
}
ret = DoCommandByTile(tile, 0,0, ts->flags & ~DC_EXEC, CMD_LANDSCAPE_CLEAR);
if (ret == CMD_ERROR) {
_terraform_err_tile = tile;
return -1;
}
ts->cost += ret;
if (ts->tile_table_count >= 625)
return -1;
ts->tile_table[ts->tile_table_count++] = tile;
return 0;
}
static bool TerraformTileHeight(TerraformerState *ts, uint tile, int height)
{
int nh;
TerraformerHeightMod *mod;
int count;
assert(tile < MapSize());
if (height < 0) {
_error_message = STR_1003_ALREADY_AT_SEA_LEVEL;
return false;
}
_error_message = STR_1004_TOO_HIGH;
if (height > 0xF)
return false;
nh = TerraformGetHeightOfTile(ts, tile);
if (nh < 0 || height == nh)
return false;
if (TerraformProc(ts, tile, 0)<0)
return false;
if (TerraformProc(ts, tile + TILE_XY(0,-1), 1)<0)
return false;
if (TerraformProc(ts, tile + TILE_XY(-1,-1), 2)<0)
return false;
if (TerraformProc(ts, tile + TILE_XY(-1,0), 3)<0)
return false;
mod = ts->modheight;
count = ts->modheight_count;
for(;;) {
if (count == 0) {
if (ts->modheight_count >= 576)
return false;
ts->modheight_count++;
break;
}
if (mod->tile == (TileIndex)tile)
break;
mod++;
count--;
}
mod->tile = (TileIndex)tile;
mod->height = (byte)height;
ts->cost += _price.terraform;
{
int direction = ts->direction, r;
const TileIndexDiffC *ttm;
static const TileIndexDiffC _terraform_tilepos[] = {
{ 1, 0},
{-2, 0},
{ 1, 1},
{ 0, -2}
};
for(ttm = _terraform_tilepos; ttm != endof(_terraform_tilepos); ttm++) {
tile += ToTileIndexDiff(*ttm);
r = TerraformGetHeightOfTile(ts, tile);
if (r != height && r-direction != height && r+direction != height) {
if (!TerraformTileHeight(ts, tile, r+direction))
return false;
}
}
}
return true;
}
/** Terraform land
* @param x,y coordinates to terraform
* @param p1 corners to terraform.
* @param p2 direction; eg up or down
*/
int32 CmdTerraformLand(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
TerraformerState ts;
TileIndex tile;
int direction;
TerraformerHeightMod modheight_data[576];
TileIndex tile_table_data[625];
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
_error_message = INVALID_STRING_ID;
_terraform_err_tile = 0;
ts.direction = direction = p2 ? 1 : -1;
ts.flags = flags;
ts.modheight_count = ts.tile_table_count = 0;
ts.cost = 0;
ts.modheight = modheight_data;
ts.tile_table = tile_table_data;
tile = TILE_FROM_XY(x,y);
if (p1 & 1) {
if (!TerraformTileHeight(&ts, tile+TILE_XY(1,0),
TileHeight(tile + TILE_XY(1, 0)) + direction))
return CMD_ERROR;
}
if (p1 & 2) {
if (!TerraformTileHeight(&ts, tile+TILE_XY(1,1),
TileHeight(tile + TILE_XY(1, 1)) + direction))
return CMD_ERROR;
}
if (p1 & 4) {
if (!TerraformTileHeight(&ts, tile+TILE_XY(0,1),
TileHeight(tile + TILE_XY(0, 1)) + direction))
return CMD_ERROR;
}
if (p1 & 8) {
if (!TerraformTileHeight(&ts, tile+TILE_XY(0,0),
TileHeight(tile + TILE_XY(0, 0)) + direction))
return CMD_ERROR;
}
if (direction == -1) {
/* Check if tunnel would take damage */
int count;
TileIndex *ti = ts.tile_table;
for (count = ts.tile_table_count; count != 0; count--, ti++) {
uint z, t;
uint tile = *ti;
z = TerraformGetHeightOfTile(&ts, tile + TILE_XY(0,0));
t = TerraformGetHeightOfTile(&ts, tile + TILE_XY(1,0));
if (t <= z) z = t;
t = TerraformGetHeightOfTile(&ts, tile + TILE_XY(1,1));
if (t <= z) z = t;
t = TerraformGetHeightOfTile(&ts, tile + TILE_XY(0,1));
if (t <= z) z = t;
if (!CheckTunnelInWay(tile, z*8))
return_cmd_error(STR_1002_EXCAVATION_WOULD_DAMAGE);
}
}
if (flags & DC_EXEC) {
/* Clear the landscape at the tiles */
{
int count;
TileIndex *ti = ts.tile_table;
for (count = ts.tile_table_count; count != 0; count--, ti++) {
DoCommandByTile(*ti, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
}
/* change the height */
{
int count;
TerraformerHeightMod *mod;
uint til;
mod = ts.modheight;
for (count = ts.modheight_count; count != 0; count--, mod++) {
til = mod->tile;
SetTileHeight(til, mod->height);
TerraformAddDirtyTileAround(&ts, til);
}
}
/* finally mark the dirty tiles dirty */
{
int count;
TileIndex *ti = ts.tile_table;
for (count = ts.tile_table_count; count != 0; count--, ti++) {
MarkTileDirtyByTile(*ti);
}
}
}
return ts.cost;
}
/** Levels a selected (rectangle) area of land
* @param x,y end tile of area-drag
* @param p1 start tile of area drag
* @param p2 unused
*/
int32 CmdLevelLand(int ex, int ey, uint32 flags, uint32 p1, uint32 p2)
{
int size_x, size_y;
int sx, sy;
uint h, curh;
TileIndex tile;
int32 ret, cost, money;
if (p1 > MapSize()) return CMD_ERROR;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
// remember level height
h = TileHeight(p1);
ex >>= 4; ey >>= 4;
// make sure sx,sy are smaller than ex,ey
sx = TileX(p1);
sy = TileY(p1);
if (ex < sx) intswap(ex, sx);
if (ey < sy) intswap(ey, sy);
tile = TILE_XY(sx,sy);
size_x = ex-sx+1;
size_y = ey-sy+1;
money = GetAvailableMoneyForCommand();
cost = 0;
BEGIN_TILE_LOOP(tile2, size_x, size_y, tile) {
curh = TileHeight(tile2);
while (curh != h) {
ret = DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags & ~DC_EXEC, CMD_TERRAFORM_LAND);
if (CmdFailed(ret)) break;
cost += ret;
if (flags & DC_EXEC) {
if ((money -= ret) < 0) {
_additional_cash_required = ret;
return cost - ret;
}
DoCommandByTile(tile2, 8, (curh > h) ? 0 : 1, flags, CMD_TERRAFORM_LAND);
}
curh += (curh > h) ? -1 : 1;
}
} END_TILE_LOOP(tile2, size_x, size_y, tile)
return (cost == 0) ? CMD_ERROR : cost;
}
/** Purchase a land area. Actually you only purchase one tile, so
* the name is a bit confusing ;p
* @param x,y the tile the player is purchasing
* @param p1 unused
* @param p2 unused
*/
int32 CmdPurchaseLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
TileIndex tile;
int32 cost;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
tile = TILE_FROM_XY(x,y);
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
if (IsTileType(tile, MP_UNMOVABLE) && _map5[tile] == 3 && _map_owner[tile] == _current_player)
return_cmd_error(STR_5807_YOU_ALREADY_OWN_IT);
cost = DoCommandByTile(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
if (CmdFailed(cost)) return CMD_ERROR;
if (flags & DC_EXEC) {
ModifyTile(tile,
MP_SETTYPE(MP_UNMOVABLE) | MP_MAPOWNER_CURRENT | MP_MAP5,
3 /* map5 */
);
}
return cost + _price.purchase_land * 10;
}
static int32 ClearTile_Clear(uint tile, byte flags)
{
static const int32 * _clear_price_table[] = {
NULL,
&_price.clear_1, &_price.clear_1,&_price.clear_1,
&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,
&_price.clear_2,&_price.clear_2,&_price.clear_2,&_price.clear_2,
&_price.clear_3,&_price.clear_3,&_price.clear_3,&_price.clear_3,
&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,
&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,&_price.purchase_land,
&_price.clear_2,&_price.clear_2,&_price.clear_2,&_price.clear_2,
};
const int32 *price = _clear_price_table[_map5[tile] & 0x1F];
if (flags & DC_EXEC)
DoClearSquare(tile);
if (price == NULL)
return 0;
return *price;
}
/** Sell a land area. Actually you only sell one tile, so
* the name is a bit confusing ;p
* @param x,y the tile the player is selling
* @param p1 unused
* @param p2 unused
*/
int32 CmdSellLandArea(int x, int y, uint32 flags, uint32 p1, uint32 p2)
{
TileIndex tile;
SET_EXPENSES_TYPE(EXPENSES_CONSTRUCTION);
tile = TILE_FROM_XY(x,y);
if (!CheckTileOwnership(tile) && _current_player != OWNER_WATER)
return CMD_ERROR;
if (!EnsureNoVehicle(tile)) return CMD_ERROR;
if (flags & DC_EXEC)
DoClearSquare(tile);
return - _price.purchase_land * 2;
}
#include "table/clear_land.h"
void DrawClearLandTile(TileInfo *ti, byte set)
{
DrawGroundSprite(0xF54 + _tileh_to_sprite[ti->tileh] + set * 19);
}
void DrawHillyLandTile(TileInfo *ti)
{
if (ti->tileh != 0) {
DrawGroundSprite(0xFA0 + _tileh_to_sprite[ti->tileh]);
} else {
DrawGroundSprite(_landscape_clear_sprites[((ti->x^ti->y) >> 4) & 0x7]);
}
}
void DrawClearLandFence(TileInfo *ti, byte img)
{
byte z = ti->z;
if (ti->tileh & 2) {
z += 8;
if (ti->tileh == 0x17)
z += 8;
}
if (img & 0x38) {
DrawGroundSpriteAt(_clear_land_fence_sprites_1[((img >> 3) & 7) - 1] + _fence_mod_by_tileh[ti->tileh], ti->x, ti->y, z);
}
if (img & 0x7) {
DrawGroundSpriteAt(_clear_land_fence_sprites_1[(img & 7) - 1] + _fence_mod_by_tileh_2[ti->tileh], ti->x, ti->y, z);
}
}
static void DrawTile_Clear(TileInfo *ti)
{
switch((ti->map5 & (7<<2)) >> 2) {
case 0:
DrawClearLandTile(ti, (ti->map5 & 3));
break;
case 1:
DrawHillyLandTile(ti);
break;
case 2:
DrawGroundSprite(0xFB7 + _tileh_to_sprite[ti->tileh]);
break;
case 3:
DrawGroundSprite( _clear_land_sprites_1[_map3_lo[ti->tile]&0xF] + _tileh_to_sprite[ti->tileh]);
break;
case 4:
DrawGroundSprite( _clear_land_sprites_2[ti->map5&3] + _tileh_to_sprite[ti->tileh]);
break;
case 5:
DrawGroundSprite( _clear_land_sprites_3[ti->map5&3] + _tileh_to_sprite[ti->tileh]);
break;
}
DrawClearLandFence(ti, _map3_hi[ti->tile] >> 2);
}
static uint GetSlopeZ_Clear(TileInfo *ti)
{
return GetPartialZ(ti->x & 0xF, ti->y & 0xF, ti->tileh) + ti->z;
}
static uint GetSlopeTileh_Clear(TileInfo *ti)
{
return ti->tileh;
}
static void GetAcceptedCargo_Clear(uint tile, AcceptedCargo ac)
{
/* unused */
}
static void AnimateTile_Clear(uint tile)
{
/* unused */
}
void TileLoopClearHelper(TileIndex tile)
{
byte img_1;
byte img_2;
static const byte img_by_map5[] = { 0, 0, 0, 2, 1, 1, 0, 0 };
TileIndex dirty = INVALID_TILE;
switch (GetTileType(tile)) {
case MP_CLEAR:
img_1 = img_by_map5[(_map5[tile] & 0x1C) >> 2];
break;
case MP_TREES:
if ((_map2[tile] & 0x30) == 0x20)
img_1 = 1;
else
img_1 = 0;
break;
default:
img_1 = 0;
break;
}
switch (GetTileType(TILE_ADDXY(tile, 1, 0))) {
case MP_CLEAR:
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 1, 0)] & 0x1C) >> 2];
break;
case MP_TREES:
if ((_map2[TILE_ADDXY(tile, 1, 0)] & 0x30) == 0x20)
img_2 = 1;
else
img_2 = 0;
break;
default:
img_2 = 0;
break;
}
if ((_map3_hi[tile] & 0xE0) == 0) {
if ((img_1 & 2) != (img_2 & 2)) {
_map3_hi[tile] |= 3 << 5;
dirty = tile;
}
} else {
if (img_1 == 1 && img_2 == 1) {
_map3_hi[tile] &= ~(3 << 5);
dirty = tile;
}
}
switch (GetTileType(TILE_ADDXY(tile, 0, 1))) {
case MP_CLEAR:
img_2 = img_by_map5[(_map5[TILE_ADDXY(tile, 0, 1)] & 0x1C) >> 2];
break;
case MP_TREES:
if ((_map2[TILE_ADDXY(tile, 0, 1)] & 0x30) == 0x20)
img_2 = 1;
else
img_2 = 0;
break;
default:
img_2 = 0;
break;
}
if ((_map3_hi[tile] & 0x1C) == 0) {
if ((img_1 & 2) != (img_2 & 2)) {
_map3_hi[tile] |= 3 << 2;
dirty = tile;
}
} else {
if (img_1 == 1 && img_2 == 1) {
_map3_hi[tile] &= ~(3 << 2);
dirty = tile;
}
}
if (dirty != INVALID_TILE)
MarkTileDirtyByTile(dirty);
}
/* convert into snowy tiles */
static void TileLoopClearAlps(uint tile)
{
int k;
byte m5,tmp;
/* distance from snow line, in steps of 8 */
k = GetTileZ(tile) - _opt.snow_line;
m5 = _map5[tile] & 0x1C;
tmp = _map5[tile] & 3;
if (k < -8) {
/* snow_m2_down */
if (m5 != 0x10)
return;
if (tmp == 0)
m5 = 3;
} else if (k == -8) {
/* snow_m1 */
if (m5 != 0x10) {
m5 = 0x10;
} else if (tmp != 0) {
m5 = (tmp - 1) + 0x10;
} else
return;
} else if (k < 8) {
/* snow_0 */
if (m5 != 0x10) {
m5 = 0x10;
} else if (tmp != 1) {
m5 = 1;
if (tmp != 0)
m5 = tmp - 1;
m5 += 0x10;
} else
return;
} else if (k == 8) {
/* snow_p1 */
if (m5 != 0x10) {
m5 = 0x10;
} else if (tmp != 2) {
m5 = 2;
if (tmp <= 2)
m5 = tmp + 1;
m5 += 0x10;
} else
return;
} else {
/* snow_p2_up */
if (m5 != 0x10) {
m5 = 0x10;
} else if (tmp != 3) {
m5 = tmp + 1 + 0x10;
} else
return;
}
_map5[tile] = m5;
MarkTileDirtyByTile(tile);
}
static void TileLoopClearDesert(uint tile)
{
if ( (_map5[tile] & 0x1C) == 0x14)
return;
if (GetMapExtraBits(tile) == 1) {
_map5[tile] = 0x17;
} else {
if (GetMapExtraBits(tile+TILE_XY(1,0)) != 1 &&
GetMapExtraBits(tile+TILE_XY(-1,0)) != 1 &&
GetMapExtraBits(tile+TILE_XY(0,1)) != 1 &&
GetMapExtraBits(tile+TILE_XY(0,-1)) != 1)
return;
_map5[tile] = 0x15;
}
MarkTileDirtyByTile(tile);
}
static void TileLoop_Clear(uint tile)
{
byte m5,m3;
TileLoopClearHelper(tile);
if (_opt.landscape == LT_DESERT) {
TileLoopClearDesert(tile);
} else if (_opt.landscape == LT_HILLY) {
TileLoopClearAlps(tile);
}
m5 = _map5[tile];
if ( (m5 & 0x1C) == 0x10 || (m5 & 0x1C) == 0x14)
return;
if ( (m5 & 0x1C) != 0xC) {
if ( (m5 & 3) == 3)
return;
if (_game_mode != GM_EDITOR) {
m5 += 0x20;
if (m5 >= 0x20) {
// Didn't overflow
_map5[tile] = m5;
return;
}
/* did overflow, so continue */
} else {
m5 = ((byte)Random() > 21) ? (2) : (6);
}
m5++;
} else if (_game_mode != GM_EDITOR) {
/* handle farm field */
m5 += 0x20;
if (m5 >= 0x20) {
// Didn't overflow
_map5[tile] = m5;
return;
}
/* overflowed */
m3 = _map3_lo[tile] + 1;
assert( (m3 & 0xF) != 0);
if ( (m3 & 0xF) >= 9) /* NOTE: will not work properly if m3&0xF == 0xF */
m3 &= ~0xF;
_map3_lo[tile] = m3;
}
_map5[tile] = m5;
MarkTileDirtyByTile(tile);
}
void GenerateClearTile(void)
{
int i,j;
uint tile,tile_new;
uint32 r;
/* add hills */
i = ScaleByMapSize((Random() & 0x3FF) + 0x400);
do {
tile = TILE_MASK(Random());
if (IsTileType(tile, MP_CLEAR))
_map5[tile] = (byte)((_map5[tile] & ~(3<<2)) | (1<<2));
} while (--i);
/* add grey squares */
i = ScaleByMapSize((Random() & 0x7F) + 0x80);
do {
r = Random();
tile = TILE_MASK(r);
if (IsTileType(tile, MP_CLEAR)) {
j = ((r >> 16) & 0xF) + 5;
for(;;) {
_map5[tile] = (byte)((_map5[tile] & ~(3<<2)) | (2<<2));
do {
if (--j == 0) goto get_out;
tile_new = tile + TileOffsByDir(Random() & 3);
} while (!IsTileType(tile_new, MP_CLEAR));
tile = tile_new;
}
get_out:;
}
} while (--i);
}
static void ClickTile_Clear(uint tile)
{
/* not used */
}
static uint32 GetTileTrackStatus_Clear(uint tile, TransportType mode)
{
return 0;
}
static const StringID _clear_land_str[4+8-1] = {
STR_080B_ROUGH_LAND,
STR_080A_ROCKS,
STR_080E_FIELDS,
STR_080F_SNOW_COVERED_LAND,
STR_0810_DESERT,
0,
0,
STR_080C_BARE_LAND,
STR_080D_GRASS,
STR_080D_GRASS,
STR_080D_GRASS,
};
static void GetTileDesc_Clear(uint tile, TileDesc *td)
{
int i = (_map5[tile]>>2) & 7;
if (i == 0)
i = (_map5[tile] & 3) + 8;
td->str = _clear_land_str[i - 1];
td->owner = _map_owner[tile];
}
static void ChangeTileOwner_Clear(uint tile, byte old_player, byte new_player)
{
return;
}
void InitializeClearLand(void)
{
_opt.snow_line = _patches.snow_line_height * 8;
}
const TileTypeProcs _tile_type_clear_procs = {
DrawTile_Clear, /* draw_tile_proc */
GetSlopeZ_Clear, /* get_slope_z_proc */
ClearTile_Clear, /* clear_tile_proc */
GetAcceptedCargo_Clear, /* get_accepted_cargo_proc */
GetTileDesc_Clear, /* get_tile_desc_proc */
GetTileTrackStatus_Clear, /* get_tile_track_status_proc */
ClickTile_Clear, /* click_tile_proc */
AnimateTile_Clear, /* animate_tile_proc */
TileLoop_Clear, /* tile_loop_clear */
ChangeTileOwner_Clear, /* change_tile_owner_clear */
NULL, /* get_produced_cargo_proc */
NULL, /* vehicle_enter_tile_proc */
NULL, /* vehicle_leave_tile_proc */
GetSlopeTileh_Clear, /* get_slope_tileh_proc */
};

536
command.c Normal file
View File

@@ -0,0 +1,536 @@
#include "stdafx.h"
#include "ttd.h"
#include "table/strings.h"
#include "map.h"
#include "gui.h"
#include "command.h"
#include "player.h"
#include "network.h"
const char* _cmd_text = NULL;
#define DEF_COMMAND(yyyy) int32 yyyy(int x, int y, uint32 flags, uint32 p1, uint32 p2)
DEF_COMMAND(CmdBuildRailroadTrack);
DEF_COMMAND(CmdRemoveRailroadTrack);
DEF_COMMAND(CmdBuildSingleRail);
DEF_COMMAND(CmdRemoveSingleRail);
DEF_COMMAND(CmdLandscapeClear);
DEF_COMMAND(CmdBuildBridge);
DEF_COMMAND(CmdBuildRailroadStation);
DEF_COMMAND(CmdRemoveFromRailroadStation);
DEF_COMMAND(CmdConvertRail);
DEF_COMMAND(CmdBuildSingleSignal);
DEF_COMMAND(CmdRemoveSingleSignal);
DEF_COMMAND(CmdTerraformLand);
DEF_COMMAND(CmdPurchaseLandArea);
DEF_COMMAND(CmdSellLandArea);
DEF_COMMAND(CmdBuildTunnel);
DEF_COMMAND(CmdBuildTrainDepot);
DEF_COMMAND(CmdBuildTrainWaypoint);
DEF_COMMAND(CmdRenameWaypoint);
DEF_COMMAND(CmdRemoveTrainWaypoint);
DEF_COMMAND(CmdBuildRoadStop);
DEF_COMMAND(CmdBuildLongRoad);
DEF_COMMAND(CmdRemoveLongRoad);
DEF_COMMAND(CmdBuildRoad);
DEF_COMMAND(CmdRemoveRoad);
DEF_COMMAND(CmdBuildRoadDepot);
DEF_COMMAND(CmdBuildAirport);
DEF_COMMAND(CmdBuildDock);
DEF_COMMAND(CmdBuildShipDepot);
DEF_COMMAND(CmdBuildBuoy);
DEF_COMMAND(CmdPlantTree);
DEF_COMMAND(CmdBuildRailVehicle);
DEF_COMMAND(CmdMoveRailVehicle);
DEF_COMMAND(CmdStartStopTrain);
DEF_COMMAND(CmdSellRailWagon);
DEF_COMMAND(CmdSendTrainToDepot);
DEF_COMMAND(CmdForceTrainProceed);
DEF_COMMAND(CmdReverseTrainDirection);
DEF_COMMAND(CmdModifyOrder);
DEF_COMMAND(CmdSkipOrder);
DEF_COMMAND(CmdDeleteOrder);
DEF_COMMAND(CmdInsertOrder);
DEF_COMMAND(CmdChangeTrainServiceInt);
DEF_COMMAND(CmdRestoreOrderIndex);
DEF_COMMAND(CmdBuildIndustry);
DEF_COMMAND(CmdBuildCompanyHQ);
DEF_COMMAND(CmdSetPlayerFace);
DEF_COMMAND(CmdSetPlayerColor);
DEF_COMMAND(CmdIncreaseLoan);
DEF_COMMAND(CmdDecreaseLoan);
DEF_COMMAND(CmdWantEnginePreview);
DEF_COMMAND(CmdNameVehicle);
DEF_COMMAND(CmdRenameEngine);
DEF_COMMAND(CmdChangeCompanyName);
DEF_COMMAND(CmdChangePresidentName);
DEF_COMMAND(CmdRenameStation);
DEF_COMMAND(CmdSellAircraft);
DEF_COMMAND(CmdStartStopAircraft);
DEF_COMMAND(CmdBuildAircraft);
DEF_COMMAND(CmdSendAircraftToHangar);
DEF_COMMAND(CmdChangeAircraftServiceInt);
DEF_COMMAND(CmdRefitAircraft);
DEF_COMMAND(CmdPlaceSign);
DEF_COMMAND(CmdRenameSign);
DEF_COMMAND(CmdBuildRoadVeh);
DEF_COMMAND(CmdStartStopRoadVeh);
DEF_COMMAND(CmdSellRoadVeh);
DEF_COMMAND(CmdSendRoadVehToDepot);
DEF_COMMAND(CmdTurnRoadVeh);
DEF_COMMAND(CmdChangeRoadVehServiceInt);
DEF_COMMAND(CmdPause);
DEF_COMMAND(CmdBuyShareInCompany);
DEF_COMMAND(CmdSellShareInCompany);
DEF_COMMAND(CmdBuyCompany);
DEF_COMMAND(CmdBuildTown);
DEF_COMMAND(CmdRenameTown);
DEF_COMMAND(CmdDoTownAction);
DEF_COMMAND(CmdSetRoadDriveSide);
DEF_COMMAND(CmdChangeDifficultyLevel);
DEF_COMMAND(CmdChangePatchSetting);
DEF_COMMAND(CmdStartStopShip);
DEF_COMMAND(CmdSellShip);
DEF_COMMAND(CmdBuildShip);
DEF_COMMAND(CmdSendShipToDepot);
DEF_COMMAND(CmdChangeShipServiceInt);
DEF_COMMAND(CmdRefitShip);
DEF_COMMAND(CmdCloneOrder);
DEF_COMMAND(CmdClearArea);
DEF_COMMAND(CmdGiveMoney);
DEF_COMMAND(CmdMoneyCheat);
DEF_COMMAND(CmdBuildCanal);
DEF_COMMAND(CmdBuildLock);
DEF_COMMAND(CmdPlayerCtrl);
DEF_COMMAND(CmdLevelLand);
DEF_COMMAND(CmdRefitRailVehicle);
DEF_COMMAND(CmdBuildSignalTrack);
DEF_COMMAND(CmdRemoveSignalTrack);
DEF_COMMAND(CmdReplaceVehicle);
/* The master command table */
static const Command _command_proc_table[] = {
{CmdBuildRailroadTrack, 0}, /* 0 */
{CmdRemoveRailroadTrack, 0}, /* 1 */
{CmdBuildSingleRail, 0}, /* 2 */
{CmdRemoveSingleRail, 0}, /* 3 */
{CmdLandscapeClear, 0}, /* 4 */
{CmdBuildBridge, 0}, /* 5 */
{CmdBuildRailroadStation, 0}, /* 6 */
{CmdBuildTrainDepot, 0}, /* 7 */
{CmdBuildSingleSignal, 0}, /* 8 */
{CmdRemoveSingleSignal, 0}, /* 9 */
{CmdTerraformLand, 0}, /* 10 */
{CmdPurchaseLandArea, 0}, /* 11 */
{CmdSellLandArea, 0}, /* 12 */
{CmdBuildTunnel, 0}, /* 13 */
{CmdRemoveFromRailroadStation, 0}, /* 14 */
{CmdConvertRail, 0}, /* 15 */
{CmdBuildTrainWaypoint, 0}, /* 16 */
{CmdRenameWaypoint, 0}, /* 17 */
{CmdRemoveTrainWaypoint, 0}, /* 18 */
{NULL, 0}, /* 19 */
{NULL, 0}, /* 20 */
{CmdBuildRoadStop, 0}, /* 21 */
{NULL, 0}, /* 22 */
{CmdBuildLongRoad, 0}, /* 23 */
{CmdRemoveLongRoad, 0}, /* 24 */
{CmdBuildRoad, 0}, /* 25 */
{CmdRemoveRoad, 0}, /* 26 */
{CmdBuildRoadDepot, 0}, /* 27 */
{NULL, 0}, /* 28 */
{CmdBuildAirport, 0}, /* 29 */
{CmdBuildDock, 0}, /* 30 */
{CmdBuildShipDepot, 0}, /* 31 */
{CmdBuildBuoy, 0}, /* 32 */
{CmdPlantTree, 0}, /* 33 */
{CmdBuildRailVehicle, 0}, /* 34 */
{CmdMoveRailVehicle, 0}, /* 35 */
{CmdStartStopTrain, 0}, /* 36 */
{NULL, 0}, /* 37 */
{CmdSellRailWagon, 0}, /* 38 */
{CmdSendTrainToDepot, 0}, /* 39 */
{CmdForceTrainProceed, 0}, /* 40 */
{CmdReverseTrainDirection, 0}, /* 41 */
{CmdModifyOrder, 0}, /* 42 */
{CmdSkipOrder, 0}, /* 43 */
{CmdDeleteOrder, 0}, /* 44 */
{CmdInsertOrder, 0}, /* 45 */
{CmdChangeTrainServiceInt, 0}, /* 46 */
{CmdBuildIndustry, 0}, /* 47 */
{CmdBuildCompanyHQ, 0}, /* 48 */
{CmdSetPlayerFace, 0}, /* 49 */
{CmdSetPlayerColor, 0}, /* 50 */
{CmdIncreaseLoan, 0}, /* 51 */
{CmdDecreaseLoan, 0}, /* 52 */
{CmdWantEnginePreview, 0}, /* 53 */
{CmdNameVehicle, 0}, /* 54 */
{CmdRenameEngine, 0}, /* 55 */
{CmdChangeCompanyName, 0}, /* 56 */
{CmdChangePresidentName, 0}, /* 57 */
{CmdRenameStation, 0}, /* 58 */
{CmdSellAircraft, 0}, /* 59 */
{CmdStartStopAircraft, 0}, /* 60 */
{CmdBuildAircraft, 0}, /* 61 */
{CmdSendAircraftToHangar, 0}, /* 62 */
{CmdChangeAircraftServiceInt, 0}, /* 63 */
{CmdRefitAircraft, 0}, /* 64 */
{CmdPlaceSign, 0}, /* 65 */
{CmdRenameSign, 0}, /* 66 */
{CmdBuildRoadVeh, 0}, /* 67 */
{CmdStartStopRoadVeh, 0}, /* 68 */
{CmdSellRoadVeh, 0}, /* 69 */
{CmdSendRoadVehToDepot, 0}, /* 70 */
{CmdTurnRoadVeh, 0}, /* 71 */
{CmdChangeRoadVehServiceInt, 0}, /* 72 */
{CmdPause, CMD_SERVER}, /* 73 */
{CmdBuyShareInCompany, 0}, /* 74 */
{CmdSellShareInCompany, 0}, /* 75 */
{CmdBuyCompany, 0}, /* 76 */
{CmdBuildTown, CMD_OFFLINE}, /* 77 */
{NULL, 0}, /* 78 */
{NULL, 0}, /* 79 */
{CmdRenameTown, CMD_SERVER}, /* 80 */
{CmdDoTownAction, 0}, /* 81 */
{CmdSetRoadDriveSide, CMD_SERVER}, /* 82 */
{NULL, 0}, /* 83 */
{NULL, 0}, /* 84 */
{CmdChangeDifficultyLevel, CMD_SERVER}, /* 85 */
{CmdStartStopShip, 0}, /* 86 */
{CmdSellShip, 0}, /* 87 */
{CmdBuildShip, 0}, /* 88 */
{CmdSendShipToDepot, 0}, /* 89 */
{CmdChangeShipServiceInt, 0}, /* 90 */
{CmdRefitShip, 0}, /* 91 */
{NULL, 0}, /* 92 */
{NULL, 0}, /* 93 */
{NULL, 0}, /* 94 */
{NULL, 0}, /* 95 */
{NULL, 0}, /* 96 */
{NULL, 0}, /* 97 */
{NULL, 0}, /* 98 */
{CmdCloneOrder, 0}, /* 99 */
{CmdClearArea, 0}, /* 100 */
{NULL, 0}, /* 101 */
{CmdMoneyCheat, CMD_OFFLINE}, /* 102 */
{CmdBuildCanal, 0}, /* 103 */
{CmdPlayerCtrl, 0}, /* 104 */
{CmdLevelLand, 0}, /* 105 */
{CmdRefitRailVehicle, 0}, /* 106 */
{CmdRestoreOrderIndex, 0}, /* 107 */
{CmdBuildLock, 0}, /* 108 */
{NULL, 0}, /* 109 */
{CmdBuildSignalTrack, 0}, /* 110 */
{CmdRemoveSignalTrack, 0}, /* 111 */
{NULL, 0}, /* 112 */
{CmdGiveMoney, 0}, /* 113 */
{CmdChangePatchSetting, CMD_SERVER}, /* 114 */
{CmdReplaceVehicle, 0}, /* 115 */
};
/* This function range-checks a cmd, and checks if the cmd is not NULL */
bool IsValidCommand(uint cmd)
{
cmd = cmd & 0xFF;
if (cmd >= lengthof(_command_proc_table) || _command_proc_table[cmd].proc == NULL)
return false;
return true;
}
byte GetCommandFlags(uint cmd) {return _command_proc_table[cmd & 0xFF].flags;}
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc)
{
return DoCommand(TileX(tile) * 16, TileY(tile) * 16, p1, p2, flags, procc);
}
//extern void _stdcall Sleep(int s);
int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc)
{
int32 res;
CommandProc *proc;
/* Do not even think about executing out-of-bounds tile-commands */
if (TILE_FROM_XY(x,y) > MapSize()) {
_cmd_text = NULL;
return CMD_ERROR;
}
proc = _command_proc_table[procc].proc;
if (_docommand_recursive == 0) {
_error_message = INVALID_STRING_ID;
// update last build coord of player
if ( (x|y) != 0 && _current_player < MAX_PLAYERS) {
DEREF_PLAYER(_current_player)->last_build_coordinate = TILE_FROM_XY(x,y);
}
}
_docommand_recursive++;
// only execute the test call if it's toplevel, or we're not execing.
if (_docommand_recursive == 1 || !(flags & DC_EXEC) || (flags & DC_FORCETEST) ) {
res = proc(x, y, flags&~DC_EXEC, p1, p2);
if (CmdFailed(res)) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
goto error;
}
if (_docommand_recursive == 1) {
if (!(flags&DC_QUERY_COST) && res != 0 && !CheckPlayerHasMoney(res))
goto error;
}
if (!(flags & DC_EXEC)) {
_docommand_recursive--;
_cmd_text = NULL;
return res;
}
}
/* Execute the command here. All cost-relevant functions set the expenses type
* themselves with "SET_EXPENSES_TYPE(...);" at the beginning of the function */
res = proc(x, y, flags, p1, p2);
if (CmdFailed(res)) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
error:
_docommand_recursive--;
_cmd_text = NULL;
return CMD_ERROR;
}
// if toplevel, subtract the money.
if (--_docommand_recursive == 0) {
SubtractMoneyFromPlayer(res);
}
_cmd_text = NULL;
return res;
}
int32 GetAvailableMoneyForCommand(void)
{
PlayerID pid = _current_player;
if (pid >= MAX_PLAYERS) return 0x7FFFFFFF; // max int
return DEREF_PLAYER(pid)->player_money;
}
// toplevel network safe docommand function for the current player. must not be called recursively.
// the callback is called when the command succeeded or failed.
bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, uint32 cmd)
{
int32 res = 0,res2;
CommandProc *proc;
uint32 flags;
bool notest;
int x = TileX(tile) * 16;
int y = TileY(tile) * 16;
/* Do not even think about executing out-of-bounds tile-commands */
if (tile > MapSize()) {
_cmd_text = NULL;
return false;
}
assert(_docommand_recursive == 0);
_error_message = INVALID_STRING_ID;
_error_message_2 = cmd >> 16;
_additional_cash_required = 0;
// spectator has no rights.
if (_current_player == OWNER_SPECTATOR) {
ShowErrorMessage(_error_message, _error_message_2, x, y);
_cmd_text = NULL;
return false;
}
flags = 0;
if (cmd & CMD_AUTO) flags |= DC_AUTO;
if (cmd & CMD_NO_WATER) flags |= DC_NO_WATER;
// get pointer to command handler
assert((cmd & 0xFF) < lengthof(_command_proc_table));
proc = _command_proc_table[cmd & 0xFF].proc;
// Some commands have a different output in dryrun than the realrun
// e.g.: if you demolish a whole town, the dryrun would say okay.
// but by really destroying, your rating drops and at a certain point
// it will fail. so res and res2 are different
// CMD_REMOVE_ROAD: This command has special local authority
// restrictions which may cause the test run to fail (the previous
// road fragments still stay there and the town won't let you
// disconnect the road system), but the exec will succeed and this
// fact will trigger an assertion failure. --pasky
notest =
(cmd & 0xFF) == CMD_CLEAR_AREA ||
(cmd & 0xFF) == CMD_CONVERT_RAIL ||
(cmd & 0xFF) == CMD_LEVEL_LAND ||
(cmd & 0xFF) == CMD_REMOVE_ROAD ||
(cmd & 0xFF) == CMD_REMOVE_LONG_ROAD;
_docommand_recursive = 1;
// cost estimation only?
if (_shift_pressed && _current_player == _local_player && !(cmd & (CMD_NETWORK_COMMAND | CMD_SHOW_NO_ERROR))) {
// estimate the cost.
res = proc(x, y, flags, p1, p2);
if (CmdFailed(res)) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
ShowErrorMessage(_error_message, _error_message_2, x, y);
} else {
ShowEstimatedCostOrIncome(res, x, y);
}
_docommand_recursive = 0;
_cmd_text = NULL;
return false;
}
if (!((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
// first test if the command can be executed.
res = proc(x,y, flags, p1, p2);
if (CmdFailed(res)) {
if (res & 0xFFFF) _error_message = res & 0xFFFF;
goto show_error;
}
// no money? Only check if notest is off
if (!notest && res != 0 && !CheckPlayerHasMoney(res)) goto show_error;
}
#ifdef ENABLE_NETWORK
// If we are in network, and the command is not from the network
// send it to the command-queue and abort execution
if (_networking && !(cmd & CMD_NETWORK_COMMAND)) {
NetworkSend_Command(tile, p1, p2, cmd, callback);
_docommand_recursive = 0;
_cmd_text = NULL;
return true;
}
#endif /* ENABLE_NETWORK */
// update last build coordinate of player.
if ( tile != 0 && _current_player < MAX_PLAYERS) DEREF_PLAYER(_current_player)->last_build_coordinate = tile;
/* Actually try and execute the command. If no cost-type is given
* use the construction one */
_yearly_expenses_type = EXPENSES_CONSTRUCTION;
res2 = proc(x,y, flags|DC_EXEC, p1, p2);
// If notest is on, it means the result of the test can be different than
// the real command.. so ignore the test
if (!notest && !((cmd & CMD_NO_TEST_IF_IN_NETWORK) && _networking)) {
assert(res == res2); // sanity check
} else {
if (CmdFailed(res2)) {
if (res2 & 0xFFFF) _error_message = res2 & 0xFFFF;
goto show_error;
}
}
SubtractMoneyFromPlayer(res2);
if (_current_player == _local_player && _game_mode != GM_EDITOR) {
if (res2 != 0)
ShowCostOrIncomeAnimation(x, y, GetSlopeZ(x, y), res2);
if (_additional_cash_required) {
SetDParam(0, _additional_cash_required);
ShowErrorMessage(STR_0003_NOT_ENOUGH_CASH_REQUIRES, _error_message_2, x,y);
if (res2 == 0) goto callb_err;
}
}
_docommand_recursive = 0;
if (callback) callback(true, tile, p1, p2);
_cmd_text = NULL;
return true;
show_error:
// show error message if the command fails?
if (_current_player == _local_player && _error_message_2 != 0)
ShowErrorMessage(_error_message, _error_message_2, x,y);
callb_err:
_docommand_recursive = 0;
if (callback) callback(false, tile, p1, p2);
_cmd_text = NULL;
return false;
}

199
command.h Normal file
View File

@@ -0,0 +1,199 @@
#ifndef COMMAND_H
#define COMMAND_H
enum {
CMD_BUILD_RAILROAD_TRACK = 0,
CMD_REMOVE_RAILROAD_TRACK = 1,
CMD_BUILD_SINGLE_RAIL = 2,
CMD_REMOVE_SINGLE_RAIL = 3,
CMD_LANDSCAPE_CLEAR = 4,
CMD_BUILD_BRIDGE = 5,
CMD_BUILD_RAILROAD_STATION = 6,
CMD_BUILD_TRAIN_DEPOT = 7,
CMD_BUILD_SIGNALS = 8,
CMD_REMOVE_SIGNALS = 9,
CMD_TERRAFORM_LAND = 10,
CMD_PURCHASE_LAND_AREA = 11,
CMD_SELL_LAND_AREA = 12,
CMD_BUILD_TUNNEL = 13,
CMD_REMOVE_FROM_RAILROAD_STATION = 14,
CMD_CONVERT_RAIL = 15,
CMD_BUILD_TRAIN_WAYPOINT = 16,
CMD_RENAME_WAYPOINT = 17,
CMD_REMOVE_TRAIN_WAYPOINT = 18,
CMD_BUILD_ROAD_STOP = 21,
CMD_BUILD_LONG_ROAD = 23,
CMD_REMOVE_LONG_ROAD = 24,
CMD_BUILD_ROAD = 25,
CMD_REMOVE_ROAD = 26,
CMD_BUILD_ROAD_DEPOT = 27,
CMD_BUILD_AIRPORT = 29,
CMD_BUILD_DOCK = 30,
CMD_BUILD_SHIP_DEPOT = 31,
CMD_BUILD_BUOY = 32,
CMD_PLANT_TREE = 33,
CMD_BUILD_RAIL_VEHICLE = 34,
CMD_MOVE_RAIL_VEHICLE = 35,
CMD_START_STOP_TRAIN = 36,
CMD_SELL_RAIL_WAGON = 38,
CMD_TRAIN_GOTO_DEPOT = 39,
CMD_FORCE_TRAIN_PROCEED = 40,
CMD_REVERSE_TRAIN_DIRECTION = 41,
CMD_MODIFY_ORDER = 42,
CMD_SKIP_ORDER = 43,
CMD_DELETE_ORDER = 44,
CMD_INSERT_ORDER = 45,
CMD_CHANGE_TRAIN_SERVICE_INT = 46,
CMD_BUILD_INDUSTRY = 47,
CMD_BUILD_COMPANY_HQ = 48,
CMD_SET_PLAYER_FACE = 49,
CMD_SET_PLAYER_COLOR = 50,
CMD_INCREASE_LOAN = 51,
CMD_DECREASE_LOAN = 52,
CMD_WANT_ENGINE_PREVIEW = 53,
CMD_NAME_VEHICLE = 54,
CMD_RENAME_ENGINE = 55,
CMD_CHANGE_COMPANY_NAME = 56,
CMD_CHANGE_PRESIDENT_NAME = 57,
CMD_RENAME_STATION = 58,
CMD_SELL_AIRCRAFT = 59,
CMD_START_STOP_AIRCRAFT = 60,
CMD_BUILD_AIRCRAFT = 61,
CMD_SEND_AIRCRAFT_TO_HANGAR = 62,
CMD_CHANGE_AIRCRAFT_SERVICE_INT = 63,
CMD_REFIT_AIRCRAFT = 64,
CMD_PLACE_SIGN = 65,
CMD_RENAME_SIGN = 66,
CMD_BUILD_ROAD_VEH = 67,
CMD_START_STOP_ROADVEH = 68,
CMD_SELL_ROAD_VEH = 69,
CMD_SEND_ROADVEH_TO_DEPOT = 70,
CMD_TURN_ROADVEH = 71,
CMD_CHANGE_ROADVEH_SERVICE_INT = 72,
CMD_PAUSE = 73,
CMD_BUY_SHARE_IN_COMPANY = 74,
CMD_SELL_SHARE_IN_COMPANY = 75,
CMD_BUY_COMPANY = 76,
CMD_BUILD_TOWN = 77,
CMD_RENAME_TOWN = 80,
CMD_DO_TOWN_ACTION = 81,
CMD_SET_ROAD_DRIVE_SIDE = 82,
CMD_CHANGE_DIFFICULTY_LEVEL = 85,
CMD_START_STOP_SHIP = 86,
CMD_SELL_SHIP = 87,
CMD_BUILD_SHIP = 88,
CMD_SEND_SHIP_TO_DEPOT = 89,
CMD_CHANGE_SHIP_SERVICE_INT = 90,
CMD_REFIT_SHIP = 91,
CMD_CLONE_ORDER = 99,
CMD_CLEAR_AREA = 100,
CMD_MONEY_CHEAT = 102,
CMD_BUILD_CANAL = 103,
CMD_PLAYER_CTRL = 104, // used in multiplayer to create a new player etc.
CMD_LEVEL_LAND = 105, // level land
CMD_REFIT_RAIL_VEHICLE = 106,
CMD_RESTORE_ORDER_INDEX = 107,
CMD_BUILD_LOCK = 108,
CMD_BUILD_SIGNAL_TRACK = 110,
CMD_REMOVE_SIGNAL_TRACK = 111,
CMD_GIVE_MONEY = 113,
CMD_CHANGE_PATCH_SETTING = 114,
CMD_REPLACE_VEHICLE = 115,
};
enum {
DC_EXEC = 1,
DC_AUTO = 2, // don't allow building on structures
DC_QUERY_COST = 4, // query cost only, don't build.
DC_NO_WATER = 8, // don't allow building on water
DC_NO_RAIL_OVERLAP = 0x10, // don't allow overlap of rails (used in buildrail)
DC_AI_BUILDING = 0x20, // special building rules for AI
DC_NO_TOWN_RATING = 0x40, // town rating does not disallow you from building
DC_FORCETEST = 0x80, // force test too.
CMD_ERROR = ((int32)0x80000000),
};
#define CMD_MSG(x) ((x)<<16)
enum {
CMD_AUTO = 0x200,
CMD_NO_WATER = 0x400,
CMD_NETWORK_COMMAND = 0x800, // execute the command without sending it on the network
CMD_NO_TEST_IF_IN_NETWORK = 0x1000, // When enabled, the command will bypass the no-DC_EXEC round if in network
CMD_SHOW_NO_ERROR = 0x2000,
};
/** Command flags for the command table
* @see _command_proc_table
*/
enum {
CMD_SERVER = 0x1, /// the command can only be initiated by the server
CMD_OFFLINE = 0x2, /// the command cannot be executed in a multiplayer game; single-player only
};
typedef struct Command {
CommandProc *proc;
byte flags;
} Command;
//#define return_cmd_error(errcode) do { _error_message=(errcode); return CMD_ERROR; } while(0)
#define return_cmd_error(errcode) do { return CMD_ERROR | (errcode); } while (0)
/**
* Check the return value of a DoCommand*() function
* @param res the resulting value from the command to be checked
* @return Return true if the command failed, false otherwise
*/
static inline bool CmdFailed(int32 res)
{
// lower 16bits are the StringID of the possible error
return res <= (CMD_ERROR | INVALID_STRING_ID);
}
/* command.c */
int32 DoCommand(int x, int y, uint32 p1, uint32 p2, uint32 flags, uint procc);
int32 DoCommandByTile(TileIndex tile, uint32 p1, uint32 p2, uint32 flags, uint procc);
extern const char* _cmd_text; // Text, which gets sent with a command
bool IsValidCommand(uint cmd);
byte GetCommandFlags(uint cmd);
int32 GetAvailableMoneyForCommand(void);
#endif /* COMMAND_H */

3667
config.lib

File diff suppressed because it is too large Load Diff

174
configure vendored
View File

@@ -1,174 +0,0 @@
#!/bin/sh
# $Id$
# 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_path_characters() {
if [ -n "`echo $ROOT_DIR | grep '[^-_A-Za-z0-9\/\\\.:]'`" ]; then
echo "WARNING: The path contains a non-alphanumeric character that might cause"
echo " failures in subsequent build stages. Any failures with the build"
echo " will most likely be caused by this."
fi
}
CONFIGURE_EXECUTABLE="$_"
# On *nix systems those two are equal when ./configure is done
if [ "$0" != "$CONFIGURE_EXECUTABLE" ]; then
# On some systems, when ./configure is triggered from 'make'
# the $_ is filled with 'make'. So if that is true, skip 'make'
# and use $0 (and hope that is correct ;))
if [ -n "`echo $CONFIGURE_EXECUTABLE | grep make`" ]; then
CONFIGURE_EXECUTABLE="$0"
else
CONFIGURE_EXECUTABLE="$CONFIGURE_EXECUTABLE $0"
fi
fi
# Find out where configure is (in what dir)
ROOT_DIR="`dirname $0`"
# For MSYS/MinGW we want to know the FULL path. This as that path is generated
# once you call an outside binary. Having the same path for the rest is needed
# for dependency checking.
# pwd -W returns said FULL path, but doesn't exist on others so fall back.
ROOT_DIR="`cd $ROOT_DIR && (pwd -W 2>/dev/null || pwd 2>/dev/null)`"
check_path_characters
# Same here as for the ROOT_DIR above
PWD="`pwd -W 2>/dev/null || pwd 2>/dev/null`"
PREFIX="$PWD/bin"
. $ROOT_DIR/config.lib
# Set default dirs
OBJS_DIR="$PWD/objs"
BASE_SRC_OBJS_DIR="$OBJS_DIR"
LANG_OBJS_DIR="$OBJS_DIR/lang"
GRF_OBJS_DIR="$OBJS_DIR/extra_grf"
SETTING_OBJS_DIR="$OBJS_DIR/setting"
BIN_DIR="$PREFIX"
SRC_DIR="$ROOT_DIR/src"
LANG_DIR="$SRC_DIR/lang"
MEDIA_DIR="$ROOT_DIR/media"
SOURCE_LIST="$ROOT_DIR/source.list"
if [ "$1" = "--reconfig" ] || [ "$1" = "--reconfigure" ]; then
if [ ! -f "config.cache" ]; then
echo "can't reconfigure, because never configured before"
exit 1
fi
# Make sure we don't lock config.cache
cat config.cache | sed 's@\\ @\\\\ @g' > cache.tmp
sh cache.tmp
RET=$?
rm -f cache.tmp
exit $RET
fi
set_default
detect_params "$@"
check_params
save_params
make_cflags_and_ldflags
EXE=""
if [ "$os" = "MINGW" ] || [ "$os" = "CYGWIN" ] || [ "$os" = "OS2" ] || [ "$os" = "DOS" ] || [ "$os" = "WINCE" ]; then
EXE=".exe"
fi
TTD="openttd$EXE"
STRGEN="strgen$EXE"
ENDIAN_CHECK="endian_check$EXE"
DEPEND="depend$EXE"
SETTINGSGEN="settings_gen$EXE"
if [ -z "$sort" ]; then
PIPE_SORT="sed s@a@a@"
else
PIPE_SORT="$sort"
fi
if [ ! -f "$LANG_DIR/english.txt" ]; then
echo "Languages not found in $LANG_DIR. Can't continue without it."
echo "Please make sure the dir exists and contains at least english.txt"
fi
# Read the source.list and process it
AWKCOMMAND='
{ }
/^( *)#end/ { if (deep == skip) { skip -= 1; } deep -= 1; next; }
/^( *)#else/ { if (deep == skip) { skip -= 1; } else if (deep - 1 == skip) { skip += 1; } next; }
/^( *)#if/ {
gsub(" ", "", $0);
gsub("^#if ", "", $0);
if (deep != skip) { deep += 1; next; }
deep += 1;
if ($0 == "ALLEGRO" && "'$allegro_config'" == "") { next; }
if ($0 == "SDL" && "'$sdl_config'" == "") { next; }
if ($0 == "PNG" && "'$png_config'" == "") { next; }
if ($0 == "OSX" && "'$os'" != "OSX") { next; }
if ($0 == "OS2" && "'$os'" != "OS2") { next; }
if ($0 == "PSP" && "'$os'" != "PSP") { next; }
if ($0 == "DEDICATED" && "'$enable_dedicated'" != "1") { next; }
if ($0 == "AI" && "'$enable_ai'" == "0") { next; }
if ($0 == "COCOA" && "'$with_cocoa'" == "0") { next; }
if ($0 == "DOS" && "'$os'" != "DOS") { next; }
if ($0 == "BEOS" && "'$os'" != "BEOS" &&
"'$os'" != "HAIKU") { next; }
if ($0 == "WIN32" && "'$os'" != "MINGW" &&
"'$os'" != "CYGWIN" && "'$os'" != "MSVC") { next; }
if ($0 == "MORPHOS" && "'$os'" != "MORPHOS") { next; }
if ($0 == "WINCE" && "'$os'" != "WINCE") { next; }
if ($0 == "MSVC" && "'$os'" != "MSVC") { next; }
if ($0 == "DIRECTMUSIC" && "'$with_direct_music'" == "0") { next; }
if ($0 == "LIBTIMIDITY" && "'$libtimidity'" == "" ) { next; }
if ($0 == "HAVE_THREAD" && "'$with_threads'" == "0") { next; }
skip += 1;
next;
}
/^( *)#/ { next }
/^$/ { next }
/\.h$/ { next }
/\.hpp$/ { next }
{
if (deep == skip) {
gsub(" ", "", $0);
print $0;
}
}
'
# Read the source.list and process it
# Please escape ALL " within ` because e.g. "" terminates the string in some sh implementations
SRCS="`< $ROOT_DIR/source.list tr '\r' '\n' | $awk \"$AWKCOMMAND\" | $PIPE_SORT`"
OBJS_C="` echo \"$SRCS\" | $awk ' { ORS = \" \" } /\.c$/ { gsub(\".c$\", \".o\", $0); print $0; }'`"
OBJS_CPP="`echo \"$SRCS\" | $awk ' { ORS = \" \" } /\.cpp$/ { gsub(\".cpp$\", \".o\", $0); print $0; }'`"
OBJS_MM="` echo \"$SRCS\" | $awk ' { ORS = \" \" } /\.mm$/ { gsub(\".mm$\", \".o\", $0); print $0; }'`"
OBJS_RC="` echo \"$SRCS\" | $awk ' { ORS = \" \" } /\.rc$/ { gsub(\".rc$\", \".o\", $0); print $0; }'`"
SRCS="` echo \"$SRCS\" | $awk ' { ORS = \" \" } { print $0; }'`"
# In makefiles, we always use -u for sort
if [ -z "$sort" ]; then
sort="sed s@a@a@"
else
sort="$sort -u"
fi
CONFIGURE_FILES="$ROOT_DIR/configure $ROOT_DIR/config.lib $ROOT_DIR/Makefile.in $ROOT_DIR/Makefile.grf.in $ROOT_DIR/Makefile.lang.in $ROOT_DIR/Makefile.src.in $ROOT_DIR/Makefile.bundle.in $ROOT_DIR/Makefile.setting.in"
generate_main
generate_lang
generate_settings
generate_grf
generate_src
check_path_characters

1113
console.c Normal file

File diff suppressed because it is too large Load Diff

163
console.h Normal file
View File

@@ -0,0 +1,163 @@
#ifndef CONSOLE_H
#define CONSOLE_H
// maximum length of a typed in command
#define ICON_CMDLN_SIZE 255
// maximum length of a totally expanded command
#define ICON_MAX_STREAMSIZE 1024
typedef enum IConsoleVarTypes {
ICONSOLE_VAR_BOOLEAN,
ICONSOLE_VAR_BYTE,
ICONSOLE_VAR_UINT16,
ICONSOLE_VAR_UINT32,
ICONSOLE_VAR_INT16,
ICONSOLE_VAR_INT32,
ICONSOLE_VAR_STRING
} IConsoleVarTypes;
typedef enum IConsoleModes {
ICONSOLE_FULL,
ICONSOLE_OPENED,
ICONSOLE_CLOSED
} IConsoleModes;
typedef enum IConsoleHookTypes {
ICONSOLE_HOOK_ACCESS,
ICONSOLE_HOOK_PRE_ACTION,
ICONSOLE_HOOK_POST_ACTION
} IConsoleHookTypes;
/** --Hooks--
* Hooks are certain triggers get get accessed/executed on either
* access, before execution/change or after execution/change. This allows
* for general flow of permissions or special action needed in some cases
*/
typedef bool IConsoleHook(void);
typedef struct IConsoleHooks{
IConsoleHook *access; // trigger when accessing the variable/command
IConsoleHook *pre; // trigger before the variable/command is changed/executed
IConsoleHook *post; // trigger after the variable/command is changed/executed
} IConsoleHooks;
/** --Commands--
* Commands are commands, or functions. They get executed once and any
* effect they produce are carried out. The arguments to the commands
* are given to them, each input word seperated by a double-quote (") is an argument
* If you want to handle multiple words as one, enclose them in double-quotes
* eg. 'say "hello sexy boy"'
*/
typedef bool (IConsoleCmdProc)(byte argc, char *argv[]);
struct IConsoleCmd;
typedef struct IConsoleCmd {
char *name; // name of command
struct IConsoleCmd *next; // next command in list
IConsoleCmdProc *proc; // process executed when command is typed
IConsoleHooks hook; // any special trigger action that needs executing
} IConsoleCmd;
/** --Variables--
* Variables are pointers to real ingame variables which allow for
* changing while ingame. After changing they keep their new value
* and can be used for debugging, gameplay, etc. It accepts:
* - no arguments; just print out current value
* - '= <new value>' to assign a new value to the variable
* - '++' to increase value by one
* - '--' to decrease value by one
*/
struct IConsoleVar;
typedef struct IConsoleVar {
char *name; // name of the variable
struct IConsoleVar *next; // next variable in list
void *addr; // the address where the variable is pointing at
uint32 size; // size of the variable, used for strings
char *help; // the optional help string shown when requesting information
IConsoleVarTypes type; // type of variable (for correct assignment/output)
IConsoleCmdProc *proc; // some variables need really special handling, use a callback function for that
IConsoleHooks hook; // any special trigger action that needs executing
} IConsoleVar;
/** --Aliases--
* Aliases are like shortcuts for complex functions, variable assignments,
* etc. You can use a simple alias to rename a longer command (eg 'lv' for
* 'list_vars' for example), or concatenate more commands into one
* (eg. 'ng' for 'load %A; unpause; debug_level 5'). Aliases can parse the arguments
* given to them in the command line.
* - "%A - %Z" substitute arguments 1 t/m 26
* - "%+" lists all parameters keeping them seperated
* - "%!" also lists all parameters but presenting them to the aliased command as one argument
* - ";" allows for combining commands (see example 'ng')
*/
struct IConsoleAlias;
typedef struct IConsoleAlias {
char *name; // name of the alias
struct IConsoleAlias *next; // next alias in list
char *cmdline; // command(s) that is/are being aliased
} IConsoleAlias;
// ** console parser ** //
IConsoleCmd *_iconsole_cmds; // list of registred commands
IConsoleVar *_iconsole_vars; // list of registred vars
IConsoleAlias *_iconsole_aliases; // list of registred aliases
// ** console colors/modes ** //
VARDEF byte _icolour_def;
VARDEF byte _icolour_err;
VARDEF byte _icolour_warn;
VARDEF byte _icolour_dbg;
VARDEF byte _icolour_cmd;
VARDEF IConsoleModes _iconsole_mode;
// ** console functions ** //
void IConsoleInit(void);
void IConsoleClear(void);
void IConsoleFree(void);
void IConsoleResize(void);
void IConsoleSwitch(void);
void IConsoleClose(void);
void IConsoleOpen(void);
// ** console cmd buffer ** //
void IConsoleHistoryAdd(const char *cmd);
void IConsoleHistoryNavigate(signed char direction);
// ** console output ** //
void IConsolePrint(uint16 color_code, const char *string);
void CDECL IConsolePrintF(uint16 color_code, const char *s, ...);
void IConsoleDebug(const char *string);
void IConsoleWarning(const char *string);
void IConsoleError(const char *string);
// *** Commands *** //
void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
void IConsoleAliasRegister(const char *name, const char *cmd);
IConsoleCmd *IConsoleCmdGet(const char *name);
IConsoleAlias *IConsoleAliasGet(const char *name);
// *** Variables *** //
void IConsoleVarRegister(const char *name, void *addr, IConsoleVarTypes type, const char *help);
void IConsoleVarStringRegister(const char *name, void *addr, uint32 size, const char *help);
IConsoleVar* IConsoleVarGet(const char *name);
void IConsoleVarPrintGetValue(const IConsoleVar *var);
void IConsoleVarPrintSetValue(const IConsoleVar *var);
// *** Parser *** //
void IConsoleCmdExec(const char *cmdstr);
void IConsoleVarExec(const IConsoleVar *var, byte tokencount, char *token[]);
void IConsoleAliasExec(const IConsoleAlias *alias, byte tokencount, char *tokens[]);
// ** console std lib (register ingame commands/aliases/variables) ** //
void IConsoleStdLibRegister(void);
// ** Hooking code ** //
void IConsoleCmdHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
void IConsoleVarHookAdd(const char *name, IConsoleHookTypes type, IConsoleHook *proc);
void IConsoleVarProcAdd(const char *name, IConsoleCmdProc *proc);
// ** Supporting functions **//
bool GetArgumentInteger(uint32 *value, const char *arg);
#endif /* CONSOLE_H */

1333
console_cmds.c Normal file

File diff suppressed because it is too large Load Diff

BIN
data/autorail.grf Normal file

Binary file not shown.

BIN
data/canalsw.grf Normal file

Binary file not shown.

BIN
data/dosdummy.grf Normal file

Binary file not shown.

BIN
data/openttd.grf Normal file

Binary file not shown.

BIN
data/opntitle.dat Normal file

Binary file not shown.

BIN
data/signalsw.grf Normal file

Binary file not shown.

BIN
data/trkfoundw.grf Normal file

Binary file not shown.

98
debug.c Normal file
View File

@@ -0,0 +1,98 @@
#include "stdafx.h"
#include <stdio.h>
#include <stdarg.h>
#include "ttd.h"
#include "console.h"
#include "debug.h"
int _debug_ai_level;
int _debug_grf_level;
int _debug_map_level;
int _debug_misc_level;
int _debug_ms_level;
int _debug_net_level;
int _debug_spritecache_level;
int _debug_oldloader_level;
int _debug_npf_level;
void CDECL debug(const char *s, ...)
{
va_list va;
char buf[1024];
va_start(va, s);
vsnprintf(buf, lengthof(buf), s, va);
va_end(va);
fprintf(stderr, "dbg: %s\n", buf);
IConsoleDebug(buf);
}
void SetDebugString(const char *s)
{
int v;
char *end;
const char *t;
typedef struct DebugLevel {
const char* name;
int* level;
} DebugLevel;
#define DEBUG_LEVEL(x) { #x, &_debug_##x##_level }
static const DebugLevel debug_level[] = {
DEBUG_LEVEL(ai),
DEBUG_LEVEL(grf),
DEBUG_LEVEL(map),
DEBUG_LEVEL(misc),
DEBUG_LEVEL(ms),
DEBUG_LEVEL(net),
DEBUG_LEVEL(spritecache),
DEBUG_LEVEL(oldloader),
DEBUG_LEVEL(npf)
};
#undef DEBUG_LEVEL
// global debugging level?
if (*s >= '0' && *s <= '9') {
const DebugLevel *i;
v = strtoul(s, &end, 0);
s = end;
for (i = debug_level; i != endof(debug_level); ++i)
*i->level = v;
}
// individual levels
for(;;) {
const DebugLevel *i;
int *p;
// skip delimiters
while (*s == ' ' || *s == ',' || *s == '\t') s++;
if (*s == '\0') break;
t = s;
while (*s >= 'a' && *s <= 'z') s++;
// check debugging levels
p = NULL;
for (i = debug_level; i != endof(debug_level); ++i)
if (s == t + strlen(i->name) && strncmp(t, i->name, s - t) == 0) {
p = i->level;
break;
}
if (*s == '=') s++;
v = strtoul(s, &end, 0);
s = end;
if (p != NULL)
*p = v;
else {
ShowInfoF("Unknown debug level '%.*s'", s - t, t);
return;
}
}
}

24
debug.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef DEBUG_H
#define DEBUG_H
#ifdef NO_DEBUG_MESSAGES
#define DEBUG(name, level)
#else
#define DEBUG(name, level) if (level == 0 || _debug_ ## name ## _level >= level) debug
extern int _debug_ai_level;
extern int _debug_grf_level;
extern int _debug_map_level;
extern int _debug_misc_level;
extern int _debug_ms_level;
extern int _debug_net_level;
extern int _debug_spritecache_level;
extern int _debug_oldloader_level;
extern int _debug_npf_level;
#endif
void CDECL debug(const char *s, ...);
void SetDebugString(const char *s);
#endif

352
dedicated.c Normal file
View File

@@ -0,0 +1,352 @@
#include "stdafx.h"
#include "ttd.h"
#include "debug.h"
#include "network.h"
#include "hal.h"
#ifdef ENABLE_NETWORK
#include "gfx.h"
#include "window.h"
#include "command.h"
#include "console.h"
#ifdef WIN32
# include <windows.h> /* GetTickCount */
# include <conio.h>
#endif
#ifdef __OS2__
# include <sys/time.h> /* gettimeofday */
# include <sys/types.h>
# include <unistd.h>
# include <conio.h>
# define STDIN 0 /* file descriptor for standard input */
extern void OS2_SwitchToConsoleMode();
#endif
#ifdef UNIX
# include <sys/time.h> /* gettimeofday */
# include <sys/types.h>
# include <unistd.h>
# include <signal.h>
# define STDIN 0 /* file descriptor for standard input */
#endif
#ifdef __MORPHOS__
/* Voids the fork, option will be disabled for MorphOS build anyway, because
* MorphOS doesn't support forking (could only implemented with lots of code
* changes here). */
int fork(void) { return -1; }
int dup2(int oldd, int newd) { return -1; }
#endif
// This file handles all dedicated-server in- and outputs
static void *_dedicated_video_mem;
extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
extern void SwitchMode(int new_mode);
#ifdef UNIX
/* We want to fork our dedicated server */
void DedicatedFork(void)
{
/* Fork the program */
pid_t pid = fork();
switch (pid) {
case -1:
perror("Unable to fork");
exit(1);
case 0:
// We're the child
/* Open the log-file to log all stuff too */
_log_file_fd = fopen(_log_file, "a");
if (!_log_file_fd) {
perror("Unable to open logfile");
exit(1);
}
/* Redirect stdout and stderr to log-file */
if (dup2(fileno(_log_file_fd), fileno(stdout)) == -1) {
perror("Rerouting stdout");
exit(1);
}
if (dup2(fileno(_log_file_fd), fileno(stderr)) == -1) {
perror("Rerouting stderr");
exit(1);
}
break;
default:
// We're the parent
printf("Loading dedicated server...\n");
printf(" - Forked to background with pid %d\n", pid);
exit(0);
}
}
/* Signal handlers */
static void DedicatedSignalHandler(int sig)
{
_exit_game = true;
signal(sig, DedicatedSignalHandler);
}
#endif
#ifdef WIN32
#include <time.h>
HANDLE hEvent;
static HANDLE hThread; // Thread to close
static char _win_console_thread_buffer[200];
/* Windows Console thread. Just loop and signal when input has been received */
void WINAPI CheckForConsoleInput(void)
{
while (true) {
fgets(_win_console_thread_buffer, lengthof(_win_console_thread_buffer), stdin);
SetEvent(hEvent); // signal input waiting that the line is ready
}
}
void CreateWindowsConsoleThread(void)
{
static char tbuffer[9];
DWORD dwThreadId;
/* Create event to signal when console input is ready */
hEvent = CreateEvent(NULL, false, false, _strtime(tbuffer));
if (hEvent == NULL)
error("Cannot create console event!");
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)CheckForConsoleInput, NULL, 0, &dwThreadId);
if (hThread == NULL)
error("Cannot create console thread!");
DEBUG(misc, 0) ("Windows console thread started...");
}
void CloseWindowsConsoleThread(void)
{
CloseHandle(hThread);
CloseHandle(hEvent);
DEBUG(misc, 0) ("Windows console thread shut down...");
}
#endif
static const char *DedicatedVideoStart(const char * const *parm)
{
_screen.width = _screen.pitch = _cur_resolution[0];
_screen.height = _cur_resolution[1];
_dedicated_video_mem = malloc(_cur_resolution[0]*_cur_resolution[1]);
_debug_net_level = 6;
_debug_misc_level = 0;
#ifdef WIN32
// For win32 we need to allocate an console (debug mode does the same)
CreateConsole();
CreateWindowsConsoleThread();
SetConsoleTitle("OpenTTD Dedicated Server");
#endif
#ifdef __OS2__
// For OS/2 we also need to switch to console mode instead of PM mode
OS2_SwitchToConsoleMode();
#endif
DEBUG(misc,0)("Loading dedicated server...");
return NULL;
}
static void DedicatedVideoStop(void)
{
#ifdef WIN32
CloseWindowsConsoleThread();
#endif
free(_dedicated_video_mem);
}
static void DedicatedVideoMakeDirty(int left, int top, int width, int height) {}
static bool DedicatedVideoChangeRes(int w, int h) { return false; }
#if defined(UNIX) || defined(__OS2__)
static bool InputWaiting(void)
{
struct timeval tv;
fd_set readfds;
byte ret;
tv.tv_sec = 0;
tv.tv_usec = 1;
FD_ZERO(&readfds);
FD_SET(STDIN, &readfds);
/* don't care about writefds and exceptfds: */
ret = select(STDIN + 1, &readfds, NULL, NULL, &tv);
if (ret > 0)
return true;
return false;
}
#else
static bool InputWaiting(void)
{
if (WaitForSingleObject(hEvent, 1) == WAIT_OBJECT_0)
return true;
return false;
}
#endif
static void DedicatedHandleKeyInput(void)
{
static char input_line[200] = "";
if (!InputWaiting())
return;
if (_exit_game)
return;
#if defined(UNIX) || defined(__OS2__)
fgets(input_line, lengthof(input_line), stdin);
#else
strncpy(input_line, _win_console_thread_buffer, lengthof(input_line));
#endif
/* XXX - strtok() does not 'forget' \n\r if it is the first character! */
strtok(input_line, "\r\n"); // Forget about the final \n (or \r)
{ /* Remove any special control characters */
uint i;
for (i = 0; i < lengthof(input_line); i++) {
if (input_line[i] == '\n' || input_line[i] == '\r') // cut missed beginning '\0'
input_line[i] = '\0';
if (input_line[i] == '\0')
break;
if (!IS_INT_INSIDE(input_line[i], ' ', 256))
input_line[i] = ' ';
}
}
IConsoleCmdExec(input_line); // execute command
}
static int DedicatedVideoMainLoop(void)
{
#ifndef WIN32
struct timeval tim;
#endif
uint32 next_tick;
uint32 cur_ticks;
#ifdef WIN32
next_tick = GetTickCount() + 30;
#else
gettimeofday(&tim, NULL);
next_tick = (tim.tv_usec / 1000) + 30 + (tim.tv_sec * 1000);
#endif
/* Signal handlers */
#ifdef UNIX
signal(SIGTERM, DedicatedSignalHandler);
signal(SIGINT, DedicatedSignalHandler);
signal(SIGQUIT, DedicatedSignalHandler);
#endif
// Load the dedicated server stuff
_is_network_server = true;
_network_dedicated = true;
_network_playas = OWNER_SPECTATOR;
_local_player = OWNER_SPECTATOR;
/* If SwitchMode is SM_LOAD, it means that the user used the '-g' options */
if (_switch_mode != SM_LOAD) {
_switch_mode = SM_NONE;
GenRandomNewGame(Random(), InteractiveRandom());
} else {
_switch_mode = SM_NONE;
/* First we need to test if the savegame can be loaded, else we will end up playing the
* intro game... */
if (!SafeSaveOrLoad(_file_to_saveload.name, _file_to_saveload.mode, GM_NORMAL)) {
/* Loading failed, pop out.. */
DEBUG(net, 0)("Loading requested map failed. Aborting.");
_networking = false;
} else {
/* We can load this game, so go ahead */
SwitchMode(SM_LOAD);
}
}
// Done loading, start game!
if (!_networking) {
DEBUG(net, 1)("Dedicated server could not be launched. Aborting.");
return ML_QUIT;
}
while (true) {
InteractiveRandom(); // randomness
if (_exit_game) return ML_QUIT;
if (!_dedicated_forks)
DedicatedHandleKeyInput();
#ifdef WIN32
cur_ticks = GetTickCount();
#else
gettimeofday(&tim, NULL);
cur_ticks = (tim.tv_usec / 1000) + (tim.tv_sec * 1000);
#endif
if (cur_ticks >= next_tick) {
next_tick += 30;
GameLoop();
_screen.dst_ptr = _dedicated_video_mem;
UpdateWindows();
}
CSleep(1);
}
return ML_QUIT;
}
const HalVideoDriver _dedicated_video_driver = {
DedicatedVideoStart,
DedicatedVideoStop,
DedicatedVideoMakeDirty,
DedicatedVideoMainLoop,
DedicatedVideoChangeRes,
};
#else
static void *_dedicated_video_mem;
static const char *DedicatedVideoStart(const char * const *parm)
{
DEBUG(misc, 0) ("OpenTTD compiled without network support, exiting.");
return NULL;
}
void DedicatedFork(void) {}
static void DedicatedVideoStop(void) { free(_dedicated_video_mem); }
static void DedicatedVideoMakeDirty(int left, int top, int width, int height) {}
static bool DedicatedVideoChangeRes(int w, int h) { return false; }
static int DedicatedVideoMainLoop(void) { return ML_QUIT; }
const HalVideoDriver _dedicated_video_driver = {
DedicatedVideoStart,
DedicatedVideoStop,
DedicatedVideoMakeDirty,
DedicatedVideoMainLoop,
DedicatedVideoChangeRes,
};
#endif /* ENABLE_NETWORK */

142
depot.c Normal file
View File

@@ -0,0 +1,142 @@
#include "stdafx.h"
#include "ttd.h"
#include "depot.h"
#include "tile.h"
#include "map.h"
#include "table/strings.h"
#include "saveload.h"
#include "order.h"
enum {
/* Max depots: 64000 (8 * 8000) */
DEPOT_POOL_BLOCK_SIZE_BITS = 3, /* In bits, so (1 << 3) == 8 */
DEPOT_POOL_MAX_BLOCKS = 8000,
};
/**
* Called if a new block is added to the depot-pool
*/
static void DepotPoolNewBlock(uint start_item)
{
Depot *depot;
FOR_ALL_DEPOTS_FROM(depot, start_item)
depot->index = start_item++;
}
/* Initialize the town-pool */
MemoryPool _depot_pool = { "Depots", DEPOT_POOL_MAX_BLOCKS, DEPOT_POOL_BLOCK_SIZE_BITS, sizeof(Depot), &DepotPoolNewBlock, 0, 0, NULL };
/**
* Gets a depot from a tile
*
* @return Returns the depot if the tile had a depot, else it returns NULL
*/
Depot *GetDepotByTile(uint tile)
{
Depot *depot;
FOR_ALL_DEPOTS(depot) {
if (depot->xy == tile)
return depot;
}
return NULL;
}
/**
* Allocate a new depot
*/
Depot *AllocateDepot(void)
{
Depot *depot;
FOR_ALL_DEPOTS(depot) {
if (!IsValidDepot(depot)) {
uint index = depot->index;
memset(depot, 0, sizeof(Depot));
depot->index = index;
return depot;
}
}
/* Check if we can add a block to the pool */
if (AddBlockToPool(&_depot_pool))
return AllocateDepot();
return NULL;
}
/**
* Delete a depot
*/
void DoDeleteDepot(uint tile)
{
Order order;
Depot *depot;
/* Get the depot */
depot = GetDepotByTile(tile);
/* Clear the tile */
DoClearSquare(tile);
/* Clear the depot */
depot->xy = 0;
/* Clear the depot from all order-lists */
order.type = OT_GOTO_DEPOT;
order.station = depot->index;
DeleteDestinationFromVehicleOrder(order);
/* Delete the depot-window */
DeleteWindowById(WC_VEHICLE_DEPOT, tile);
}
void InitializeDepot(void)
{
CleanPool(&_depot_pool);
AddBlockToPool(&_depot_pool);
}
static const byte _depot_desc[] = {
SLE_CONDVAR(Depot, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
SLE_CONDVAR(Depot, xy, SLE_UINT32, 6, 255),
SLE_VAR(Depot,town_index, SLE_UINT16),
SLE_END()
};
static void Save_DEPT(void)
{
Depot *depot;
FOR_ALL_DEPOTS(depot) {
if (IsValidDepot(depot)) {
SlSetArrayIndex(depot->index);
SlObject(depot, _depot_desc);
}
}
}
static void Load_DEPT(void)
{
int index;
while ((index = SlIterateArray()) != -1) {
Depot *depot;
if (!AddBlockIfNeeded(&_depot_pool, index))
error("Depots: failed loading savegame: too many depots");
depot = GetDepot(index);
SlObject(depot, _depot_desc);
}
}
const ChunkHandler _depot_chunk_handlers[] = {
{ 'DEPT', Save_DEPT, Load_DEPT, CH_ARRAY | CH_LAST},
};

120
depot.h Normal file
View File

@@ -0,0 +1,120 @@
#ifndef DEPOT_H
#define DEPOT_H
#include "pool.h"
#include "tile.h"
struct Depot {
TileIndex xy;
uint16 town_index;
uint16 index;
};
extern MemoryPool _depot_pool;
/**
* Get the pointer to the depot with index 'index'
*/
static inline Depot *GetDepot(uint index)
{
return (Depot*)GetItemFromPool(&_depot_pool, index);
}
/**
* Get the current size of the DepotPool
*/
static inline uint16 GetDepotPoolSize(void)
{
return _depot_pool.total_items;
}
static inline bool IsDepotIndex(uint index)
{
return index < GetDepotPoolSize();
}
#define FOR_ALL_DEPOTS_FROM(d, start) for (d = GetDepot(start); d != NULL; d = (d->index + 1 < GetDepotPoolSize()) ? GetDepot(d->index + 1) : NULL)
#define FOR_ALL_DEPOTS(d) FOR_ALL_DEPOTS_FROM(d, 0)
#define MIN_SERVINT_PERCENT 5
#define MAX_SERVINT_PERCENT 90
#define MIN_SERVINT_DAYS 30
#define MAX_SERVINT_DAYS 800
/** Get the service interval domain.
* Get the new proposed service interval for the vehicle is indeed, clamped
* within the given bounds. @see MIN_SERVINT_PERCENT ,etc.
* @param index proposed service interval
*/
static inline uint16 GetServiceIntervalClamped(uint index)
{
return (_patches.servint_ispercent) ? clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
}
VARDEF TileIndex _last_built_train_depot_tile;
VARDEF TileIndex _last_built_road_depot_tile;
VARDEF TileIndex _last_built_aircraft_depot_tile;
VARDEF TileIndex _last_built_ship_depot_tile;
/**
* Check if a depot really exists.
*/
static inline bool IsValidDepot(const Depot* depot)
{
return depot->xy != 0; /* XXX: Replace by INVALID_TILE someday */
}
/**
* Check if a tile is a depot of the given type.
*/
static inline bool IsTileDepotType(TileIndex tile, TransportType type)
{
switch(type)
{
case TRANSPORT_RAIL:
return IsTileType(tile, MP_RAILWAY) && (_map5[tile] & 0xFC) == 0xC0;
break;
case TRANSPORT_ROAD:
return IsTileType(tile, MP_STREET) && (_map5[tile] & 0xF0) == 0x20;
break;
case TRANSPORT_WATER:
return IsTileType(tile, MP_WATER) && (_map5[tile] & ~3) == 0x80;
break;
default:
assert(0);
return false;
}
}
/**
* Returns the direction the exit of the depot on the given tile is facing.
*/
static inline uint GetDepotDirection(TileIndex tile, TransportType type)
{
assert(IsTileDepotType(tile, type));
switch (type)
{
case TRANSPORT_RAIL:
case TRANSPORT_ROAD:
/* Rail and road store a diagonal direction in bits 0 and 1 */
return _map5[tile] & 3;
case TRANSPORT_WATER:
/* Water is stubborn, it stores the directions in a different order. */
switch (_map5[tile] & 3) {
case 0: return 0;
case 1: return 2;
case 2: return 3;
case 3: return 1;
}
default:
return 0; /* Not reached */
}
}
Depot *GetDepotByTile(uint tile);
void InitializeDepot(void);
Depot *AllocateDepot(void);
void DoDeleteDepot(uint tile);
#endif /* DEPOT_H */

1000
disaster_cmd.c Normal file

File diff suppressed because it is too large Load Diff

359
dock_gui.c Normal file
View File

@@ -0,0 +1,359 @@
#include "stdafx.h"
#include "ttd.h"
#include "table/sprites.h"
#include "table/strings.h"
#include "map.h"
#include "window.h"
#include "station.h"
#include "gui.h"
#include "viewport.h"
#include "gfx.h"
#include "sound.h"
#include "command.h"
static void ShowBuildDockStationPicker(void);
static void ShowBuildDocksDepotPicker(void);
static byte _ship_depot_direction;
void CcBuildDocks(bool success, uint tile, uint32 p1, uint32 p2)
{
if (success) {
SndPlayTileFx(SND_02_SPLAT, tile);
ResetObjectToPlace();
}
}
void CcBuildCanal(bool success, uint tile, uint32 p1, uint32 p2)
{
if (success) SndPlayTileFx(SND_02_SPLAT, tile);
}
static void PlaceDocks_Dock(uint tile)
{
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_DOCK | CMD_AUTO | CMD_MSG(STR_9802_CAN_T_BUILD_DOCK_HERE));
}
static void PlaceDocks_Depot(uint tile)
{
DoCommandP(tile, _ship_depot_direction, 0, CcBuildDocks, CMD_BUILD_SHIP_DEPOT | CMD_AUTO | CMD_MSG(STR_3802_CAN_T_BUILD_SHIP_DEPOT));
}
static void PlaceDocks_Buoy(uint tile)
{
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_BUOY | CMD_AUTO | CMD_MSG(STR_9835_CAN_T_POSITION_BUOY_HERE));
}
static void PlaceDocks_DemolishArea(uint tile)
{
VpStartPlaceSizing(tile, VPM_X_AND_Y | GUI_PlaceProc_DemolishArea);
}
static void PlaceDocks_BuildCanal(uint tile)
{
VpStartPlaceSizing(tile, VPM_X_OR_Y);
}
static void PlaceDocks_BuildLock(uint tile)
{
DoCommandP(tile, 0, 0, CcBuildDocks, CMD_BUILD_LOCK | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_LOCKS));
}
static void BuildDocksClick_Canal(Window *w)
{
HandlePlacePushButton(w, 3, SPR_OPENTTD_BASE + 11, 1, PlaceDocks_BuildCanal);
}
static void BuildDocksClick_Lock(Window *w)
{
HandlePlacePushButton(w, 4, SPR_OPENTTD_BASE + 64, 1, PlaceDocks_BuildLock);
}
static void BuildDocksClick_Demolish(Window *w)
{
HandlePlacePushButton(w, 6, ANIMCURSOR_DEMOLISH, 1, PlaceDocks_DemolishArea);
}
static void BuildDocksClick_Depot(Window *w)
{
if (HandlePlacePushButton(w, 7, 0x2D1, 1, PlaceDocks_Depot)) ShowBuildDocksDepotPicker();
}
static void BuildDocksClick_Dock(Window *w)
{
if (HandlePlacePushButton(w, 8, 0xE54, 3, PlaceDocks_Dock)) ShowBuildDockStationPicker();
}
static void BuildDocksClick_Buoy(Window *w)
{
HandlePlacePushButton(w, 9, 0x2BE, 1, PlaceDocks_Buoy);
}
static void BuildDocksClick_Landscaping(Window *w)
{
ShowTerraformToolbar();
}
typedef void OnButtonClick(Window *w);
static OnButtonClick * const _build_docks_button_proc[] = {
BuildDocksClick_Canal,
BuildDocksClick_Lock,
0,
BuildDocksClick_Demolish,
BuildDocksClick_Depot,
BuildDocksClick_Dock,
BuildDocksClick_Buoy,
BuildDocksClick_Landscaping,
};
static void BuildDocksToolbWndProc(Window *w, WindowEvent *e)
{
switch(e->event) {
case WE_PAINT:
DrawWindowWidgets(w);
break;
case WE_CLICK: {
if (e->click.widget - 3 >= 0 && e->click.widget != 5) _build_docks_button_proc[e->click.widget - 3](w);
} break;
case WE_KEYPRESS: {
switch(e->keypress.keycode) {
case '1': BuildDocksClick_Canal(w); break;
case '2': BuildDocksClick_Lock(w); break;
case '3': BuildDocksClick_Demolish(w); break;
case '4': BuildDocksClick_Depot(w); break;
case '5': BuildDocksClick_Dock(w); break;
case '6': BuildDocksClick_Buoy(w); break;
case 'l': BuildDocksClick_Landscaping(w); break;
default:
return;
}
} break;
case WE_PLACE_OBJ:
_place_proc(e->place.tile);
break;
case WE_PLACE_DRAG: {
VpSelectTilesWithMethod(e->place.pt.x, e->place.pt.y, e->place.userdata);
return;
}
case WE_PLACE_MOUSEUP:
if (e->click.pt.x != -1) {
if ((e->place.userdata & 0xF) == VPM_X_AND_Y) { // dragged actions
GUIPlaceProcDragXY(e);
} else if(e->place.userdata == VPM_X_OR_Y)
DoCommandP(e->place.tile, e->place.starttile, 0, CcBuildCanal, CMD_BUILD_CANAL | CMD_AUTO | CMD_MSG(STR_CANT_BUILD_CANALS));
}
break;
case WE_ABORT_PLACE_OBJ:
UnclickWindowButtons(w);
SetWindowDirty(w);
w = FindWindowById(WC_BUILD_STATION, 0);
if (w != NULL) WP(w,def_d).close=true;
w = FindWindowById(WC_BUILD_DEPOT, 0);
if (w != NULL) WP(w,def_d).close=true;
break;
case WE_PLACE_PRESIZE: {
uint tile_from, tile_to;
tile_from = tile_to = e->place.tile;
switch(GetTileSlope(tile_from, NULL)) {
case 3: tile_to += TILE_XY(-1,0); break;
case 6: tile_to += TILE_XY(0,-1); break;
case 9: tile_to += TILE_XY(0,1); break;
case 12:tile_to += TILE_XY(1,0); break;
}
VpSetPresizeRange(tile_from, tile_to);
} break;
}
}
static const Widget _build_docks_toolb_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 145, 0, 13, STR_9801_DOCK_CONSTRUCTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_STICKYBOX, RESIZE_NONE, 7, 146, 157, 0, 13, 0x0, STR_STICKY_BUTTON},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 21, 14, 35, SPR_IMG_BUILD_CANAL, STR_BUILD_CANALS_TIP},
{ WWT_PANEL, RESIZE_NONE, 7, 22, 43, 14, 35, SPR_IMG_BUILD_LOCK, STR_BUILD_LOCKS_TIP},
{ WWT_PANEL, RESIZE_NONE, 7, 44, 47, 14, 35, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 7, 48, 69, 14, 35, 703, STR_018D_DEMOLISH_BUILDINGS_ETC},
{ WWT_PANEL, RESIZE_NONE, 7, 70, 91, 14, 35, 748, STR_981E_BUILD_SHIP_DEPOT_FOR_BUILDING},
{ WWT_PANEL, RESIZE_NONE, 7, 92, 113, 14, 35, 746, STR_981D_BUILD_SHIP_DOCK},
{ WWT_PANEL, RESIZE_NONE, 7, 114, 135, 14, 35, 693, STR_9834_POSITION_BUOY_WHICH_CAN},
{ WWT_PANEL, RESIZE_NONE, 7, 136, 157, 14, 35, SPR_IMG_LANDSCAPING, STR_LANDSCAPING_TOOLBAR_TIP},
{ WIDGETS_END},
};
static const WindowDesc _build_docks_toolbar_desc = {
640-158, 22, 158, 36,
WC_BUILD_TOOLBAR,0,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET | WDF_STICKY_BUTTON,
_build_docks_toolb_widgets,
BuildDocksToolbWndProc
};
void ShowBuildDocksToolbar(void)
{
if (_current_player == OWNER_SPECTATOR) return;
DeleteWindowById(WC_BUILD_TOOLBAR, 0);
AllocateWindowDesc(&_build_docks_toolbar_desc);
}
static void BuildDockStationWndProc(Window *w, WindowEvent *e)
{
int rad;
switch(e->event) {
case WE_PAINT: {
if (WP(w,def_d).close)
return;
w->click_state = (1<<3) << _station_show_coverage;
DrawWindowWidgets(w);
if (_patches.modified_catchment) {
rad = CA_DOCK;
} else {
rad = 4;
}
if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad);
else SetTileSelectBigSize(0, 0, 0, 0);
DrawStringCentered(74, 17, STR_3066_COVERAGE_AREA_HIGHLIGHT, 0);
DrawStationCoverageAreaText(4, 50, (uint)-1, rad);
} break;
case WE_CLICK: {
switch(e->click.widget) {
case 3: case 4:
_station_show_coverage = e->click.widget - 3;
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_dock_station_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_3068_DOCK, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 147, 14, 74, 0x0, STR_NULL},
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 14, 73, 30, 40, STR_02DB_OFF, STR_3065_DON_T_HIGHLIGHT_COVERAGE},
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 74, 133, 30, 40, STR_02DA_ON, STR_3064_HIGHLIGHT_COVERAGE_AREA},
{ WIDGETS_END},
};
static const WindowDesc _build_dock_station_desc = {
-1, -1, 148, 75,
WC_BUILD_STATION,WC_BUILD_TOOLBAR,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_build_dock_station_widgets,
BuildDockStationWndProc
};
static void ShowBuildDockStationPicker(void)
{
AllocateWindowDesc(&_build_dock_station_desc);
}
static void UpdateDocksDirection(void)
{
if (_ship_depot_direction != 0) {
SetTileSelectSize(1, 2);
} else {
SetTileSelectSize(2, 1);
}
}
static void BuildDocksDepotWndProc(Window *w, WindowEvent *e)
{
switch(e->event) {
case WE_PAINT:
w->click_state = (1<<3) << _ship_depot_direction;
DrawWindowWidgets(w);
DrawShipDepotSprite(67, 35, 0);
DrawShipDepotSprite(35, 51, 1);
DrawShipDepotSprite(135, 35, 2);
DrawShipDepotSprite(167, 51, 3);
return;
case WE_CLICK: {
switch(e->click.widget) {
case 3:
case 4:
_ship_depot_direction = e->click.widget - 3;
SndPlayFx(SND_15_BEEP);
UpdateDocksDirection();
SetWindowDirty(w);
break;
}
} break;
case WE_MOUSELOOP:
if (WP(w,def_d).close)
DeleteWindow(w);
break;
case WE_DESTROY:
if (!WP(w,def_d).close)
ResetObjectToPlace();
break;
}
}
static const Widget _build_docks_depot_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 7, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 7, 11, 203, 0, 13, STR_3800_SHIP_DEPOT_ORIENTATION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_PANEL, RESIZE_NONE, 7, 0, 203, 14, 85, 0x0, STR_NULL},
{ WWT_PANEL, RESIZE_NONE, 14, 3, 100, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION},
{ WWT_PANEL, RESIZE_NONE, 14, 103, 200, 17, 82, 0x0, STR_3803_SELECT_SHIP_DEPOT_ORIENTATION},
{ WIDGETS_END},
};
static const WindowDesc _build_docks_depot_desc = {
-1, -1, 204, 86,
WC_BUILD_DEPOT,WC_BUILD_TOOLBAR,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_build_docks_depot_widgets,
BuildDocksDepotWndProc
};
static void ShowBuildDocksDepotPicker(void)
{
AllocateWindowDesc(&_build_docks_depot_desc);
UpdateDocksDirection();
}
void InitializeDockGui(void)
{
_ship_depot_direction = 0;
}

View File

@@ -1,72 +0,0 @@
OpenTTD and strgen
Last updated: 2009-06-30
------------------------------------------------------------------------
Table of contents
-----------------
1.0) strgen usage
* 1.1) Examples
* 1.2) strgen command switches
1.0) strgen usage
---- ------------
This guide is only interesting for people who want to alter something
themselves without access to translator.openttd.org. Please note that
your compiled language file will only be compatible with the OpenTTD version
you have downloaded english.txt, the master language file, for. While this is
not always true, namely when changes in the code have not touched language
files, your safest bet is to assume this 'limitation'.
As a first step you need to compile strgen. This is as easy as typing
'make strgen'. You can download the precompile strgen from:
http://www.openttd.org/download-strgen
strgen takes as argument a txt file and translates it to a lng file, allowing
it to be used inside OpenTTD. strgen needs the master language file
english.txt to work. Below are some examples of strgen usage.
1.1) Examples
---- --------
Example 1:
if you are in the root of your working copy (svn code), you should type
strgen/strgen -s lang lang/english.txt
to compile englist.txt into english.lng. It will be placed in the lang dir
Example 2:
you only have the strgen executable (no working copy) and you want to compile
a txt file in the same directory. You should type
./strgen english.txt
and you will get and english.lng in the same dir
Example 3:
you have strgen somewhere, english.txt in /usr/openttd/lang and you want the
resulting language file to go to /tmp. Use
./strgen -s /usr/openttd/lang -d /tmp english.txt
You can interchange english.txt to whichever language you want to generate a
.lng file for.
1.2) strgen command switches
---- -----------------------
-v | --version
strgen will tell what svn revision it was last modified
-t | --todo
strgen will add <TODO> to any untranslated/missing strings and use the english
strings while compiling the language file
-w | --warning
strgen will print any missing strings or wrongly translated (bad format)
to standard error output(stderr)
-h | --help | -?
Print out a summarized help message explaining these switches
-s | --source_dir
strgen will search for the master file english.txt in the directory specified
by this switch instead of the current directory
-d | --dest_dir
strgen will put <language>.lng in the directory specified by this switch; if
no dest_dir is given, output is the same as source_dir

View File

@@ -0,0 +1,49 @@
This is a guide to compile strgen on gcc
All this is done in the makefile, so it's only interesting for people, who wants to alter something themselves (translators)
HOWTO compile lng files:
First you get strgen compiled (look below/download nightly build/run makefile)
strgen takes the argument of a txt file and translates it to a lng file and places that lng file in the same dir as the txt file.
Example 1:
if you are in the root of your working copy (svn code), you should type
strgen/strgen lang/english.txt
to compile englist.lng. It will be placed in the lang dir
Example 2:
you have strgen but not the source and you want to compile a txt file in the same dir. YOu should type
./strgen english.txt
and you will get english.lng in the same dir
You can change english to whatever language you want
Commands used by strgen
-v --version
strgen will tell what svn revision it is based on
-t
strgen will add <TODO> to the missing strings and use the english strings while compiling
this will need english.txt to be present
-w
strgen will print any missing strings to standard error output(stderr)
this will need english.txt to be present
here are a very useful tool for translators:
http://openttd.rulez.org/
HOWTO compile strgen:
(this should be useless as you can just type make)
Goto the main dir
Compile by typing
gcc strgen/strgen.c -o strgen/strgen -DUNIX
or if you want it to tell the revision too
gcc strgen/strgen.c rev.o -o strgen/strgen -DUNIX -DWITH_REV (this is the one the makefile uses)
you now have a program called strgen in the strgen directory

102
docs/Manual.txt Normal file
View File

@@ -0,0 +1,102 @@
Welcome to the manual for OpenTTD. The latest release version at the time of writing is 0.3.2.
1 Obtaining OpenTTD.
You can obtain built binaries of OpenTTD for the 4 supported platforms - Win32, Linux,-x86, BeOS 5 and MacOS-X from the projects Sourceforge page, at http://sourceforge.net/projects/openttd . For the non-Win32 builds you will need libSDL.so, libpng.so and zlib.so compiled for your platform. Some builds will include these.
If you use another platform, such as FreeBSD, which has POSIX file i/o and an SDL port, you should be able to build OpenTTD from its source. This is available in the proejcts Subversion repository at svn://svn.openttd.com . The module name is "trunk".
1.1 Building OpenTTD.
Once you have obtained a recent copy of the source, you must build it. Windows build instructions will be provided later.
On UNIX platforms (including OS-X and BeOS), ensure you have a recent GCC (2.9 or above, or 3 and above).You will also need SDL development headers and libraries (libSDL 1.2 or higher). For PNG screenshot support and zlib compressed games, you will need libpng 1.0.12 or higher and zlib 1.2 or higher.
Most UNIX platforms:
Use make or gmake to compile OpenTTD. You can adjust Makefile.config to compile with other options.
BeOS:
On BeOS, run ./configure and then use jam. There are a variaty of options you can pass to your build tool, these are reported by ./configure.
1.2 Installing OpenTTD.
On Windows, insert your "Transport Tycoon Deluxe for Windows 95" disk. You can use a DOS version, but your graphics will be purple. NB: Even if your version of Transport Tycoon Deluxe ran on Windows 95, it may still be the DOS version. Then run the OpenTTD installer.
On UNIX platforms; decompress your OpenTTD archive, or otherwise run the installer. You should be left with an OpenTTD directory on your system. In this directory, make a subdirectory called 'data', and into this place the sample.cat file and all the .grf files from the install CD of 'Transport Tycoon Deluxe for Windows 95".
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
If you want MIDI music, copy the 'gm' folder from the original game directory/CD to the OpenTTD folder.
1.3 Running OpenTTD.
On Windows, you can use a third-party launcher such as OTTD-Launcher to run OpenTTD directly from Explorer. Otherwise, navigate via the command prompt to the correct location and launch ttd.exe.
On Linux, navigate at the shell to the correct location and run ttd.
On BeOS and Mac OS-X, just double click the ttd binary in the Tracker/Finder. You can also start from the shell.
1.4 Configuring OpenTTD
OpenTTD's launch menu contains three configuration menus - Difficulty Settings, Configure Patches and Game Settings. Most of these menus can be configured from within a running game as well.
Difficulty Settings lets you configure settings that affect the difficulty of playing the game. These include when your (computer-controlled) competitors can start building, how many of them there are, and how intelligent they are. You can also control how much the subsidy mutliplier is for subsidised routes, and how stable/volitile the in-game economy is. You can also set how you want the terrain to be configured in a random game.
Game Settings lets you set regional settings - currency, language, town names, etc. It also lets you select the resolution to run the game at, as well as the screenshot format to use.
Configure Patches lets you select which patches to use in the game. This allows you to set the game play to either original Transport Tycoon Deluxe compatible mode or a mode more like playing under TTD-Patch. Patches include building on slopes, longer bridges, longer trains, pre-signals, and TTD-Patch compatible handling of non-stop orders.
2.1 Gameplay
This section of the manual is written with the assumption that you already know the gameplay basics of Transport Tycoon Deluxe, on either DOS or Windows. As you must have the Windows Transport Tycoon Deluxe CD to play OpenTTD, you should either have a paper manual or the complete manual in PDF format on the disk. This section will only cover the gameplay differences from Transport Tycoon Deluxe.
2.2 Station Construction
In OpenTTD, you can build rail stations up to seven squares long and with up to seven platforms. You can also have stations spreading across far larger distances, allowing a large rail station to be connected to a large airport, for instance.
However, there is an even more noticable difference in rail station construction. You may now add platforms and lenght to a station after it has been built, and you may also add platforms of a different type. Users of TTDPatch will be used to this behaviour. But beyond what TTDPatch has, you can make stations of uneven lenght/width, and even ones with perpendicular tracks. You can also delete single tiles or tracks from a station, by holding down Shift before pressing the station construction button.
2.3 Checkpoint Stations
Checkpoint stations (the small blue item in the rail construction window) are small 1x1 stations. They must be built on top of pre-existing track. They do not accept or produce carge of any kind. They exist solely for use as route points. They become useful when dealing with large networks where trains may attempt to route themselves along undesirable or impossible routes. As an alternative to checkpoint stations, you can also direct trains to visit depots along the way. This has the advantage of also servicing the train and hence the train will rarely to never need to depart from its route to be serviced.
2.4 Freeform Rail Laying.
Along side the other rail laying buttons, you will see a button that looks somewhat like a crossing. This is the freeform rail laying tool., and it allows you to drag rail in any direction to lay it. This has a number of advantages, one of the main ones being that it can seriously speed up the laying of diagonal tracks.
2.5 Vehicle Queuing (with Quantum Effects)
This useful addition to OpenTTD means that road vehicles will queue outside a road station to wait for a space rather than attempt to enter it immediately. As anyone who has operated a large road network with busy stations will know, road vehicles quickly pile up inside stations. This will prevent that. The Quantum Effects are down to a bug in the game that means that mutliple vehicles will often only take up one space in the queue. However, this is almost too useful to fix, and should still be there in later versions. This can be enabled/disabled.
2.6 Building On Slopes
This allows you to build roads, rails, stations and depots on slopes. It also allows the construction of trasmitters and lighthouses on slopes in the scenario editor. There are some minor differences between OpenTTD's and TTD-Patch's handling of building on slopes, the main one being that bridges must still have solid land at their endings.
2.7 Long Bridges
OpenTTD allows you to constuct bridges up to 127 squares - half the size of the current map. This means that the crossing of large estuaries, such at the Bristol Channel in the original "West Country 90210" scenario can be acheived with one bridge instead of many bridges with staging points.
2.8 Long trains
OpenTTD allows trains of around 60 cars length, hence allowing you to use 7 square stations to their capacity and beyond.
2.9 Speed Display
This addition to OpenTTD allows you to see the current speed of any vehicle in their status window. Just open the status window of a vehicle and you can see the speed at that given moment. This allows you to see wheter better bridges, flatter/straighter track or more powerful engines could be used to increase the speed of a vehicle
2.10 More Trains, More Ships, More Everything!
Virtually any settings - train numbers, start date, what vehicles your competitors can use, etc - can be set in OpenTTD. Just use the Configure Patches menu on the main screen.
2.11 Network Play
See multiplayer.txt for more info.
2.12 Rail Recycling.
This button, at the end of the train construction window, lets you 'recycle' track to a new type. It also works on bridges, tunnels, stations and depots.
2.13 Canal Building
This button, at the end of the water construction window, lets you build canals and shiplifts across the landscape. These act just like normal water.

View File

@@ -0,0 +1,24 @@
It's gone
The main goal with the package system was to make it as simple as possible to update. The problem was that some files inside the data folder should be updated and not others. Now the data files have been moved inside OpenTTD itself and to make it even easier, the same goes for the lang dir. There will no longer be an issue where people have different versions of grf files, language files and OpenTTD.
To install simply copy OpenTTD into the folder you want
If it is your current folder with outdated grf files, you should remove
canalsw.grf
openttd.grf
opntitle.dat
signalsw.grf
trkfoundw.grf
THE TTD GRF FILES ARE STILL NEEDED!
They need to be inside a folder called "data" in the same folder as OpenTTD. Create it if you have none. It should contain:
sample.cat
trg1r.grf
trgcr.grf
trghr.grf
trgir.grf
trgtr.grf
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
You should also use the data folder to add any custom grf files if you like

View File

@@ -0,0 +1,36 @@
Since you are reading this, OpenTTD have crashed. This file tells you how
to fix the most common problems or make to make a bug report, that the
developers can use to track down the problem
If it is an assert, OpenTTD will open the console for you, if it is truly a crash, you have to do it yourself. The Console is located at /Applications/Utilities/Console.
The problem is near the button of the page
The problems are as follows:
NOTE: build from source means to download the source and compile
yourself. If you get one of the build from source error with the version
that is downloaded on a dmg file, you should make a bug report
--Didn't find a needed file:
you just give it the file it asks for. It even tells you what
folder it wants it in
most common version of this problem is "Error: Cannot open file
'data/sample.cat'"
if you get that one, that means that you haven't got all the
needed files from the WINDOWS version of TTD
or if you build from source,
--Error: No available language packs
you need at least one .lng file in your lang folder. This applies
only to people who build from source
--spritecache.c:237: failed assertion `b'
you got an outdated grf file. Update from the data folder in the
source. This applies only to people, who build from source
--assertion error that are not triggered by one of the errors listed in
this file:
you most likely found a bug. Write down the assertion and try to
see if you can reproduce it. If you can, make a
savegame from just before it happens (autosaves are useful here)
and post a bugreport with it on sourceforge
Write what you did to trigger the bug and what assertion it made

View File

@@ -0,0 +1,62 @@
Compiling and developing OpenTTD on MandrakeLinux 10.0 Official
A quick guide to get started with OpenTTD development on Linux.
---------------------------------------------------------------
1.) RPMs:
Most packages that are required for development (like gcc) should already be installed on your box. You will require those RPMs additionally:
- libsdl1.2-devel-1.2.7-2mdk
- subversion-1.0.1-1mdk (+ dependencies)
- libsvn_ra_svn1_0-1.0.1-1mdk
2.) Subversion:
To obtain the source code from the subversion server type
$ svn co svn://svn.openttd.com/openttd/trunk openttd
from command line to dump the code into the directory 'openttd'.
To update your working copy to the latest revision use
$ svn update
Don't worry, your version will be merged with the latest version.
The command
$ svn diff > mypatch.diff
creates a patch file (aka diff file) which you can submit to the developers to share your improvements.
You can undo changes to a file with
$svn revert filename
3.) Required data files:
Copy the following files from Transport Tycoon Deluxe to openttd/data/
sample.cat
trg1r.grf
trgcr.grf
trghr.grf
trgir.grf
trgtr.grf
(Alternatively you can use the TTD GRF files from the DOS version: TRG1.GRF, TRGC.GRF, TRGH.GRF, TRGI.GRF, TRGT.GRF. A few minor graphical glitches with the DOS graphics remain. E.g. the autorail button in the rail toolbar doesn't look as nice as with the Windows graphics.)
4.) Compiling and running:
Compile OpenTTD with
$ make
and run it with
$ ./ttd
5.) Playing the soundtrack:
If you want the original TTD music you need to copy the whole /gm/ directory from Windows. Additionally the TiMidity driver is required:
TiMidity++-2.12.0-0.pre1.4mdk (+ dependencies)
To run OpenTTD with music support type
$ ./ttd -m extmidi
X.) Last Update: $Date: 2004-06-01 19:08:09 +0200 (Tue, 01 Jun 2004) $
Written for revision $Rev: 710 $

View File

@@ -15,13 +15,10 @@ LIBRARIES REQUIRED FOR END USERS
SDL.DLL (SDL 1.2.7) and FSLib.dll are required to use this program: SDL.DLL (SDL 1.2.7) and FSLib.dll are required to use this program:
these can be downloaded from the Files section at these can be downloaded from the Files section at
http://sourceforge.net/projects/openttd/ - see "os2-useful-v1.1.zip". http://sourceforge.net/projects/openttd/ - see "os2-useful.zip".
Version 20051222 of SDL or later is required. This can be found at (Note that a newer version of SDL is now available at
http://sdl.netlabs.org/. ftp://ftp.netlabs.org/pub/sdl/sdl-dev-os2-2004-12-22.zip which may
help solve some problems).
Please note that earlier SDL releases will probably NOT work with
OpenTTD. If you experience problems with OpenTTD, please check
your SDL and FSLib.dll versions (both must match).
Note that to actually play the game, I have found in my own Note that to actually play the game, I have found in my own
experience that a version of the Scitech Display Drivers or its later experience that a version of the Scitech Display Drivers or its later
@@ -50,10 +47,6 @@ To enable music, start OpenTTD with the command line:
If I hear enough responses that both music and sound work together (it might If I hear enough responses that both music and sound work together (it might
just be my system), I'll have the defaults changed. just be my system), I'll have the defaults changed.
Please note also that the GCC version does not currently support the MCI MIDI
system.
A NOTE ABOUT DEDICATED MULTIPLAYER SERVERS A NOTE ABOUT DEDICATED MULTIPLAYER SERVERS
------------------------------------------ ------------------------------------------
@@ -64,8 +57,6 @@ directly will result in the console not being displayed. You may
still pass any other parameters ('-D' is already passed) to still pass any other parameters ('-D' is already passed) to
dedicated.cmd. dedicated.cmd.
You can find the dedicated.cmd file in the os/os2 directory.
========================= =========================
BUILDING THE OS/2 VERSION BUILDING THE OS/2 VERSION
========================= =========================
@@ -73,33 +64,16 @@ BUILDING THE OS/2 VERSION
Compiler Compiler
-------- --------
Innotek GCC, an OS/2 port of the popular GCC compiler, was used to build OpenTTD. Open Watcom 1.3 was used to build OpenTTD (earlier versions will
See www.innotek.de for more information. You WILL need a reasonably UNIX-like NOT work). See http://www.openwatcom.org/ to download it. It may
build environment in order to build OpenTTD successfully - the following link also be possible to build OpenTTD with GCC: I attempted this
may help to set one up (although some of the links from that page are broken): before using Open Watcom, but found the tools available for OS/2
at the time to be a bit more tricky to get working.
http://www.mozilla.org/ports/os2/gccsetup.html Due to complexities in my set-up, I actually used the Win32 version
of Open Watcom to initially compile OpenTTD for OS/2. There should
Alternatively, Paul Smedley's ready-to-go GCC build environment has been known to be no reason of course why the OS/2 version cannot be used, and I
successfully build the game: have subsequently built OpenTTD successfully this way.
http://www.smedley.info/os2ports/index.php?page=build-environment
To build, you should, if your environment is set up well enough, be able to just
type `./configure' (or `sh configure' if you're using the OS/2 shell) and `make'.
You may have to manually specify `--os OS2' on the configure command line, as
configure cannot always detect OS/2 correctly.
A note on Open Watcom
---------------------
Open Watcom C/C++ was previously used to build OpenTTD (version 0.4.x and earlier).
However, due to advanced C++ features used in the YAPF portion of OpenTTD 0.5
in particular, the compiler is no longer able to build the game at the moment.
Hopefully one day Open Watcom will be able to catch up and we will be able to build
the game once again (it's easier than getting an OS/2 UNIX-like environment set up
in my opinion!), but until then, OpenTTD 0.5 and later can only be built with GCC.
Libraries Required Libraries Required
------------------ ------------------
@@ -110,22 +84,42 @@ to an IDE project file and built a library. Do not use the makefiles
provided, they are not designed for Watcom (apart from SDL): provided, they are not designed for Watcom (apart from SDL):
- zlib - zlib
http://www.zlib.org/ http://www.zlib.org/ - contains a makefile for OS/2, but is out
of date and uses EMX, ignore this
- libpng - libpng
http://www.libpng.org/ http://www.libpng.org/ - contains an EMX/gcc makefile, ignore this
- SDL for OS/2 - SDL for OS/2
ftp://ftp.netlabs.org/pub/sdl/sdl-1.2.7-src-20051222.zip used for For 0.3.5, I used ftp://ftp.netlabs.org/pub/sdl/SDL-1.2.7-src-20040908a.zip -
0.4.7 take SDL.dll and SDL.lib from the src/ directory. Note that 20041222 is
out now, which is recommended for stability updates.
- Freetype If you do not wish to build the libraries yourself, pre-built versions
http://freetype.sourceforge.net/ can be downloaded from the Files section at
http://sourceforge.net/projects/openttd/ - see "os2-useful.zip".
Currently, there are no pre-built libraries available for GCC. If you manage to get A Note About Subversion Revision Numbers
OpenTTD working on Watcom though (do let us know if this is the case!), pre-built ----------------------------------------
versions can be downloaded from the Files section at
http://sourceforge.net/projects/openttd/ - see "os2-useful-v1.1.zip". The project file uses a bit of a hack to find out the SVN revision number and
create an appropriate rev.c file. You'll need the SVN tools in your path
(specifically, "svnversion"). If "svnversion" can't be found, a generic rev.c
with the revision set to "norev000" will be created. To specifically force a
version number, set the environment variable "RELEASE" to the number (eg, "0.3.6")
-before- starting the Open Watcom IDE (which must be launched from the same shell
session). Also, beware, as you WILL cause incompatibilities if you try to
play a multiplayer game with a different version.
Compiling
---------
To compile, open the os/os2/openttd.wpj file in the IDE and first build
the strgen.exe target. This will build the .lng file generator, and will
also attempt to build all the language files (plus the table\strings.h
file which is required for openttd.exe to be built). Once strgen.exe and
the language files are built successfully, you can build the openttd.exe
target.
Contact Information Contact Information
------------------- -------------------
@@ -134,6 +128,4 @@ If you have any questions regarding OS/2 issues, please contact me
(owen@owenrudge.net) and I'll try to help you out. For general OpenTTD (owen@owenrudge.net) and I'll try to help you out. For general OpenTTD
issues, see the Contacting section of readme.txt. issues, see the Contacting section of readme.txt.
Thanks to Paul Smedley for his help with getting OpenTTD to compile under GCC on OS/2. - Owen Rudge
- Owen Rudge, 24th June 2007

View File

@@ -1,108 +0,0 @@
Compiling OpenTTD using Microsoft Visual C++
Last updated: 2010-01-03
--------------------------------------------
PLEASE READ THE ENTIRE DOCUMENT BEFORE DOING ANY ACTUAL CHANGES!!
SUPPORTED MSVC COMPILERS
------------------------
OpenTTD includes projects for MSVC 2005.NET and MSVC 2008.NET. Both will
compile out of the box, providing you have the required libraries/headers;
which ones, see below. There is no support for VS6 or MSVC 2002, or
MSVC 2003.NET. You are therefore strongly encouraged to either upgrade to
MSVC 2008 Express (free) or use GCC.
1) REQUIRED FILES
-----------------
You might already have some of the files already installed, so check before
downloading; mostly because the DirectX SDK and Platform SDK are about
500MB each.
Download the following files:
* openttd-useful.zip (http://binaries.openttd.org/extra/openttd-useful/)
* DirectX 8.1 SDK (http://neuron.tuke.sk/~mizanin/eng/Dx81sdk-include-lib.rar) (or alternatively the latest DirectX SDK from Microsoft)
* MS Windows Platform SDK (http://www.microsoft.com/downloads/details.aspx?FamilyId=A55B6B43-E24F-4EA3-A93E-40C0EC4F68E5&displaylang=en)
* afxres.h (http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H)
...and of course the newest source from svn://svn.openttd.org/trunk
You need an SVN-client to download the source from subversion:
* CLI Subversion (http://subversion.tigris.org/)
* GUI TortoiseSVN (http://tortoisesvn.tigris.org/)
2) INCLUDES AND LIBRARIES
-------------------------
Put the newly downloaded files in the VC lib\ and include\ directories; where
"C:\Program Files\Microsoft Visual Studio 9.0\VC" is your location of Visual C.
If you are compiling for an x64 system, use the include\ and lib\ directories
from the win64/ folder.
* openttd-useful.zip\include\*
* afxresh.h
to > C:\Program Files\Microsoft Visual Studio 9.0\VC\Include
* openttd-useful.zip\lib\*
to > C:\Program Files\Microsoft Visual Studio 9.0\VC\Lib
Custom directories might be recommended, check 2.2)
2.1) INCLUDES AND LIBRARIES - DIRECTX/PLATFORM SDK
--------------------------------------------------
Basically the same procedure as with the useful zip file, providing
you are not using the Microsoft installer. Put the include files in the
include\ directory and the library files to the Lib\ directory.
It is recommended to use custom directories so you don't overwrite any
default header or library files.
2.2) CUSTOM DIRECTORIES
-----------------------
If you have put the above include and/or library files into custom folders,
MSVC will not find them by default. You need to add these paths to VC through:
Tools > Options > Projects and Solutions > VC++ Directories > show directories for
* Include files: Add the DirectX/Platform SDK include dir you've created
* Library files: Add the path to the SDK custom lib dir
NOTE: make sure that the directory for the DirectX SDK is the first one in the
list, above all others, otherwise compilation will most likely fail!!
3) TTD GRAPHICS FILES
---------------------
See section 4.1 of readme.txt for the required 3rdparty files and how to install them.
4) COMPILING
------------
Open trunk/openttd_vs[89]0.sln
Set the build mode to 'Release' in
Build > Configuration manager > Active solution configuration > select "Release"
Compile...
If everything works well the binary should be in trunk/objs/Win[32|64]/Release/openttd.exe
5) EDITING, CHANGING SOURCE CODE
--------------------------------
Set the build mode (back to) 'Debug'
Change the startup project to openttd by right-clicking the 'openttd' project
in the Solution Explorer and selecting 'Set as Startup Project'. The 'openttd'
project should now show up bold instead of 'strgen'.
6) PROBLEMS?
------------
If compilation fails, double-check that you are using the latest SVN (!)
source. If it still doesn't work, check in on IRC (irc://irc.oftc.net/openttd),
to ask about reasons; or just wait. The problem will most likely solve itself
within a few days as the problem is noticed and fixed.
An up-to-date version of this README can be found on the wiki:
http://wiki.openttd.org/Microsoft_Visual_C%2B%2B_2008_Express_Editions

View File

@@ -0,0 +1,105 @@
Compiling OpenTTD using Microsoft Visual C++ 6.0
---Step 1
Download the following files:
* Useful.zip (http://sourceforge.net/project/showfiles.php?group_id=103924&package_id=114307&release_id=228633)
* SDL-1.2.8-VC6.zip (http://www.libsdl.org/release/SDL-devel-1.2.8-VC6.zip)
* DirectX7.0 SDK (http://www.tt-forums.net/download.php?id=15989) (or alternatively the latest DirectX SDK from Microsoft)
* afxres.h (http://www-d0.fnal.gov/d0dist/dist/packages/d0ve/devel/windows/AFXRES.H)
...and of course the newest source from svn://svn.openttd.com/trunk
(The alpha version of the new map array can be found at svn://svn.openttd.com/branch/map)
You have to have and SVN-client to download the source:
* Command line version (http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=91)
* TortoiseSVN (http://tortoisesvn.tigris.org/download.html)
---Step 2
Put the newly downloaded files in the VC lib and include directories (Where C:\program files\ is your local location of VC)
* zconf.h [useful.zip]
* zlib.h [useful.zip]
* png.h [useful.zip]
* pngconf.h [useful.zip]
* afxres.h
in
C:\Program Files\Microsoft Visual Studio\VC98\Include
and
* zlibstat.lib [useful.zip]
* SDL.lib [SDL.zip]
* libpng.lib [useful.zip]
in
C:\Program Files\Microsoft Visual Studio\VC98\Lib
---Step 3: DirectX SDK
(This should work with the latest DirectX SDK as well.) The installation with DirectX 7 was odd, so you'd better use the version available via the forum, see also the download link on top.
There are 2 folder in the compressed file: Include and Lib
Copy all files from Include folder to
C:\Program Files\Microsoft Visual Studio\VC98\Include
and all files from Lib folder to
C:\Program Files\Microsoft Visual Studio\VC98\Lib
You can also make custom directories, for libraries (.lib) and includes/header files (.h) and add it to the VC paths via:
Tools -> Options -> Directories -> show directories for:
a) include files (the include dir: C:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\include )
b) library files (the lib dir, C:\Program Files\Microsoft Visual Studio\VC98\DirectX 7 SDK\lib )
---Step 4
Copy the following files from Transport Tycoon Deluxe to the data folder
* sample.cat
* trg1r.grf
* trgcr.grf
* trghr.grf
* trgir.grf
* trgtr.grf
---Step 5
Open trunk/ttd.dsw
Build menu > Set active configuration > Select: "ttd - Win32 Release with PNG"
Compile...
Now it should work, it worked for me :)
From r1319 you can compile branch/map in Debug mode (by Bociusz)
If it's not working, and you checked that you using the newest SVN (!) report to Bociusz on IRC (irc://irc.freenode.net/#openttd)
Go ahead and make that patch! Happy Hacking! :)
Originally written by Dribbel
Project file updating by Bociusz

View File

@@ -1,211 +0,0 @@
OpenTTD's admin network
Last updated: 2011-01-20
------------------------------------------------------------------------
Table of contents
-----------------
1.0) Preface
2.0) Joining the network
3.0) Asking for updates
* 3.1) Polling manually
4.0) Sending rcon commands
5.0) Sending chat
* 5.1) Receiving chat
6.0) Disconnecting
7.0) Certain packet information
1.0) Preface
---- -------
The admin network provides a dedicated network protocol designed for other
applications to communicate with OpenTTD. Connected applications can execute
console commands remotely (rcon commands) with no further authentication.
Furthermore information about clients and companies can be provided.
Admin applications remain connected when starting a new game or loading a saved
game in contrast to normal OpenTTD clients that get disconnected.
This document describes the admin network and its protocol.
Please refer to the mentioned enums in src/network/core/tcp_admin.h
Please also note that further improvements to the admin protocol can mean that
more packet types will be sent by the server. For forward compatibility it is
therefore wise to ignore unknown packets. Future improvements might also add
additional data to packets. This data should be ignored. Data will never be
removed from packets in later versions, except the possibility that complete
packets are dropped in favour of a new packet.
This though will be reflected in the protocol version as announced in the
ADMIN_PACKET_SERVER_PROTOCOL in section 2.0).
A reference implementation in Java for a client connecting to the admin interface
can be found at: http://dev.openttdcoop.org/projects/joan
2.0) Joining the network
---- -------------------
Create a TCP connection to the server on port 3977. The application is
expected to authenticate within 10 seconds.
To authenticate send a ADMIN_PACKET_ADMIN_JOIN packet.
The server will reply with ADMIN_PACKET_SERVER_PROTOCOL followed directly by
ADMIN_PACKET_SERVER_WELCOME.
ADMIN_PACKET_SERVER_PROTOCOL contains details about the protocol version.
It is the job of your application to check this number and decide whether
it will remain connected or not.
Furthermore, this packet holds details on every AdminUpdateType and the
supported AdminFrequencyTypes (bitwise representation).
ADMIN_PACKET_SERVER_WELCOME contains details on the server and the map,
e.g. if the server is dedicated, its NetworkLanguage, size of the Map, etc.
Once you have received ADMIN_PACKET_SERVER_WELCOME you are connected and
authorized to do your thing.
The server will not provide any game related updates unless you ask for them.
There are four packets the server will none the less send, if applicable:
- ADMIN_PACKET_SERVER_ERROR
- ADMIN_PACKET_SERVER_WELCOME
- ADMIN_PACKET_SERVER_NEWGAME
- ADMIN_PACKET_SERVER_SHUTDOWN
However, ADMIN_PACKET_SERVER_WELCOME only after a ADMIN_PACKET_SERVER_NEWGAME
3.0) Asking for updates
---- ------------------
Asking for updates is done with ADMIN_PACKET_ADMIN_UPDATE_FREQUENCY.
With this packet you define which update you wish to receive at which
frequency.
Note: not every update type supports every frequency. If in doubt, you can
verify against the data received in ADMIN_PACKET_SERVER_PROTOCOL.
The server will not confirm your registered update. However, asking for an
invalid AdminUpdateType or a not supported AdminUpdateFrequency you will be
disconnected from the server with NETWORK_ERROR_ILLEGAL_PACKET.
Additional debug information can be found with a debug level of net=3.
ADMIN_UPDATE_DATE results in the server sending:
- ADMIN_PACKET_SERVER_DATE
ADMIN_UPDATE_CLIENT_INFO results in the server sending:
- ADMIN_PACKET_SERVER_CLIENT_JOIN
- ADMIN_PACKET_SERVER_CLIENT_INFO
- ADMIN_PACKET_SERVER_CLIENT_UPDATE
- ADMIN_PACKET_SERVER_CLIENT_QUIT
- ADMIN_PACKET_SERVER_CLIENT_ERROR
ADMIN_UPDATE_COMPANY_INFO results in the server sending:
- ADMIN_PACKET_SERVER_COMPANY_NEW
- ADMIN_PACKET_SERVER_COMPANY_INFO
- ADMIN_PACKET_SERVER_COMPANY_UPDATE
- ADMIN_PACKET_SERVER_COMPANY_REMOVE
ADMIN_UPDATE_COMPANY_ECONOMY results in the server sending:
- ADMIN_PACKET_SERVER_COMPANY_ECONOMY
ADMIN_UPDATE_COMPANY_STATS results in the server sending:
- ADMIN_PACKET_SERVER_COMPANY_STATS
ADMIN_UPDATE_CHAT results in the server sending:
- ADMIN_PACKET_SERVER_CHAT
ADMIN_UPDATE_CONSOLE results in the server sending:
- ADMIN_PACKET_SERVER_CONSOLE
ADMIN_UPDATE_CMD_LOGGING results in the server sending:
- ADMIN_PACKET_SERVER_CMD_LOGGING
3.1) Polling manually
---- ----------------
Certain AdminUpdateTypes can also be polled:
- ADMIN_UPDATE_DATE
- ADMIN_UPDATE_CLIENT_INFO
- ADMIN_UPDATE_COMPANY_INFO
- ADMIN_UPDATE_COMPANY_ECONOMY
- ADMIN_UPDATE_COMPANY_STATS
- ADMIN_UPDATE_CMD_NAMES
ADMIN_UPDATE_CLIENT_INFO and ADMIN_UPDATE_COMPANY_INFO accept an additional
parameter. This parameter is used to specify a certain client or company.
Setting this parameter to UINT32_MAX (0xFFFFFFFF) will tell the server you
want to receive updates for all clients or companies.
Not supported AdminUpdateType in the poll will result in the server
disconnecting the application with NETWORK_ERROR_ILLEGAL_PACKET.
Additional debug information can be found with a debug level of net=3.
4.0) Sending rcon commands
---- ---------------------
Rcon runs separate from the ADMIN_UPDATE_CONSOLE AdminUpdateType. Requesting
the execution of a remote console command is done with the packet
ADMIN_PACKET_ADMIN_RCON.
Note: No additional authentication is required for rcon commands.
The server will reply with a ADMIN_PACKET_SERVER_RCON packet. Applications
will not receive the answer twice if they have asked for the AdminUpdateType
ADMIN_UPDATE_CONSOLE, as the result is not printed on the servers console
(just like clients rcon commands).
Furthermore, sending a 'say' command (or any similar command) will not
be sent back into the admin network.
Chat from the server itself will only be sent to the admin network when it
was not sent from the admin network.
5.0) Sending chat
---- ------------
Sending a ADMIN_PACKET_ADMIN_CHAT results in chat originating from the server.
Currently four types of chat are supported:
- NETWORK_ACTION_CHAT
- NETWORK_ACTION_CHAT_CLIENT
- NETWORK_ACTION_CHAT_COMPANY
- NETWORK_ACTION_SERVER_MESSAGE
NETWORK_ACTION_SERVER_MESSAGE can be sent to a single client or company
using the respective DestType and ID.
This is a message prefixed with the 3 stars, e.g. *** foo has joined the game
5.1) Receiving chat
---- -------------
Register ADMIN_UPDATE_CHAT at ADMIN_FREQUENCY_AUTOMATIC to receive chat.
The application will be able to receive all chat the server can see.
The configuration option network.server_admin_chat specifies whether
private chat for to the server is distributed into the admin network.
6.0) Disconnecting
---- -------------
It is a kind thing to say good bye before leaving. Do this by sending the
ADMIN_PACKET_ADMIN_QUIT packet.
7.0) Certain packet information
---- --------------------------
All ADMIN_PACKET_SERVER_* packets have an enum value greater 100.
ADMIN_PACKET_SERVER_WELCOME
Either directly follows ADMIN_PACKET_SERVER_PROTOCOL or is sent
after a new game has been started or a map loaded, i.e. also
after ADMIN_PACKET_SERVER_NEWGAME.
ADMIN_PACKET_SERVER_CLIENT_JOIN and ADMIN_PACKET_SERVER_COMPANY_NEW
These packets directly follow their respective INFO packets. If you receive
a CLIENT_JOIN / COMPANY_NEW packet without having received the INFO packet
it may be a good idea to POLL for the specific ID.
ADMIN_PACKET_SERVER_CMD_NAMES and ADMIN_PACKET_SERVER_CMD_LOGGING
Data provided with these packets is not stable and will not be
treated as such. Do not rely on IDs or names to be constant
across different versions / revisions of OpenTTD.
Data provided in this packet is for logging purposes only.

58
docs/console.txt Normal file
View File

@@ -0,0 +1,58 @@
OPENTTD INGAME CONSOLE DOCUMENTATION
====================================
http://wiki.openttd.org/index.php/OpenTTDDevBlackBook
for detailed information
*** WARNING **
This document is out of date
*** WARNING **
HOTKEY: BACKQUOTE (aka tilde, the key left to "1")
COMMANDS:
---------
echo [string]
echoc [color-code] [string]
exit
debug_level [0-9]
dump_vars [filter]
help
list_cmds [filter]
list_vars [filter]
printf [formatstring] [var] [var] [var]....
printfc [color-code] [formatstring] [var] [var] [var]....
quit
random
screenshot ["big"/"no_con"]
VARIABLES:
----------
*con_developer
-> true = console debugging info
-> false = no output
*developer
-> 0 = no output
-> 1 = console error output [like command not found]
-> 2 = console error and debug output
*cursor_rate
-> 1-12 = defines the cursor blink interval
VARIABLE HANDLING:
------------------
developer = 0
developer ++
temp_string = test
temp_string = "my little"
printf "%s world" temp_string
---------------------------------------------------
feel free to add more commands and use this in-game
console for your debugging / enhancements

20
docs/directmusic.txt Normal file
View File

@@ -0,0 +1,20 @@
Notes about DirectMusic driver for Win32
----------------------------------------
If compiling under MinGW32, you require the DirectX 7.0 files for MinGW32, available from
http://alleg.sourceforge.net/files/dx70_mgw.zip.
If compiling under MSVC 6.0, you require the equivalent for MSVC, available from
http://alleg.sourceforge.net/files/dx70_min.zip. MSVC 7.0/7.1 include header files that
are recent enough.
If you do not want to compile the DirectMusic driver, undefine WIN32_ENABLE_DIRECTMUSIC_SUPPORT
in stdafx.h.
Bugs, etc
---------
- The volume control doesn't work properly. I'll fix this soon.
Owen Rudge
14th March 2004

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

File diff suppressed because it is too large Load Diff

View File

@@ -1,616 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name="Author" content="Marcin Grzegorczyk">
<meta name="Description" content="Structure of OpenTTD (OTTD) landscape arrays">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>OpenTTD Landscape externals</title>
</head>
<body>
<h3><a name="Landscape">Landscape</a></h3>
<p>
These are the different house types available on standard game.<br>
<small>Note: In the climate list, 'sub-arctic' means below the snow line, and 'snow' means above the snow line in the sub-arctic climate.</small>
</p>
<table>
<tr>
<th align=left>Type&nbsp;</th>
<th align=left>Size&nbsp;</th>
<th align=left>Climates&nbsp;</th>
<th align=left>Description</th>
</tr>
<tr>
<td nowrap valign=top><tt>00</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>01</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>02</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>small block of flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>03</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>church</td>
</tr>
<tr>
<td nowrap valign=top><tt>04</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-arctic, sub-tropical</td>
<td align=left>large office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>05</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>large office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>06</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>town houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>07</tt>..<tt>08</tt>&nbsp; </td>
<td>1&times;2</td>
<td>temperate</td>
<td align=left>hotel</td>
</tr>
<tr>
<td nowrap valign=top><tt>09</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-arctic, sub-tropical&nbsp;&nbsp;</td>
<td align=left>statue</td>
</tr>
<tr>
<td nowrap valign=top><tt>0A</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-arctic, sub-tropical</td>
<td align=left>fountain</td>
</tr>
<tr>
<td nowrap valign=top><tt>0B</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>park (with a pond)</td>
</tr>
<tr>
<td nowrap valign=top><tt>0C</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>park (with an alley)</td>
</tr>
<tr>
<td nowrap valign=top><tt>0D</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>0E</tt>..<tt>10</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>various types of shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>11</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-arctic, sub-tropical</td>
<td align=left>modern office building</td>
</tr>
<tr>
<td nowrap valign=top><tt>12</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>warehouse</td>
</tr>
<tr>
<td nowrap valign=top><tt>13</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>office block (with spiral stairway on the side)</td>
</tr>
<tr>
<td nowrap valign=top><tt>14</tt>..<tt>17</tt>&nbsp; </td>
<td>2&times;2</td>
<td>temperate</td>
<td align=left>stadium</td>
</tr>
<tr>
<td nowrap valign=top><tt>18</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>old houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>19</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>cottages</td>
</tr>
<tr>
<td nowrap valign=top><tt>1A</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>1B</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>1C</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>1D</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>1E</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-tropical</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>1F</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>theatre</td>
</tr>
<tr>
<td nowrap valign=top><tt>20</tt>..<tt>23</tt>&nbsp; </td>
<td>2&times;2</td>
<td>temperate, sub-arctic, sub-tropical</td>
<td align=left>stadium (modern style)</td>
</tr>
<tr>
<td nowrap valign=top><tt>24</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate, sub-arctic, sub-tropical</td>
<td align=left>offices (the modern 'vertical tube' style)</td>
</tr>
<tr>
<td nowrap valign=top><tt>25</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>26</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>27</tt>&nbsp; </td>
<td>1&times;1</td>
<td>temperate</td>
<td align=left>cinema</td>
</tr>
<tr>
<td nowrap valign=top><tt>28</tt>..<tt>2B</tt>&nbsp; </td>
<td>2&times;2</td>
<td>temperate</td>
<td align=left>shopping mall</td>
</tr>
<tr>
<td nowrap valign=top><tt>2C</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>2D</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>2E</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>2F</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>30</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>31</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>32</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic, sub-tropical</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>33</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>34</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>35</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>36</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic, sub-tropical</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>37</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>38</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>39</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>3A</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>3B</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>3C</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>church</td>
</tr>
<tr>
<td nowrap valign=top><tt>3D</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>church</td>
</tr>
<tr>
<td nowrap valign=top><tt>3E</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>3F</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>40</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>41</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>42</tt>..<tt>43</tt>&nbsp; </td>
<td>1&times;2</td>
<td>sub-arctic</td>
<td align=left>hotel</td>
</tr>
<tr>
<td nowrap valign=top><tt>44</tt>..<tt>45</tt>&nbsp; </td>
<td>1&times;2</td>
<td>snow</td>
<td align=left>hotel</td>
</tr>
<tr>
<td nowrap valign=top><tt>46</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic, sub-tropical</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>47</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>48</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-arctic</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>49</tt>&nbsp; </td>
<td>1&times;1</td>
<td>snow</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>4A</tt>..<tt>4B</tt>&nbsp; </td>
<td>2&times;1</td>
<td>sub-arctic</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>4C</tt>..<tt>4D</tt>&nbsp; </td>
<td>2&times;1</td>
<td>snow</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>4E</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>houses (with a tree in a corner)</td>
</tr>
<tr>
<td nowrap valign=top><tt>4F</tt>, <tt>50</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>51</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>houses (suburb-type)</td>
</tr>
<tr>
<td nowrap valign=top><tt>52</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>53</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>church</td>
</tr>
<tr>
<td nowrap valign=top><tt>54</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>houses (with two trees in front)</td>
</tr>
<tr>
<td nowrap valign=top><tt>55</tt>, <tt>56</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>57</tt>..<tt>58</tt>&nbsp; </td>
<td>2&times;1</td>
<td>sub-tropical</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>59</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>flats</td>
</tr>
<tr>
<td nowrap valign=top><tt>5A</tt>&nbsp; </td>
<td>1&times;1</td>
<td>sub-tropical</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>5B</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>church</td>
</tr>
<tr>
<td nowrap valign=top><tt>5C</tt>..<tt>61</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>various types of toyland houses</td>
</tr>
<tr>
<td nowrap valign=top><tt>62</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>63</tt>..<tt>64</tt>&nbsp; </td>
<td>1&times;2</td>
<td>toyland</td>
<td align=left>houses ('shoe' style)</td>
</tr>
<tr>
<td nowrap valign=top><tt>65</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>66</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>igloo</td>
</tr>
<tr>
<td nowrap valign=top><tt>67</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>tepees</td>
</tr>
<tr>
<td nowrap valign=top><tt>68</tt>, <tt>69</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>shops and offices</td>
</tr>
<tr>
<td nowrap valign=top><tt>6A</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>tall office block</td>
</tr>
<tr>
<td nowrap valign=top><tt>6B</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>statue</td>
</tr>
<tr>
<td nowrap valign=top><tt>6C</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>teapot-house</td>
</tr>
<tr>
<td nowrap valign=top><tt>6D</tt>&nbsp; </td>
<td>1&times;1</td>
<td>toyland</td>
<td align=left>piggy-bank</td>
</tr>
</table>
</body>
</html>

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