[atanks] 01/13: Import Upstream version 5.5+dfsg

Markus Koschany apo at moszumanska.debian.org
Sat Nov 26 23:05:25 UTC 2016


This is an automated email from the git hooks/post-receive script.

apo pushed a commit to branch master
in repository atanks.

commit e9b004c25eadbb1163d892a80f56118cf26425f4
Author: Markus Koschany <apo at debian.org>
Date:   Sat Nov 26 23:42:30 2016 +0100

    Import Upstream version 5.5+dfsg
---
 COPYING                    |  340 +++
 Changelog                  | 2295 ++++++++++++++++
 Makefile                   |   84 +
 README                     |  241 ++
 README_ru.txt              |  198 ++
 TODO                       |   53 +
 atanks-4.3.spec            |  301 +++
 atanks.desktop             |   10 +
 atanks.ico                 |  Bin 0 -> 23814 bytes
 atanks.png                 |  Bin 0 -> 3140 bytes
 button/0.bmp               |  Bin 0 -> 22854 bytes
 button/1.bmp               |  Bin 0 -> 22854 bytes
 button/10.bmp              |  Bin 0 -> 22854 bytes
 button/11.bmp              |  Bin 0 -> 22854 bytes
 button/12.bmp              |  Bin 0 -> 22854 bytes
 button/13.bmp              |  Bin 0 -> 22854 bytes
 button/14.bmp              |  Bin 0 -> 22854 bytes
 button/15.bmp              |  Bin 0 -> 22854 bytes
 button/16.bmp              |  Bin 0 -> 22854 bytes
 button/17.bmp              |  Bin 0 -> 22854 bytes
 button/18.bmp              |  Bin 0 -> 22854 bytes
 button/19.bmp              |  Bin 0 -> 22854 bytes
 button/2.bmp               |  Bin 0 -> 22854 bytes
 button/20.bmp              |  Bin 0 -> 22854 bytes
 button/21.bmp              |  Bin 0 -> 22854 bytes
 button/22.bmp              |  Bin 0 -> 22854 bytes
 button/23.bmp              |  Bin 0 -> 22854 bytes
 button/24.bmp              |  Bin 0 -> 22854 bytes
 button/25.bmp              |  Bin 0 -> 22854 bytes
 button/26.bmp              |  Bin 0 -> 22854 bytes
 button/27.bmp              |  Bin 0 -> 22854 bytes
 button/3.bmp               |  Bin 0 -> 22854 bytes
 button/4.bmp               |  Bin 0 -> 22854 bytes
 button/5.bmp               |  Bin 0 -> 22854 bytes
 button/6.bmp               |  Bin 0 -> 22854 bytes
 button/7.bmp               |  Bin 0 -> 22854 bytes
 button/8.bmp               |  Bin 0 -> 22854 bytes
 button/9.bmp               |  Bin 0 -> 22854 bytes
 credits.txt                |   69 +
 exporter/export.cpp        |   49 +
 exporter/move.cpp          |   35 +
 misc/0.bmp                 |  Bin 0 -> 662 bytes
 misc/1.bmp                 |  Bin 0 -> 14454 bytes
 misc/10.bmp                |  Bin 0 -> 974 bytes
 misc/11.bmp                |  Bin 0 -> 18054 bytes
 misc/12.bmp                |  Bin 0 -> 1782 bytes
 misc/13.bmp                |  Bin 0 -> 1782 bytes
 misc/14.bmp                |  Bin 0 -> 1782 bytes
 misc/15.bmp                |  Bin 0 -> 1782 bytes
 misc/16.bmp                |  Bin 0 -> 3078 bytes
 misc/17.bmp                |  Bin 0 -> 3932214 bytes
 misc/2.bmp                 |  Bin 0 -> 15054 bytes
 misc/3.bmp                 |  Bin 0 -> 414 bytes
 misc/4.bmp                 |  Bin 0 -> 58 bytes
 misc/5.bmp                 |  Bin 0 -> 58 bytes
 misc/6.bmp                 |  Bin 0 -> 374 bytes
 misc/7.bmp                 |  Bin 0 -> 9094 bytes
 misc/8.bmp                 |  Bin 0 -> 9094 bytes
 misc/9.bmp                 |  Bin 0 -> 90054 bytes
 missile/0.bmp              |  Bin 0 -> 894 bytes
 missile/1.bmp              |  Bin 0 -> 1334 bytes
 missile/10.bmp             |  Bin 0 -> 390 bytes
 missile/11.bmp             |  Bin 0 -> 1134 bytes
 missile/12.bmp             |  Bin 0 -> 2214 bytes
 missile/13.bmp             |  Bin 0 -> 3246 bytes
 missile/14.bmp             |  Bin 0 -> 1134 bytes
 missile/15.bmp             |  Bin 0 -> 1878 bytes
 missile/16.bmp             |  Bin 0 -> 2134 bytes
 missile/17.bmp             |  Bin 0 -> 1350 bytes
 missile/18.bmp             |  Bin 0 -> 1914 bytes
 missile/19.bmp             |  Bin 0 -> 3702 bytes
 missile/2.bmp              |  Bin 0 -> 1654 bytes
 missile/20.bmp             |  Bin 0 -> 670 bytes
 missile/21.bmp             |  Bin 0 -> 1854 bytes
 missile/22.bmp             |  Bin 0 -> 3354 bytes
 missile/23.bmp             |  Bin 0 -> 558 bytes
 missile/24.bmp             |  Bin 0 -> 1026 bytes
 missile/25.bmp             |  Bin 0 -> 4854 bytes
 missile/26.bmp             |  Bin 0 -> 4854 bytes
 missile/27.bmp             |  Bin 0 -> 1134 bytes
 missile/28.bmp             |  Bin 0 -> 4854 bytes
 missile/29.bmp             |  Bin 0 -> 2334 bytes
 missile/3.bmp              |  Bin 0 -> 2334 bytes
 missile/30.bmp             |  Bin 0 -> 2334 bytes
 missile/4.bmp              |  Bin 0 -> 2334 bytes
 missile/5.bmp              |  Bin 0 -> 2334 bytes
 missile/6.bmp              |  Bin 0 -> 2490 bytes
 missile/7.bmp              |  Bin 0 -> 3162 bytes
 missile/8.bmp              |  Bin 0 -> 1110 bytes
 missile/9.bmp              |  Bin 0 -> 2034 bytes
 sound/0.wav                |  Bin 0 -> 12461 bytes
 sound/1.wav                |  Bin 0 -> 35948 bytes
 sound/10.wav               |  Bin 0 -> 966 bytes
 sound/11.wav               |  Bin 0 -> 30139 bytes
 sound/12.wav               |  Bin 0 -> 81202 bytes
 sound/2.wav                |  Bin 0 -> 33708 bytes
 sound/3.wav                |  Bin 0 -> 41126 bytes
 sound/4.wav                |  Bin 0 -> 43436 bytes
 sound/5.wav                |  Bin 0 -> 44332 bytes
 sound/6.wav                |  Bin 0 -> 44588 bytes
 sound/7.wav                |  Bin 0 -> 66348 bytes
 sound/8.wav                |  Bin 0 -> 280 bytes
 sound/9.wav                |  Bin 0 -> 34904 bytes
 src/Makefile               |  148 ++
 src/Makefile.bsd           |  151 ++
 src/Makefile.windows       |  157 ++
 src/allegro.h              |   82 +
 src/atanks.cpp             | 6284 ++++++++++++++++++++++++++++++++++++++++++++
 src/atanks.rc              |   37 +
 src/beam.cpp               |  286 ++
 src/beam.h                 |   74 +
 src/button.cpp             |   67 +
 src/button.h               |   30 +
 src/client.cpp             |  518 ++++
 src/client.h               |   67 +
 src/decor.h                |  169 ++
 src/environment.cpp        | 1168 ++++++++
 src/environment.h          |  180 ++
 src/explosion.cpp          |  439 ++++
 src/explosion.h            |   68 +
 src/externs.h              |   59 +
 src/fade.cpp               |  235 ++
 src/files.cpp              | 1106 ++++++++
 src/files.h                |   90 +
 src/floattext.cpp          |  273 ++
 src/floattext.h            |   95 +
 src/gameloop.cpp           |  590 +++++
 src/gameloop.h             |   16 +
 src/globaldata.cpp         | 1389 ++++++++++
 src/globaldata.h           |  234 ++
 src/globals.h              |  295 +++
 src/imagedefs.h            |   29 +
 src/land.cpp               |  209 ++
 src/land.h                 |  169 ++
 src/main.h                 |  474 ++++
 src/menu.h                 |   69 +
 src/menucontent.h          |  852 ++++++
 src/missile.cpp            |  798 ++++++
 src/missile.h              |   74 +
 src/network.cpp            |  509 ++++
 src/network.h              |   98 +
 src/perlin.cpp             |  158 ++
 src/physobj.cpp            |  250 ++
 src/physobj.h              |   59 +
 src/player.cpp             | 4828 ++++++++++++++++++++++++++++++++++
 src/player.h               |  207 ++
 src/satellite.cpp          |   81 +
 src/satellite.h            |   31 +
 src/sky.cpp                |  433 +++
 src/sky.h                  |  189 ++
 src/tank.cpp               | 1431 ++++++++++
 src/tank.h                 |  100 +
 src/team.cpp               |   35 +
 src/team.h                 |   26 +
 src/teleport.cpp           |  211 ++
 src/teleport.h             |   59 +
 src/text.cpp               |  227 ++
 src/text.h                 |   59 +
 src/update.cpp             |  105 +
 src/update.h               |   43 +
 src/virtobj.cpp            |  212 ++
 src/virtobj.h              |   93 +
 stock/0.bmp                |  Bin 0 -> 4854 bytes
 stock/1.bmp                |  Bin 0 -> 4854 bytes
 stock/10.bmp               |  Bin 0 -> 4854 bytes
 stock/11.bmp               |  Bin 0 -> 4854 bytes
 stock/12.bmp               |  Bin 0 -> 4854 bytes
 stock/13.bmp               |  Bin 0 -> 4854 bytes
 stock/14.bmp               |  Bin 0 -> 4854 bytes
 stock/15.bmp               |  Bin 0 -> 4854 bytes
 stock/16.bmp               |  Bin 0 -> 4854 bytes
 stock/17.bmp               |  Bin 0 -> 4854 bytes
 stock/18.bmp               |  Bin 0 -> 4854 bytes
 stock/19.bmp               |  Bin 0 -> 4854 bytes
 stock/2.bmp                |  Bin 0 -> 4854 bytes
 stock/20.bmp               |  Bin 0 -> 4854 bytes
 stock/21.bmp               |  Bin 0 -> 4854 bytes
 stock/22.bmp               |  Bin 0 -> 4854 bytes
 stock/23.bmp               |  Bin 0 -> 4854 bytes
 stock/24.bmp               |  Bin 0 -> 4854 bytes
 stock/25.bmp               |  Bin 0 -> 4854 bytes
 stock/26.bmp               |  Bin 0 -> 4854 bytes
 stock/27.bmp               |  Bin 0 -> 4854 bytes
 stock/28.bmp               |  Bin 0 -> 4854 bytes
 stock/29.bmp               |  Bin 0 -> 4854 bytes
 stock/3.bmp                |  Bin 0 -> 4854 bytes
 stock/30.bmp               |  Bin 0 -> 4854 bytes
 stock/31.bmp               |  Bin 0 -> 4854 bytes
 stock/32.bmp               |  Bin 0 -> 4854 bytes
 stock/33.bmp               |  Bin 0 -> 4854 bytes
 stock/34.bmp               |  Bin 0 -> 4854 bytes
 stock/35.bmp               |  Bin 0 -> 4854 bytes
 stock/36.bmp               |  Bin 0 -> 1782 bytes
 stock/37.bmp               |  Bin 0 -> 4854 bytes
 stock/38.bmp               |  Bin 0 -> 4854 bytes
 stock/39.bmp               |  Bin 0 -> 4854 bytes
 stock/4.bmp                |  Bin 0 -> 4854 bytes
 stock/40.bmp               |  Bin 0 -> 4854 bytes
 stock/41.bmp               |  Bin 0 -> 4854 bytes
 stock/42.bmp               |  Bin 0 -> 4854 bytes
 stock/43.bmp               |  Bin 0 -> 4854 bytes
 stock/44.bmp               |  Bin 0 -> 4854 bytes
 stock/45.bmp               |  Bin 0 -> 4854 bytes
 stock/46.bmp               |  Bin 0 -> 4854 bytes
 stock/47.bmp               |  Bin 0 -> 4854 bytes
 stock/48.bmp               |  Bin 0 -> 4854 bytes
 stock/49.bmp               |  Bin 0 -> 4854 bytes
 stock/5.bmp                |  Bin 0 -> 4854 bytes
 stock/50.bmp               |  Bin 0 -> 4854 bytes
 stock/51.bmp               |  Bin 0 -> 4854 bytes
 stock/52.bmp               |  Bin 0 -> 4854 bytes
 stock/53.bmp               |  Bin 0 -> 4854 bytes
 stock/54.bmp               |  Bin 0 -> 4854 bytes
 stock/55.bmp               |  Bin 0 -> 4854 bytes
 stock/56.bmp               |  Bin 0 -> 4854 bytes
 stock/57.bmp               |  Bin 0 -> 4854 bytes
 stock/58.bmp               |  Bin 0 -> 4854 bytes
 stock/59.bmp               |  Bin 0 -> 4854 bytes
 stock/6.bmp                |  Bin 0 -> 4854 bytes
 stock/60.bmp               |  Bin 0 -> 4854 bytes
 stock/61.bmp               |  Bin 0 -> 4854 bytes
 stock/62.bmp               |  Bin 0 -> 4854 bytes
 stock/63.bmp               |  Bin 0 -> 4854 bytes
 stock/64.bmp               |  Bin 0 -> 4854 bytes
 stock/65.bmp               |  Bin 0 -> 4854 bytes
 stock/66.bmp               |  Bin 0 -> 4854 bytes
 stock/67.bmp               |  Bin 0 -> 4854 bytes
 stock/68.bmp               |  Bin 0 -> 4854 bytes
 stock/69.bmp               |  Bin 0 -> 4854 bytes
 stock/7.bmp                |  Bin 0 -> 4854 bytes
 stock/70.bmp               |  Bin 0 -> 4854 bytes
 stock/71.bmp               |  Bin 0 -> 4854 bytes
 stock/72.bmp               |  Bin 0 -> 4854 bytes
 stock/73.bmp               |  Bin 0 -> 4854 bytes
 stock/74.bmp               |  Bin 0 -> 4854 bytes
 stock/75.bmp               |  Bin 0 -> 4854 bytes
 stock/76.bmp               |  Bin 0 -> 4854 bytes
 stock/77.bmp               |  Bin 0 -> 4854 bytes
 stock/78.bmp               |  Bin 0 -> 4854 bytes
 stock/8.bmp                |  Bin 0 -> 4854 bytes
 stock/9.bmp                |  Bin 0 -> 4854 bytes
 tank/0.bmp                 |  Bin 0 -> 1894 bytes
 tank/1.bmp                 |  Bin 0 -> 4554 bytes
 tank/10.bmp                |  Bin 0 -> 1894 bytes
 tank/11.bmp                |  Bin 0 -> 2454 bytes
 tank/12.bmp                |  Bin 0 -> 1894 bytes
 tank/13.bmp                |  Bin 0 -> 1894 bytes
 tank/14.bmp                |  Bin 0 -> 1894 bytes
 tank/15.bmp                |  Bin 0 -> 1894 bytes
 tank/2.bmp                 |  Bin 0 -> 4554 bytes
 tank/3.bmp                 |  Bin 0 -> 4554 bytes
 tank/4.bmp                 |  Bin 0 -> 1894 bytes
 tank/5.bmp                 |  Bin 0 -> 1894 bytes
 tank/6.bmp                 |  Bin 0 -> 1894 bytes
 tank/7.bmp                 |  Bin 0 -> 1894 bytes
 tank/8.bmp                 |  Bin 0 -> 1894 bytes
 tank/9.bmp                 |  Bin 0 -> 1894 bytes
 tankgun/0.bmp              |  Bin 0 -> 3126 bytes
 tankgun/1.bmp              |  Bin 0 -> 3126 bytes
 tankgun/2.bmp              |  Bin 0 -> 3126 bytes
 tankgun/3.bmp              |  Bin 0 -> 3126 bytes
 tankgun/4.bmp              |  Bin 0 -> 4150 bytes
 tankgun/5.bmp              |  Bin 0 -> 3126 bytes
 tankgun/6.bmp              |  Bin 0 -> 3126 bytes
 tankgun/7.bmp              |  Bin 0 -> 4150 bytes
 tankgun/8.bmp              |  Bin 0 -> 3126 bytes
 text/Help.pt_BR.txt        |  104 +
 text/Help.txt              |  111 +
 text/Help_ES.txt           |  112 +
 text/Help_fr.txt           |  110 +
 text/Help_it.txt           |  112 +
 text/Help_ru.txt           |  127 +
 text/Help_sk.txt           |  110 +
 text/gloat.pt_BR.txt       |    5 +
 text/gloat.txt             |   17 +
 text/gloat_ES.txt          |   17 +
 text/gloat_de.txt          |   18 +
 text/gloat_fr.txt          |   15 +
 text/gloat_it.txt          |   17 +
 text/gloat_ru.txt          |   17 +
 text/gloat_sk.txt          |   16 +
 text/ingame.pt_BR.txt      |   83 +
 text/ingame.txt            |   83 +
 text/ingame_ES.txt         |   81 +
 text/ingame_de.txt         |   83 +
 text/ingame_fr.txt         |   83 +
 text/ingame_it.txt         |   83 +
 text/ingame_ru.txt         |   83 +
 text/ingame_sk.txt         |   83 +
 text/instr.pt_BR.txt       |   35 +
 text/instr.txt             |   35 +
 text/instr_ES.txt          |   33 +
 text/instr_de.txt          |   35 +
 text/instr_fr.txt          |   35 +
 text/instr_it.txt          |   33 +
 text/instr_ru.txt          |   47 +
 text/instr_sk.txt          |   35 +
 text/kamikaze.pt_BR.txt    |    8 +
 text/kamikaze.txt          |    8 +
 text/kamikaze_ES.txt       |    8 +
 text/kamikaze_de.txt       |    8 +
 text/kamikaze_fr.txt       |    8 +
 text/kamikaze_it.txt       |    8 +
 text/kamikaze_ru.txt       |    8 +
 text/kamikaze_sk.txt       |    8 +
 text/retaliation.pt_BR.txt |   10 +
 text/retaliation.txt       |   10 +
 text/retaliation_ES.txt    |   10 +
 text/retaliation_de.txt    |   10 +
 text/retaliation_fr.txt    |   10 +
 text/retaliation_it.txt    |   10 +
 text/retaliation_ru.txt    |   10 +
 text/retaliation_sk.txt    |   10 +
 text/revenge.pt_BR.txt     |   16 +
 text/revenge.txt           |   24 +
 text/revenge_ES.txt        |   10 +
 text/revenge_de.txt        |   21 +
 text/revenge_fr.txt        |   21 +
 text/revenge_it.txt        |   24 +
 text/revenge_ru.txt        |   24 +
 text/revenge_sk.txt        |   21 +
 text/suicide.pt_BR.txt     |    8 +
 text/suicide.txt           |   16 +
 text/suicide_ES.txt        |   16 +
 text/suicide_de.txt        |   16 +
 text/suicide_fr.txt        |   14 +
 text/suicide_it.txt        |   16 +
 text/suicide_ru.txt        |   16 +
 text/suicide_sk.txt        |   16 +
 text/war_quotes.txt        |   35 +
 text/war_quotes_ES.txt     |   35 +
 text/war_quotes_it.txt     |   35 +
 text/war_quotes_ru.txt     |   21 +
 text/weapons.pt_BR.txt     |  343 +++
 text/weapons.txt           |  343 +++
 text/weapons_ES.txt        |  343 +++
 text/weapons_de.txt        |  343 +++
 text/weapons_fr.txt        |  343 +++
 text/weapons_it.txt        |  343 +++
 text/weapons_ru.txt        |  343 +++
 text/weapons_sk.txt        |  343 +++
 title/.directory           |    3 +
 title/0.bmp                |  Bin 0 -> 921654 bytes
 title/1.bmp                |  Bin 0 -> 1082 bytes
 title/2.bmp                |  Bin 0 -> 1082 bytes
 title/3.bmp                |  Bin 0 -> 1082 bytes
 unicode.dat                |  Bin 0 -> 969257 bytes
 347 files changed, 35254 insertions(+)

diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..4e12446
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+

+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+

+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/Changelog b/Changelog
new file mode 100644
index 0000000..9f6ab17
--- /dev/null
+++ b/Changelog
@@ -0,0 +1,2295 @@
+NOTE: From now on, new changes appear at the top of this file.
+
+May 17, 2012
+    - Fixed typos in makefiles in src directory.
+      Thanks to Ville for submitting this patch.
+
+
+April 8, 2012
+
+    - Updated Portuguese language files in text folder.
+    - Updated menu file with new Portuguese translation.
+      (Thanks ot Jose for providing the new translations.)
+    - Applied src/Makefile patch from Gentoo build process.
+      (Thanks to Michael Sterrett for providing this patch.)
+
+
+============ Atanks-5.3 released ==============
+
+Feb 23, 2012
+
+    - Updated makefile to remove un-needed debugging information.
+    - Various memory leak fixes and checks.
+      Patches provided by Nathan.
+    - Various memory fixes and typo fix.
+      Patches provided by Nathan.
+    - Removed some un-needed variables.
+    - Added locking system which should make Atanks
+      thread safe and more stable.
+      Thanks to Nathan for providing these patches.
+
+
+============ Atanks-5.2 released ==============
+
+    - Updated desktop file with Spanish comment.
+    - Modified makefile to support optional DESTDIR
+      variable.
+    - Added -pthread flag in src/makefile to avoid
+      linking issues.
+      The three patches above all provided by
+      Cristian Morales Vega.
+
+============ Atanks-5.1 released ==============
+
+    - Fixed close button so it skips remaining rounds.
+      Close button now also works during Demo Mode.
+    - Updated atanks.rc file.
+
+
+============ Atanks-5.0 released ===============
+
+June 4, 2011
+    - Window's close button now works on buying screen 
+      and during rounds.
+
+
+============= Atanks-4.9 released ================
+
+
+March 23, 2011
+    - Added Italian language support. 
+      (provided by Roby Alice.)
+
+
+March 7, 2011
+    - Applied update to atanks.rc file to implement
+      game icon in the corner of the window.
+      (Update supplied by Billy Buerger)
+
+
+============ Atanks-4.8 released ==================
+
+
+March 6, 2011
+    - Put in check to prevent AI from buying weapons and items
+      above their tech level.
+    - Fixed lock-up when playing in Demo mode.
+
+Jan 13, 2011
+    - Fixed SDI point defense code so the lasers point at the
+      incoming missile. Thanks to Nolan for supplying this fix.
+
+
+============== Atanks-4.7 released ===================
+
+Sept 5, 2010
+    - Fixed header file includes for FreeBSD.
+    - Now we try to find out if Allegro can't start and exit
+      if we run into a problem.
+    - Fixed bug where command line flags for width and height were ignored.
+    - Partitial shields are restored at the end of rounds.
+    - Tanks should no longer get extra turns during rounds.
+
+
+July 18, 2010
+    - Added patch from CtHx which allows alternative key usage.
+      A, D, W, S for left, right, up, down. The R and F keys in place of
+      pageup and pagedown. The P key will now work like ESC during rounds.
+    - Added header file needed for newer versions of gcc. Thanks to CtHx
+      for pointing out this requirement.
+    - Added patch to support tank movement, using H and J.
+
+
+June 28, 2010
+    - Made it possible to adjust game speed in a more fine-tuned manner.
+    - Shields now reactivate at the end of the player's turn, not beginning.
+    - Large code clean-up to remove support for older config file format.
+
+
+June 12, 2010
+    - Fixed custom background code so that if no image
+      exists, we avoid a crash and generate a standard image.
+
+June 2, 2010
+    - Updated Makefile to match Billy Buerger's.
+    - Shields reactivate if knocked out.
+    - Fixed error where if the first player was neutral, they
+      would not receive credit for victories.
+      Bug reported by CtHx.
+    - Added fix for credits where all players are neutral or
+      the round ends in a draw.
+
+
+========== Atanks-4.6 released =================
+
+May 24, 2010
+    - Added new makefile for OS X and FreeBSD users.
+      Should allow users on both systems to run
+      gmake osxuser
+      To build Atanks
+    - Tank text bounces on player's turn.
+    - Ingame menu is now displayed.
+    - Screen refreshes properly after quitting to menu mid-game.
+    - Tanks fall when they should.
+    - Added timed shots.
+    - Walls are re-drawn occasionally to make sure the player can see them.
+    - Avoid game lock-up when player dies during their turn.
+    - Skip AI when humans are dead now works.
+    - Client cannot take infinte turns.
+
+
+May 7, 2010
+    - Tanks wait to explode after other things have stopped exploding.
+      Makes action easier to follow.
+    - Server IP address can now be 16 characters long on the
+      Network Options menu.
+
+
+April 17, 2010
+    - Updated Makefile to work better with Ubuntu.
+      Fix provided by Neil.
+    - Added Spanish language support.
+      Provided by Marcelo Camacho Moreno.
+    - There are now two game loops. Which one is used depends on
+      on the compiler flags in the Makefile. The options are
+      OLD_GAMELOOP or NEW_GAMELOOP
+    - When using new gameloop, tanks can fire vollies
+      (like the jackhammer) in simultanious mode.
+
+
+============== Atanks-4.5 released ==================
+
+April 7, 2010
+    - Separated tank explosions from tank memory clean up. This
+      should prevent some memory leaks on the client side.
+    - Damage text on the client side now rises and disappears.
+    - When a client is taking too long to fire, the AI will
+      take over the take briefly to shoot.
+
+
+April 1, 2010
+    - Updated OS X entry in Makefile. Hopefully this will allow
+      people to compile on Mac.
+    - Updated main.h to support OS X. This used to piggy-back on
+      the Linux defines, but we can't do that anymore because of
+      Allegro's sound system.
+    - When only AI and netowrk clients are left, the game no longer
+      moves into foast forward (skip AI mode).
+    - Added "make ubuntu" build to work around the default sound driver
+      not working. Thanks to Neil for helping to trouble-shoot this and
+      test the patch.
+
+
+March 16, 2010
+    - Animations move at the proper speed on the client side.
+    - Server now updates client with tank health and shield status.
+    - Client displays tank shields.
+    - Client now displays shield and health information.
+    - Moved war quote code to allow smoother ending for networked games.
+
+
+March 5, 2010
+    - Removed debugging output from Help and Credits screens.
+    - Added client_message variable for passing messages from the client
+      to the main menu.
+    - When players fire before client has received all ground data,
+      the client will resume getting the data.
+    - Corrected spelling in German weapons file.
+      Provided by Simeon.
+    - Upgraded client-side terrain graphics.
+    - Cleaned up compiler warnings.
+    - Code clean-up in do_winner function.
+    - Server now lets client know who won the game.
+    - Client displays winner after game is finished.
+
+
+============== Atanks-4.4 released ================
+
+Febraury 18, 2010
+    - Entire Help text is now displayed when the language is set to Russian.
+
+January 22, 2010
+    - Removed old title screen from data files.
+    - Introduced repaired weapons file from Simeon.
+    - Added check in weapon damage to prevent recursive bug.
+    - Added Locale settings to file loads/saves to fix crash
+      in some regions. Fix submitted by CtHx.
+
+============== Atanks-4.3 released =================
+
+December 27, 2009
+    - Cleaned up memory leak in floating text code.
+    - Made Atanks _not_ use threads by default.
+    - Added command line option to enable thread use.
+    - Removed old shield drawing code.
+    - Created new shield animation.
+    - Added Bigfoot tank style. (Provided by GtHx)
+    - Networking threads are now able to function even
+      if background drawing threads are turned off.
+    - Clicking on tank style buttons causes the
+      new tank style to display properly.
+    - Put a cap on money to make sure even players in loaded games
+      get less than one billion dollars.
+    - Added code to detect where data files are. This
+      removes the need for the system makefile.
+
+
+December 4, 2009
+    - Updated Russian translation for in game menu.
+      Provided by CtHx.
+    - Updated German weapons file.
+      Translation provided by Simeon.
+    - Added new Spider tank images, provided by CtHx.
+    - Added updated Slovak language support.
+      Provided by Jozef.
+    - Made sure all ingame text files are the same length to
+      avoid empty strings.
+    - Switched to using new button design, provided by CtHx.
+    - Blue rectangle is drawn properly around new buttons
+      on the main menu.
+    - Changed the way menu backgrounds are drawn to avoid crashes
+      with various resolutions.
+    - Updated spec file to include all data files.
+    - In place of the name of the style, a preview of the player's
+      tank style is shown on the Player menu.
+    - Added new menu background, provided by CtHx.
+    - War quotes now appear in white for better contrast with new background.
+
+
+======================== Atanks-4.2 released ==========================
+
+
+November 27, 2009
+    - German language now uses unicode font to avoid weird symbols
+      in the text.
+
+November 13, 2009
+    - Fixed floating text so that Russian comments are not cut short.
+    - Added new Slovak weapons file. Provided by Jozef.
+    - Adjusted the way rollers move if they hit a flat surface.
+    - Added ingame Russian text. Provided by MyO.
+    - Client side now tries to maintain inventory.
+    - Try to make sure network players are returned to their original type
+      after each game.
+    - Added new tank styles, UFO, Future, Heavy. These were provided by CtHx.
+    - Added command line option "--nothread" to prevent the game from
+      using background threads.
+
+November 6, 2009
+    - Fixed Russian war quotes so odd symbols do not appear in the text.
+    - Teleports are now visible on client.
+    - Tried to make sure AI buys parachutes and spreads its money around more.
+    - Client should now stay connected in multi-round games.
+    - Fixed compile error when threads are not being used.
+    - Client now changes rounds and ends game when it should.
+    - Client can see which weapons they have and select which weapons to fire.
+    - If client does not do anything after about 10-15 seconds, AI takes over
+      for one shot.
+    - Fixed Heavy Riot Bomb price from $300 to $3000 to match similar weapons.
+    - Fixed client crash when using riot bombs.
+    - Client side no long fills up memory with unused objects.
+
+October 30, 2009
+    - Added basic game networking.
+    - The game will now compile without threads.
+    - Try to avoid crashes on large screens/64-bit computers.
+    - Tank positions sync across network every few shots.
+    - Added .rc file
+
+
+=========================== Atanks-4.1 released ==============================
+
+October 19, 2009
+    - Rollers should now fall down walls and roll properly before exploding.
+    - If satellite is turned off, it may still appear, but will no longer fire.
+    - Fixed crash which would happen if napalm hit steel floor.
+    - Made sure in game text gets cleaned up at the end of the game.
+    - Fixed a Windows bug which would cause crash at start-up.
+    - Added Network Game buttons to main menu.
+
+October 10, 2009
+    - Added Small Dirt Spread weapon.
+    - Updated Russian translation.
+      Text provided by MyO and Sergei.
+    - Created new weapon called Cluster Mirv. It releases a cluster
+      bomb while coming down.
+    - Created new weapon called the Per Cent Bomb. Causes the target
+      to lose half of its health (armour + shield).
+    - Tank speech text rarely over-laps now and travels at different
+      speeds.
+    - Added item called SDI Missile Defense. This device attempts to shoot
+      down missiles coming too close to the player's tank.
+    - When playing in full screen on Windows, the mouse should now
+      be visible.
+    - Added new weapon which reduces the explosive power of the target's
+      missiles. The new weapon is called a Reducer.
+    - Game text now lives in "ingame" text files (see "text" folder). Each
+      language has its own file to allow for easy translation without
+      recompiling.
+    - SDI no longer shoots at napalm jelly, causing it to hover.
+    - Updated spec file to reflect directory/file changes.
+
+October 4, 2009
+    - Fixed system wide makefile to build client.o
+    - Text can now be loaded into memory, rather than relying
+      on files and checking the disk.
+    - Updated Makefile to install text in new "text" folder.
+    - Text files, including weapons, help and tank text are now kept in
+      the "text" directory.
+    - Game loads text into memory and switches languages on the fly.
+    - Fixed comma showing up at start of money.
+    - When launching the game in full screen mode, the game using the
+      system's screen resolution. If the resolution cannot be detected,
+      it reverts back to safe values.
+    - Amount of money earned for a hit is displayed above the shooter's tank.
+    - Misc code clean up to remove old, commented code blocks.
+    - Added Full Screen option to Graphics Options menu.
+    - Added two new tank types for the players to choose from.
+      The new types are called Big Grey and T34.
+      Thanks to CtHx for providing these tank images.
+
+
+================ Atanks-4.0 released =======================
+
+September 24, 2009
+    - Fixed memory leaks with new text block code.
+    - Running "make install" should now do a "make system"
+      for you first, rather than a local build.
+    - The game now remembers if the window was set to full screen
+      mode or not. Command line over-rides either mode.
+    - Firing rockets while under dirt does not cause the tank to fly
+      sideways.
+    - Added fix which should prevent Russian tank text from being
+      broken into multiple lines.
+    - Fixed on/off text in menu code. Thanks to ctHx for pointing out this
+      problem.
+    - Applied fix to avoid crash on 64-bit systems when choosing which
+      weapon to fire.
+    - Fixed Russian font on the buying screen.
+    - If the game is skipping the AI, the AI should now self destruct
+      if nobody is winning after 10 seconds.
+      Thanks to Yama and Draco for providing the code/suggestion for this.
+    - Money values are now displayed with comma separators to make
+      them easier to read.
+
+
+September 19, 2009
+    - The unicode font should now install properly, editted makefile.
+    - Changing language in the Options menu now causes the proper
+      weapons file to be loaded.
+    - Added fix to avoid pink lines showing up in detailed terrain.
+    - When selecting players, buttons should toggle properly now
+      if Russian font is being used.
+    - Placed Russian main menu buttons in proper order, I hope.
+      Thanks to CtHx for providing the correct order.
+    - Blue box on main menu is now the right size when viewing Russian
+      buttons.
+    - Added better German language support for in game menu.
+    - Added German weapons file.
+    - Added German Options menu translation.
+      Thanks to Roland for providing German language files
+      and menu translations.
+    - Added short delay in threaded land generation to reduce CPU
+      load at beginning of rounds.
+    - Tanks use all Russian chat files now.
+    - Fixed text on top bar during rounds.
+    - Added TEXTBLOCK class for easy access to text files.
+    - Added text.cpp and text.h to makefiles.
+    - Removed old lineseq.h file and references.
+    - Cleaned up renderTextLines function to display cyrillic
+      text properly.
+      
+
+September 14, 2009
+    - Added unicode fonts to support cyrillic.
+      Thanks to Netscape (I think) for supplying this font.
+    - Placed unicode font in a datafile to greatly reduce project size
+      and decrease load/start-up time.
+    - Fixed bug which would prevent Portuegese help file from displaying.
+    - Fixed bug which prevented Russian Help text from displaying.
+    - The correct weapons file is now loaded to match the selected language.
+    - Floating text has been reorganized.
+    - Adjusted options screen to display unicode font better.
+    - Fixed speech text during rounds when using unicode font.
+    - Added command line option "--nobackground". This causes the green
+      background seen on most screens and menus to not be drawn. Instead
+      the background is left plain black. This is to avoid crashes on
+      some 64-bit machines.
+    - Updated spec file for RPM building.
+    - Adjusted text positioning on rounds screen to better handle
+      different fonts.
+    - Added Russian language buttons for the main menu.
+      Thanks to Sergei for making these and donating them.
+    - Land colours and textures are now generated in the background
+      before they are needed. This makes rendering detailed land much
+      faster on most computers.
+
+
+September 8, 2009
+    - Changed menu screens to use more common key commands.
+      Up/Down arrows move up and down through menus.
+      Space selects/deselects items.
+      Enter is the same as clicking OK.
+      ESC backs up to the previous screen.
+      The right/left arrow keys adjust item values or buy/sell.
+    - Updated README file to reflect new key mapping.
+    - Moved some define statements out of main.h and into the
+      Makefile for global availablity.
+    - Made buying screen moving more logically when responding
+      to keyboard.
+    - Made keyboard work smoothly on buying screen.
+    - Cleaned up buying items with keybaord to make sure proper
+      items are purchased and screen scrolls as expected.
+    - The ENTER key now leaves the buying screen, not SPACE.
+    - On the buying screen, the item selector stays on the screen
+      when the mouse is being used.
+    - Weapons can now be cycled through during a round by
+      using the Z and C keys. (Tab and Backspace still work.)
+    - Running "make system" will build Atanks in a way compatible with
+      installing on Linux systems.
+    - Changed Mass Teleport to make sure all tanks get teleported.
+    - Fixed Options menu to make sure ENTER key would return to main menu.
+
+
+September 4, 2009
+    - Added Windows icon, resource and makefile.
+      Thanks to Billy Buerger for supplying these.
+    - Added Allegro .dll file for easier Windows portability.
+    - Replaced some pieces of code from checking to see if we are running
+      on Linux to checking if we have threads and/or network access.
+      This should make the code easier to port.
+    - On the Help screen, arrow keys can be used to scroll up or
+      down through the text. Spacebar resumes scrolling. ESC or
+      a mouse click returns to the main menu.
+    - Re-added English version of the Help file.
+    - Made sure the "*" appears next to player names in the
+      Player menu.
+    - Removed long delay between menu screens on Windows/wine.
+    - Fixed Windows crash bug in aiming code and player handling.
+    - Fast sky generation should now work in Windows, if compiled with
+      mingw compiler and THREADS is defined.
+    - Some code clean-up to make porting network features to Windows easier.
+
+==================== Atanks-3.9 released ==================================
+
+August 28, 2009
+    - Added patch from BillyBuerger which allows computer only
+      play to be skipped, even if the setting to watch the full
+      round is enabled. This is accessed by pressing ESC during
+      the round and selecting Skip AI. The action is then
+      skipped for the remainder of that round only.
+    - Added Russian language support for instructions, README
+      file, tank speech and menu. Many thanks to MyO for submitting
+      the translations.
+
+
+August 21, 2009
+    - Fixed bug which would cause the game to hang while AI was
+      buying items.
+    - Fixed bug which would cause AI to purchase only small missiles
+      if no preferences had been generated.
+    - Fixed a compile bug on Windows related to the new sound
+      driver code.
+    - Fixed a bug that would cause the Windows version to crash if
+      the AI was fighting in a round with less than ten players.
+    - Fixed a bug which would cause the Windows build to crash if
+      repulsor shields were used with less than ten tanks in the game.
+    - Fixed compile errors on Windows.
+    - Added function which will create a "music" folder in the .atanks
+      config folder.
+    - Game will now play wav files which are saved in the .atanks/music
+      folder. One track is played each round and looped.
+      The wav file must be 16-bit.
+    - Added item to main option menu called the Sound menu. The sound menu
+      contains all sound related options. Removed sound driver options
+      from the Graphics menu.
+
+
+August 7, 2009
+    - Players can now select which sound driver they want. This should
+      usually be left on Auto Detect, but Linux users can select from
+      a variety of other sound drivers if need be.
+    - Saving and loading games is now done using text files again.
+    - Settings are saved in regular .txt files again for easy editing.
+      The game should automatically switch from the old .dat files.
+    - Added --nonetwork command line option to avoid using any
+      network server code.
+
+
+August 1, 2009
+    - Fixed bug where pressing a key on the Select Players screen
+      would cause the game to run without any players.
+    - Removed crash when sound is not properly initalised.
+    - Added keybaord support for options menu and select player
+      menu. Tab and Backspace switch between fields. ENTER toggles
+      toggle boxes. Up and down arrows adjust values. Space is OK
+      and ESC is cancel.
+    - Removed most un-needed exit calls to avoid having the game crash
+      needlessly.
+    - Added keyboard support for the main game menu. Tab and Backspace
+      navigate the menu. Enter and Spacebar select items. Esc quits
+      the game.
+    - Added check to make sure unselectable items are not selected
+      during the battle.
+    - Added a quick note on keybaord controls to the README file.
+    - Removed AI's ability to cheat by "megically" getting more money.
+    - Made teams divide up money more fairly.
+    - Fixed dependencies in the Makefile.
+    - Game should no longer crash if a mouse is no present.
+    - Added keyboard support to buying screen.
+
+
+July 25, 2009
+    - Created exporter utility, which takes all images out of
+      an Allegro datafile and saves the bitmaps in the current
+      directory.
+    - Replaced all datafiles with sub-directories. This allows easy
+      access to view and edit all images and sounds.
+    - The game now manually loads all images and sounds
+      in the globaldata class.
+    - Atanks now uses manually loaded images. Datafiles are no longer
+      used. Removed datafiles.
+    - Napalm looks a little more firey.
+    - Added Rocket item, which shoots the tank up into the air.
+    - Fixed drawing of the tank when using the rocket.
+    - Reduced cost of auto-repair kit.
+    - Added rocket flames.
+    - Prevented tank from launching itself into orbit.
+    - Rockets can move a tank left or right, depending on the direction of
+      the tank gun. Straight up causes the tank not to drift either way.
+    - Updated Makefile to handle new image and sound handling.
+
+
+================== Atanks-3.8 released ============================
+
+July 24, 2009
+    - Fixed some code to be more compatible with Windows.
+
+July 16, 2009
+    - Fixed bug where the error message would be garbled if no weapons file
+      was found. Thanks to BillyBuerger for reporting this bug.
+    - Placed virtual object functions back in their source file. Removed
+      inline statements.
+    - Placed physical object code back in source file. Removed inline
+      statements.
+    - Funky bomblets (and funky deathlets) now display in different colours.
+    - Removed all the un-needed private constructors and deconstructors.
+      Removed un-needed inline declarations.
+    - Removed white bubbles from menus to improve contrast and reduce
+      CPU usage.
+
+
+
+July 8, 2009
+    - Removed code which caused crash if settings were not saved.
+    - Fixed crash in retaliation text code.
+    - Added Demo mode. Leaving Atanks on the main menu for one
+      minute causes the game to play by itself for five rounds.
+      This can be stopped at any time by pressing the ESC key.
+    - On Linux, the sky is now generated in a background thread. This
+      removes most of the delay at the end of the buying screen, before
+      a round starts.
+      (I forget who suggested this a year or so back, but I didn't have
+       the time to implement it then. I think they were a Java developer
+       and they deserve the credit for this idea.)
+    - Fixed a problem with cluster bombs not having the proper sub-missile.
+    - Moved some floating functions out of atanks.cpp and placed them in
+      files.cpp for better access from other source files.
+    - Fixed land drawing under threaded mode.
+    - Changed war quotes to display in black for better contrast.
+    - Fixed blank patches in sky when using threads.
+
+
+
+July 4, 2009
+    - Changed main game loop to go through objects twice rather than loop
+      twice for each class. Should reduce CPU usage by about 5%.
+    - Tried to make teams more evenly matched.
+    - Added Option menu called "Network".
+    - Made checking for updates on the web an option, under the Network menu.
+    - Made MIRVs detect their position much more efficently.
+    - Created new weapon (Driller), which will dig a deep hole where ever it lands. Does
+      minor damage to any tanks hit.
+
+June 27, 2009
+    - Added Chain Missile and Jackhammer weapons. (Provided by Yama.)
+    - Weapons such as chain gun, chain missile and jack hammer now correctly
+      display the number of shots the player has left, rather than the total
+      amount of missiles in the spread.
+    - In the Store, the correct number of items purchased now show up next to
+      items such as the chaingun, chain missile and jack hammer.
+    - Updated README file.
+
+
+
+============= Atanks-3.7 released ========================================
+
+June 22, 2009
+    - Napalm should now fall if no dirt is under it.
+    - Player colours should look the same in 16 and 32 bit colour modes now.
+    - Cleaned up old fog code.
+    - Fixed fan graphic in different colour modes.
+    - Game now automatically checks for updates, if the user is running Linux.
+      Availible updates are displayed on the main page.
+
+June 19, 2009
+    - Added option to allow players not not share money with team mates.
+      (menucontent.h, globaldata.h, globaldata.cpp, atanks.cpp)
+    - Fixed crash when checking tank status.
+      (globaldata.h, player.cpp, tank.cpp)
+    - Atanks now uses the desktop's default colour depth. The user
+      can over-ride the default by using the "-d" option on the command line.
+    - Applied code from Yama to make satellite drawing more smooth. Should
+      avoid leaving artifacts.
+
+June 15, 2009
+    - Fixed abs() calls in player.cpp and tank.cpp
+    - Replaced old Teleport animation with Yama's. 
+
+June 4, 2009
+    - Added war quotes to display at the end of games. (files.cpp, files.h,
+      atanks.cpp (do_winner))
+    - Added war_quotes.txt data file with list of quotes about war.
+    - Added Reset All button on the options page (atanks.cpp options,
+      globaldata.h, globaldata.cpp, evironment.h environment.cpp)
+    - Made default colour theme "crispy".
+    - Moved do_winner screen up a little to give room to the war quotes.
+    - Added option for custom background (menucontent.h, environment.h
+      environment.cpp)
+    - Any bitmaps found in the config folder (.atanks) can be used
+      as custom backgrounds. (files.cpp, files.h, atanks.cpp, environment.h,
+      environment.cpp)
+    - Added Mass Teleport item, teleports all tanks on the screen to
+      random locations. (tank.cpp, weapons.txt, main.h)
+
+
+================== Atanks-3.6 released ================================
+
+June 1, 2009
+    - Fixed Makefile to make sure binary does to correct directory.
+    - Moved giant inline function out of header file and into environment.cpp
+    - Added deconstructor to ENVIRONMENT class fpr clean-up.
+
+May 19, 2009
+    - Settings from previous versions (prior to 3.5) can now be imported.
+    - Fixed Makefile to handle changes to source files.
+    - Re-added debugging codes to Makefile.
+    - Fixed various crashes that would happen with the computer was aiming
+      at tanks which had already been destroyed.
+    - Prevented tanks from getting credit after they die.
+    - Players should no longer show up as winning a round if they have died.
+    - New game menu should look better now at higher resolution.
+    - When selecting options or game rounds, the options now "wrap" around
+      from highest to lowest and lowest to highest.
+    - Added menu support for Slovak. (Provided by Jozef.)
+
+
+
+==================== Atanks-3.5-r1 released ==========================
+March 25, 2009
+    - Important Bugfix:
+      Fixed a bug that could cause atanks to crash if a game with players which
+      do not belong to the first 10 set up players chosen is loaded.
+    - Important Bugfix:
+      A typo made atanks impossible to be compiled on windows platform
+
+===================== Atanks-3.5 released ============================
+
+March 19, 2009
+    - Fixed a bug that caused players to be skipped, if their predecessor died
+      during their own attack. (now really working!)
+    - rewrote loading and saving of game settings and games.
+      Important: Old save games and settings can not be imported!
+    - Bots no might a) forget their revenge plans on new rounds, b) drop revenge
+      plans if the revengee is on the same team and c) go for the not-same-team
+      leader as a new revengee if the difference of won rounds grows too high.
+    - Smoke desolves now a bit more realistic.
+    - Napalm Jellies now grow first instead of spawning fully sized.
+    - If a "winner" dies during end-of-round waiting, the score and money bonuses
+      are substracted. (No more "Die-But-Keep-The-Points"-behavior!)
+    - Fixed a bug that made Sith go for their team mates in special circumstances.
+    - Changed the Makefiles to the new source layout and fixed some issues.
+    - dynamized the new targetting system, so that there should be no more "lags"
+
+February 21, 2009
+    -- Finally "-Wno-write-strings" is no longer needed to compile the sources
+    -- Rewrote the environment method to calculate average background colors. It is 
+    now inline and somewhat optimized, making shadowed + fading text more 
+    performant.
+    -- Rewrote File handling, apart from three tiny points atanks is now fully ISO 
+    C++ compliant.
+    -- Made rollers a bit faster dropping
+    -- No more roller-breaking of shields by hammering them above the enemy onto 
+    the steel/wrap ceiling! They explode now.
+    -- Two tiny patches make bots targetting a bit faster and destroy (hopefully) 
+    any possibility for the system to go infinite
+    -- prepared all neccessary files to be translated. But please note:
+    -- English: Is always there
+    -- Portuguese: Is borked. But maybe it's only my utf-8 system showing the 
+    wrong characters. I looked into the atanks-2.9 files and it is broken there as 
+    well. If its just my system, don't mind. ;)
+    -- French: Has some tiny things that has to be translated. Retaliation is 
+    still english, and I am not sure how to translate "Shadowed Text" and "Fading 
+    Text", so some french natural speaker might do this?
+    -- German: Only weapons_de.txt needs to be translated, I'll do it next year.
+    -- Slovak: Only the gloating texts *are* translated so the rest is missing 
+    completely, but I have prepared the files and menucontent.h for a slovak 
+    natural speaker to be translated.
+    -- Added weapons_*language*.txt files so we can (finally) translate the weapon 
+    texts as well.
+    -- Fixed a bug that could cause roller tracking to go infinite.
+    -- Balanced fading texts some more
+    -- Corrected some text messages
+    -- added new roller code. Rollers now really roll!
+    -- fixed a bug that made tracking report wrong hit points when tracking 
+    rollers and burrowers
+    -- Added average background color calculation and fixed fading text offset. It 
+    should look far better now.
+    -- Balanced shadowed text color calculation
+    -- added a new retaliation text. When bots aim at opponents they have a grudge 
+    against, they might tell you now.
+    For this to work you'll have to copy retaliation*.txt into 
+    /usr/share/games/atanks/ (or wherever you have your atanks data files) 
+    directory.
+    -- removed waiting for explosions to finish when tanks blow up after being hit 
+    by violent death missiles.
+    I was longing to change that for ages, because I grew rather sick of tanks 
+    being suspended in mid-air for ages while all those violent death missile fly 
+    around. Now, they blow up immediately. However, when a normal missile is shot 
+    and destroys a tank, it still waits for the missile's explosion to finish.
+    -- changed tank falling behavior: They now can fall a short distance (2-5 
+    pixels) without getting damage and without the parachutes to open.
+    I was longing for that one, too. The reason is, that it is madness to waste 
+    30+ parachutes and/or getting alot of damage while moving (!!) a tank down a 
+    flat slope.
+    -- Fixed a bug with the tracing of spreads which resulted in bots hitting self 
+    but not the opponent.
+    -- added a security check when calculating offsets to napalm. Bots should not 
+    drop napalm onto themselves any more when trying to hit a neighbor.
+    -- added shadows to the text to increase readability. (Has to be turned on in 
+    the graphics menu, for compatibilities sake this option defaults to "off")
+    -- added fading to the text, to ... well... to have a bit of eye candy. ;) 
+    (Has to be turned on in the graphics menu, for compatibilities sake this 
+    option defaults to "off")
+    -- cleaned up aiming calculation
+    -- cleaned up debugging messages for "DEBUG_AIM" and added some more info.
+    -- Fixed a bug that could cause riot shots and blasts to start 10-20 pixels 
+    away from the tank cannon.
+    -- Fixed a bug that caused the the aiming system to fail in a very special 
+    (and rare, but still existing) situation, resulting in bots shooting into the 
+    ceiling.
+    -- Added a cleanup for all objects. No more debris on the screen!
+    -- As the new aiming system doesn't need it any more, the wall type and boxed 
+    mode aren't changed any more once the last human player dies and skipping is 
+    turned on.
+    -- added boxed mode (Finally!)
+    -- riot blasts fixed, they no longer shoot downwards when too less power is 
+    chosen
+    -- chain missiles now blast through dirt. (vertical spreads, too)
+    -- Walltypes on non-human rounds with skip-AI on will now all change to 
+    Wrapped Walls & non-Boxed mode, but not before the current destructions 
+    (violent deaths, falling tanks) are finished. (happy, sylikc? ;))
+    -- a completely new aiming system has been written to make the boxed mode 
+    possible
+    -- added tweaks to reduce "debris" left on screen
+    -- added tweaks to reduce "choking" of the display when too much is going on
+    -- removed HLR_DEBUG, because in over 1000 rounds the speed-up-system never 
+    failed
+    -- There are now three different defines for debugging:
+        -- DEBUG
+        Will show everything concerning inventories, shopping system, item 
+        selection and target selection of the bots on the console.
+        -- DEBUG_AIM
+        Will show all relevant numbers of the new aiming system on the console
+        -- DEBUG_AIM_SHOW
+        Will draw dots and circles on the screen to make the "thinking" of the 
+        aiming process visible.
+        (Warning: The game is no longer playable in this mode)
+    -- balanced computer player values, according to the new aiming system. 
+    Generally speaking, the "useless" bot won't hit a barn with a pumpgun, while 
+    the "deadly" bot is very precise.
+    -- If no target can be reached by normal means, bots now might teleport (or 
+    swap) out of their corner, or try to get rid of the obstacle by using riot 
+    blasts
+    -- While aiming bots now try to avoid hitting themselves or team mebers (when 
+    non-neutral) and are somewhat carefull not to hit themselves or team members 
+    with the blast damage their weapon produces. If a target can't be hit 
+    otherwise, there have sacrefices to be made, though...
+    -- target selection now uses the new aiming system to value targets lower 
+    which are hard (or impossible) to hit
+    -- item selection now uses the new aiming system to value weapons lower with 
+    which the chosen target can't be hit properly
+    -- The target system now calculates burrowers and rollers. (Which leads to 
+    some highly entertaining results! :))
+    -- The more intelligent a bot is, the more "bounces" of walls or "wraps" it 
+    can calculate.
+    -- The more intelligent a bot is, the more spread it can calculate. So don't 
+    wonder if a useless or guesser bot fires a super spread, happily hitting 
+    itself. It simply couldn't see that coming.
+    -- Velocity check rewritten. It now a) works and b) fixes the "Repulsor-
+    Shield-Bug" :D Yes, I am very happy about that!
+    It is handled in three different ways:
+        -- No Spring Wall: The limit is set by maximum power, influenced by 
+        the mass of the weapon.
+        -- Spring Wall and Not Boxed: The Limit is doubled, or shooting at the 
+        wall would destroy your missile.
+        -- Spring Wall in a box: The limit is four times the normal limit, or 
+        it won't be any fun!
+        I had very entertaining results with that! :)
+    -- hit 2500! This means I have now tested over 2500 rounds with the new 
+    shopping- and target-selection systems since the last changes and/or bugfixes!
+    -- The Boost Value calculation is changed to be more dynamic to future changes
+    -- added a private member to count how many boost items are bought
+    -- changed boost buying: inserted a per-round-limit aka iBoostItemsBought with 
+    the help of the above count
+    -- language menu fixed
+    -- changed interest to be dynamically gained
+    -- Added a new define, HLR_DEBUG which, when set, causes the round to end 
+    after each bot having one last shot if no human players are left. (Default, 
+    currently, is 16)
+    -- Fixed a bug that caused aTanks to freeze for seconds everytime too much is 
+    going on. (Explo, Text, Smoke, etc.) On some occasions there still can be a 
+    "hang" for a split second or so. But that could have been my computer, the 
+    issue needs to be tested and watched.
+    -- Started to add boxed mode (not implemented yet! But the menu item is there 
+    and the Wall-Display is changed)
+    -- Fixed a bug causing accelerated AI to crash
+    -- Included sylikc's Anti-Crash-Fix
+    -- When bots have enough money, they do not spend everything. Jedi keep 50%, 
+    Neutrals 25% and sith 5% (the squanderers! ;) *hrhr*) for "bad times"
+    -- Repulsor Shield handling changed:
+        changed ydist to be always negative, so missiles are *always* handled 
+        like they came from above! It remains to be tested whether this 
+        balances the repulsor shields, or renders them unbeatable (which could 
+        happen...)
+        Note: In over 500 rounds they perform better, but are still far away 
+        from being "unbeatable"
+    -- When determining pre-Buy items bots enforce buying of boost-Items if they 
+    are too far away from the peak.
+    -- Limit for items raised up to 999 (like humans)
+    -- limited AI-Only Rounds. If the last human players dies the remaining bots 
+    get 10 tries each to find a winner. If they do not succeed, the round is ended 
+    and the most healthy tank wins. (Or the round draws if two or more are equal)
+    I added this, because there is a tiny chance (it never happened in the last 
+    weeks, but thrice only yesterday!) that the games gos infinite in AI-only 
+    turns. Situation: bots left have only small missiles and regenerate more each 
+    round than the small missile delivers.
+    With this limit it won't happen any more.
+    -- When the last human dies and the wall type is changed, it is redrawn at 
+    once now.
+    -- limited interest && team money
+    It is too easy to become super-marvel-universium-mega-hero by just waiting a 
+    couple of rounds until the bank has pumped up your account to some millions. 
+    Currently the bank refuses to pay more interest than 100k, but that hard limit 
+    will be changed to a dynamic one. (see todo list)
+    As for team money, bots now refuse to spend more than 500k into the pot. 
+    Humans, too, of course.
+    -- team win->WinRoundBonus divided instead of applied full.
+    It is just extremely unfair that the teams get much more money for winning a 
+    round when it is easier for them to do so.
+    -- 75% was too much, thus jedi now only pay 50% into the team account.
+    -- Bots try to save up money to get better equipment
+    -- Bots look at basic equipment first before heading for the weapons-shop.
+        -- Parachutes (if gravity is on)
+        -- Basic weapons (aka 5 medium and 3 large missiles
+        -- Armor/Amps
+        -- "Tools" to free themselves like Riot Blasts
+        -- Shields, if enough money is there
+        -- if all is set, look for dimpled/slick projectiles!
+    Armor/Amps (aka "Boost-Items"), however, are limited, so they will only buy 
+    them, if someone has a higher value in boost-items. As these items can be 
+    bought randomly as well, they won't neccessarily wait for the human player(s) 
+    to go ahead!
+    -- Buying is no longer purely random but takes the bots weapon preferences 
+    into account.
+    -- The amount of money a bot wants to save up is used for the target-finding-
+    system as well:
+    If a bot has less money, it is more likely to target weak opponents to fetch 
+    the kill-bonus. If it has enough money, it will more likely chose the biggest 
+    threat.
+    -- Money-saving is now limited, so that no bot tries to sum up millions. Right 
+    now the highest maximum, depending on type and weapon preferences, is 1M. 
+    (Deadly(=5) * 2 * Armageddon cost)
+    -- Teams are now handled differently in alot of places:
+        -- Prior the shopping tour, every jedi adds 75%, and every sith 25% of 
+        their money to the "team-account". The team-money is reduced by a 
+        "transaction fee" (jedi: 5%, sith: 10%) and then divided onto all 
+        team-members to help each other out.
+        -- While searching for a target jedi try not to hit their team mates, 
+        while sith do not care so much.
+        -- While searching for a target jedi give alot less than neutrals 
+        about revenge, while sith can become furious (even against team 
+        members!)
+        -- jedi *can* become "super-defensive" (defensive > 1.0) while sith 
+        *can* become "super-offensive (defensive < -1.0). By this jedi can be 
+        extremely cautious every now and then, while sith like to throw 
+        caution out of the window. :)
+    -- Riot blasts/bombs are no longer chosen to be shot onto enemies!
+    -- fixed a bug with the rating of buried targets while searching for a 
+    target/chosing an apropriate weapon
+    -- target selection and weapon selection now work together:
+    A bot choses a weapon and tries to find the best target for it. Then the bot 
+    decides whether another weapon would be better for that target and switches to 
+    that. But they value weapons higher they like more, now.
+    -- corrected the _targetX modification for shaped charges and napalm:
+    Bots trie to aim shaped charges so that they do not directly hit, for aiming 
+    napalm they try to take wind into account.
+    -- added blast check, to avoid using weapons which blast hit self, depending 
+    on intelligence and defensiveness
+    -- added laser check to see whether a laser can be fired or would hit solid 
+    rock only
+    -- added check for buried targets and appropriate weapons (burrower, 
+    penetrator, tremor-tectonic)
+    -- added a check to get more intelligent bots to do collateral damage when 
+    possible
+    -- Added a custom Kamikaze text for the situation when bots decide to blow 
+    them selves up.
+    -- Money interest was added right before entering the shop, resulting in 
+    interest added everytime a game was reloaded (and reloaded, and reloaded...). 
+    I changed that so that interest is added after leaving the shop, fixing the 
+    "Add-money-by-reload"-Bug. Further there is no more interest for money that is 
+    just earned in the last round.
+    -- added offset if no human players left, raising the class of the bots to 
+    speed up the game without changing the difference in intelligence between bots 
+    too much.
+    -- bots perform best on rubber and wrap walls. If no human players are left, 
+    the wall type is changed if steel/spring is chosen to speed up the accelerated 
+    game.
+    -- calculation of the shaped charge type weapons was improved (and corrected).
+    -- Added preference generation for bots that are set to "per play" when a game
+    is loaded. The loading of the preferences is (unfortunately) disabled and I do 
+    not know why. As long as they *are* disabled, PerPlay-Config bots have to get 
+    a new config on game load, or they use the global config, rendering PerPlay-
+    Config useless.
+    -- For PhysObjects: reduced "virtual" height to 25 times screen height and
+    changed velocity check for the real velocity and >200 x mass.
+    -- Re-Added german language, it flew out of the release.
+
+===================== Atanks-3.2 released ============================
+
+September 25, 2008
+    -- Player references are now removed from dying tanks to
+    void game crash.
+
+Setpember 20, 2008
+    -- Close button should now work on Windows.
+    (Patch provided by sylikc.)
+    -- Weapons should no longer bounce off repulse shields and
+    fly up forever.
+    (Patch from Yama.)
+    -- Explosions on wrap-around walls appear on the far side of the
+    screen too.
+    (Patch from Yama.)
+    -- Code clean up.
+    (Patch from Yama.)
+    -- Added fix to avoid skipping turns when spring
+    walls are used.
+
+
+
+September 2, 2008
+    -- Credits and Help screens now ignore extra DOS return
+    characters in the text file.
+    (Submitted by sylikc)
+    -- Added German language support. 
+    (Provided by Yama.)
+    -- Changed formula for dealing damage with shaped charges.
+    (Provided by Yama.)
+    -- Added language support for instructions.
+    (Provided by Yama.)
+    -- Adjusted time clock to avoid skipping human player turns.
+    -- Fixed typo which prevented penetrators from detonating when they
+    hit the ground.
+    (Provided by Yama.)
+
+
+August 28, 2008
+    -- Added patch from sylikc to prevent rounds ending
+    before the winner gets credit. Changes atanks.cc
+    -- Winners are now sorted by score at the end of the game.
+    -- Added patch to make Atanks able to run in the background
+    on Windows OS. (Provided by sylikc)
+    -- Added custom data dir for Gentoo distro.
+    (Provided by Yama)
+    -- Fixed pointer warning in menucontent.h file.
+    (Fix provided by Yama)
+    -- Added advanced AI weapon and item preferences.
+    (Provided by Yama.)
+    -- Fixed potential crash in player menu. (Patch from Yama)
+
+
+
+August 11, 2008
+    -- Added Mac OS X makefile for compatibility on that platform.
+    -- Patched files.cc and files.h to work with OS X.
+    (Patch provided by ryandesign)
+    -- Added Slovak language for tank dialog.
+    (Provided by Jozef Riha)
+    -- Applied item selection patch and loading patch from
+    Yama.
+
+
+===================== Atanks-3.1 released ============================
+
+July 26, 2008
+    -- Removed strcasestr from Win32 build to avoid compiler error.
+    -- Fixed error with time delay and simulanious firing.
+
+
+July 12, 2008
+    -- Corrected error where tanks firing chain missiles would be skipped a turn.
+
+July 1, 2008
+    -- Added time limit for shots. Can be changed in the Physics option
+    screen.
+    -- The timed shots limit is now saved in the game settings.
+    -- Adjusted compile flags to avoid annoying messages from gcc-4.3.0
+
+
+
+June 6, 2008
+    -- Fixed bug where if no saved game exists,
+    atanks will crash.
+    -- Added Windows compatibility code for saved
+    game searches. Provided by Keilaron.
+    -- Fixed Windows search for saved games.
+
+
+
+
+
+===================== Atanks-3.0 released ====================
+
+May 23, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added patch to avoid skipping turns when
+    violent death is on.
+    -- Adjusted final score layout.
+
+
+
+May 6, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Introduced browsing option for saved games.
+    -- Completed "select saved game to continue" feature.
+    -- Fixed bug where a team would get credit for winning
+    when all tanks were destroyed.
+    -- Added kill/died ratio to end game stats.
+    -- Fixed bug in detecting which player/team wins.
+
+
+April 15, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Graphics should display properly if the
+    game needs to recover graphic settings.
+    -- When the player dies, the game will not skip
+    ahead to the end of the round until violent deaths
+    are finished.
+    (Thanks to Scott for providing this patch.)
+    -- Updated Portuguese language files to use latin1
+    encoding. Should display better than old files.
+    -- Fixed floating point calculation bug in the
+    interpolate() function. Thanks to pyeatt for providing
+    this fix.
+
+
+March 25, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Re-implemented fog. Made fog smoother, where
+    tanks disappear and re-appear.
+    -- Fixed medium napalm so it drops napalm, not
+    tremors.
+    -- The fog option no longer shows up as incomplete.
+    -- Massive code clean up. Removed old versions of save/load,
+    took out old aiming code. Breaks backward compatiblity with
+    versions of Atanks prior to 2.4.
+    -- Made the satellite slightly less violent.
+    -- Tanks should no longer waste lasers trying to fire below
+    their level.
+    -- Updated gloat, revenge and suicide remarks.
+
+
+=============== Atanks-2.9 released ======================
+
+March 18, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added text to buying screen to indicate arrows can
+    be used to scroll through items.
+    -- Re-wrote AI aiming. Target tanks, rather than areas.
+    -- AI no longer shoots at steel walls.
+    -- Added levels of violent tank deaths.
+    -- Added dirt that randomly falls from the sky, similar to meteors.
+       Option is in the Weather menu.
+    -- Removed old satellite system
+    -- Created new satellite object.
+    -- Satellite now fires lasers.
+    -- AI controlled tanks no longer adjust power for items. 
+       Saves time.
+
+
+March 2, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added command line option "--noconfig" which
+    avoids loading game settings, but still loads
+    players, to allow game settings to be reset.
+    -- If no tanks fire a shot, natruals are paused until
+    someone fires. This fixes two problems:
+    A) If you leave the keyboard and come back 5 minutes
+       later, there is still some dirt left.
+    B) It is not possible to simply buy a lot of parachuts
+       and armour and wait for enemy tanks to die from naturals.
+    -- Added Physics option "Violent Death" which causes tanks to
+    die in violent explosions when turned on. Is left off by default.
+    -- Added Land Slide option called "Tank Only", which causes tanks
+    to fall, but dirt hover in the air.
+    -- Reworked loading players to make it more flexible.
+    -- Attempted fix for start-up screen size.
+    -- Added item called Armour Piercing. Makes a very small explosion
+       but does a fairly large amount of damage.
+
+
+
+February 19, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Fixed spelling error on desktop file.
+    Thanks to Keilaron for pointing this out.
+    -- Added French language files, menu option.
+    Thanks to Olivier for providing the translation.
+    -- Added command line option "-c" to specify
+    where the config file should be created/used.
+    -- Removed weapons.h from source tree.
+    -- Avoid memory fault in moving config file.
+
+
+========== Atanks-2.8 released ========================
+
+February 11, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Changed MIRV settings to cause wider spread of sub missiles.
+    -- AI returns to regular difficulty level after each game when
+    in campaign mode.
+    -- Added land type None, which plays rounds with no land at all.
+    Using Random land will not cause None to be used.
+
+
+January, 29, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- When a neutral player wins the same number of rounds
+       as a team, the game is a draw.
+
+
+January 18, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Weapon, naturals and items are now stored in
+    a text file (weapons.txt). The data in weapons.h
+    is no longer used.
+       A) Created function to read in weapon/item data.
+       B) Commented out weapons.h
+       C) Implemented weapons.txt -- provided by action9000
+       D) Replaced named constants in weapons.txt
+       E) Weapon, items and naturals declared in globals.h
+    -- Re-wrote AI weapon selection system, hopefully this will be
+       less CPU intensive.
+    -- The icon for the current weapon is displayed on the
+       top bar during rounds.
+    -- If the AI does not have a fun weapon to use, it may
+       select an item.
+    -- AI does not select self-destructive items or teleports
+       unless parachutes are in inventory.
+    -- Created small MIRV missile. A device that releases payload
+       while still above the ground.
+    -- Created MIRV images.
+
+
+January 7, 2008
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Introduced Campaign mode, which causes the AI
+    to get progressively smarter each round.
+    -- Removed liquid.cc from source tree.
+    -- Removed list.cc and list.h from source tree.
+    -- AI players randomly select weapons rather than
+       using an item until they run out.
+
+    
+December 28, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Firing a chian missile no longer fires another
+    shot, such as a death head.
+    -- Dirt balls that explode above the screen
+    no longer produce endless stream of dirt.
+    -- Program should no longer crash when
+    creating a new player.
+    -- Fixed lightning sound.
+    -- Created menu option for Laser Satellite.
+    -- Added laser-armed satellite that randomly fires
+    on the battle field.
+
+
+December 23, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Put fan item picture back to fan. Had been
+    accidently changed to fuel image.
+    -- Fixed mkdir call for Windows.
+
+
+
+=============== Atanks-2.7 Released ======================
+
+
+December 15, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Fixed bug where the game would crash if two players on the
+    same team have a duel.
+    -- Added a new type of weapon, the Chain Missile. This weapon
+    fires small missiles in vollies of three.
+    -- Fixed bug that prevents the config file to be saved
+    on systems without a previous version of Atanks installed.
+
+
+December 9, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added a .desktop file for atanks (atanks.desktop).
+    -- Wrap around walls are now displayed using the colour yellow.
+
+November 29, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Fixed bug where, if a tank shoots itself and falls
+    and the money penalty for self-damage drops the player's money 
+    below $0, then the money is "corrected" to $1,000,000,000.
+    Thanks to Andy for pointing this out.
+    -- If both teams have the same number of wins, then
+    the game is a draw.
+    -- Game settings are saved along with the saved game.
+    Settings are saved in the same directory as the saved game
+    as a .txt (plain text) file. Replacing your atanks-config.txt
+    file with this will give you the same game settings as you had
+    while playing the original game.
+    -- Display directions for saving game on buying screen.
+    -- Added fuel item, which allows the player's tank to
+    move using the < and > keys (or period and comma).
+    -- Amount of fuel the tank has is displayed on the top bar.
+
+
+November 18, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added different settings on the Options menu
+    for tech levels. One relating to weapons and the
+    other for items.
+    -- Keilaron added code for setting the window's
+    title (caption) under Winodws.
+    -- Added wrap-around walls. When missiles reach the side
+    of the screen, they wrap around to the other side.
+    -- Wind Strength is now saved in the settings file.
+    -- Increased buffer size for options to avoid over-flow.
+
+    
+November 15, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Corrected timing bug that causes freeze on
+    the buying screen.
+    -- Games that are not given a name are given the
+    default name of "unamed".
+    -- Changed name of player type from "Range Finder"
+    to "Ranger" to make it fit in the text box.
+    -- Windows version now saves settings and saved games
+    under user's AppData folder, rather than current working
+    directory.
+    -- Atanks will attempt to create a sub-directory in the user's
+    HOME directory called .atanks. The config file will be
+    copied there, if it exists. If the file does not yet exist,
+    future config files will be saved there.
+    Note: The game does not attempt to copy saved game files.
+    -- Saved games are now saved and loaded from the player's
+    HOME/.atanks/ directory.
+
+
+============== Atanks-2.6 released ====================
+
+
+November 3, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added Load Game option to the new game menu.
+    -- Games can be loaded from the Select Players screen.
+    -- Corrected minor load bugs and removed testing output.
+
+October 24, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Player can now create a name for the
+    game about to begin on the Select Players screen.
+    -- Moved a few functions out of atanks.cc and
+    into files.cc
+    -- Moved some headers into files.h
+    -- Games can now be saved from the buying screen
+    by pressing F10.
+    -- Tanks that have hit another tank now gloat
+    when the target dies only. Tanks do not
+    gloat for near-deaths.
+
+
+October 14, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Game speed is now adjustable through the Graphics
+    option menu.
+    Adjusting the game speed may help avoid errors where
+    the game would lockup before.
+    -- Rollers now hit Steel walls and fall normally instead
+    of instantly appearing at the bottom of the screen.
+    -- When the player pressed a key in the range of 0-9
+    the tank's team name is displayed along with the health status.
+
+October 9, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added variable land slide option. Player
+    can now control the delay in cartoon gravity.
+    -- Tanks delay falling the same way land does
+    on cartoon gravity.
+    -- Added Portuguese text to menus.
+    Many thanks to Fred Maranhão for the translation.
+
+September 29, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added more tank text (English)
+    -- Which team a tank is on is now shown on the top menu bar.
+    -- Changed default player names to ones more historical.
+    -- Intelligent AI players now buy parachutes when
+    gravity exists.
+    -- When there is no gravity, tanks no longer fall.
+    -- Introduced variable gravity delay for Cartoony gravity.
+
+August 17, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added Portuguese language files to the Makefile.
+
+
+============== Atanks-2.5 released ====================
+August 11, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- The Floattext class no longer frees up text passed to
+    its constructor. Text is now allocated and freed outside of
+    the class for easier debugging.
+
+    -- Players now try to avoid shooting fellow team mates.
+    Neutral players are not considered members of a team.
+
+    -- When only the members of one team are alive, the round
+    is over. Neutral players are not considered a team.
+
+    -- At the end of the game, teams are credited with wins.
+
+    -- Minor Makefile typo corrections.
+
+
+August 4, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- When tanks talk, the text is selected using
+    Random_Line (new function) rather than the
+    previously used LINESEQ for increased flexibility.
+
+    -- Player can now switch languages without re-starting
+    the game.
+
+    -- Added new colour theme, provided by Jim of the FreeDOS
+    project. The colour theme can be changed in the Graphics
+    menu. The options are "Regular" for the original theme and
+    "Crispy" for the new theme.
+    Note: Sky and landscape change colour when the theme is
+    changed. To see different explosions currently requires
+    a game restart.
+
+    -- Added Team option to the Player menu. Possible teams
+    are Sith, Neutral and Jedi.
+    Note: Teams do not have any effect on the game, yet.
+
+    -- Updated the Help.txt file. Thanks to Fred for pointing
+    out the incorrect text.
+
+    -- Removed AutoPlay option from the main Options menu
+    under Auto-Skip as it seems to be redundant.
+
+    -- Fixed Cartoon gravity to make it more cartoony.
+
+    -- When buying items, the AI now understands repair kits
+    have cumlitive effect.
+
+
+July 29, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added a new gravity type (Cartoon) which causes
+    the landscape to hover for a variable amount of time.
+
+    -- Tanks now hover for a few seconds when using
+    Cartoon gravity.
+
+    -- Reduced CPU usage when displaying the main menu.
+
+    -- Added Portuguese language files for gloat, revenge,
+    suicide and Help. Added menu option called Languages
+    to allow the player to switch between English and
+    Portuguese. Thanks to Fred for the translations.
+
+
+July 25, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- When you drop a burrower or penterator onto
+    a Steel floor, the game no longer hangs.
+
+    -- Players can now buy and sell items in bulk by
+    holding the CONTROL key while clicking on an item
+    in the buying screen. Items are bought/sold in
+    bulk 10 times their normal amount.
+
+    -- Fixed bug that prevented most tanks from buying
+    parachutes.
+
+    -- Fixed bug in loading preferences from a text file.
+
+    -- When starting the game in full screen mode,
+    previous width and height settings are ignored.
+    Fixes a weird display issue.
+
+    -- Try to avoid pausing the game when user switches
+    to a different window. (Windows only.)
+
+    -- Fixed screen centring on higher resolution settings.
+
+    -- Worked on text scrolling to make it more efficent.
+
+    -- Money no longer over-flows to become negative.
+
+
+================ Released Atomic Tanks 2.4 ========================
+
+June 22, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Fixed typo in Makefiles.
+    -- Created spec file for Red Hat/Fedora
+    Linux distros.
+    -- Created .rpm file for Fedora (Linux distro).
+    -- Fixed saving screen width and height.
+
+June 18, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- When turning the sound ON or OFF in the Options menu,
+    the game no longer requires a restart for the setting
+    to take effect.
+    -- When switching between Default OS mouse cursor and
+    the Custom Atanks cursor, the change no longer
+    requires a game restart.
+    -- If the constant "DOS" is defined, the background
+    should not be cached. This should fix weird menu issue on DOS.
+    -- When Steel walls are in effect, the computer usually
+    avoids shooting them.
+    -- When a new player is created, their default colour is
+    a high contrast to avoid blending.
+    -- Max missile age has been changed from 60 seconds to
+    20 seconds to speed up game play.
+
+June 10, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- In rest points, Linux uses usleep() and Windows
+    now uses native Sleep() call to avoid high CPU usage.
+    -- If there are no tanks alive at the end of a round
+    the game annouces a "Draw" and no one gets credit for
+    a win.
+    -- Try to avoid sub-index in tank::draw function.
+    -- Draw tank base _after_ the shield to avoid dis-colouration.
+
+June 6, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Removed Windows version of LINUX_SLEEP to avoid
+    very slow response from the game.
+    -- Put set_display_switch_mode() call in init_game_settings()
+    for Windows to avoid pausing the game when the window
+    loses focus.
+    -- Wall type indicator no longer appears across the top of the
+    screen. On the walls and floor only, where wall type
+    actually matters.
+
+June 2, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Config settings are now stored in a text file
+    called .atanks-config.txt
+    The old config files can still be read for backward
+    compatibility.
+    -- A new wall type (random) has been added, which causes the
+    type of wall to change each round.
+    -- The side of the screen now shows a thin band of colour which
+    indicates which wall type is being used. Red for Steel, Green
+    for Rubber and Blue for Spring.
+
+May 14, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Windows build now uses rest() calls where Linux uses usleep
+    in the hope of reducing CPU usage on Win32 systems.
+    -- Pressing the 0-9 keys will display the coresponding tank's
+    name, health and shield status. This information is removed
+    from the top bar when a weapon is fired.
+
+May 4, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Created files.h to hold common file defines and data.
+    -- Increased the delay in LINUX_SLEEP to 10000 (on Linux)
+    to reduce CPU usage.
+    -- When printing Credits and Help, we now use the Allegro
+    rest() function to reduce CPU usage. Estimated 3x easier
+    on CPU usage.
+
+April 22, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Moved BUTTON code out of atanks.cc into its
+    own source file (button.cc).
+    -- Added checks at the top of header files weapons.h,
+    player.h and menucontent.h to avoid duplicate defines.
+    -- Removed extra calls of srand() from atanks.cc
+    -- Tanks now make comments when they kill themselves.
+
+April 18, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Moved VERSION definition to main.h from the Makefiles
+    -- Fixed typo in Makefiles which caused Windows compile error.
+
+
+================== Atanks-2.3 Released ========================
+
+April 3, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Changed title screen. Art provided by Keilaron.
+    -- Settings are saved as soon as the player leaves the
+    Option screen. This avoids losing settings if the game
+    crashes or exits unexpectedly.
+
+
+March 27, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Changed the Auto-repair kit from tech level 4
+    to tech level 2.
+
+
+March 21, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- The player can now select to use either the custom
+    Atomic Tanks mouse cursor or the default OS cursor.
+    Note: The OS cursor is probably faster. 
+    The option is located under the Graphics menu and 
+    may require the game be restarted to take effect.
+    -- The ENTER key on the number pad can now be used
+    to indicate you are done entering text on Options
+    and Player editing screens.
+
+
+March 18, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- When the player presses TAB or BACKSPACE to change
+    weapons, the weapon text no longer flickers. The text
+    no longer flickers at the begining of new rounds.
+    -- The CTRL key now works to more finely tune PGUP and
+    PGDW commands. Of course, this still causes the power to
+    vary a lot (100 points per tap).
+    -- Created new device called "Fan" which changes the direction
+    and strength of the wind. The change in wind depends on the
+    direction of the player's turret and the power behind the "shot".
+    This only really works well in high-wind environments.
+
+
+March 15, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Changed drawing code so that different tank
+    styles can have the turrent in different positions.
+    See tank::draw()
+    -- When exiting the game to the main menu, the next game no
+    longer speeds up dramatically.
+    -- Fixed bug on Windows where exiting the game
+    causes all tanks to fire their weapons.
+    See tank::activateSelection()
+
+    
+March 12, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- The spelling of "lazer" has been changed to "laser".
+    -- Items that are not weapons are no longer displayed
+    left-aligned on the top bar. they are right-aligned like
+    the other items.
+    -- The Page Up and Page Down keys now cause the player's
+    power to go up or down dramatically (100 points instead of 5).
+    -- Players can now choose to make their tanks 
+    appear differently. The options are Normal or Classic.
+    This is changed in the Players menu.
+    -- Tank style preferences are now saved in the config file.
+
+
+March 6, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Human players can now be put under temporary
+    computer control (highest AI setting). This can
+    be done during the player's turn by pressing F10.
+
+    -- Repair kit's name changed to Auto-repair kit
+    to reflect its ability to repair without user intervention.
+
+    -- Text colour in Help and Credits changed to white from
+    black to increase contrast.
+
+    -- If a player is saved as a part time bot, then they
+    are re-loaded as a human player.
+
+
+================== Atanks-2.2 released ===========================
+
+Feb 27, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- We now save the Wind Strength option properly from
+    the Weather menu.
+    -- Avoid segfault when displaying gloating messages.
+    -- Meteors only live for 5 seconds. This is to prevent loops
+    where lots of meteors appear and don't self destruct, causing
+    an endless loop.
+    -- Meteors no longer fall while players are aiming in SIMUL turn
+    mode. They will fall at any time in other turn modes. Meteors will
+    also fall in SIMUL turn mode while weapons are in the air.
+    Note: Lightning remains the same as before.
+
+
+Feb 24, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Cleared up some compiler warnings we were getting from
+    the Windows compiler. Shouldn't effect game play at all,
+    but makes the build process nicer.
+    -- Added a device called Swapper, which will cause the
+    player's tank to switch places with another tank. The
+    other tank is picked at random.
+    -- Added a new wall type, Spring. The spring wall type 
+    causes missiles to bounce off the walls and floor
+    with more speed (x1.25) than they had before.
+    -- When one player kills another, the attacker gloats.
+    Only one gloat message is displayed if multiple tanks
+    are destroyed.
+
+
+Feb 21, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Disabled window closing in Windows to prevent hangs.
+    -- Added item: repair kit. A device which will slowly
+    repair the player's tank each turn.
+    -- The number of rounds of play remaining 
+    can be adjusted on the buying screen.
+    This is performed using the "-" and "+" signs on the keyboard.
+    Note, the "=" will also act like a "+" to add rounds.
+    -- Clear key buffer before accepting input from each player
+    to prevent accidently fireing a weapon.
+
+
+Feb 19, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Expanded final score box to prevent
+    money from running on to the background.
+    -- The mouse wheel can now be used to scroll through
+    items on the buying screen. Makes navigator quicker.
+    -- Game now clears keybaord buffer at the end of each turn.
+    Avoids weapons being un-intentionally activated.
+
+Feb 13, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Permissions on title.dat changed to 644. Corrects
+    bug where a system-wide install would run for root only.
+
+
+==================== Atanks-2.1 released ==========================
+
+Feb 11, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Added an option under the optins->Physics menu
+    to change the type of wall being used during the game.
+    The types are Rubber and Steel. Rubber acts as before,
+    allowing missiles to bounce off the walls and bottom of
+    the screen. The steel walls cause missiles to detonate on
+    impact.
+    -- Added the wall type option to the config file to
+    allow the setting to be saved.
+    -- When pressing the BACKSPACE key during the game, players
+    can cycle backward through their weapon selections.
+    -- Changed computer's targeting AI so the computer understands
+    the difference between rubber walls and steel walls. This prevents
+    the computer from shooting at steel walls repeatedly.
+
+
+Feb 9, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Option to enable or disable sound is now on
+    the main Options menu. At this time, changing the
+    sound on/off will not take effect until the game
+    is re-started.
+    -- Changed config file to save the sound option.
+    -- Made sure the command line option "--nosound"
+    over-rides the sound setting in the config file.
+    -- The width and height of the Atanks window can now be 
+    changed from the Options menu, under Graphics. Changes
+    take effect after the game is exited and re-started.
+    -- Added screen width and height to the config file.
+    -- Made sure the command line given width or height
+    takes priority over the width and height settings from
+    the config file.
+    -- Tank health is now printed in the same colour as the
+    player's tank.
+
+
+Feb 5, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Corrected bug where missles would not die from old
+    age. Missles should now properly detonate after 60
+    seconds (MAX_MISSLE_AGE) whether they hit anything.
+    This is to avoid infinate loops where missles bouce
+    forever.
+    -- Corrected problem with text lingering from the end
+    of one round and showing up in the next. Insults should
+    no longer carry over into the new round.
+
+
+Jan 31, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- The player's name now appears over their tank. Text
+    colour matches the tank's colour.
+    -- Changed money to signed int. Cleared up some
+    type problems. Put in check to keep money from
+    over-flowing. See Player::newRound()
+    -- Command-line option "--noname" added to allow the
+    player name above tank feature to be disabled.
+
+
+Jan 27, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Allow player names to be more than 10 characters. Names 
+    should now be able to expand to 23. Changed some output
+    code to allow for longer names without over-writing other
+    text on the screen. Changed file format to allow longer names
+    and backward compatibility.
+
+Jan 25, 2007
+     Mike (CaptainNeeda+atanks at gmail.com)
+    -- Added feature to allow all tanks to fire at the same time.
+    This is accessible by selecting "Simul" under Turn Order
+    in the options menu.
+
+
+Jan 21, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Floating text no longer carries over to the next round.
+       Added newRound() function to FLOATTEXT object.
+    -- When the window's "X" or close button is clicked, the game 
+       will exit immediately.
+
+=============== Atanks-2.0 Released ===========================
+
+Jan 10, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Fixed serious bug which causes game to crash
+    when there are more than two players.
+
+Jan 9, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Corrected serious bug where tanks did not take damage
+    when they free-fall.
+
+Jan 7, 2007
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Removed custom my_abs() function. Replaced it
+    with built-in fabs().
+    -- Where a char variable is used as a boolean, change the
+    type to int or bool to avoid compiler warnings.
+    -- Created a Debian spefic Makefile (Makefile.debian)
+    to make Atanks more compatible with Debian's package.
+
+
+Dec 19, 2006
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Version information is now displayed on the
+    command line properly at start up. This should
+    clear up some confusion about what version we have
+    during debuging.
+    Note: Version number is stored in Makefile
+    -- Fixed command line option for height. "-h" was
+    already being used for "help". Height can now be
+    given using "-t" or "--tall".
+    -- When one tank falls on another, the falling tank
+    now rests on top of the other, rather than over-lapping
+    on the screen.
+    -- Added command line option "--nosound" to disable
+    game sounds.
+    -- Updated command line help.
+    -- Re-wrote README file to be more up-to-date and
+    organized.
+    -- Updated Makefiles. Create new Makefile.windows for
+    people compiling on Win32 systems.
+    Use "make Makefile.windows" to compile.
+
+
+Dec 4, 2006
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- When a player runs out of ammo, the game switches
+    to a different type of ammo. The new ammo is displayed
+    in flashing RED instead of BLACK to warn the player.
+
+Nov 27, 2006
+    Jesse (jessefrgsmith at yahoo.ca)
+    -- Made code compatible with gcc 4.1
+    -- Updated code to use current Allegro 4.2 API
+       text output functions, set_clip and text_mode
+    -- Made player money unsigned to avoid negative funds.
+    -- When player runs out of a type of ammo, game automatically
+       switches to a new ammo type.
+    
+
+================= Atanks-1.1.0 released ===================================
+
+4. 9. 2002
+
+    Juraj Michalek (georgik at host.sk -- http://kota543.host.sk):
+    -- added wind
+    -- added indication bars
+    -- added pay off functions
+    -- added menu control by keyboard arrows
+6. 9. 2002
+
+    -- I rewrite all code to C++ -> hard work
+    there were a lot of bugs in type definition,
+    it's mirracle that game worked!
+
+7. 9. 2002
+
+    -- new structure of weapon record
+    -- eek, many and many type mistakes
+    -- added usleep for schedule optimization in Linux
+
+8. 9. 2002
+
+    -- changed structure of ITEM
+    -- added TANK method for boosting up shield
+    -- automatic shield boost
+    -- fixed buystuff algorithm
+    -- fixed colors and information in credits
+    -- speed up redrawing algorith
+    -- new title screen
+    -- new top-bar in game
+    
+15. 9. 2002
+
+    -- fixed bug with game engine (this bug came with
+    conversion to C++ :()
+
+2. 11. 2002
+
+    -- fixed some minor bugs
+    -- code indent fix
+    -- added command line functions
+    -- implicit select of windowed mode
+
+3. 11. 2002
+
+    -- back button in Option menu
+    -- icons of weapons
+    -- upgrade graphics
+    -- release of 0.5
+    
+5. 01. 2003 - Tom Hudson (tom at singular.org.uk):
+    -- Modified code to allow resizing of screen (currently only
+    at compile time, positions now scale)
+
+8. 01. 2003 - Tom Hudson (tom at singular.org.uk):
+    -- some previously static graphics are now generated (scalable)
+    -- modified way wind changes from turn to turn
+    -- added wind options to options screen
+
+12. 01. 2003 - Tom Hudson (tom at singular.org.uk):
+    -- changed dirtfall routines
+    -- missiles no longer have to pause while explosion happens
+    -- combine nearby make_updates (one blit instead of n)
+
+14. 01. 2003 - Tom Hudson (tom at singular.org.uk):
+    -- Fixed bug, t[z].ni is ITEMS long but
+        zero'd up to t[z].ni[WEAPONS] in newgame()
+    -- topbar now generated to fit screen
+
+15. 01. 2003 - Tom Hudson (tom at singular.org.uk):
+    -- Fixed another bug, setting t[z] variables in
+        z < MAX_MISSILES for-loop
+    -- Added FLOATTEXT class
+    -- Added permanent display of health and shields over tanks
+
+22. 01. 2003 - Tom Hudson (tom at singular.org.uk):
+    -- Modified missiles, more OO than before
+    -- Modified funky-bomb delivery (slower delivery, needs tweaking)
+    -- Added dirt-bombs
+
+24. 01. 2003 - Juraj Michalek (georgik at host.sk):
+    -- dirt ball explosion don't cover terrain
+    -- changed some weapon's costs
+
+26. 01 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Missiles once again bounce off the bottom of the screen.
+    -- Arrow no longer used to indicate current player,
+        uses bouncing health text instead
+
+28. 01 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Replaced unneeded images in .dat files,
+        reducing total download by 250k
+
+29. 01 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Explosion images are now generated at runtime,
+        saves 1Mb of download
+    -- Explosions now 'disperse' for 10 frames after initial explosion
+
+31. 01 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Change nature of land-slide to improve efficiency,
+        reduces changes/frame, smoother.
+    -- Fixed a bug in explosions (incomplete dispersal due to
+        land-slide finishing first).
+
+02. 02 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Added earthquake range of weapons (tremor, shock-wave,
+        tectonic-shift)
+    -- Improved update method for explosions and land-slides.
+
+06. 02 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Added new screen fades
+    -- Fixed bug in landslides where slide was calculated several times
+        per frame, once per active missile
+    -- Reorganised code, making it more OO, added VIRTUAL_OBJECT,
+        PHYSICAL_OBJECT above MISSILE and TANK and FLOATTEXT
+
+09. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Further large-scale reorganisation
+    -- Landfall accelerates with gravity
+    -- Improved graphics 'engine' (more efficient scheduling etc.)
+    -- Hierarchical menu system
+    -- Weather options (Meteor showers)
+    -- Physics options
+    -- Basic AI added
+    -- Improved credit attribution for damage done
+    -- EXPLOSION object added (explosions no longer part of missile)
+    -- tech level added to restrict availability of weapons
+    -- Added shaped-charge range of weapons
+    -- Added repulsion shields
+    -- Improved shield drawing routine
+    -- Player colours randomly generated (needs refining)
+    -- Bomblets for funky and cluster now separate weapons
+    -- Weapon buying now displays a description of each weapon
+        in a panel on the left of the screen
+
+11. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Fixed bugs in AI that made the AI really useless.
+    -- Added riot bomb and heavy riot bomb
+    -- Added riot charge and riot blast
+    -- Modified AI to choose riot gear if buried
+    -- Added Page Up and Page Down functionality to buying screen
+
+12. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Fixed bug where repulsion shields would continue to repulse
+        if shield was reduced to exactly 0
+    -- Fixed bug where angle of drawn object set to 0
+
+13. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Added teleport
+    -- Added functionality to allow items to be selected and used
+    -- Fixed bug where game would crash if everyone was dead
+        at the end of a round
+    -- Fixed bug where player would be incorrectly marked as COMPUTER_PLAYER
+    -- Added self/auto-destruct items (vengeance, dying wrath, fatal fury)
+    -- Added tech levels to items
+    -- Modified AI to mostly avoid selecting self/auto-destruct items
+
+14. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Changed landscape generation algorithm to use perlin noise
+
+15. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Added new landscape-type option to menu
+
+17. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Modifications to AI targetting
+    -- Fix to self-destruct
+
+18. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Implemented AI device preferences
+    -- Improved AI purchasing routines
+    -- AI now no longer uses teleport recreationally unless has parachute
+    -- Improved AI device-selection routine
+
+19. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Added landSlideType option to physics menu
+    -- Separated floating text from tank, the better to display damage with
+
+20. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Added permanent armour upgrades
+    -- Added drag-reduction items
+    -- Increased max number of each item to 999 from 99
+
+21. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Animated shields
+    -- Tidied in-game stats bar
+    -- Fixed bug in Funky Death due to incorrect settings in weapons.h
+    -- Modified AI item preference selection code to not favour the higher numbered items
+    -- Balance changes, effectiveness of Vengeance decreased, prices of some items changed
+
+26. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Added nicer/more complex looking landscape rendering
+    -- Added nicer/more complex looking sky rendering
+    -- Added graphics options to turn on nicer rendering
+        as it's a lot slower to render
+    -- Added moon to sky
+    -- Fixed bug where ingamemenu wasn't being cleared from screen
+        on return
+    -- Fixed colorDistance () algorithm, should now have
+        meaningful results
+    -- Modified options menu to not need bitmap anymore,
+        still not great (e.g. tiny title) but getting there
+
+27. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Added config file (.atanks-config) which records settings
+
+28. 04 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Implemented Versioning system in config file
+
+14. 06 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Implemented player persistence between games
+    -- Improvements to BUTTON class and usage on front menu
+    -- Teleport sound-effect + visual effect
+    -- Player selection before game
+    -- a variety of other things
+
+25. 06 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Implemented new DECOR class (decorative)
+    -- Implemented smoke trails on missiles
+    -- Implemented new TELEPORT class
+
+10. 07 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Implemented new BEAM class
+    -- Implemented new weather (lightning)
+    -- Implemented new Lazer weapon
+
+14. 07 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Fixed bug with damage text displaying even if damage rounds to 0
+
+15. 07 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Implemented 3 difficulty levels for computer players
+    -- Fixed TOGGLE options bounce-effect (select, deselect, select
+        rapidly)
+
+18. 07 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Implemented numerical display of angle and power
+        (suggested by krajzega, allegro.cc)
+    -- Animated lightning a little
+    -- AI will now not attempt to use a lazer on a target lower than
+        itself
+
+22. 07 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Fixed bug due to number of weapons changing between versions
+
+25. 07 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Modified credits screen, broke it down into several functions
+        to make it re-usable.
+
+30. 07 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Added instructions screen from new button on main menu
+
+31. 07 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Fixed bug where explosion constantly checked if it was causing
+        fall damage. This would cause money to often not be awarded
+        to the player that fired the weapon.
+    -- Changed the money model slightly, now a player should not be able
+        to go below 0 money.
+
+31. 07 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- When entering text (such as the Name field when editing a player)
+        the mouse now continues to be visible, also the typing
+        cursor flashes.
+
+01. 08 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Added usleep under linux to try and prevent 100% cpu on
+        instruction and credits screens.
+    -- Modified Guesser, should now be slightly more random. Previously
+        it would consistently overshoot (guaranteed to miss, rather
+        than just unlikely to hit).
+    -- If a config file doesn't already exist, 10 players are created.
+    -- Also, it will create a new (human) player and have you edit it when
+        you run it.
+
+02. 08 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Changes for easier packaging (thanks to Michael Sterrett) including
+        -DDATA_DIR option to modify the built-in path to the data
+        files.
+    -- Checks on various initialisation return-codes to see if they were
+        successful, and returning errors if not. Previously these were
+        ignored.
+
+03. 08 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Initialisation of previously uninitialized variables (as reported
+        by 'gcc -O2 -Wall').
+
+04. 08 .2003 - Tom Hudson (tom at singular.org.uk):
+    -- Moved up/down arrows on buying screen to more logical location
+    -- Added Fast up/down arrows to buying screen to provide GUI
+        equivalent of existing page-up/page-down functionality
+    -- Added new arrow images for above purpose
+    -- Added Napalm weapons
+
+07. 08 .2003 - Kalle Toivonen (kato at korpikuu.fi)
+    -- Found and fixed bug with backspace in text entry fields
+
+11. 08 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Added new Burrower and Penetrator subterranean weapons
+
+12. 08 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Any remaining shields are now recharged at the end of a round.
+    -- Fixed a bug where it didn't pick up on failure to open title.dat
+        then went ahead and tried to use it anyway (bug #787283).
+    -- Money is now no longer lost when you damage yourself.
+        This is the default behaviour.
+    -- Bonus money now awarded to the tank which wins the round.
+    -- Added options for financial side of things (bounty, bonuses,
+        penalties for self damage and interest rate).
+    -- Rewrote High/Low player ordering routine (turn order).
+        Previously I'm not sure it ever worked.
+
+13. 08 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Made 'action' options on menus possible to implement
+
+14. 08 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Player Deletion now possible
+    -- Moved number of rounds selector to player selection screen
+
+17. 08 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Fixed 'pause' bug, it really does now.
+    -- When all human players are out of the game and only computer
+        players remain, goes into Accelerated AI mode (Doesn't draw
+        anything, speeds up the game and ends the round quicker,
+        less sitting around waiting).
+    -- Added option for Accelerated AI
+    -- Added incremental stepping of angle and power via ctrl being
+        held down (Patrick Bogen's suggestion)
+
+18. 08 .2003 - Patrick Bogen
+    -- Fixed divide by zero bug in wind variation routine which would
+        happen if windvariation == 0;
+
+20. 08 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Added display of AI difficulty on selection screen and player menu.
+    -- Fixed bug in win32 version causing config to screw up, it was
+        due to file read and write being non-binary.
+        This was already fixed in an earlier version but apparently
+        overwritten before it made it to CVS.
+
+22. 08 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Added checks for memory allocation failures and handle them
+        more gracefully (print an error and exit).
+
+23. 08 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Added FRAMES_PER_SECOND define
+    -- 15 second time limit on missiles before they just detonate
+    -- Maximum altitude (-65535) on missiles before they just detonate
+
+24. 08 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Last words added, along with revenge memory (AI more likely to
+        fire on last player to do significant damage to them).
+    -- Dropped FRAMES_PER_SECOND to 60 from 100
+    -- Modified various things to cope with FRAMES_PER_SECOND changes
+
+01. 09 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Fixed AI targetting bug resulting from FRAME_RATE changes (thanks
+        to vossman77)
+
+02. 09 .2003 - Justin Ronco (jronco at umich.edu)
+    -- Removed z, zz, zzz, z4, z5, z6 globals.
+    -- fade.cc & lineseq.h should be complete
+
+02. 09 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Fixed bug in drawFracture which would cause a hang
+        (Eugeni Andreechtchev)
+
+06. 09 .2003 - Justin Ronco (jronco at umich.edu)
+    -- Relocated Tom's Perlin Noise code to "perlin.cc".  Documented.
+
+07. 09 .2003 - Justin Ronco (jronco at umich.edu)
+    -- Relocated Sky rendering code to sky.cc.  Documented.
+    -- Modified moon drawing system;  some cleanup, some additions.
+    -- Made global gradients constant.  Changed functions appropriately.
+    -- Changed interface to generate_sky, removed all other functions
+        from external view
+    -- set_level_settings modified to call new sky functionality
+
+07. 09 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Fixed tremor-freeze bug (I thought this was already fixed?)
+
+08. 09 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Bugfix (workaround) for objects carrying through from the end of
+        one round to the beginning of the next. This is temporary
+        until a better fix can be made.
+
+09. 09 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Added detect_digi_driver before install_sound to see if sound is
+        possible
+
+20. 11 .2003 - Eden (eden99_99 at users.sourceforge.net)
+    -- Fixed bug with funky bomblet leaving the top of the screen.
+    -- Fixed problem with not frequent-enough position sampling for
+        collision detection.
+
+01. 12 .2003 - Eden (eden99_99 at users.sourceforge.net)
+    -- Fixed bug with burrower leaving the top of the screen.
+    -- AI improved to buy more parachutes along with a new player option
+        to change when CPU players generate their weapon
+        preferences.
+
+11. 12 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Fixed bug introduced in earlier version which printed 'advice' type
+        errors ("You must have at least 2 players") to the console,
+        rather than the screen.
+
+15. 12 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Improvement to AI, targetting now based on optimum positioning for
+        maximum damage, with weighting for revenge, avoiding damaging
+        self and several other factors.
+
+16. 12 .2003 - Tom Hudson (tom at singular.org.uk)
+    -- Further improvement to AI, added wind factoring into targetting
+        for 2 stage weapons, which should make cluster bombs etc.
+        used more effectively.
+    -- Added 'shopping trolley', allowing items to be put back.
+
+04. 01. 2004 - Tom Hudson (tom at singular.org.uk)
+    -- Improved shopping trolley to allow sell-back of previously bought
+        items at a loss (adjustable via money menu).
+    -- Changed money from int to long int as int is apparently too small
+
+06. 01. 2004 - Tom Hudson (tom at singular.org.uk)
+    -- Changes to missile-specific code, allowing a wide variety
+        of definitions and tweaks via weapons.h and simplifying
+        certain sections.
+
+08. 01. 2004 - Tom Hudson (tom at singular.org.uk)
+    -- Further improvements to AI to allow better targetting
+    -- Changes to calculation of weapon damage
+
+20. 01. 2004 - Tom Hudson (tom at singular.org.uk)
+    -- Added new items Intensity Amplifier and Violent Force which
+        increase the damage done by the player's explosive weapons.
+
+28. 01. 2004 - Tom Hudson (tom at singular.org.uk)
+    -- Fixed bug where failure to set_gfx_mode would report semi-random
+        and unrelated system errors ("directory not found").
+    -- Attempted fix to lazer-only-sometimes-doing-damage bug by
+        adding lazer radius to cause-damage area.
+
+31. 01. 2004 - Tom Hudson (tom at singular.org.uk)
+    -- Added command-line options to set screen/window width and height
+    -- Added command-line option to set gfx depth (16 or 32)
+    -- Added Valleys terrain type
+
+02. 02. 2004 - Tom Hudson (tom at singular.org.uk)
+    -- Changed AI purchasing algorithm to increase chances of purchasing
+        'cumulative' items. This is done by decreasing the chances
+        of purchasing a given item in proportion to the number of
+        items already purchased, unless it's a cumulative item.
+    -- Right mouse-button for larger increase/decrease in values in
+        menus.
+    -- Added --datadir switch for specifying an alternative data directory
+
+03. 02. 2004 - Tom Hudson (tom at singular.org.uk)
+    -- Fixed lazer only sometimes causing damage bug
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..34bc2ad
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,84 @@
+VERSION=5.5
+PREFIX ?= /usr/
+DESTDIR ?= 
+BINPREFIX = $(PREFIX)
+
+BINDIR = ${BINPREFIX}bin/
+INSTALLDIR = ${PREFIX}share/games/atanks
+
+export VERSION
+export PREFIX
+export INSTALLDIR
+
+FILENAME=atanks-${VERSION}
+INSTALL=$(PREFIX)bin/install -c
+DISTCOMMON=atanks/*.dat atanks/COPYING atanks/README atanks/TODO atanks/Changelog atanks/BUGS atanks/*.txt
+INCOMMON=COPYING README TODO Changelog *.txt unicode.dat
+
+all:
+	FLAGS=-DLINUX $(MAKE) -C src
+
+install: 
+	mkdir -p $(DESTDIR)${BINDIR}
+	$(INSTALL) -m 755 atanks $(DESTDIR)${BINDIR}
+	mkdir -p $(DESTDIR)/usr/share/applications
+	$(INSTALL) -m 644 atanks.desktop $(DESTDIR)/usr/share/applications
+	mkdir -p $(DESTDIR)/usr/share/icons/hicolor/48x48/apps
+	$(INSTALL) -m 644 atanks.png $(DESTDIR)/usr/share/icons/hicolor/48x48/apps
+	mkdir -p $(DESTDIR)${INSTALLDIR}
+	mkdir -p $(DESTDIR)${INSTALLDIR}/button
+	mkdir -p $(DESTDIR)${INSTALLDIR}/misc
+	mkdir -p $(DESTDIR)${INSTALLDIR}/missile
+	mkdir -p $(DESTDIR)${INSTALLDIR}/sound
+	mkdir -p $(DESTDIR)${INSTALLDIR}/stock
+	mkdir -p $(DESTDIR)${INSTALLDIR}/tank
+	mkdir -p $(DESTDIR)${INSTALLDIR}/tankgun
+	mkdir -p $(DESTDIR)${INSTALLDIR}/title
+	mkdir -p $(DESTDIR)${INSTALLDIR}/text
+	$(INSTALL) -m 644 $(INCOMMON) $(DESTDIR)${INSTALLDIR}
+	$(INSTALL) -m 644 button/* $(DESTDIR)${INSTALLDIR}/button
+	$(INSTALL) -m 644 misc/* $(DESTDIR)${INSTALLDIR}/misc
+	$(INSTALL) -m 644 missile/* $(DESTDIR)${INSTALLDIR}/missile
+	$(INSTALL) -m 644 sound/* $(DESTDIR)${INSTALLDIR}/sound
+	$(INSTALL) -m 644 stock/* $(DESTDIR)${INSTALLDIR}/stock
+	$(INSTALL) -m 644 tank/* $(DESTDIR)${INSTALLDIR}/tank
+	$(INSTALL) -m 644 tankgun/* $(DESTDIR)${INSTALLDIR}/tankgun
+	$(INSTALL) -m 644 title/* $(DESTDIR)${INSTALLDIR}/title
+	$(INSTALL) -m 644 text/* $(DESTDIR)${INSTALLDIR}/text
+
+user:
+	INSTALLDIR=./ FLAGS=-DLINUX $(MAKE) -C src
+
+winuser:
+	INSTALLDIR=./ FLAGS=-DWIN32 $(MAKE) -C src -f Makefile.windows
+
+osxuser:
+	INSTALLDIR=./ FLAGS="-DMACOSX" $(MAKE) -C src -f Makefile.bsd
+
+ubuntu:
+	FLAGS="-DLINUX -DUBUNTU" $(MAKE) -C src
+
+clean:
+	rm -f atanks atanks.exe
+	$(MAKE) -C src clean
+
+dist: source-dist i686-dist win32-dist
+
+source-dist:
+	cd ../; \
+	rm -f ${FILENAME}.tar.gz; \
+	tar cvf ${FILENAME}.tar atanks/src/*.cpp atanks/src/*.h atanks/src/Makefile atanks/src/Makefile.windows atanks/Makefile ${DISTCOMMON}; \
+	gzip ${FILENAME}.tar
+
+i686-dist:
+	cd ../; \
+	rm -f ${FILENAME}-i686-dist.tar; \
+	rm -f ${FILENAME}-i686-dist.tar.gz; \
+	strip atanks/atanks; \
+	tar cvf ${FILENAME}-i686-dist.tar atanks/atanks ${DISTCOMMON}; \
+	gzip ${FILENAME}-i686-dist.tar;
+
+win32-dist:
+	cd ../; \
+	rm -f ${FILENAME}-win32-dist.zip; \
+	zip ${FILENAME}-win32-dist.zip atanks/Atanks.exe atanks/alleg40.dll ${DISTCOMMON};
diff --git a/README b/README
new file mode 100644
index 0000000..245912c
--- /dev/null
+++ b/README
@@ -0,0 +1,241 @@
+README file for Atomic Tanks 
+============================================
+
+What is Atomic Tanks?
+========================
+
+Atomic Tanks is a game in which you control an overly-powerful
+tank and attempt to blow up other highly powerful tanks. Players
+get to select a number of weapons and defensive items and then
+attack each other in a turn-based manner. The last tank standing
+is the winner.
+
+
+
+How to I get/install Atomic Tanks?
+===================================
+
+To gain a copy of Atomic Tanks, go to our
+website at http://atanks.sourceforge.net
+Click on the "Download" link and select the
+latest version of Atanks.
+
+Note: If you have a pre-compiled (binary) copy
+of Atomic Tanks, you will need the Allegro graphic
+package. See http://allegro.cc/
+Also, if you are going to compile/build Atomic Tanks
+from source code, you will need the Allegro development
+package. These packages can be found at
+http://allegro.cc/files/
+Please also note, those of you running Linux can
+usually get Allegro packages through your distribution's
+package manager. These packages are named (at least on Fedora)
+"allegro" and "allegro-devel" respectively. Debian
+uses, I think, "allegro" and "allegro-dev".
+
+
+If you are using a pre-built, binary copy of Atomic Tanks,
+please see the next section on running the game. Next
+we will cover compiling from source.
+
+
+To compile Atomic Tanks, please make sure you have
+the Allegro libraries installed (see above). Next,
+open a command console (shell) and move into the
+directory containing the Atomic Tanks package.
+This file will probably be named "atanks-5.5.tar.gz".
+Then run the following commands:
+
+tar zxf atanks-5.5.tar.gz
+cd atanks-5.5
+
+Now it depends on your preferences:
+
+Default linux installation.
+The Binary goes to: /usr/games/bin
+The data files go to: /usr/share/games/atanks
+
+make
+make install
+
+Linux User installation, where everything stays in
+the atanks folder:
+
+make
+
+Windows User installation where everything stays in
+the atanks folder:
+
+make winuser
+
+OSX User installation where everything stays in
+the atanks folder:
+
+make osxuser
+(BSD or OS X users may wish to use "gmake osxuser" instead.)
+
+For people compiling on Ubuntu (or one of Ubuntu's children distributions)
+please compile with
+
+make ubuntu
+
+Now we can get to running the game. If you encounter
+an error while running "make", then please see the
+last section of this document, which covers reporting
+bugs.
+
+
+
+
+
+How do I run Atomic Tanks?
+====================================
+
+You can run the atanks file by typing "./atanks"
+from a command line, or double-clicking the file
+in a file browser. Atomic Tanks tries to use
+reasonable defaults, so there is rarely a need to
+use the command-line options. However, Atomic Tanks
+supports the following options:
+
+./atanks -h   (Print list of credits, command-line options and exit.)
+./atanks -fs  (Run the game using the entire screen. Full screen mode.)
+./atanks --windowed  (Run the game in a window. This is the default).
+./atanks --nosound  (Run the game without sound. Sound is on by default.)
+./atanks --noname   (Do not display player names over the tanks.)
+./atanks --width <number>  (Run the game in a window with a set width in pixels.)
+./atanks --tall <number>  (Run the game in a window with a set height in pixels.)
+./atanks --datadir <data directory>  (Path to the directory with Atank's data files.)
+./atanks --depth <number>  (Sets pixel depth. Use either 16 or 32 here.)
+./atanks --noconfig   (Resets all config options back to defaults.)
+./atanks --nonetwork  (Prevents atanks from setting up a server.)
+./atanks --nobackground  (Does not display the green menu background. May prevent crashes on 64-bit.)
+./atanks --nothread   (Stops threads for running in the background.)
+./atanks --thread     (Enabled use of threads to speed up things.)
+
+Most of these options can be used together, with the exception of "-fs"
+for full screen mode. Simply running "./atanks" is the same as running
+Atomic Tanks with the following options:
+./atanks --windowed --width 800 --tall 600 --datadir . depth 32
+
+Please note that as of version 4.3, threads are disabled by default. Use
+the "--thread" flag to enable background threads.
+
+
+
+How do I go about creating a player for myself?
+================================================
+
+when you first run Atomic Tanks, the first thing you'll need to
+do is create a player/tank for youself. Click on the "Players"
+button and click "Create New". Enter the name you want and
+pick the colour you'd like your tank to be. That's all you'll
+need to do. Click the "Okay" button. Then click the
+"Back" button and, most importantly, click "Play"!
+
+Once you click play, you'll have a chance to select which
+tanks you'll be playing against. You can get anywhere from 2
+to 10 tanks on the playing field at one time. Don't forget
+to select yourself!
+
+The next screen gives you a chance to buy weapons and defensive
+items. There is no perfect combination, so experiment a little.
+You can buy an item (assuming you have enough funds) by
+left-clicking on the item. To sell the item, right-click on
+the item. When you've completed your selection, click "Done".
+
+The final screen you'll see is where the action takes place!
+Use the left and right arrow buttons on your keyboard to
+aim your tank's gun. The up and down arrow keys adjust the
+speed (power) of the shot. The space bar fires the tanks gun. If
+you want to change which weapon you will be using, press the
+TAB button or the BACKSPACE button. The round is over when 
+there is one tank left standing.
+
+
+
+
+
+Keyboard Controls
+=========================================
+
+Atomic Tanks tries to be keybaord friendly and much of
+the tank's controls require the keyboard. Here is a quick
+over-view of which keys do what:
+
+SPACEBAR -- Fires weapons and selects/toggles menu items.
+ENTER -- Is similar to pressing the OK button on a menu.
+UP/DOWN arrows -- Adjusts tank power and cycles through menu items. Scrolls on the buying screen.
+LEFT/RIGHT arrows -- Aim the tank's gun. Also buys and sells on the buying screen or adjusts values in menus.
+ESC -- Cancel out of a menu.
+
+F10 -- Tells the computer to take over your tank for the remainder of the round.
+       Also saves games when on the buying screen.
+
+
+
+
+
+How to play a game over a network?
+=========================================
+
+Atomic Tanks has just introduced network play and it is still a bit rough.
+However, if you'd like to try playing this way, here are a new points to help
+you along.
+
+Playing over a network requires two or more people. One person must be the Host
+and the other person is the Client. If you are hosting the game, make sure
+you have networking enabled. To check this, go into the Options menu and select
+the Network option. Make sure "Networking" is set to "On". If it was "Off", then change it to "On" and then exit Atanks and re-start the game. Congratulations, you're now running a Host. You can continue to play as you normally would from this point. Clients will connect to your game and take over computer-controled tanks. To connect to you the Clients will need your IP address. To get this, visit the website whatismyip.com.
+
+For clients, to connect to a host, you'll need to first get the IP address of your Host. Once you have that, go to the Option menu and select the Network option. Change the box marked "Server Address" to match the IP address of your Host. Then return to the main menu and click the button labled Network Game. Atanks will then try to connect to the server and introduce you to the game.
+
+Things are still a bit flakey on the Client side. Hopefully it will improve as time goes on.
+
+If the Client cannot connect to the Host, there are a few possible problems. Perhaps there is a firewall in the way? Maybe the Host is using a non-default port number. Perhaps the Client side just isn't working well enough yet. If you run into problems, please let us know about them on the forum.
+
+When you're playing a game (as the client) you'll notice the various tanks
+some in four different colours. The Jedi Team is marked in Green, the
+Sith are marked as Purple, Neutral tanks are Blue and the player's
+tank is indicated with Red. Hopefully this will prevent you from shooting
+your team mates.
+
+
+
+Known issues
+=========================================
+
+There are some known issues which players should be aware of. We
+are trying to fix these, but in the mean time, it's best to know they
+exist and how to work around them. The issues are, in no particular order.
+
+1. Changing the game's language and then going into the Players menu
+will cause weird text to display and may cause problems. If you change the
+game's language, it's best to Quit the game fro mthe main menu and then
+start Atanks again.
+
+2. The default sound driver doesn't work on Ubuntu Linux and its related
+distributions. If sound isn't working for you, go into the Options menu,
+select Sound. Make sure Sound is turned on and that the Sound Driver is
+switched from AutoDetect to OSS. Then return to the main menu, Quit and
+then re-start the game. If this doesn't resolve the issue, then Quit the
+game and delete all of the files and folders in your computer's /tmp
+folder with the name "pulse".
+
+3. The client side of the network games is buggy. We're working on that.
+
+
+
+
+
+Where do I report bugs or send requests?
+=========================================
+
+Atomic Tanks is a great game, but it isn't perfect.
+We, the developers, are always trying to improve the
+experience our game brings to you. If you have
+a problem with installing or playing Atomic Tanks,
+please let us know. Mail me at jessefrgsmith at yahoo.ca 
+We encourage you to give your feedback. Please give
+as many details as possible so we can help you.
+
diff --git a/README_ru.txt b/README_ru.txt
new file mode 100644
index 0000000..afdb03a
--- /dev/null
+++ b/README_ru.txt
@@ -0,0 +1,198 @@
+README для программы Atomic Tanks 
+============================================
+
+Что такое Atomic Tanks?
+========================
+
+Atomic Tanks - это игра, в которой вы управляете мощным танком.
+Ваша задача - уничтожить танки противника и не пропасть самому.
+Игроки могут покупать различное оружие и снаряжение. Сражения
+происходят в пошаговом режиме. Побеждает единственный
+уцелевший танк.
+
+
+Как мне получить/установить Atomic Tanks?
+===================================
+
+Чтобы получить Atomic Tanks, зайдите на наш сайт:
+http://atanks.sourceforge.net
+Затем зайдите в секцию "Download" и скачайте самую
+последнюю версию Atomic Tanks.
+
+Внимание: Если у вас уже есть скомпилированная (запускаемая)
+копия Atomic Tanks, вам понадобится графический пакет Allegro.
+Подробнее на сайте: http://allegro.cc/
+Помимо этого, если вы собираетесь скомпилировать Atomic
+Tanks из исходников, вам потребуется development-пакет
+Allegro.
+Все эти пакеты могут быть найдены на странице:
+http://allegro.cc/files
+Пользователи Linux могут скачать вышеназванные пакеты
+с помощью менеджера пакетов в своём дистрибутиве.
+В Fedora Linux эти пакеты называются "allegro"
+и "allegro-devel". В Ubuntu эти пакеты называются
+"liballegro*" и "liballegro*-dev", где "*" - номер
+последней версии.
+
+
+Если вы используете уже собранную (запускаемую) копию
+Atomic Tanks, загляните в следующий раздел, описывающий
+запуск игры. Дальнейший текст этого раздела посвящён
+компиляции игры из исходников.
+
+
+Прежде чем компилировать Atomic Tanks, проверьте,
+установлены ли библиотеки Allegro (см. выше).
+После этого откройте командную консоль (shell, bash, etc)
+и перейдите в директорию, в которой находится архив
+с исходниками Atomic Tanks.
+Архив версии 5.5 называется "atanks-5.5.tar.gz".
+
+После этого выполните следующие команды:
+
+tar zxf atanks-5.5.tar.gz
+cd atanks-5.5
+
+
+
+Дальнейшие настройки зависят от ваших предпочтений.
+
+Команда
+make
+устанавливает игру в папку с распакованным архивом.
+Все настройки сохраняются в этой папке.
+Можно сразу же запускать команду "./atanks", чтобы
+начать играть. ;)
+
+
+Команды
+make system
+make install
+устанавливают Atomic Tanks в директории по умолчанию.
+Бинарные файлы будут перемещены в /usr/games/bin
+Данные игры будут перемещены в /usr/share/games/atanks
+
+
+Команда
+make winuser
+устанавливает Atomic Tanks в ту же папку, в которой
+находятся исходники, для пользователя ОС Windows.
+
+
+Команда
+make osxuser
+устанавливает Atomic Tanks в ту же папку, в которой
+находятся исходники, для пользователя Mac OS X.
+
+
+
+После выполнения соответствующих команд можно
+запускать игру.
+Если у вас возникают сообщения об ошибках во время
+выполнения make, пожалуйста, изучите последний раздел
+этого документа, посвящённый сообщениям об ошибках.
+
+
+
+
+
+
+Как запустить игру?
+====================================
+
+Вы можете запустить игру, введя "./atanks" в
+командной консоли или дважды щёлкнув по
+запускаемому файлу в файловом менеджере.
+При запуске Atomic Tanks использует специально подобранные
+настройки по умолчанию, так что в большинстве случаев
+использовать опции командной строки нет необходимости.
+Тем не менее, игра поддерживает следующие команды:
+
+./atanks -h   (Выводит список разработчиков, опции командной строки и завершает работу.)
+./atanks -fs  (Запускает игру в полноэкранном режиме.)
+./atanks --windowed  (Запускает игру в оконном режиме. Это режим по умолчанию.)
+./atanks --nosound  (Запускает игру без звука.)
+./atanks --noname   (Отключает отображение имён игроков над танками.)
+./atanks --width <number>  (Запускает игру с указанной в пикселях шириной экрана.)
+./atanks --tall <number>  (Запускает игру с указанной в пикселях высотой экрана.)
+./atanks --datadir <data directory>  (Указывает директорию с данными для Atomic Tanks.)
+./atanks --depth <number>  (Устанавливает глубину цвета. Допустимые значения: 16, 32)
+./atanks --noconfig   (Сбрасывает конфигурацию, использует настройки по умолчанию.)
+./atanks --nonetwork  (Не даёт Atanks подключаться к сети.)
+./atanks --nobackground  (Убирает зелёный фон в главном меню. Помогает от глюков на 64-битных системах.)
+
+Большинство этих опций могут использоваться вместе, за исключением "-fs"
+для включения полноэкранного режима.
+Простая команда "./atanks" запускает игру с теми же параметрами, что и команда:
+./atanks --windowed --width 800 --tall 600 --datadir . depth 32
+
+
+
+
+Как мне создать игрока для себя?
+================================================
+
+Сразу после запуска Atomic Tanks вам понадобится создать себе
+игрока. Для этого щёлкните по кнопке "Игроки" ("Players")
+и выберите пункт "Создать нового" ("Create new").
+Введите желаемое имя для игрока (не забудьте нажать Enter)
+и выберите цвет для себя. Это все основные настройки;
+можно щёлкнуть кнопку "Okay".
+После этого щёлкните по кнопке "Назад" ("Back") и затем по
+желанной кнопке "Играть" ("Play")!
+
+Сразу после этого откроется меню новой игры, в которой вам
+будет предложено выбрать те танки, которые будут участвовать
+в сражениях. Не забудьте выбрать себя (рядом с вами есть
+фиолетовый кружок) и несколько танков противника!
+Если вы начинающий игрок, лучше выбирать себе противников
+меньшего уровня (чем меньше зелёных полос рядом с именем танка,
+тем проще будет его победить).
+После этого выберите количество раундов, имя игры (необязательно)
+и нажмите "Okay"!
+
+На следующем экране вам будет предложено купить себе оружие
+и снаряжение на следующий раунд. Этот экран будет появляться перед
+каждым новым раундом, так что у вас будет время хорошенько
+попрактиковаться и подобрать себе хорошую комбинацию оружия.
+Щёлкнув левой кнопкой мыши, вы покупаете оружие. Правая кнопка
+мыши продаёт оружие или отменяет покупку.
+После того, как вы закупились, нажмите "Готово".
+
+После этого начинается игра.
+Ваша задача: используя всё то вооружение, которое вы приобрели,
+уничтожить все танки противника и при этом уцелеть самому.
+Используйте стрелки влево и вправо для изменения угла выстрела,
+стрелки вверх и вниз для изменения силы (дальности) выстрела
+и стреляйте кнопкой "Пробел"!
+Если вы купили какое-нибудь оружие, используйте клавиши
+"Z" и "C" для выбора нужного типа снаряда или ракеты.
+
+В каждом раунде побеждает единственный уцелевший танк.
+
+За каждое попадание в противника вплоть до его уничтожения
+вы получаете дополнительные деньги, которые вы можете потратить
+после каждого раунда.
+
+
+
+Где можно сообщить об ошибке или посоветовать что-либо разработчикам?
+=========================================
+
+Atomic Tanks - здоровская игра! ;)
+Но она не совершенна и находится в постоянной разработке.
+Мы, разработчики, всегда стремимся улучшить игру.
+Если у вас возникли проблемы с установкой или запуском
+Atomic Tanks, пожалуйста, сообщите нам на форуме:
+http://atanks.forumwise.com/
+Мы благодарны каждому, кто сообщил об ошибке.
+Пожалуйста, сообщите как можно больше деталей (версия
+операционной системы, версия игры, особенности вашего
+компьютера, которые могли повлиять на работу игры) -
+это облегчит нам задачу и позволит исправить ошибку
+и помочь вам в кратчайшие сроки.
+
+Авторы перевода:
+MyO <myothehedgefox at gmail.com>
+Sergi <grayman2000 at gmail.com>
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..62e7f68
--- /dev/null
+++ b/TODO
@@ -0,0 +1,53 @@
+There is now some small attempt at prioritisation in this file, 
+higher priority stuff should be at the top of the file, 
+lower priority at the bottom. It is currently only vaguely correct.
+
+   	- Field repair kit: Spend a turn to repair your tank rather than fire.           Limited uses, heals more than Auto Repair Kit 
+	- Radar resistant missile: A missile designed to avoid the missile 
+          defence system by masking its heat signature 
+          Yield: Large missile
+	- Better AI against tanks with SDI.
+	- Make sure network client doesn't get
+          unlimited shots.
+	- Update client ground surface more often.
+	- When switching languages, player menu should display correct text.
+	- Client needs a buying screen.
+	- Atanks crashes when Windows players click the Network option
+          in the main Options menu.
+	- Make tank size variable.
+	- Add rocks as semi-destructable items.
+
+
+===============================================
+
+	   Items from here to the bottom of the file
+	   are under consideration by the development
+	   team and may (or may not) be implemented.   
+
+===============================================
+
+	-- It's different in ATanks because I'm assuming it would require more hard coding to use a mouse like they do in Worms to place a girder. 
+
+So in our case, you would treat the missile for the floating dirt as any weapon projectile initially. You can set the angle+power for firing the weapon, except the explosion would be based on time if there is no collision with a wall/floor. 
+
+Say for example the player sets the power at 2000 that would mean throwing the projectile with max strength 5s projectile flight before solidifying into empty space. Setting a power of 0 would mean the player sets 0 time and doesn't fire anywhere before the block becomes dirt thus locking themself into a circular patch of dirt.
+
+
+        -- under ground mines
+
+	-- rocket like fireworks
+
+	-- Make it possible to shoot down the UFO
+
+	-- Make main window scalable
+           (Needs to wait until Allegro 5.x)
+
+	-- Harder ground
+
+	-- High voltage missiles (discharge on impact or when within range)
+		(Bharat Dhareshwar)
+
+	-- Tornadoes (pick up tanks and objects) (Bharat Dhareshwar)
+
+	-- Another level of armour improvement
+
diff --git a/atanks-4.3.spec b/atanks-4.3.spec
new file mode 100644
index 0000000..a9d6dfa
--- /dev/null
+++ b/atanks-4.3.spec
@@ -0,0 +1,301 @@
+%define    name    atanks
+%define    version 4.3
+%define    release 1
+%define    prefix  /usr
+
+Summary:   A fun tank game, which plays like Scorched Earth.
+Name:      %{name}
+Version:   %{version}
+Release:   %{release}
+License:   GPL
+Group:     Games Arcade
+Vendor:    Jesse Smith <jessefrgsmith at yahoo.ca>
+URL:       http://atanks.sourceforge.net/
+Source0:   http://atanks.sourceforge.net/downloads/%{name}-%{version}.tar.gz
+BuildArch: i386
+#BuildRoot: /var/tmp/%{name}-root
+Provides:  atanks
+
+%description
+Atomic Tanks is a simple tank game, similar to
+Scorched Earth or Worms, where small tanks use large weapons
+to destroy each other.
+
+%prep
+%setup
+
+%build
+make
+
+%install
+make install
+
+%clean
+rm -rf "$RPM_BUILD_ROOT"
+
+%files
+%{prefix}/games/bin/atanks
+/usr/share/games/atanks/README_ru.txt
+/usr/share/games/atanks/button/22.bmp
+/usr/share/games/atanks/button/19.bmp
+/usr/share/games/atanks/button/7.bmp
+/usr/share/games/atanks/button/1.bmp
+/usr/share/games/atanks/button/0.bmp
+/usr/share/games/atanks/button/6.bmp
+/usr/share/games/atanks/button/20.bmp
+/usr/share/games/atanks/button/10.bmp
+/usr/share/games/atanks/button/5.bmp
+/usr/share/games/atanks/button/2.bmp
+/usr/share/games/atanks/button/18.bmp
+/usr/share/games/atanks/button/23.bmp
+/usr/share/games/atanks/button/12.bmp
+/usr/share/games/atanks/button/13.bmp
+/usr/share/games/atanks/button/4.bmp
+/usr/share/games/atanks/button/17.bmp
+/usr/share/games/atanks/button/9.bmp
+/usr/share/games/atanks/button/11.bmp
+/usr/share/games/atanks/button/14.bmp
+/usr/share/games/atanks/button/8.bmp
+/usr/share/games/atanks/button/16.bmp
+/usr/share/games/atanks/button/15.bmp
+/usr/share/games/atanks/button/3.bmp
+/usr/share/games/atanks/button/21.bmp
+/usr/share/games/atanks/button/24.bmp
+/usr/share/games/atanks/button/25.bmp
+/usr/share/games/atanks/button/26.bmp
+/usr/share/games/atanks/button/27.bmp
+/usr/share/games/atanks/sound/0.wav
+/usr/share/games/atanks/sound/2.wav
+/usr/share/games/atanks/sound/3.wav
+/usr/share/games/atanks/sound/1.wav
+/usr/share/games/atanks/sound/11.wav
+/usr/share/games/atanks/sound/12.wav
+/usr/share/games/atanks/sound/10.wav
+/usr/share/games/atanks/sound/8.wav
+/usr/share/games/atanks/sound/5.wav
+/usr/share/games/atanks/sound/9.wav
+/usr/share/games/atanks/sound/6.wav
+/usr/share/games/atanks/sound/7.wav
+/usr/share/games/atanks/sound/4.wav
+/usr/share/games/atanks/atanks.ico
+/usr/share/games/atanks/missile/22.bmp
+/usr/share/games/atanks/missile/19.bmp
+/usr/share/games/atanks/missile/7.bmp
+/usr/share/games/atanks/missile/1.bmp
+/usr/share/games/atanks/missile/0.bmp
+/usr/share/games/atanks/missile/6.bmp
+/usr/share/games/atanks/missile/20.bmp
+/usr/share/games/atanks/missile/25.bmp
+/usr/share/games/atanks/missile/10.bmp
+/usr/share/games/atanks/missile/5.bmp
+/usr/share/games/atanks/missile/2.bmp
+/usr/share/games/atanks/missile/18.bmp
+/usr/share/games/atanks/missile/27.bmp
+/usr/share/games/atanks/missile/23.bmp
+/usr/share/games/atanks/missile/24.bmp
+/usr/share/games/atanks/missile/12.bmp
+/usr/share/games/atanks/missile/13.bmp
+/usr/share/games/atanks/missile/28.bmp
+/usr/share/games/atanks/missile/4.bmp
+/usr/share/games/atanks/missile/17.bmp
+/usr/share/games/atanks/missile/26.bmp
+/usr/share/games/atanks/missile/9.bmp
+/usr/share/games/atanks/missile/11.bmp
+/usr/share/games/atanks/missile/14.bmp
+/usr/share/games/atanks/missile/8.bmp
+/usr/share/games/atanks/missile/16.bmp
+/usr/share/games/atanks/missile/30.bmp
+/usr/share/games/atanks/missile/15.bmp
+/usr/share/games/atanks/missile/3.bmp
+/usr/share/games/atanks/missile/29.bmp
+/usr/share/games/atanks/missile/21.bmp
+/usr/share/games/atanks/Changelog
+/usr/share/games/atanks/atanks.png
+/usr/share/games/atanks/title/1.bmp
+/usr/share/games/atanks/title/0.bmp
+/usr/share/games/atanks/title/2.bmp
+/usr/share/games/atanks/title/4.bmp
+/usr/share/games/atanks/title/3.bmp
+/usr/share/games/atanks/unicode.dat
+/usr/share/games/atanks/text/weapons_de.txt
+/usr/share/games/atanks/text/retaliation_fr.txt
+/usr/share/games/atanks/text/weapons_fr.txt
+/usr/share/games/atanks/text/Help.txt
+/usr/share/games/atanks/text/ingame.pt_BR.txt
+/usr/share/games/atanks/text/war_quotes_ru.txt
+/usr/share/games/atanks/text/gloat.txt
+/usr/share/games/atanks/text/weapons.txt
+/usr/share/games/atanks/text/retaliation.txt
+/usr/share/games/atanks/text/ingame_sk.txt
+/usr/share/games/atanks/text/instr_de.txt
+/usr/share/games/atanks/text/kamikaze.pt_BR.txt
+/usr/share/games/atanks/text/weapons.pt_BR.txt
+/usr/share/games/atanks/text/war_quotes.txt
+/usr/share/games/atanks/text/Help.pt_BR.txt
+/usr/share/games/atanks/text/Help_fr.txt
+/usr/share/games/atanks/text/suicide_fr.txt
+/usr/share/games/atanks/text/weapons_ru.txt
+/usr/share/games/atanks/text/gloat_ru.txt
+/usr/share/games/atanks/text/gloat_sk.txt
+/usr/share/games/atanks/text/ingame_de.txt
+/usr/share/games/atanks/text/revenge_de.txt
+/usr/share/games/atanks/text/ingame_ru.txt
+/usr/share/games/atanks/text/retaliation.pt_BR.txt
+/usr/share/games/atanks/text/revenge_sk.txt
+/usr/share/games/atanks/text/suicide.txt
+/usr/share/games/atanks/text/kamikaze_ru.txt
+/usr/share/games/atanks/text/retaliation_ru.txt
+/usr/share/games/atanks/text/instr_sk.txt
+/usr/share/games/atanks/text/suicide.pt_BR.txt
+/usr/share/games/atanks/text/instr.pt_BR.txt
+/usr/share/games/atanks/text/kamikaze.txt
+/usr/share/games/atanks/text/gloat_fr.txt
+/usr/share/games/atanks/text/revenge.pt_BR.txt
+/usr/share/games/atanks/text/instr_ru.txt
+/usr/share/games/atanks/text/instr_fr.txt
+/usr/share/games/atanks/text/revenge_fr.txt
+/usr/share/games/atanks/text/revenge.txt
+/usr/share/games/atanks/text/retaliation_de.txt
+/usr/share/games/atanks/text/retaliation_sk.txt
+/usr/share/games/atanks/text/kamikaze_fr.txt
+/usr/share/games/atanks/text/suicide_sk.txt
+/usr/share/games/atanks/text/suicide_ru.txt
+/usr/share/games/atanks/text/revenge_ru.txt
+/usr/share/games/atanks/text/weapons_sk.txt
+/usr/share/games/atanks/text/kamikaze_sk.txt
+/usr/share/games/atanks/text/kamikaze_de.txt
+/usr/share/games/atanks/text/instr.txt
+/usr/share/games/atanks/text/gloat_de.txt
+/usr/share/games/atanks/text/ingame_fr.txt
+/usr/share/games/atanks/text/gloat.pt_BR.txt
+/usr/share/games/atanks/text/suicide_de.txt
+/usr/share/games/atanks/text/Help_ru.txt
+/usr/share/games/atanks/text/ingame.txt
+/usr/share/games/atanks/tank/7.bmp
+/usr/share/games/atanks/tank/1.bmp
+/usr/share/games/atanks/tank/0.bmp
+/usr/share/games/atanks/tank/6.bmp
+/usr/share/games/atanks/tank/10.bmp
+/usr/share/games/atanks/tank/5.bmp
+/usr/share/games/atanks/tank/2.bmp
+/usr/share/games/atanks/tank/4.bmp
+/usr/share/games/atanks/tank/9.bmp
+/usr/share/games/atanks/tank/8.bmp
+/usr/share/games/atanks/tank/11.bmp
+/usr/share/games/atanks/tank/12.bmp
+/usr/share/games/atanks/tank/13.bmp
+/usr/share/games/atanks/tank/14.bmp
+/usr/share/games/atanks/tank/3.bmp
+/usr/share/games/atanks/atanks.desktop
+/usr/share/games/atanks/COPYING
+/usr/share/games/atanks/Makefile
+/usr/share/games/atanks/TODO
+/usr/share/games/atanks/misc/7.bmp
+/usr/share/games/atanks/misc/1.bmp
+/usr/share/games/atanks/misc/0.bmp
+/usr/share/games/atanks/misc/6.bmp
+/usr/share/games/atanks/misc/10.bmp
+/usr/share/games/atanks/misc/5.bmp
+/usr/share/games/atanks/misc/2.bmp
+/usr/share/games/atanks/misc/12.bmp
+/usr/share/games/atanks/misc/13.bmp
+/usr/share/games/atanks/misc/4.bmp
+/usr/share/games/atanks/misc/9.bmp
+/usr/share/games/atanks/misc/11.bmp
+/usr/share/games/atanks/misc/14.bmp
+/usr/share/games/atanks/misc/8.bmp
+/usr/share/games/atanks/misc/16.bmp
+/usr/share/games/atanks/misc/15.bmp
+/usr/share/games/atanks/misc/3.bmp
+/usr/share/games/atanks/README
+/usr/share/games/atanks/stock/22.bmp
+/usr/share/games/atanks/stock/19.bmp
+/usr/share/games/atanks/stock/35.bmp
+/usr/share/games/atanks/stock/7.bmp
+/usr/share/games/atanks/stock/31.bmp
+/usr/share/games/atanks/stock/1.bmp
+/usr/share/games/atanks/stock/0.bmp
+/usr/share/games/atanks/stock/69.bmp
+/usr/share/games/atanks/stock/49.bmp
+/usr/share/games/atanks/stock/56.bmp
+/usr/share/games/atanks/stock/6.bmp
+/usr/share/games/atanks/stock/48.bmp
+/usr/share/games/atanks/stock/53.bmp
+/usr/share/games/atanks/stock/55.bmp
+/usr/share/games/atanks/stock/51.bmp
+/usr/share/games/atanks/stock/20.bmp
+/usr/share/games/atanks/stock/65.bmp
+/usr/share/games/atanks/stock/25.bmp
+/usr/share/games/atanks/stock/43.bmp
+/usr/share/games/atanks/stock/78.bmp
+/usr/share/games/atanks/stock/34.bmp
+/usr/share/games/atanks/stock/57.bmp
+/usr/share/games/atanks/stock/10.bmp
+/usr/share/games/atanks/stock/33.bmp
+/usr/share/games/atanks/stock/71.bmp
+/usr/share/games/atanks/stock/45.bmp
+/usr/share/games/atanks/stock/5.bmp
+/usr/share/games/atanks/stock/2.bmp
+/usr/share/games/atanks/stock/74.bmp
+/usr/share/games/atanks/stock/18.bmp
+/usr/share/games/atanks/stock/32.bmp
+/usr/share/games/atanks/stock/27.bmp
+/usr/share/games/atanks/stock/23.bmp
+/usr/share/games/atanks/stock/24.bmp
+/usr/share/games/atanks/stock/12.bmp
+/usr/share/games/atanks/stock/76.bmp
+/usr/share/games/atanks/stock/39.bmp
+/usr/share/games/atanks/stock/13.bmp
+/usr/share/games/atanks/stock/73.bmp
+/usr/share/games/atanks/stock/28.bmp
+/usr/share/games/atanks/stock/4.bmp
+/usr/share/games/atanks/stock/58.bmp
+/usr/share/games/atanks/stock/36.bmp
+/usr/share/games/atanks/stock/17.bmp
+/usr/share/games/atanks/stock/26.bmp
+/usr/share/games/atanks/stock/42.bmp
+/usr/share/games/atanks/stock/40.bmp
+/usr/share/games/atanks/stock/68.bmp
+/usr/share/games/atanks/stock/59.bmp
+/usr/share/games/atanks/stock/46.bmp
+/usr/share/games/atanks/stock/9.bmp
+/usr/share/games/atanks/stock/54.bmp
+/usr/share/games/atanks/stock/11.bmp
+/usr/share/games/atanks/stock/14.bmp
+/usr/share/games/atanks/stock/44.bmp
+/usr/share/games/atanks/stock/8.bmp
+/usr/share/games/atanks/stock/41.bmp
+/usr/share/games/atanks/stock/16.bmp
+/usr/share/games/atanks/stock/30.bmp
+/usr/share/games/atanks/stock/61.bmp
+/usr/share/games/atanks/stock/75.bmp
+/usr/share/games/atanks/stock/15.bmp
+/usr/share/games/atanks/stock/64.bmp
+/usr/share/games/atanks/stock/63.bmp
+/usr/share/games/atanks/stock/66.bmp
+/usr/share/games/atanks/stock/47.bmp
+/usr/share/games/atanks/stock/37.bmp
+/usr/share/games/atanks/stock/3.bmp
+/usr/share/games/atanks/stock/70.bmp
+/usr/share/games/atanks/stock/29.bmp
+/usr/share/games/atanks/stock/21.bmp
+/usr/share/games/atanks/stock/62.bmp
+/usr/share/games/atanks/stock/38.bmp
+/usr/share/games/atanks/stock/77.bmp
+/usr/share/games/atanks/stock/52.bmp
+/usr/share/games/atanks/stock/60.bmp
+/usr/share/games/atanks/stock/72.bmp
+/usr/share/games/atanks/stock/50.bmp
+/usr/share/games/atanks/stock/67.bmp
+/usr/share/games/atanks/credits.txt
+/usr/share/games/atanks/tankgun/1.bmp
+/usr/share/games/atanks/tankgun/0.bmp
+/usr/share/games/atanks/tankgun/2.bmp
+/usr/share/games/atanks/tankgun/3.bmp
+/usr/share/games/atanks/tankgun/4.bmp
+/usr/share/games/atanks/tankgun/5.bmp
+/usr/share/games/atanks/tankgun/6.bmp
+/usr/share/games/atanks/tankgun/7.bmp
+
+%changelog
+
diff --git a/atanks.desktop b/atanks.desktop
new file mode 100644
index 0000000..69454ae
--- /dev/null
+++ b/atanks.desktop
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Name=Atomic Tanks
+Comment=Destroy your opponents' tanks.
+Comment[es]=Destruye los tanques de tus oponentes.
+Type=Application
+Exec=atanks
+Icon=atanks.png
+Categories=Game;ArcadeGame;
+Terminal=false
+
diff --git a/atanks.ico b/atanks.ico
new file mode 100644
index 0000000..e87ff3c
Binary files /dev/null and b/atanks.ico differ
diff --git a/atanks.png b/atanks.png
new file mode 100644
index 0000000..1b6a498
Binary files /dev/null and b/atanks.png differ
diff --git a/button/0.bmp b/button/0.bmp
new file mode 100644
index 0000000..8f3631f
Binary files /dev/null and b/button/0.bmp differ
diff --git a/button/1.bmp b/button/1.bmp
new file mode 100644
index 0000000..6260e30
Binary files /dev/null and b/button/1.bmp differ
diff --git a/button/10.bmp b/button/10.bmp
new file mode 100644
index 0000000..dee7315
Binary files /dev/null and b/button/10.bmp differ
diff --git a/button/11.bmp b/button/11.bmp
new file mode 100644
index 0000000..dbf95df
Binary files /dev/null and b/button/11.bmp differ
diff --git a/button/12.bmp b/button/12.bmp
new file mode 100644
index 0000000..7e95ddf
Binary files /dev/null and b/button/12.bmp differ
diff --git a/button/13.bmp b/button/13.bmp
new file mode 100644
index 0000000..dc4423d
Binary files /dev/null and b/button/13.bmp differ
diff --git a/button/14.bmp b/button/14.bmp
new file mode 100644
index 0000000..705d246
Binary files /dev/null and b/button/14.bmp differ
diff --git a/button/15.bmp b/button/15.bmp
new file mode 100644
index 0000000..7cd6f9c
Binary files /dev/null and b/button/15.bmp differ
diff --git a/button/16.bmp b/button/16.bmp
new file mode 100644
index 0000000..4190edc
Binary files /dev/null and b/button/16.bmp differ
diff --git a/button/17.bmp b/button/17.bmp
new file mode 100644
index 0000000..cb30849
Binary files /dev/null and b/button/17.bmp differ
diff --git a/button/18.bmp b/button/18.bmp
new file mode 100644
index 0000000..0a8bd0c
Binary files /dev/null and b/button/18.bmp differ
diff --git a/button/19.bmp b/button/19.bmp
new file mode 100644
index 0000000..2512c20
Binary files /dev/null and b/button/19.bmp differ
diff --git a/button/2.bmp b/button/2.bmp
new file mode 100644
index 0000000..7c7189f
Binary files /dev/null and b/button/2.bmp differ
diff --git a/button/20.bmp b/button/20.bmp
new file mode 100644
index 0000000..342a0b9
Binary files /dev/null and b/button/20.bmp differ
diff --git a/button/21.bmp b/button/21.bmp
new file mode 100644
index 0000000..fe2b9ff
Binary files /dev/null and b/button/21.bmp differ
diff --git a/button/22.bmp b/button/22.bmp
new file mode 100644
index 0000000..53ea8d8
Binary files /dev/null and b/button/22.bmp differ
diff --git a/button/23.bmp b/button/23.bmp
new file mode 100644
index 0000000..ec8d2f9
Binary files /dev/null and b/button/23.bmp differ
diff --git a/button/24.bmp b/button/24.bmp
new file mode 100644
index 0000000..04867df
Binary files /dev/null and b/button/24.bmp differ
diff --git a/button/25.bmp b/button/25.bmp
new file mode 100644
index 0000000..33b6ac5
Binary files /dev/null and b/button/25.bmp differ
diff --git a/button/26.bmp b/button/26.bmp
new file mode 100644
index 0000000..95cda26
Binary files /dev/null and b/button/26.bmp differ
diff --git a/button/27.bmp b/button/27.bmp
new file mode 100644
index 0000000..7608097
Binary files /dev/null and b/button/27.bmp differ
diff --git a/button/3.bmp b/button/3.bmp
new file mode 100644
index 0000000..a3f192a
Binary files /dev/null and b/button/3.bmp differ
diff --git a/button/4.bmp b/button/4.bmp
new file mode 100644
index 0000000..ae9e30c
Binary files /dev/null and b/button/4.bmp differ
diff --git a/button/5.bmp b/button/5.bmp
new file mode 100644
index 0000000..f692268
Binary files /dev/null and b/button/5.bmp differ
diff --git a/button/6.bmp b/button/6.bmp
new file mode 100644
index 0000000..aff8573
Binary files /dev/null and b/button/6.bmp differ
diff --git a/button/7.bmp b/button/7.bmp
new file mode 100644
index 0000000..850d8ee
Binary files /dev/null and b/button/7.bmp differ
diff --git a/button/8.bmp b/button/8.bmp
new file mode 100644
index 0000000..a18cf09
Binary files /dev/null and b/button/8.bmp differ
diff --git a/button/9.bmp b/button/9.bmp
new file mode 100644
index 0000000..d732bfa
Binary files /dev/null and b/button/9.bmp differ
diff --git a/credits.txt b/credits.txt
new file mode 100644
index 0000000..62e5dd0
--- /dev/null
+++ b/credits.txt
@@ -0,0 +1,69 @@
+Atomic Tanks
+Coding
+Tom Hudson (tom at singular.org.uk)
+Justin Ronco (jronco at users.sourceforge.net)
+eden99_99 (eden99_99 at users.sourceforge.net)
+Jesse Smith (jessefrgsmith at yahoo.ca)
+Mike Wilson (CaptainNeeda+atanks at gmail.com)
+Kevin (sylikc at gmail.com)
+Sven Eden (yamakuzure at users.sourceforge.net)
+
+Graphics
+Tom Hudson (tom at singular.org.uk)
+CtHx
+
+Documentation
+Justin Soles (wordsamurai at users.sourceforge.net)
+Jesse Smith (jessefrgsmith at yahoo.ca)
+
+
+Translations
+Roland (German)
+Yama (German)
+MyO (Russian)
+Sergei (Russian)
+Fred Maranhão (Portuguese)
+Olivier (French)
+Jozef (Slovak)
+Roby Alice (Italian)
+
+
+
+Ideas
+This is by no means an exhaustive list and thanks go to everyone who has
+contributed ideas to the project.
+Patrick Bogen (pdbogen at users.sourceforge.net)
+Rocky Dean Pulley (rdpulley at users.sourceforge.net)
+Mr. Mips (mrmips at users.sourceforge.net)
+Justin Ronco (jronco at users.sourceforge.net)
+Joshua Kruck (krujos at users.sourceforge.net)
+Neil (vossman77 at users.sourceforge.net)
+Tom Hudson (tom at singular.org.uk)
+
+Sound
+Tom Hudson (tom at singular.org.uk)
+
+Original Code & Graphics
+Steve Condie (stevante at yahoo.com)
+Juraj Michalek (georgik at host.sk)
+
+Original Graphics
+Trevor Paulsen (supergass at aol.com)
+Ricky Galati (benogalati at yahoo.com)
+
+Original Sound
+Unknown
+
+Webmasters
+Mike Volmar (mvolmar at users.sourceforge.net)
+Tom Hudson (tom at singular.org.uk)
+Jesse Smith (jessefrgsmith at yahoo.ca)
+
+Any Other Role not listed
+Tom Hudson (tom at singular.org.uk)
+
+Allegro
+Shawn Hargreaves (shawn at talula.demon.co.uk) - http://allegro.sf.net
+
+Games for Linux: http://games.linux.sk
+Text Logos: http://www.cooltext.com
diff --git a/exporter/export.cpp b/exporter/export.cpp
new file mode 100644
index 0000000..e0390b7
--- /dev/null
+++ b/exporter/export.cpp
@@ -0,0 +1,49 @@
+#include <allegro.h>
+#include <stdio.h>
+
+/*
+ * Compile with the line g++ -o Export export.cpp `allegro-config --libs`
+ *
+ * This program extracts all bitmaps from an Allegro datafile.
+*/
+
+int main(int argc, char *argv[])
+{
+   int counter = 0;
+   char filename[256];
+   BITMAP *new_bitmap;
+   DATAFILE *my_datafile;
+
+   if (argc < 2)
+   {
+      printf("usage: export datafile\n");
+      return 0;
+   }
+
+   allegro_init();
+   set_color_depth(24);
+
+   // load a datafile
+   my_datafile = load_datafile(argv[1]);
+   if (! my_datafile)
+   {
+        printf("Unable to open datafile.\n");
+        return 1;
+   }
+
+   // for each bitmap, save to a new file
+   while (counter < 256)
+   {
+      new_bitmap = (BITMAP *) my_datafile[counter].dat;
+      if (new_bitmap)
+      {
+        sprintf(filename, "%d.bmp", counter);
+        save_bmp(filename, new_bitmap, NULL);
+      }
+      counter++;
+   }
+
+   unload_datafile(my_datafile);
+   return 0;
+}
+
diff --git a/exporter/move.cpp b/exporter/move.cpp
new file mode 100644
index 0000000..7667ecf
--- /dev/null
+++ b/exporter/move.cpp
@@ -0,0 +1,35 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+   int highest, lowest;
+   int current;
+   char command[256];
+
+   if (argc < 3)
+   {
+       printf("Usage: move highest_number lowest_number\n\n");
+       return 1;
+   }
+
+   sscanf(argv[1], "%d", &highest);
+   sscanf(argv[2], "%d", &lowest);
+
+   if (highest <= lowest)
+   {
+      printf("Values are not in right order.\n\n");
+      return 1;
+   }
+
+   current = highest;
+   while (current >= lowest)
+   {
+      sprintf(command, "mv %d.bmp %d.bmp", current, current + 1);
+      system(command);
+      current--;
+   }
+
+   return 0;
+}
+
diff --git a/misc/0.bmp b/misc/0.bmp
new file mode 100644
index 0000000..a6df66e
Binary files /dev/null and b/misc/0.bmp differ
diff --git a/misc/1.bmp b/misc/1.bmp
new file mode 100644
index 0000000..0bd08e2
Binary files /dev/null and b/misc/1.bmp differ
diff --git a/misc/10.bmp b/misc/10.bmp
new file mode 100644
index 0000000..eb8c836
Binary files /dev/null and b/misc/10.bmp differ
diff --git a/misc/11.bmp b/misc/11.bmp
new file mode 100644
index 0000000..7b27a5c
Binary files /dev/null and b/misc/11.bmp differ
diff --git a/misc/12.bmp b/misc/12.bmp
new file mode 100644
index 0000000..6fbf860
Binary files /dev/null and b/misc/12.bmp differ
diff --git a/misc/13.bmp b/misc/13.bmp
new file mode 100644
index 0000000..78b32f9
Binary files /dev/null and b/misc/13.bmp differ
diff --git a/misc/14.bmp b/misc/14.bmp
new file mode 100644
index 0000000..fc84722
Binary files /dev/null and b/misc/14.bmp differ
diff --git a/misc/15.bmp b/misc/15.bmp
new file mode 100644
index 0000000..b154c57
Binary files /dev/null and b/misc/15.bmp differ
diff --git a/misc/16.bmp b/misc/16.bmp
new file mode 100644
index 0000000..61e4303
Binary files /dev/null and b/misc/16.bmp differ
diff --git a/misc/17.bmp b/misc/17.bmp
new file mode 100644
index 0000000..2c5a1a9
Binary files /dev/null and b/misc/17.bmp differ
diff --git a/misc/2.bmp b/misc/2.bmp
new file mode 100644
index 0000000..ef91da4
Binary files /dev/null and b/misc/2.bmp differ
diff --git a/misc/3.bmp b/misc/3.bmp
new file mode 100644
index 0000000..46e7644
Binary files /dev/null and b/misc/3.bmp differ
diff --git a/misc/4.bmp b/misc/4.bmp
new file mode 100644
index 0000000..9075011
Binary files /dev/null and b/misc/4.bmp differ
diff --git a/misc/5.bmp b/misc/5.bmp
new file mode 100644
index 0000000..9075011
Binary files /dev/null and b/misc/5.bmp differ
diff --git a/misc/6.bmp b/misc/6.bmp
new file mode 100644
index 0000000..1539dbb
Binary files /dev/null and b/misc/6.bmp differ
diff --git a/misc/7.bmp b/misc/7.bmp
new file mode 100644
index 0000000..e4e654f
Binary files /dev/null and b/misc/7.bmp differ
diff --git a/misc/8.bmp b/misc/8.bmp
new file mode 100644
index 0000000..ff1ae3c
Binary files /dev/null and b/misc/8.bmp differ
diff --git a/misc/9.bmp b/misc/9.bmp
new file mode 100644
index 0000000..e7bd47c
Binary files /dev/null and b/misc/9.bmp differ
diff --git a/missile/0.bmp b/missile/0.bmp
new file mode 100644
index 0000000..c50470a
Binary files /dev/null and b/missile/0.bmp differ
diff --git a/missile/1.bmp b/missile/1.bmp
new file mode 100644
index 0000000..500d8d8
Binary files /dev/null and b/missile/1.bmp differ
diff --git a/missile/10.bmp b/missile/10.bmp
new file mode 100644
index 0000000..d60489a
Binary files /dev/null and b/missile/10.bmp differ
diff --git a/missile/11.bmp b/missile/11.bmp
new file mode 100644
index 0000000..5363edc
Binary files /dev/null and b/missile/11.bmp differ
diff --git a/missile/12.bmp b/missile/12.bmp
new file mode 100644
index 0000000..a78d3a3
Binary files /dev/null and b/missile/12.bmp differ
diff --git a/missile/13.bmp b/missile/13.bmp
new file mode 100644
index 0000000..f51bbf3
Binary files /dev/null and b/missile/13.bmp differ
diff --git a/missile/14.bmp b/missile/14.bmp
new file mode 100644
index 0000000..6069080
Binary files /dev/null and b/missile/14.bmp differ
diff --git a/missile/15.bmp b/missile/15.bmp
new file mode 100644
index 0000000..16b2441
Binary files /dev/null and b/missile/15.bmp differ
diff --git a/missile/16.bmp b/missile/16.bmp
new file mode 100644
index 0000000..541b9a5
Binary files /dev/null and b/missile/16.bmp differ
diff --git a/missile/17.bmp b/missile/17.bmp
new file mode 100644
index 0000000..3797b98
Binary files /dev/null and b/missile/17.bmp differ
diff --git a/missile/18.bmp b/missile/18.bmp
new file mode 100644
index 0000000..bd5b8e8
Binary files /dev/null and b/missile/18.bmp differ
diff --git a/missile/19.bmp b/missile/19.bmp
new file mode 100644
index 0000000..e7ccb14
Binary files /dev/null and b/missile/19.bmp differ
diff --git a/missile/2.bmp b/missile/2.bmp
new file mode 100644
index 0000000..9259c83
Binary files /dev/null and b/missile/2.bmp differ
diff --git a/missile/20.bmp b/missile/20.bmp
new file mode 100644
index 0000000..c143133
Binary files /dev/null and b/missile/20.bmp differ
diff --git a/missile/21.bmp b/missile/21.bmp
new file mode 100644
index 0000000..b978369
Binary files /dev/null and b/missile/21.bmp differ
diff --git a/missile/22.bmp b/missile/22.bmp
new file mode 100644
index 0000000..9fa7feb
Binary files /dev/null and b/missile/22.bmp differ
diff --git a/missile/23.bmp b/missile/23.bmp
new file mode 100644
index 0000000..e539482
Binary files /dev/null and b/missile/23.bmp differ
diff --git a/missile/24.bmp b/missile/24.bmp
new file mode 100644
index 0000000..427c83e
Binary files /dev/null and b/missile/24.bmp differ
diff --git a/missile/25.bmp b/missile/25.bmp
new file mode 100644
index 0000000..32dc3e1
Binary files /dev/null and b/missile/25.bmp differ
diff --git a/missile/26.bmp b/missile/26.bmp
new file mode 100644
index 0000000..aa161ef
Binary files /dev/null and b/missile/26.bmp differ
diff --git a/missile/27.bmp b/missile/27.bmp
new file mode 100644
index 0000000..97abfa4
Binary files /dev/null and b/missile/27.bmp differ
diff --git a/missile/28.bmp b/missile/28.bmp
new file mode 100644
index 0000000..f2a27e2
Binary files /dev/null and b/missile/28.bmp differ
diff --git a/missile/29.bmp b/missile/29.bmp
new file mode 100644
index 0000000..71c145d
Binary files /dev/null and b/missile/29.bmp differ
diff --git a/missile/3.bmp b/missile/3.bmp
new file mode 100644
index 0000000..d5c8bc4
Binary files /dev/null and b/missile/3.bmp differ
diff --git a/missile/30.bmp b/missile/30.bmp
new file mode 100644
index 0000000..6a2065f
Binary files /dev/null and b/missile/30.bmp differ
diff --git a/missile/4.bmp b/missile/4.bmp
new file mode 100644
index 0000000..f39682b
Binary files /dev/null and b/missile/4.bmp differ
diff --git a/missile/5.bmp b/missile/5.bmp
new file mode 100644
index 0000000..973d1d8
Binary files /dev/null and b/missile/5.bmp differ
diff --git a/missile/6.bmp b/missile/6.bmp
new file mode 100644
index 0000000..7780b07
Binary files /dev/null and b/missile/6.bmp differ
diff --git a/missile/7.bmp b/missile/7.bmp
new file mode 100644
index 0000000..ff1cd59
Binary files /dev/null and b/missile/7.bmp differ
diff --git a/missile/8.bmp b/missile/8.bmp
new file mode 100644
index 0000000..b35d5cb
Binary files /dev/null and b/missile/8.bmp differ
diff --git a/missile/9.bmp b/missile/9.bmp
new file mode 100644
index 0000000..1a0c9a1
Binary files /dev/null and b/missile/9.bmp differ
diff --git a/sound/0.wav b/sound/0.wav
new file mode 100644
index 0000000..be6007b
Binary files /dev/null and b/sound/0.wav differ
diff --git a/sound/1.wav b/sound/1.wav
new file mode 100644
index 0000000..0ed9d07
Binary files /dev/null and b/sound/1.wav differ
diff --git a/sound/10.wav b/sound/10.wav
new file mode 100644
index 0000000..9ae290c
Binary files /dev/null and b/sound/10.wav differ
diff --git a/sound/11.wav b/sound/11.wav
new file mode 100644
index 0000000..c2ee04d
Binary files /dev/null and b/sound/11.wav differ
diff --git a/sound/12.wav b/sound/12.wav
new file mode 100644
index 0000000..a52bc4e
Binary files /dev/null and b/sound/12.wav differ
diff --git a/sound/2.wav b/sound/2.wav
new file mode 100644
index 0000000..86200ee
Binary files /dev/null and b/sound/2.wav differ
diff --git a/sound/3.wav b/sound/3.wav
new file mode 100644
index 0000000..fab1992
Binary files /dev/null and b/sound/3.wav differ
diff --git a/sound/4.wav b/sound/4.wav
new file mode 100644
index 0000000..3f74387
Binary files /dev/null and b/sound/4.wav differ
diff --git a/sound/5.wav b/sound/5.wav
new file mode 100644
index 0000000..b66b9e4
Binary files /dev/null and b/sound/5.wav differ
diff --git a/sound/6.wav b/sound/6.wav
new file mode 100644
index 0000000..6038f20
Binary files /dev/null and b/sound/6.wav differ
diff --git a/sound/7.wav b/sound/7.wav
new file mode 100644
index 0000000..e3f4e63
Binary files /dev/null and b/sound/7.wav differ
diff --git a/sound/8.wav b/sound/8.wav
new file mode 100644
index 0000000..1bb18b5
Binary files /dev/null and b/sound/8.wav differ
diff --git a/sound/9.wav b/sound/9.wav
new file mode 100644
index 0000000..845db24
Binary files /dev/null and b/sound/9.wav differ
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..608dc68
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,148 @@
+.PHONY: all clean veryclean
+
+MODULES = atanks.o beam.o button.o environment.o explosion.o fade.o files.o globaldata.o \
+          missile.o perlin.o physobj.o player.o satellite.o sky.o tank.o team.o teleport.o virtobj.o \
+          update.o network.o floattext.o land.o text.o client.o gameloop.o
+
+LIB=ar
+WINDRES=
+# FLAGS += -DDATA_DIR=\".\" -Wno-write-strings -DNETWORK -DTHREADS
+FLAGS += -DDATA_DIR=\"${INSTALLDIR}\" -DNEW_GAMELOOP -Wno-write-strings -DNETWORK -DTHREADS -pthread
+OUTPUT = ../atanks
+WFLAGS = 
+OFLAGS = 
+LFLAGS +=
+LDFLAGS +=  `allegro-config --libs` -lm -lpthread
+
+CXXFLAGS += -Wall -Iinclude # -fprofile-arcs -ftest-coverage 
+
+SRCS  = $(MODULES:.o=.cpp)
+GLOBALS	= main.h imagedefs.h externs.h
+
+all: 	$(OUTPUT)
+
+clean:  
+	rm -f *.o
+
+veryclean: clean
+	rm $(OUTPUT)
+
+$(MODULES): Makefile
+
+atanks.o: atanks.cpp globals.h main.h menucontent.h
+	$(CXX) -c atanks.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+button.o: button.cpp button.h
+	$(CXX) -c button.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+client.o: client.h client.cpp
+	$(CXX) -c client.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+environment.o: environment.cpp environment.h
+	$(CXX) -c environment.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+explosion.o: explosion.cpp explosion.h
+	$(CXX) -c explosion.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+files.o: files.cpp files.h text.h text.cpp
+	$(CXX) -c files.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+floattext.o: floattext.cpp floattext.h
+	$(CXX) -c floattext.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+gameloop.o: gameloop.cpp atanks.cpp main.h
+	$(CXX) -c gameloop.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+globaldata.o: globaldata.cpp globaldata.h
+	$(CXX) -c globaldata.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+land.o: land.cpp land.h globaldata.h environment.h
+	$(CXX) -c land.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+missile.o: missile.cpp missile.h
+	$(CXX) -c missile.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+teleport.o: teleport.cpp teleport.h
+	$(CXX) -c teleport.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+physobj.o: physobj.cpp physobj.h
+	$(CXX) -c physobj.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+player.o: player.cpp player.h
+	$(CXX) -c player.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+tank.o: tank.cpp tank.h
+	$(CXX) -c tank.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+team.o: team.cpp team.h
+	$(CXX) -c team.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+virtobj.o: virtobj.cpp virtobj.h
+	$(CXX) -c virtobj.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+fade.o: fade.cpp
+	$(CXX) -c fade.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+perlin.o: perlin.cpp
+	$(CXX) -c perlin.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+sky.o: sky.cpp sky.h
+	$(CXX) -c sky.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+satellite.o: satellite.cpp satellite.h
+	$(CXX) -c satellite.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+text.o: text.cpp text.h
+	$(CXX) -c text.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+update.o: update.cpp update.h
+	$(CXX) -c update.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+network.o: network.cpp network.h
+	$(CXX) -c network.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+%.o: %.cpp %.h
+	$(CXX) -c $< -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CXXFLAGS)
+
+$(OUTPUT): $(OBJECTS) $(MODULES)
+	$(CXX) $(MODULES) -o $(OUTPUT) $(FLAGS) $(LFLAGS) $(LDFLAGS) $(SFLAGS) $(CXXFLAGS)
+	# strip $(OUTPUT)
+
+# dependencies:
+physobj.h: main.h virtobj.h globaldata.h
+virtobj.h: main.h player.h
+main.h: imagedefs.h externs.h
+globaldata.h: main.h
+player.h: main.h menu.h
+tank.h: physobj.h
+floattext.h: virtobj.h main.h environment.h
+menu.h: globaldata.h
+environment.h: main.h tank.h
+files.h: globaldata.h environment.h 
+globals.h: virtobj.h floattext.h physobj.h tank.h missile.h explosion.h player.h environment.h globaldata.h teleport.h decor.h beam.h
+button.h: globaldata.h environment.h
+team.h: globaldata.h
+satellite.h: environment.h globaldata.h virtobj.h
+beam.h: main.h virtobj.h physobj.h
+missile.h: main.h physobj.h
+teleport.h: main.h virtobj.h
+decor.h: main.h physobj.h environment.h globaldata.h
+explosion.h: main.h physobj.h
+virtobj.cpp: virtobj.h environment.h
+physobj.cpp: physobj.h environment.h
+atanks.cpp: globals.h menu.h button.h team.h files.h satellite.h menucontent.h
+beam.cpp: environment.h globaldata.h physobj.h player.h decor.h tank.h beam.h
+button.cpp: button.h
+environment.cpp: environment.h globaldata.h virtobj.h missile.h tank.h files.h
+explosion.cpp: environment.h globaldata.h explosion.h missile.h decor.h tank.h player.h
+fade.cpp: globaldata.h main.h
+files.cpp: player.h files.h main.h
+globaldata.cpp: player.h globaldata.h files.h
+missile.cpp: environment.h globaldata.h explosion.h missile.h decor.h tank.h
+perlin.cpp: main.h
+player.cpp: environment.h globaldata.h player.h tank.h menu.h files.h floattext.h
+satellite.cpp: environment.h satellite.h beam.h
+sky.cpp: globaldata.h main.h sky.h
+tank.cpp: environment.h globaldata.h floattext.h explosion.h teleport.h missile.h player.h beam.h tank.h
+team.cpp: tank.h team.h player.h
+teleport.cpp: environment.h globaldata.h teleport.h
diff --git a/src/Makefile.bsd b/src/Makefile.bsd
new file mode 100644
index 0000000..37dfa4f
--- /dev/null
+++ b/src/Makefile.bsd
@@ -0,0 +1,151 @@
+.PHONY: all clean veryclean
+
+MODULES = atanks.o beam.o button.o environment.o explosion.o fade.o files.o globaldata.o \
+          missile.o perlin.o physobj.o player.o satellite.o sky.o tank.o team.o teleport.o virtobj.o \
+          update.o network.o floattext.o land.o text.o client.o gameloop.o
+
+CPP=g++
+CC=gcc
+LD=g++
+LIB=ar
+WINDRES=
+# FLAGS += -DDATA_DIR=\".\" -Wno-write-strings -DNETWORK -DTHREADS
+FLAGS += -DDATA_DIR=\"${INSTALLDIR}\" -DNEW_GAMELOOP -Wno-write-strings -DTHREADS
+OUTPUT = ../atanks
+WFLAGS = 
+OFLAGS = 
+LFLAGS +=
+LDFLAGS =  `allegro-config --libs`
+
+CFLAGS += -g -Wall -Iinclude -I/usr/local/include 
+
+SRCS  = $(MODULES:.o=.cpp)
+GLOBALS	= main.h imagedefs.h externs.h
+
+all: 	$(OUTPUT)
+
+clean:  
+	rm -f *.o
+
+veryclean: clean
+	rm $(OUTPUT)
+
+$(MODULES): Makefile
+
+atanks.o: atanks.cpp globals.h main.h menucontent.h
+	$(CPP) -c atanks.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+button.o: button.cpp button.h
+	$(CPP) -c button.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+client.o: client.h client.cpp
+	$(CPP) -c client.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+environment.o: environment.cpp environment.h
+	$(CPP) -c environment.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+explosion.o: explosion.cpp explosion.h
+	$(CPP) -c explosion.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+files.o: files.cpp files.h text.h text.cpp
+	$(CPP) -c files.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+floattext.o: floattext.cpp floattext.h
+	$(CPP) -c floattext.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+gameloop.o: gameloop.cpp atanks.cpp main.h
+	$(CPP) -c gameloop.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+globaldata.o: globaldata.cpp globaldata.h
+	$(CPP) -c globaldata.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+land.o: land.cpp land.h globaldata.h environment.h
+	$(CPP) -c land.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+missile.o: missile.cpp missile.h
+	$(CPP) -c missile.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+teleport.o: teleport.cpp teleport.h
+	$(CPP) -c teleport.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+physobj.o: physobj.cpp physobj.h
+	$(CPP) -c physobj.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+player.o: player.cpp player.h
+	$(CPP) -c player.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+tank.o: tank.cpp tank.h
+	$(CPP) -c tank.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+team.o: team.cpp team.h
+	$(CPP) -c team.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+virtobj.o: virtobj.cpp virtobj.h
+	$(CPP) -c virtobj.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+fade.o: fade.cpp
+	$(CPP) -c fade.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+perlin.o: perlin.cpp
+	$(CPP) -c perlin.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+sky.o: sky.cpp sky.h
+	$(CPP) -c sky.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+satellite.o: satellite.cpp satellite.h
+	$(CPP) -c satellite.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+text.o: text.cpp text.h
+	$(CPP) -c text.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+update.o: update.cpp update.h
+	$(CPP) -c update.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+network.o: network.cpp network.h
+	$(CPP) -c network.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+%.o: %.cpp %.h
+	$(CPP) -c $< -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+$(OUTPUT): $(OBJECTS) $(MODULES)
+	$(CPP) $(MODULES) -o $(OUTPUT) $(FLAGS) $(LFLAGS) $(LDFLAGS) $(SFLAGS) $(CFLAGS)
+	# strip $(OUTPUT)
+
+# dependencies:
+physobj.h: main.h virtobj.h globaldata.h
+virtobj.h: main.h player.h
+main.h: imagedefs.h externs.h
+globaldata.h: main.h
+player.h: main.h menu.h
+tank.h: physobj.h
+floattext.h: virtobj.h main.h environment.h
+menu.h: globaldata.h
+environment.h: main.h tank.h
+files.h: globaldata.h environment.h 
+globals.h: virtobj.h floattext.h physobj.h tank.h missile.h explosion.h player.h environment.h globaldata.h teleport.h decor.h beam.h
+button.h: globaldata.h environment.h
+team.h: globaldata.h
+satellite.h: environment.h globaldata.h virtobj.h
+beam.h: main.h virtobj.h physobj.h
+missile.h: main.h physobj.h
+teleport.h: main.h virtobj.h
+decor.h: main.h physobj.h environment.h globaldata.h
+explosion.h: main.h physobj.h
+virtobj.cpp: virtobj.h environment.h
+physobj.cpp: physobj.h environment.h
+atanks.cpp: globals.h menu.h button.h team.h files.h satellite.h menucontent.h
+beam.cpp: environment.h globaldata.h physobj.h player.h decor.h tank.h beam.h
+button.cpp: button.h
+environment.cpp: environment.h globaldata.h virtobj.h missile.h tank.h files.h
+explosion.cpp: environment.h globaldata.h explosion.h missile.h decor.h tank.h player.h
+fade.cpp: globaldata.h main.h
+files.cpp: player.h files.h main.h
+globaldata.cpp: player.h globaldata.h files.h
+missile.cpp: environment.h globaldata.h explosion.h missile.h decor.h tank.h
+perlin.cpp: main.h
+player.cpp: environment.h globaldata.h player.h tank.h menu.h files.h floattext.h
+satellite.cpp: environment.h satellite.h beam.h
+sky.cpp: globaldata.h main.h sky.h
+tank.cpp: environment.h globaldata.h floattext.h explosion.h teleport.h missile.h player.h beam.h tank.h
+team.cpp: tank.h team.h player.h
+teleport.cpp: environment.h globaldata.h teleport.h
diff --git a/src/Makefile.windows b/src/Makefile.windows
new file mode 100644
index 0000000..3aaf235
--- /dev/null
+++ b/src/Makefile.windows
@@ -0,0 +1,157 @@
+.PHONY: all clean veryclean
+
+MODULES = atanks.o beam.o button.o environment.o explosion.o fade.o files.o globaldata.o \
+          missile.o perlin.o physobj.o player.o satellite.o sky.o tank.o team.o teleport.o virtobj.o update.o network.o \
+          floattext.o land.o text.o client.o gameloop.o
+MODULES += atanks.res
+
+# CPP=g++
+CPP=mingw32-g++
+CC=gcc
+LD=g++
+LIB=ar
+WINDRES=windres.exe
+FLAGS += -DNEW_GAMELOOP -DDATA_DIR=\".\" -Wno-write-strings
+#FLAGS += -DDATA_DIR=\"${INSTALLDIR}\"  -Wno-write-strings -DTHREADS
+OUTPUT = ../atanks.exe
+WFLAGS = 
+OFLAGS = 
+LFLAGS += -mwindows
+LDFLAGS = -L../.. -lalleg
+#LDFLAGS += -lpthread
+
+CFLAGS += -Wall -Iinclude # -fprofile-arcs -ftest-coverage 
+
+SRCS  = $(MODULES:.o=.cpp)
+GLOBALS    = main.h imagedefs.h externs.h
+
+all:     $(OUTPUT)
+
+clean:  
+	rm -f *.o
+
+veryclean: clean
+	rm $(OUTPUT)
+
+$(MODULES): Makefile
+
+atanks.res:
+	$(WINDRES) -i atanks.rc --input-format=rc -o atanks.res -O coff
+
+atanks.o: atanks.cpp globals.h main.h menucontent.h
+	$(CPP) -c atanks.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+button.o: button.cpp button.h
+	$(CPP) -c button.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+client.o: client.h client.cpp
+	$(CPP) -c client.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+environment.o: environment.cpp environment.h
+	$(CPP) -c environment.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+explosion.o: explosion.cpp explosion.h
+	$(CPP) -c explosion.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+files.o: files.cpp files.h text.h text.cpp
+	$(CPP) -c files.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+floattext.o: floattext.cpp floattext.h
+	$(CPP) -c floattext.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+gameloop.o: gameloop.h gameloop.cpp
+	$(CPP) -c gameloop.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+globaldata.o: globaldata.cpp globaldata.h
+	$(CPP) -c globaldata.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+land.o: land.cpp land.h globaldata.h environment.h
+	$(CPP) -c land.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+missile.o: missile.cpp missile.h
+	$(CPP) -c missile.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+teleport.o: teleport.cpp teleport.h
+	$(CPP) -c teleport.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+physobj.o: physobj.cpp physobj.h
+	$(CPP) -c physobj.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+player.o: player.cpp player.h
+	$(CPP) -c player.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+tank.o: tank.cpp tank.h
+	$(CPP) -c tank.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+team.o: team.cpp team.h
+	$(CPP) -c team.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+virtobj.o: virtobj.cpp virtobj.h
+	$(CPP) -c virtobj.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+fade.o: fade.cpp
+	$(CPP) -c fade.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+perlin.o: perlin.cpp
+	$(CPP) -c perlin.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+sky.o: sky.cpp sky.h
+	$(CPP) -c sky.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+satellite.o: satellite.cpp satellite.h
+	$(CPP) -c satellite.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+text.o: text.cpp text.h
+	$(CPP) -c text.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+update.o: update.cpp update.h
+	$(CPP) -c update.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+network.o: network.cpp network.h
+	$(CPP) -c network.cpp -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+%.o: %.cpp %.h
+	$(CPP) -c $< -o $@ $(FLAGS) $(LFLAGS) $(OFLAGS) $(CFLAGS)
+
+$(OUTPUT): $(OBJECTS) $(MODULES)
+	$(CPP) $(MODULES) -o $(OUTPUT) $(FLAGS) $(LFLAGS) $(LDFLAGS) $(SFLAGS) $(CFLAGS)
+
+# dependencies:
+physobj.h: main.h virtobj.h globaldata.h
+virtobj.h: main.h player.h
+main.h: imagedefs.h externs.h
+globaldata.h: main.h
+player.h: main.h menu.h
+tank.h: physobj.h
+floattext.h: virtobj.h main.h environment.h
+menu.h: globaldata.h
+environment.h: main.h tank.h
+files.h: globaldata.h environment.h
+globals.h: virtobj.h floattext.h physobj.h tank.h missile.h explosion.h player.h environment.h globaldata.h teleport.h decor.h beam.h
+button.h: globaldata.h environment.h
+team.h: globaldata.h
+satellite.h: environment.h globaldata.h virtobj.h
+beam.h: main.h virtobj.h physobj.h
+missile.h: main.h physobj.h
+teleport.h: main.h virtobj.h
+decor.h: main.h physobj.h environment.h globaldata.h
+explosion.h: main.h physobj.h
+virtobj.cpp: virtobj.h environment.h
+physobj.cpp: physobj.h environment.h
+atanks.cpp: globals.h menu.h button.h team.h files.h satellite.h menucontent.h
+beam.cpp: environment.h globaldata.h physobj.h player.h decor.h tank.h beam.h
+button.cpp: button.h
+environment.cpp: environment.h globaldata.h virtobj.h missile.h tank.h files.h
+explosion.cpp: environment.h globaldata.h explosion.h missile.h decor.h tank.h player.h
+fade.cpp: globaldata.h main.h
+files.cpp: player.h files.h main.h
+globaldata.cpp: player.h globaldata.h files.h
+missile.cpp: environment.h globaldata.h explosion.h missile.h decor.h tank.h
+perlin.cpp: main.h
+player.cpp: environment.h globaldata.h player.h tank.h menu.h files.h floattext.h
+satellite.cpp: environment.h satellite.h beam.h
+sky.cpp: globaldata.h main.h sky.h
+tank.cpp: environment.h globaldata.h floattext.h explosion.h teleport.h missile.h player.h beam.h tank.h
+team.cpp: tank.h team.h player.h
+teleport.cpp: environment.h globaldata.h teleport.h
+
diff --git a/src/allegro.h b/src/allegro.h
new file mode 100644
index 0000000..d5e7fc3
--- /dev/null
+++ b/src/allegro.h
@@ -0,0 +1,82 @@
+/*         ______   ___    ___
+ *        /\  _  \ /\_ \  /\_ \
+ *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
+ *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
+ *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
+ *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
+ *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
+ *                                           /\____/
+ *                                           \_/__/
+ *
+ *      Main header file for the entire Allegro library.
+ *      (separate modules can be included from the allegro/ directory)
+ *
+ *      By Shawn Hargreaves.
+ *
+ *      Vincent Penquerc'h split the original allegro.h into separate headers.
+ *
+ *      See readme.txt for copyright information.
+ */
+
+
+#ifndef ALLEGRO_H
+#define ALLEGRO_H
+
+#include "allegro/base.h"
+
+#include "allegro/system.h"
+#include "allegro/debug.h"
+
+#include "allegro/unicode.h"
+
+#include "allegro/mouse.h"
+#include "allegro/timer.h"
+#include "allegro/keyboard.h"
+#include "allegro/joystick.h"
+
+#include "allegro/palette.h"
+#include "allegro/gfx.h"
+#include "allegro/color.h"
+#include "allegro/draw.h"
+#include "allegro/rle.h"
+#include "allegro/compiled.h"
+#include "allegro/text.h"
+#include "allegro/font.h"
+
+#include "allegro/fli.h"
+#include "allegro/config.h"
+#include "allegro/gui.h"
+
+#include "allegro/sound.h"
+
+#include "allegro/file.h"
+#include "allegro/lzss.h"
+#include "allegro/datafile.h"
+
+#include "allegro/fixed.h"
+#include "allegro/fmaths.h"
+#include "allegro/matrix.h"
+#include "allegro/quat.h"
+
+#include "allegro/3d.h"
+#include "allegro/3dmaths.h"
+
+
+#ifndef ALLEGRO_NO_COMPATIBILITY
+   #include "allegro/alcompat.h"
+#endif
+
+#ifndef ALLEGRO_NO_FIX_CLASS
+   #ifdef __cplusplus
+      #include "allegro/fix.h"
+   #endif
+#endif
+
+
+#ifdef ALLEGRO_EXTRA_HEADER
+   #include ALLEGRO_EXTRA_HEADER
+#endif
+
+#endif          /* ifndef ALLEGRO_H */
+
+
diff --git a/src/atanks.cpp b/src/atanks.cpp
new file mode 100644
index 0000000..81403ce
--- /dev/null
+++ b/src/atanks.cpp
@@ -0,0 +1,6284 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2002,2003  Thomas Hudson,Juraj Michalek
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include <dirent.h>
+
+#include "globals.h"
+#include "menu.h"
+#include "button.h"
+#include "team.h"
+#include "files.h"
+#include "satellite.h"
+#include "update.h"
+#include "network.h"
+#include "land.h"
+
+#include "floattext.h"
+#include "explosion.h"
+#include "beam.h"
+#include "missile.h"
+#include "decor.h"
+#include "teleport.h"
+#include "sky.h"
+#include "gameloop.h"
+
+#ifdef THREADS
+#include <pthread.h>
+#endif
+
+#ifdef NETWORK
+#include "client.h"
+#endif
+
+
+enum cmdTokens
+{
+  ARGV_NOTHING_EXPECTED,
+  ARGV_GFX_DEPTH,
+  ARGV_SCREEN_WIDTH,
+  ARGV_SCREEN_HEIGHT,
+  ARGV_DATA_DIR,
+  ARGV_CONFIG_DIR
+};
+#define SWITCH_HELP "-h"
+#define SWITCH_FULL_SCREEN "-fs"
+#define SWITCH_WINDOWED "--windowed"
+#define SWITCH_NOSOUND "--nosound"
+#define SWITCH_DATADIR "--datadir"
+#define SWITCH_CONFIGDIR "-c"
+#define SWITCH_NO_CONFIG "--noconfig"
+
+
+int screen_mode = GFX_AUTODETECT_WINDOWED;
+
+// BITMAP *create_gradient_strip (const gradient *gradient, int length);
+// int draw_circlesBG (GLOBALDATA *global, BITMAP *dest, int x, int y, int width, int height, bool image);
+
+using namespace std;
+
+void fpsadd()
+{
+  fps = frames;
+  frames = 0;
+}
+
+pthread_mutex_t* cclock_lock;
+void destroy_cclock_lock() {
+  #ifdef THREADS
+  if (cclock_lock)
+  {
+    int result = pthread_mutex_destroy(cclock_lock);
+    switch (result)
+    {
+      case 0:
+        //Successfully destroyed
+        break;
+      case EBUSY:
+        //Some thread forgot to unlock result
+        printf("%s:%i: Lock is still held.\n", __FILE__, __LINE__);
+        break;
+      case EINVAL:
+        //Invalid lock
+        printf("%s:%i: Lock is invalid.\n", __FILE__, __LINE__);
+        break;
+      default:
+        printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_destroy.\n", __FILE__, __LINE__, result);
+        break;
+    }
+    free(cclock_lock);
+  }
+  #endif
+}
+void init_cclock_lock()
+{
+  #ifdef THREADS
+  cclock_lock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
+  if (cclock_lock == NULL)
+  {
+    printf("%s:%i: Could not allocate memory.\n", __FILE__, __LINE__);
+  }
+  int result = pthread_mutex_init(cclock_lock, NULL);
+  switch (result)
+  {
+    case 0:
+      //Succesfully initialized
+      break;
+    case EAGAIN:
+      //Not enough resources
+      printf("%s:%i: Not enough resources to create mutex.\n", __FILE__, __LINE__);
+      break;
+    case ENOMEM:
+      printf("%s:%i: Not enough memory to create mutex.\n", __FILE__, __LINE__);
+      break;
+    case EPERM:
+      printf("%s:%i: Not authorized.\n", __FILE__, __LINE__);
+      break;
+    case EBUSY:
+      printf("%s:%i: The mutex is already initialized.\n", __FILE__, __LINE__);
+      break;
+    case EINVAL:
+      printf("%s:%i: Invalid attribute.\n", __FILE__, __LINE__);
+      break;
+    default:
+      printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_init.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  atexit(destroy_cclock_lock);
+  #endif
+}
+void lock_cclock()
+{
+  #ifdef THREADS
+  int result = pthread_mutex_lock(cclock_lock);
+  switch (result)
+  {
+    case 0:
+      //Got the lock.
+      break;
+    case EINVAL:
+      //Priority too high
+      printf("%s:%i: Either this thread's priority is higher than the mutex's priority, or the mutex is uninitialized.\n", __FILE__, __LINE__);
+      break;
+    case EAGAIN:
+      printf("%s:%i: Too many locks on the mutex.\n", __FILE__, __LINE__);
+      break;
+    case EDEADLK:
+      //We have the lock already
+      printf("%s:%i: Already have lock.\n", __FILE__, __LINE__);
+      break;
+    default:
+      //What error is this?
+      printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_lock.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+}
+void unlock_cclock()
+{
+  #ifdef THREADS
+  int result = pthread_mutex_unlock(cclock_lock);
+  switch (result)
+  {
+    case 0:
+      //Released the lock
+      break;
+    case EPERM:
+      //Forgot to get a lock on the mutex
+      printf("%s:%i: Mutex isn't locked\n", __FILE__, __LINE__);
+      break;
+    case EINVAL:
+      //Uninitialized mutex
+      printf("%s:%i: cclock_lock is uninitialized.\n", __FILE__, __LINE__);
+      break;
+    default:
+      //?
+      printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_unlock.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+}
+int get_cclock()
+{
+  lock_cclock();
+  int c = cclock;
+  unlock_cclock();
+  return c;
+}
+void clockadd()
+{
+  lock_cclock();
+  cclock++;
+  unlock_cclock();
+}
+END_OF_FUNCTION(clockadd)
+
+
+
+
+/*****************************************************************************
+drawMenuBackground
+
+Draws a 600x400 centered box, fills it with some random lines or circles.
+Someday, we should make this more generic; have it take the box dimensions
+as an input parameter.
+*****************************************************************************/
+void drawMenuBackground (GLOBALDATA *global, ENVIRONMENT *env, int itemType, int tOffset, int numItems)
+{
+  rectfill (env->db, global->halfWidth - 300, global->menuBeginY, // 100,
+            global->halfWidth + 300, global->menuEndY, // global->screenHeight - 100,
+            makecol (0,79,0));
+  rect     (env->db, global->halfWidth - 300, global->menuBeginY, // 100,
+            global->halfWidth + 300, global->menuEndY, // global->screenHeight - 100,
+            makecol (128,255,128));
+
+  drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
+  env->current_drawing_mode = DRAW_MODE_TRANS;
+  set_trans_blender (0, 0, 0, 15);
+  for (int tCount = 0; tCount < numItems; tCount++)
+    {
+      int radius, xpos, ypos;
+      switch (itemType)
+        {
+        case BACKGROUND_CIRCLE: // circles
+          radius = (int)((perlin1DPoint (1.0, 5, (tOffset * 0.02) + tCount + 423346, 0.5, 8) + 1) / 2 * 40);
+          xpos = global->halfWidth + (int)(perlin1DPoint (1.0, 3, (tOffset * 0.02) + tCount + 232662, 0.3, 6) * 250);
+          ypos = global->halfHeight + (int)(perlin1DPoint (1.0, 2, (tOffset * 0.02) + tCount + 42397, 0.3, 6) * (global->halfHeight - 100));
+          circlefill (env->db, xpos, ypos, radius,
+                      makecol (200,255,200));
+          break;
+        case BACKGROUND_LINE: // Horz lines
+          radius = (int)((perlin1DPoint (1.0, 5, (tOffset * 0.02) + tCount + 423346, 0.5, 8) + 1) / 2 * 40);
+          xpos = global->halfWidth + (int)(perlin1DPoint (1.0, 3, (tOffset * 0.02) + tCount + 232662, 0.3, 6) * 250);
+          rectfill (env->db, xpos - radius / 2, 101,
+                    xpos + radius / 2, global->screenHeight - 101,
+                    makecol (200,255,200));
+          break;
+        case BACKGROUND_BLANK:
+        default:
+          break;
+        }
+
+    }
+  solid_mode ();
+  env->current_drawing_mode = DRAW_MODE_SOLID;
+}
+
+
+void initialisePlayers (GLOBALDATA *global)
+{
+  int z;
+
+  for (z = 0; z < global->numPlayers; z++)
+    {
+      global->players[z]->money = (int)global->startmoney;
+      global->players[z]->score = 0;
+      // global->players[z]->initialise ();
+      // global->players[z]->type_saved = global->players[z]->type;
+      if (((int)global->players[z]->type != HUMAN_PLAYER) &&
+          (global->players[z]->preftype == PERPLAY_PREF))
+        {
+          global->players[z]->generatePreferences();
+        }
+      global->players[z]->initialise();
+      global->players[z]->type_saved = global->players[z]->type;
+    }
+}
+
+
+
+void wait_for_input()
+{
+  do
+    {
+      LINUX_SLEEP;
+    }
+  while ((!keypressed()) && (!mouse_b));
+
+  flush_inputs();
+
+}
+
+int pickColor (int left, int top, int width, int height, int x, int y)
+{
+  int r, g, b;
+  double value, saturation;
+  double hue = ((double)(x - left) / width) * 360;
+
+  double hPos = (double)(y - top) / height;
+  if (hPos > 0.5)
+    {
+      value = 1.0 - ((hPos - 0.5) * 2);
+      saturation = 1.0;
+    }
+  else
+    {
+      value = 1.0;
+      saturation = hPos * 2;
+    }
+
+  hsv_to_rgb (hue, saturation, value, &r, &g, &b);
+
+  return (makecol (r, g, b));
+}
+
+void colorBar (ENVIRONMENT *env, int left, int top, int width, int height)
+{
+  int right = left + width;
+  int bottom = top + height;
+
+  for (int x = left; x < right; x++)
+    {
+      for (int y = top; y < bottom; y++)
+        {
+          putpixel (env->db, x, y, pickColor (left, top, width, height, x, y));
+        }
+    }
+}
+
+int textEntryBox (GLOBALDATA *global, ENVIRONMENT *env, int modify, int x, int y, char *text, unsigned int textLength)
+{
+  int ke = 0;
+  int fontWidth = text_length (font, (char *)"Z");
+  int fontHeight = text_height (font);
+  int leftX = x - (fontWidth * textLength / 2);
+  int rightX = x + (fontWidth * textLength / 2);
+  int boxWidth = fontWidth * textLength;
+//  char tempText[textLength + 1];
+  char * tempText;
+  int flashCount = 0;
+  int lx = mouse_x, ly = mouse_y;
+
+  tempText = (char *)calloc(textLength + 1, sizeof(char));
+
+  if (!tempText)
+    {
+      // Die hard!
+      cerr << "ERROR: Unable to allocate " << (textLength + 1) << " bytes in textEntryBox() !!!" << endl;
+      // exit (1);
+    }
+
+  if (! text) text = (char *)"";
+  rectfill (env->db, leftX, y - 2, rightX, y + fontHeight + 2, WHITE);
+  rect (env->db, leftX, y - 2, rightX, y + fontHeight + 2, BLACK);
+  if (!modify)
+    {
+      textout_centre_ex (env->db, font, text, x, y, BLACK, -1);
+    }
+  env->make_update (leftX - 2, y - 4, fontWidth * textLength + 4, fontHeight + 6);
+  env->do_updates ();
+
+  if (!modify)
+    {
+      free(tempText);
+      return (boxWidth);
+    }
+  strncpy (tempText, text, textLength + 1);
+
+  while (((ke >> 8) != KEY_ENTER && (ke >> 8) != KEY_ESC && (ke >> 8) != KEY_ENTER_PAD)
+         || strlen (tempText) < 1)
+    {
+      int tWidth = text_length (font, tempText);
+
+      LINUX_SLEEP;
+
+      rectfill (env->db, leftX, y - 2, rightX, y + fontHeight + 2, WHITE);
+      rect (env->db, leftX, y - 2, rightX, y + fontHeight + 2, BLACK);
+      //rectfill (screen, x - (tWidth / 2), y, x + (tWidth / 2) + 10, y + text_height (font), (flashCount < 5)?WHITE:BLACK);
+      textout_centre_ex (env->db, font, tempText, x, y, BLACK, -1);
+      rectfill (env->db, x + (tWidth / 2) + 2, y, x + (tWidth / 2) + 10, y + text_height (font), (flashCount < 25)?WHITE:BLACK);
+      env->make_update (leftX - 2, y - 4, fontWidth * textLength + 4, fontHeight + 6);
+      env->make_update (mouse_x, mouse_y, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
+      env->make_update (lx, ly, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
+      lx = mouse_x;
+      ly = mouse_y;
+      if (! global->os_mouse) show_mouse (NULL);
+
+      if (keypressed ())
+        {
+          ke = readkey ();
+        }
+      else
+        {
+          ke = 0;
+        }
+
+      if ( ((ke >> 8) == KEY_BACKSPACE) && ( strlen(tempText) > 0 ) )
+        {
+          tempText[strlen (tempText) - 1] = 0;
+          rectfill (screen, x - (tWidth / 2), y, x + (tWidth / 2) + 10, y + text_height (font), WHITE);
+          env->make_update (x - (tWidth / 2) - 2, y - 2, tWidth + 14, text_height (font) + 4);
+        }
+      else if ((ke & 0xff) >= 32 && strlen (tempText) < textLength)
+        {
+          // tempText[strlen (tempText)] = ke & 0xff;
+          tempText[strlen (tempText) + 1] = 0;
+          tempText[strlen(tempText)] = ke & 0xff;
+          //textprintf (screen, font, x + text_length (font, tempText), y, WHITE, (char *)"%c", ke & 0xff);
+        }
+      else
+        env->do_updates ();
+      if (! global->os_mouse) show_mouse (screen);
+      rest (1);
+      flashCount++;
+      flashCount = flashCount % 50;
+    }
+  if ((ke >> 8) != KEY_ESC)
+    strncpy (text, tempText, textLength);
+
+  flush_inputs ();
+
+  free(tempText);
+
+  return (boxWidth);
+}
+
+
+void credits (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  char dataDir[2048];
+  TEXTBLOCK *my_text;
+
+  sprintf (dataDir, "%s/credits.txt", global->dataDir);
+  my_text = new TEXTBLOCK(dataDir);
+  scrollTextList (global, env, my_text  );
+  delete my_text;
+}
+
+
+/*
+ * Save all players to a text file.
+*/
+int savePlayers_Text(GLOBALDATA *global, FILE *my_file)
+{
+   int count = 0;
+  
+   while (count < global->numPermanentPlayers)
+   {
+      global->allPlayers[count]->saveToFile_Text(my_file);
+      count++;
+   } 
+   return TRUE;
+}
+
+
+
+
+
+int loadPlayers_Text (GLOBALDATA *global, ENVIRONMENT *env, FILE *file)
+{
+  int count, max;
+  int status = TRUE;
+  PLAYER *new_player;
+
+  max = global->numPermanentPlayers;
+  if (global->allPlayers) free(global->allPlayers);   // avoid leak
+  global->allPlayers = (PLAYER **) malloc (sizeof(PLAYER*) * max);
+  if (! global->allPlayers)
+    {
+      perror("atanks.cc: Failed to allocate memory for allPlayers in loadPlayers_Text");
+      return FALSE;
+    }
+
+  count = 0;
+  while (status)
+    {
+      // global->allPlayers[count] = new PLAYER(global, env, file, true);
+      new_player = new PLAYER(global, env);
+      if (! new_player)
+        {
+          perror( (char *)"atanks.cc: Failed to allocate memory for players in loadPlayers_Text");
+          return FALSE;
+        }
+      status = new_player->loadFromFile_Text(file);
+      if (status)
+        {
+          global->allPlayers[count] = new_player;
+          count++;
+          if (count == max)
+            {
+              max += 5;
+              global->allPlayers = (PLAYER**) realloc(global->allPlayers, sizeof(PLAYER *) * max);
+            }
+        }
+      else
+        // free(new_player);
+        delete new_player;
+    }     // end of while status
+
+  global->numPermanentPlayers = count;
+  return TRUE;
+}
+
+
+void newgame (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  int objCount;
+  TANK *tank;
+
+  env->initialise ();
+  global->initialise ();
+
+  // if a game should be loaded, try it or deny loading of the game
+  if ( (global->load_game) && (!Load_Game(global, env)) )
+    global->load_game = false;
+
+  // Now check back whether to load a game
+  if (!global->load_game)
+    initialisePlayers (global);
+
+  // There must not be any tanks!
+  for (objCount = 0; (tank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && tank; objCount++)
+    {
+      tank->player = NULL; // To avoid violent death!
+      delete(tank);
+    }
+
+  // This is always true here, as a newly started game is handled like a loaded one:
+  global->bIsGameLoaded = true;
+}
+
+
+
+// This function draws the background for most screens
+int draw_circlesBG (GLOBALDATA *global, BITMAP *dest, int x, int y, int width, int height, bool image)
+{
+  // int largestCircle, circleCount;
+  // BITMAP *drawTo = dest;
+
+  // try to prevent crashes on 64-bit systems by avoiding this function
+  if (! global->draw_background)
+  {
+      rectfill(dest, 0, 0, global->screenWidth - 1, global->screenHeight - 1, BLACK);
+      return 0;
+  }
+
+  if ( (image) && (global->misc[17]) )
+     stretch_blit(global->misc[17], dest, 0, 0, global->misc[17]->w, global->misc[17]->h, 0, 0,
+                  global->screenWidth, global->screenHeight);
+  else
+     rectfill(dest, 0, 0, global->screenWidth - 1, global->screenHeight - 1, DARK_GREEN);
+
+  /*
+  if (global->cacheCirclesBG)
+    {
+      if (!global->gfxData.circlesBG)
+        {
+          global->gfxData.circlesBG = create_bitmap (width, height);
+          drawTo = global->gfxData.circlesBG;
+        }
+      else
+        {
+          blit (global->gfxData.circlesBG, dest, 0, 0, 0, 0, width, height);
+          return (0);
+        }
+    }
+  else
+    {
+      drawTo = dest;
+    }
+ 
+  largestCircle = (int)(global->halfWidth * (4.0/3.0));
+  if (largestCircle > 1000) largestCircle = 1000;    // perhaps avoid crash on large screens
+  global->gfxData.circle_gradient_strip = create_gradient_strip (circles_gradient, largestCircle);
+  for (circleCount = largestCircle; circleCount > 0; circleCount -= 2)
+    circlefill (drawTo, width/2, height/2, circleCount, getpixel (global->gfxData.circle_gradient_strip, 0, largestCircle - circleCount));
+
+  if (global->cacheCirclesBG)
+    draw_circlesBG (global, dest, x, y, width, height);
+  */
+  return (0);
+}
+
+ENVIRONMENT *init_game_settings (GLOBALDATA *global)
+{
+  int count, x, y, z;
+  ENVIRONMENT *env;
+  double expSize, disperseSize;
+  // char dataDir[2048];
+  int colour_theme = (int) global->colour_theme;
+  int status;
+
+  #ifdef WIN32
+  if (global->full_screen == FULL_SCREEN_TRUE)
+      global->os_mouse = FALSE;
+  #endif
+
+  status = allegro_init ();
+  if (status)
+  {
+    printf("Unable to start Allegro.\n");
+    return NULL;
+  }
+
+  set_window_title( "Atomic Tanks");
+  // before we get started, make sure if we are using
+  // full screen mode to ignore width and height settings
+  if (global->full_screen == FULL_SCREEN_TRUE)
+  {
+      status = get_desktop_resolution(& (global->screenWidth), & (global->screenHeight) );
+      if (status < 0)
+      {
+          global->screenWidth = 800;
+          global->screenHeight = 600;
+      }
+      screen_mode = GFX_AUTODETECT_FULLSCREEN;
+  }
+  // check for X pressed on the window bar
+  LOCK_FUNCTION(close_button_handler);
+  set_close_button_callback(close_button_handler);
+
+  if (! global->colourDepth)
+    global->colourDepth = desktop_color_depth();
+
+  if ( (global->colourDepth != 16) && (global->colourDepth != 32) )
+    global->colourDepth = 16;
+
+  set_color_depth (global->colourDepth);
+  if (global->width_override)
+  {
+    global->screenWidth = global->width_override;
+    global->halfWidth = global->screenWidth / 2;
+  }
+  if (global->height_override)
+  {
+    global->screenHeight = global->height_override;
+    global->halfHeight = global->screenHeight / 2;
+  }
+  if (set_gfx_mode (screen_mode, global->screenWidth, global->screenHeight, 0, 0) < 0)
+    {
+      perror( "set_gfx_mode");
+      // exit (1);
+      status = set_gfx_mode(screen_mode, 800, 600, 0, 0);
+      if ( status < 0 ) exit(1);
+      global->screenWidth = 800;
+      global->screenHeight = 600;
+      global->halfWidth = 400;
+      global->halfHeight = 300;
+    }
+
+#ifdef WIN32
+  if (global->full_screen == FULL_SCREEN_TRUE)
+    set_display_switch_mode(SWITCH_BACKAMNESIA);
+  else
+    set_display_switch_mode(SWITCH_BACKGROUND);
+#endif
+
+  if (install_keyboard () < 0)
+    {
+      perror ( "install_keyboard failed");
+      exit (1);
+    }
+  if (install_timer () < 0)
+    {
+      perror ( "install_timer failed");
+      exit (1);
+    }
+  if (install_mouse () < 0)
+    {
+      perror ( "install_mouse failed");
+      // exit (1);
+    }
+
+  // check to see if we want sound
+  if (global->sound > 0.0)
+  {
+    /*
+      // don't stop program if no sound since the game can be played without
+      if (install_sound (DIGI_AUTODETECT, MIDI_NONE, NULL) < 0)
+        fprintf (stderr, "install_sound: %s", allegro_error);
+    }
+    */
+        int sound_type = DIGI_AUTODETECT;
+        #ifdef LINUX
+        switch ( (int) global->sound_driver )
+        {
+        case SOUND_OSS: sound_type = DIGI_OSS; break;
+        case SOUND_ESD: sound_type = DIGI_ESD; break;
+        case SOUND_ARTS: sound_type = DIGI_ARTS; break;
+        case SOUND_ALSA: sound_type = DIGI_ALSA; break;
+        case SOUND_JACK: sound_type = DIGI_JACK; break;
+        default: sound_type = DIGI_AUTODETECT; break;
+        }
+	#endif
+        #ifdef UBUNTU
+        if (sound_type == DIGI_AUTODETECT)
+            sound_type = DIGI_OSS;
+        #endif
+        if (detect_digi_driver(sound_type)) 
+        {
+    	       if (install_sound (sound_type, MIDI_NONE, NULL) < 0)
+               {
+	           fprintf (stderr, "install_sound: failed initialising sound\n");
+                   fprintf (stderr, "Please try selecting a different Sound Driver from the Options menu.\n");
+               }
+	} 
+        else 
+		fprintf (stderr, "detect_digi_driver detected no sound device\n");
+  }      // end of we want sound
+
+  lock_cclock();
+  LOCK_VARIABLE(cclock);
+  unlock_cclock();
+  LOCK_FUNCTION(clockadd);
+  // if (install_int_ex (clockadd, BPS_TO_TIMER (FRAMES_PER_SECOND)) < 0) {
+  if (install_int_ex (clockadd, BPS_TO_TIMER(global->frames_per_second)) < 0)
+    {
+      perror ( "install_int_ex");
+      exit (1);
+    }
+  if (install_int (fpsadd, 1000) < 0)
+    {
+      perror ( "install_int");
+      exit (1);
+    }
+
+  srand (time (0));
+  WHITE = makecol (255, 255, 255);
+  BLACK = makecol (0, 0, 0);
+  PINK = makecol (255, 0, 255);
+  RED = makecol (255, 0, 0);
+  GREEN = makecol (0, 255, 0);
+  DARK_GREEN = makecol(0, 80, 0);
+  BLUE = makecol (0, 0, 255);
+  PURPLE = makecol (200, 0, 200);
+  YELLOW = makecol (255, 255, 0);
+
+  global->Load_Bitmaps();
+  global->Load_Fonts();
+
+  if (! global->os_mouse) show_mouse(NULL);
+  blit ((BITMAP *) global->title[0], screen, 0, 0, global->halfWidth - 320, global->halfHeight - 240, 640, 480);
+  if (! global->os_mouse) show_mouse (screen);
+
+  global->Load_Sounds();
+
+  for (count = 0; count < ALL_LANDS; count++)
+    global->gfxData.land_gradient_strips[count] = NULL;
+  for (count = 0; count < ALL_SKIES; count++)
+    global->gfxData.sky_gradient_strips[count] = NULL;
+
+  global->gfxData.explosion_gradient_strip = create_gradient_strip (explosion_gradients[colour_theme], 200);
+  // for (count = 0; count < 2; count++)
+  //  global->gfxData.explosion_gradient_strips[count] = create_gradient_strip (explosion_gradients[count], 200);
+
+  expSize = 0;
+  disperseSize = 0;
+  for (count = 0; count < EXPLOSIONFRAMES; count++)
+    {
+      global->gfxData.explosions[count] = create_bitmap (214, 214);
+      if (count == 0)
+        {
+          expSize = 25;
+          disperseSize = 0;
+        }
+      else if (count < EXPLODEFRAMES - 4)
+        expSize += (107 - expSize) / 3;
+      else if (count < EXPLODEFRAMES)
+        expSize--;
+      else if (count == EXPLODEFRAMES)
+        disperseSize = 25;
+      else
+        disperseSize += (107 - disperseSize) / 2;
+
+      clear_to_color (global->gfxData.explosions[count], PINK);
+      for (y = (int)expSize; y > disperseSize; y--)
+        {
+          double value;
+          value = pow ((double)y / expSize, count / 4 + 1);
+          circlefill (global->gfxData.explosions[count], 107, 107, y, getpixel (global->gfxData.explosion_gradient_strip, 0, (int)(value * 200)));
+        }
+      if (disperseSize)
+        circlefill (global->gfxData.explosions[count], 107, 107, (int)disperseSize, PINK);
+    }
+
+  expSize = 0;
+  disperseSize = 0;
+  for (count = 0; count < EXPLOSIONFRAMES; count++)
+    {
+      global->gfxData.flameFront[count] = create_bitmap (600, 30);
+      if (count == 0)
+        {
+          expSize = 10;
+          disperseSize = 0;
+        }
+      else if (count < EXPLODEFRAMES - 4)
+        expSize += (300 - expSize) / 3;
+      else if (count < EXPLODEFRAMES)
+        expSize--;
+      else if (count == EXPLODEFRAMES)
+        disperseSize = 10;
+      else
+        disperseSize += (300 - disperseSize) / 2;
+
+      clear_to_color (global->gfxData.flameFront[count], PINK);
+      for (y = (int)expSize; y > disperseSize; y--)
+        {
+          double value;
+          value = pow ((double)y / expSize, count / 4 + 1);
+          ellipsefill (global->gfxData.flameFront[count], 300, 15, y, y / 20, getpixel (global->gfxData.explosion_gradient_strip, 0, (int)(value * 200)));
+        }
+      if (disperseSize)
+        ellipsefill (global->gfxData.flameFront[count], 300, 15, (int)disperseSize, (int)disperseSize / 16, PINK);
+    }
+
+  global->gfxData.topbar = create_bitmap (global->screenWidth, MENUHEIGHT);
+  global->gfxData.topbar_gradient_strip = create_gradient_strip (topbar_gradient, 100);
+  if (!global->ditherGradients)
+    {
+      for (count = 0; count < MENUHEIGHT; count++)
+        {
+          float adjCount = (100.0 / MENUHEIGHT) * count;
+          line (global->gfxData.topbar, 0, count, global->screenWidth - 1, count, getpixel (global->gfxData.topbar_gradient_strip, 0, (int)adjCount));
+        }
+    }
+  else
+    {
+      for (x = 0; x < global->screenWidth; x++)
+        {
+          for (y = 0; y < MENUHEIGHT; y++)
+            {
+              float adjY = (100.0 / MENUHEIGHT) * y;
+              int offset;
+              if ((adjY < 2) || (adjY > 100 - 2))
+                offset = 0;
+              else
+                offset = rand () % 4 - 2;
+              putpixel (global->gfxData.topbar, x, y, getpixel (global->gfxData.topbar_gradient_strip, 0, (int)adjY + offset));
+            }
+        }
+    }
+
+  global->gfxData.stuff_bar[0] = create_bitmap (STUFF_BAR_WIDTH, STUFF_BAR_HEIGHT);
+  global->gfxData.stuff_bar[1] = create_bitmap (STUFF_BAR_WIDTH, STUFF_BAR_HEIGHT);
+  global->gfxData.stuff_icon_base = create_bitmap (STUFF_BAR_WIDTH/10, STUFF_BAR_HEIGHT);
+  clear_to_color (global->gfxData.stuff_bar[0], PINK);
+  clear_to_color (global->gfxData.stuff_bar[1], PINK);
+  clear_to_color (global->gfxData.stuff_icon_base, PINK);
+  global->gfxData.stuff_bar_gradient_strip = create_gradient_strip (stuff_bar_gradient, STUFF_BAR_WIDTH);
+  for (x = 0; x < STUFF_BAR_WIDTH; x++)
+    {
+      for (y = 0; y < STUFF_BAR_HEIGHT; y++)
+        {
+          double sides_dist = 0.1, circle_dist;
+          circle_dist = vector_length_f ((float)x-(STUFF_BAR_WIDTH - 75), (float)y - (STUFF_BAR_HEIGHT/2 - 2), 0);
+          if (circle_dist < 75)
+            circle_dist = 1 - (circle_dist / 75.0);
+          else
+            circle_dist = 0;
+
+          if (x < (STUFF_BAR_HEIGHT/2 - 2))
+            sides_dist -= 0.1 - ((float)x / 150.0);
+          else if (x > STUFF_BAR_WIDTH - (STUFF_BAR_HEIGHT/2 - 2))
+            sides_dist -= ((float)(x - (STUFF_BAR_WIDTH - (STUFF_BAR_HEIGHT/2 - 2))) / 150.0);
+
+          if (y < STUFF_BAR_HEIGHT/2 - 2)
+            sides_dist -= 0.1 - ((float)(y) / 150.0);
+          else
+            sides_dist -= ((float)(y - (STUFF_BAR_HEIGHT/2 - 2)) / 150.0);
+
+          sides_dist -= circle_dist * circle_dist;
+          if (sides_dist > ((double)x / 1000.0))
+            sides_dist = ((double)x / 1000.0);
+          if (sides_dist < 0)
+            sides_dist = 0;
+          if (circle_dist > 1)
+            circle_dist = 1;
+
+          if (x < STUFF_BAR_WIDTH/10)
+            putpixel (global->gfxData.stuff_icon_base, x, y, getpixel (global->gfxData.stuff_bar_gradient_strip, 0, (int)((sides_dist + circle_dist) * (STUFF_BAR_WIDTH-1))));
+
+          if (y < STUFF_BAR_HEIGHT - 5)
+            {
+              putpixel (global->gfxData.stuff_bar[0], x, y, getpixel (global->gfxData.stuff_bar_gradient_strip, 0, (int)((sides_dist + circle_dist) * (STUFF_BAR_WIDTH-1))));
+              putpixel (global->gfxData.stuff_bar[1], x, y, getpixel (global->gfxData.stuff_bar_gradient_strip, 0, (int)((sides_dist + circle_dist + 0.05) * (STUFF_BAR_WIDTH-1))));
+            }
+        }
+    }
+
+  if (! global->os_mouse )
+    {
+      set_mouse_sprite ((BITMAP *) global->misc[0]);
+      set_mouse_sprite_focus (0, 0);
+    }
+
+  global->window.x = 0;
+  global->window.y = 0;
+  global->window.w = 0;
+  global->window.h = 0;
+  for (z = 0; z < MAXUPDATES; z++)
+    {
+      global->updates[z].x = 0;
+      global->updates[z].y = 0;
+      global->updates[z].w = 0;
+      global->updates[z].h = 0;
+    }
+
+  env = new ENVIRONMENT (global);
+  if (!env)
+    {
+      perror ( "atanks.cc: Allocating env in init_game_settings");
+      exit (1);
+    }
+
+  clear_to_color (env->db, BLACK);
+  global->env = env;
+
+  return (env);
+}
+
+int options (GLOBALDATA *global, ENVIRONMENT *env, MENUDESC *menu);
+
+int createNewPlayer (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  PLAYER *newPlayer = global->createNewPlayer (env);
+  if (!newPlayer)
+    {
+      perror ( "atanks.cc: Failed allocating memory in createNewPlayer");
+      // exit (1);
+    }
+  options (global, env, (MENUDESC*)newPlayer->menudesc);
+  return (-1);
+}
+
+int destroyPlayer (GLOBALDATA *global, ENVIRONMENT *env, void *data)
+{
+  int optionsRetVal;
+  char sureMessage[200];
+  PLAYER *tempPlayer = (PLAYER*)data;
+  MENUDESC areYouSureMenu = { "Are You Sure?", 0, NULL, TRUE, TRUE};
+
+  sprintf (sureMessage, "This player (%s) will be permanently deleted", tempPlayer->getName ());
+  errorMessage = sureMessage;
+  errorX = global->halfWidth - text_length (font, errorMessage) / 2;
+  errorY = 170;
+  optionsRetVal = options (global, env, &areYouSureMenu);
+  if (optionsRetVal >> 8 != KEY_ESC)
+    {
+      global->destroyPlayer (tempPlayer);
+      return (-2);
+    }
+  return (KEY_SPACE << 8);
+}
+
+int displayPlayerName (ENVIRONMENT *env, int x, int y, void *data)
+{
+  PLAYER *player = (PLAYER*)data;
+  char *name = player->getName ();
+  int textHeight = text_height (font);
+  int textLength = text_length (font, name);
+
+  if ((int)player->type == HUMAN_PLAYER)
+    {
+      int radius = 5;
+      circlefill (env->db, x - textLength - textHeight / 2 - 2,
+                  y + textHeight / 2,
+                  radius, makecol (200, 100, 255));
+      circle (env->db, x - textLength - textHeight / 2 - 2,
+              y + textHeight / 2,
+              radius, BLACK);
+    }
+  else
+    {
+      rectfill (env->db,
+                x - textLength - 2 - ((int)player->type * 3),
+                y + textHeight - 10,
+                x - textLength - 2,
+                y + textHeight - 2,
+                makecol (100, 255, 100));
+      rect (env->db,
+            x - textLength - 2 - ((int)player->type * 3),
+            y + textHeight - 10,
+            x - textLength - 2,
+            y + textHeight - 2,
+            BLACK);
+      for (int lineCount = 1; lineCount < player->type; lineCount++)
+        {
+          vline (env->db,
+                 x - textLength - 2 - (lineCount * 3),
+                 y + textHeight - 2,
+                 y + textHeight - 10,
+                 BLACK);
+        }
+    }
+  textout_ex (env->db, font, name, x - textLength, y, player->color, -1);
+
+  return (0);
+}
+
+
+int options (GLOBALDATA *global, ENVIRONMENT *env, MENUDESC *menu)
+{
+  MENUENTRY *opts;
+  BUTTON *reset_button = NULL;
+  int selected_index = 0, my_key = 0;
+  int numEntries;
+  const char *title;
+  int ke, z;
+  int mouseLeftPressed;
+  char *reset_text, *back_text;
+#include "menucontent.h"
+
+     if (global->language == LANGUAGE_GERMAN)
+     {
+           reset_text = "Alles zurucksetzen";
+           back_text = "Zuruck";
+     }
+     else
+     {
+           reset_text = "Reset All";
+           back_text = "Back";
+     }
+
+  if (!menu)
+  {
+    menu = &mainMenu;
+    reset_button = new BUTTON(global, env, global->halfWidth - 5 - text_length (font, menu->title), global->menuBeginY + 70, // 170, 
+                    reset_text, (BITMAP *) global->misc[7], (BITMAP *) global->misc[7], 
+                    (BITMAP *) global->misc[8]);
+  }
+
+  opts = menu->entries;
+  numEntries = menu->numEntries;
+  title = menu->title;
+
+  char name_buff[64];
+  char format_buff[64];
+  int done, lb;
+  int stop = 0;
+
+  int *updateoption;
+
+  updateoption = (int *)calloc(numEntries, sizeof(int));
+  if (!updateoption)
+    {
+      // Die hard!
+      cerr << "ERROR: Unable to allocate " << numEntries << " bytes in options() !!!" << endl;
+      // exit (1);
+    }
+
+  BUTTON *but_okay = NULL, *but_quit = NULL;
+  if (menu->okayButton)
+    {
+      int xpos = global->halfWidth - 80;
+      if (menu->quitButton)
+        xpos -= 80;
+      // but_okay = new BUTTON (global, env, xpos, global->halfHeight + 160, "Okay", (BITMAP*)global->misc[7], (BITMAP*)global->misc[7], (BITMAP*)global->misc[8]);
+      but_okay = new BUTTON (global, env, xpos, global->menuBeginY + 360 , "Okay", (BITMAP*)global->misc[7], (BITMAP*)global->misc[7], (BITMAP*)global->misc[8]);
+      if (!but_okay)
+        {
+          perror ( "atanks.cc: Failed allocating memory for but_okay in options");
+          // exit (1);
+        }
+    }
+  if (menu->quitButton)
+    {
+      int xpos = global->halfWidth - 80;
+      if (menu->okayButton)
+        xpos += 80;
+      but_quit = new BUTTON (global, env, xpos, global->menuBeginY + 360, back_text, (BITMAP*)global->misc[7], (BITMAP*)global->misc[7], (BITMAP*)global->misc[8]);
+      // but_quit = new BUTTON (global, env, xpos, global->halfHeight + 160, back_text, (BITMAP*)global->misc[7], (BITMAP*)global->misc[7], (BITMAP*)global->misc[8]);
+      if (!but_quit)
+        {
+          perror ( "atanks.cc: Failed allocating memory for but_quit in options");
+          // exit (1);
+        }
+    }
+
+  lock_cclock();
+  mouseLeftPressed = done = lb = env->mouseclock = cclock = 0;
+  unlock_cclock();
+  fi = 1;
+
+  for (z = 0; z < numEntries; z++)
+    {
+      updateoption[z] = 1;
+    }
+
+  flush_inputs ();
+
+  do
+    {
+      LINUX_SLEEP;
+      while (get_cclock() > 0)
+        {
+          lock_cclock();
+          cclock--;
+          unlock_cclock();
+          my_key = 0;
+          if ( keypressed() )
+          {
+             my_key = readkey();
+             my_key = my_key >> 8;
+             if (my_key == KEY_DOWN)
+             {
+                selected_index++;
+                if (selected_index >= numEntries)
+                   selected_index = 0;
+                my_key = 0;
+             }
+             else if (my_key == KEY_UP)
+             {
+                 selected_index--;
+                 if (selected_index < 0)
+                   selected_index = numEntries - 1;
+                 my_key = 0;
+             }
+             else if (my_key == KEY_ENTER_PAD)
+                  my_key = KEY_ENTER;
+
+             for (z = 0; z < numEntries; z++)
+                updateoption[z] = TRUE;
+             fi = TRUE;
+             
+          }     // end of a key was pressed
+
+          if (!lb && mouse_b & 1)
+            {
+              env->mouseclock = 0;
+              mouseLeftPressed = 1;
+            }
+          else
+            {
+              mouseLeftPressed = 0;
+            }
+          lb = (mouse_b & 1) ? 1 : 0;
+          if ( ((mouse_b & 1 || mouse_b & 2) && !env->mouseclock) || (my_key) )
+            {
+              for (z = 0; z < numEntries; z++)
+                {
+                  int midX = opts[z].x;
+                  int midY = opts[z].y;
+                  if (opts[z].type == OPTION_MENUTYPE)
+                    {
+                      sprintf (name_buff, "-> %s", opts[z].name);
+                      if ( ((!opts[z].viewonly) && mouse_x > midX - text_length (font, name_buff) && mouse_x < midX && mouse_y >= midY && mouse_y < midY + 10) || 
+                         ( (my_key == KEY_SPACE) && (selected_index == z)) )
+                        {
+                          int optsRetVal = options (global, env, (MENUDESC*)opts[z].value);
+                          if (optsRetVal < 0)
+                            {
+                              return (optsRetVal + 1);
+                            }
+                          fi = 1;
+                          for (z = 0; z < numEntries; z++)
+                            {
+                              updateoption[z] = 1;
+                            }
+                          my_key = selected_index = 0;
+                        }
+                    }
+                  else if (opts[z].type == OPTION_ACTIONTYPE)
+                    {
+                      sprintf (name_buff, "-> %s", opts[z].name);
+                      if ( ((!opts[z].viewonly) && mouse_x > midX - text_length (font, name_buff) && mouse_x < midX && mouse_y >= midY && mouse_y < midY + 10) ||
+                           ( (my_key == KEY_SPACE) && (selected_index == z) ) )
+                        {
+                          int (*action) (GLOBALDATA*, ENVIRONMENT*, void*)
+                          = (int (*)(GLOBALDATA*, ENVIRONMENT*, void*))opts[z].value;
+                          int actionRetVal = action (global, env, opts[z].data);
+                          if (actionRetVal)
+                            return (actionRetVal);
+                        }
+                    }
+                  else if (opts[z].type == OPTION_TEXTTYPE)
+                    {
+                      int my_text_length;
+                      strcmp(opts[z].name, "Name") ? my_text_length = 11 : my_text_length = NAME_LENGTH;
+                      int boxWidth;
+                      if (! strcmp(opts[z].name, "Server address") )
+                         my_text_length = ADDRESS_LENGTH;
+
+                      if (my_text_length == NAME_LENGTH)
+                        boxWidth = textEntryBox (global, env, FALSE, midX + 100, midY, (char*)opts[z].value, my_text_length);
+                      else if (my_text_length == ADDRESS_LENGTH)
+                        boxWidth = textEntryBox(global, env, FALSE, midX + 70, midY, (char*) opts[z].value, my_text_length);
+                      else
+                        boxWidth = textEntryBox (global, env, FALSE, midX + 50, midY, (char*)opts[z].value, my_text_length);
+                      if ( ((!opts[z].viewonly) && mouse_x > midX - text_length (font, name_buff) && mouse_x < midX + 50 + boxWidth && mouse_y >= midY && mouse_y < midY + 10) ||
+                           ( (selected_index == z) && (my_key == KEY_SPACE) ) )
+                        {
+                          if (my_text_length == NAME_LENGTH)
+                            textEntryBox (global, env, TRUE, midX + 100, midY, (char*)opts[z].value, my_text_length);
+                          else if (my_text_length == ADDRESS_LENGTH)
+                            textEntryBox(global, env, TRUE, midX + 70, midY, (char *)opts[z].value, my_text_length);
+                          else
+                            textEntryBox (global, env, TRUE, midX + 50, midY, (char*)opts[z].value, my_text_length);
+                          updateoption[z] = 1;
+                        }
+                    }
+                  else if (opts[z].type == OPTION_COLORTYPE)
+                    {
+                      if ((!opts[z].viewonly) && mouse_x > midX && mouse_x < midX + 100 && mouse_y >= midY && mouse_y < midY + 15)
+                        {
+                          *(int*)opts[z].value = pickColor (midX, midY, 100, 15, mouse_x, mouse_y);
+                          updateoption[z] = 1;
+                        }
+                      colorBar (env, midX, midY, 100, 15);
+                      rectfill (env->db, midX + 110, midY, midX + 130, midY + 10, *(int*)opts[z].value);
+                      rect (env->db, midX + 110, midY, midX + 130, midY + 10, BLACK);
+                    }
+                  else if (opts[z].type == OPTION_TOGGLETYPE)
+                    {
+                      int tlen = text_length (font, name_buff);
+                      int thgt = text_height (font);
+                      int temp_counter;
+                      if ( (mouseLeftPressed && (!opts[z].viewonly) && mouse_x > midX - tlen / 2 && mouse_x < midX + tlen / 2 && mouse_y >= midY && mouse_y < midY + thgt) ||
+                         ( (my_key == KEY_SPACE) && (selected_index == z) ) )
+                        {
+                          if (*opts[z].value == 0)
+                            *opts[z].value = 1;
+                          else
+                            *opts[z].value = 0;
+                          mouseLeftPressed = 1;
+                          // updateoption[z] = 1;
+                          // Crude, but hopefulyl useful
+                          for (temp_counter = 0; temp_counter < numEntries; temp_counter++)
+                               updateoption[temp_counter] = 1;
+                        }
+                    }
+                  else
+                    {
+                      if (!opts[z].viewonly)
+                        {
+                          if (mouse_x >= midX + 100 && mouse_x < midX + 110 && mouse_y >= midY && mouse_y < midY + 10)
+                            {
+                              if (mouse_b & 1)
+                                *opts[z].value -= opts[z].increment;
+                              else if (mouse_b & 2)
+                                *opts[z].value -= opts[z].increment * 10;
+                              updateoption[z] = 1;
+                            }
+                          if (mouse_x >= midX + 112 && mouse_x < midX + 122 && mouse_y >= midY && mouse_y < midY + 10)
+                            {
+                              if (mouse_b & 1)
+                                *opts[z].value += opts[z].increment;
+                              else if (mouse_b & 2)
+                                *opts[z].value += opts[z].increment * 10;
+                              updateoption[z] = 1;
+                            }
+
+                          if ( (my_key == KEY_RIGHT) && (selected_index == z) )
+                          {
+                              *opts[z].value += opts[z].increment;
+                              updateoption[z] = 1;
+                          }
+                          else if ( (my_key == KEY_LEFT) && (selected_index == z) )
+                          {
+                              *opts[z].value -= opts[z].increment;
+                              updateoption[z] = 1;
+                          }
+
+                          // This if block is a nasty hack to get the tank
+                          // styles to redraw on the Players menu.
+                          if (updateoption[z])
+                          {
+                              int my_counter;
+                              for (my_counter = 0; my_counter < numEntries; my_counter++)
+                                 updateoption[my_counter] = TRUE;
+                              fi = TRUE;
+                          }
+                          /*if (mouse_x >= midX + 134 && mouse_x < midY + 154 && mouse_y >= midY && mouse_y < midY + 10) {
+                          	*opts[z].value = opts[z].defaultv;
+                          	updateoption[z] = 1;
+                          }*/
+                          if (*opts[z].value > opts[z].max)
+                            {
+                              *opts[z].value = opts[z].min;
+                            }
+                          if (*opts[z].value < opts[z].min)
+                            {
+                              *opts[z].value = opts[z].max;
+                            }
+                        }
+                    }
+                }
+            }
+          env->mouseclock++;
+          if (env->mouseclock > 10)
+            {
+              env->mouseclock = 0;
+            }
+        }
+
+      env->make_update (mouse_x, mouse_y, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
+      env->make_update (lx, ly, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
+      lx = mouse_x;
+      ly = mouse_y;
+      if (! global->os_mouse) show_mouse (NULL);
+
+      // draw menu stuff
+      if (fi)
+        {
+          drawMenuBackground (global, env, BACKGROUND_BLANK, rand (), 400);
+          textout_ex (env->db, font, title, global->halfWidth - 3 - text_length (font, title), global->menuBeginY + 50, BLACK, -1);
+          textout_ex (env->db, font, title, global->halfWidth - 5 - text_length (font, title), global->menuBeginY + 50, WHITE, -1);
+          for (z = 0; z < numEntries; z++)
+            {
+              int midX = opts[z].x;
+              int midY = opts[z].y;
+              char my_pointer[2];
+
+              if (z == selected_index)
+                  strcpy(my_pointer, "*");
+              else
+                  my_pointer[0] = '\0';
+
+              if (opts[z].type == OPTION_TOGGLETYPE)
+                {
+                  int color = (*opts[z].value)?WHITE:BLACK;
+                  int radius = text_length(font, opts[z].name) / 2;
+                  int y_radius = text_height(font);
+                  if (y_radius > 8)
+                      y_radius = 8;
+                  ellipsefill (env->db, midX, midY + text_height (font) / 2, radius, y_radius, color);
+                  textout_ex(env->db, font, my_pointer, (midX - radius) - 40 , midY, WHITE, -1);
+                }
+
+              if (opts[z].displayFunc)
+                {
+                  if (opts[z].type == OPTION_TOGGLETYPE)
+                  {
+                      opts[z].displayFunc (env,
+                                           midX + text_length (font, opts[z].name) / 2, midY,
+                                           opts[z].data);
+                  }
+                  else if (opts[z].type == OPTION_MENUTYPE)
+                  {
+                      opts[z].displayFunc (env,
+                                           midX, midY,
+                                           opts[z].data);
+                      sprintf(name_buff, "%s", my_pointer);
+                      textout_ex(env->db, font, name_buff, midX - 125, midY, WHITE, -1);
+                  }
+                  else if (opts[z].type == OPTION_SPECIALTYPE)
+                  {
+                      opts[z].displayFunc(env, 
+                                          midX + text_length(font, opts[z].name) / 2, midY,
+                                          opts[z].value );
+                      sprintf (name_buff, "%s %s:", my_pointer, opts[z].name);
+                      textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), 
+                                  midY, opts[z].color, -1);
+                      if (!opts[z].viewonly)
+                      {
+                          draw_sprite_v_flip (env->db, (BITMAP *) global->misc[6], midX + 100, midY);
+                          draw_sprite (env->db, (BITMAP *) global->misc[6], midX + 112, midY);
+                      }
+                  }
+                }
+              else if (opts[z].type == OPTION_MENUTYPE)
+                {
+                  sprintf (name_buff, "%s -> %s", my_pointer, opts[z].name);
+                  textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), midY, opts[z].color, -1);
+                }
+              else if (opts[z].type == OPTION_ACTIONTYPE)
+                {
+                  sprintf (name_buff, "%s -> %s", my_pointer, opts[z].name);
+                  textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), midY, opts[z].color, -1);
+                }
+              else if (opts[z].type == OPTION_TEXTTYPE)
+                {
+                  sprintf (name_buff, "%s %s:", my_pointer, opts[z].name);
+                  textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), midY, opts[z].color, -1);
+                }
+              else if (opts[z].type == OPTION_COLORTYPE)
+                {
+                  sprintf (name_buff, "%s %s:", my_pointer, opts[z].name);
+                  textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), midY, opts[z].color, -1);
+                }
+              else if (opts[z].type == OPTION_TOGGLETYPE)
+                {
+                  sprintf (name_buff, "%s %s", my_pointer, opts[z].name);
+                  textout_centre_ex (env->db, font, name_buff, midX, midY, opts[z].color, -1);
+                }
+              else
+                {
+                  sprintf (name_buff, "%s %s:", my_pointer, opts[z].name);
+                  textout_ex (env->db, font, name_buff, midX - text_length (font, name_buff), midY, opts[z].color, -1);
+                  if (!opts[z].viewonly)
+                    {
+                      draw_sprite_v_flip (env->db, (BITMAP *) global->misc[6], midX + 100, midY);
+                      draw_sprite (env->db, (BITMAP *) global->misc[6], midX + 112, midY);
+                    }
+                }
+
+                if (my_pointer[0])
+                     env->make_update(midX - 200, midY - 20, 400, 40);
+
+            }        // end of for loop
+          if (but_okay) but_okay->draw (env->db);
+          if (but_quit) but_quit->draw (env->db);
+          if (reset_button) reset_button->draw(env->db);
+        }      // end of if fi
+
+      for (z = 0; z < numEntries; z++)
+        {
+          int midX = opts[z].x;
+          int midY = opts[z].y;
+          if (updateoption[z])
+            {
+              updateoption[z] = 0;
+              if (opts[z].type == OPTION_TOGGLETYPE)
+                {
+                  int color = (*opts[z].value)?WHITE:BLACK;
+                  int text_tall = text_height(font);
+                  if (text_tall > 8)
+                      text_tall = 8;
+                  ellipsefill (env->db, midX, midY + text_height (font) / 2, text_length (font, opts[z].name) / 2, text_tall, color);
+                }
+              if (opts[z].displayFunc)
+                {
+                  if (opts[z].type == OPTION_TOGGLETYPE)
+                    {
+                      opts[z].displayFunc (env,
+                                           midX + text_length (font, opts[z].name) / 2, midY,
+                                           opts[z].data);
+                    }
+                  else if (opts[z].type == OPTION_MENUTYPE)
+                    {
+                      opts[z].displayFunc (env,
+                                           midX, midY,
+                                           opts[z].data);
+                    }
+                  env->make_update (midX - 200, midY - text_height (font), 450, 50);
+                  env->do_updates();
+                }
+              else if (opts[z].type != OPTION_MENUTYPE && opts[z].type != OPTION_ACTIONTYPE)
+                {
+                  if (opts[z].type == OPTION_DOUBLETYPE)
+                    {
+                      sprintf (format_buff, opts[z].format, *opts[z].value);
+                      textEntryBox (global, env, FALSE, midX + 50, midY, format_buff, 11);
+                    }
+                  else if (opts[z].type == OPTION_TEXTTYPE)
+                    {
+                      textEntryBox (global, env, FALSE, midX + 100, midY, (char*)opts[z].value, NAME_LENGTH);
+                    }
+                  else if (opts[z].type == OPTION_COLORTYPE)
+                    {
+                      colorBar (env, midX, midY, 100, 15);
+                      rectfill (env->db, midX + 110, midY, midX + 130, midY + 10, *(int*)opts[z].value);
+                      rect (env->db, midX + 110, midY, midX + 130, midY + 10, BLACK);
+                    }
+                  else if (opts[z].type == OPTION_TOGGLETYPE)
+                    {
+                      sprintf (format_buff, "%s", opts[z].name);
+                      textout_centre_ex (env->db, font, format_buff, midX, midY, opts[z].color, -1);
+                    }
+                  else if (opts[z].specialOpts)
+                    {
+                      textEntryBox (global, env, FALSE, midX + 50, midY, opts[z].specialOpts[(int) *opts[z].value], 11);
+                    }
+                  env->make_update (midX - 100, midY - 2, 250, 20);
+                }
+            }
+        }
+
+      if (fi)
+        {
+          fi = 0;
+          quickChange (global, env->db);
+        }
+
+      if ( (but_quit && but_quit->isPressed()) || (my_key == KEY_ESC) )
+        {
+          global->wr_lock_command();
+          global->command = GLOBAL_COMMAND_MENU;
+          global->unlock_command();
+          stop = 1;
+        }
+      if ( (but_okay && but_okay->isPressed()) || (my_key == KEY_ENTER) )
+        {
+          stop = 2;
+        }
+
+      if ( (reset_button) && (reset_button->isPressed() ) )
+      {
+         // RESET all options!
+         env->Reset_Options();
+         global->Reset_Options();
+      }
+
+      if (but_okay) but_okay->draw (env->db);
+      if (but_quit) but_quit->draw (env->db);
+      if (reset_button) reset_button->draw(env->db);
+
+      if (! global->os_mouse) show_mouse(env->db);
+      if (global->close_button_pressed) stop = 1;
+      env->do_updates ();
+    }
+  // while ((!keypressed ()) && (!stop) );
+  while (! stop);
+
+  if (!stop)
+    ke = readkey ();
+  else if (stop == 2)
+    ke = KEY_ENTER << 8;
+  else
+    ke = KEY_ESC << 8;
+
+  flush_inputs();
+
+  if (but_quit)
+    delete but_quit;
+  if (but_okay)
+    delete but_okay;
+
+  if ( reset_button )
+    delete reset_button;
+
+  free(updateoption);
+
+  return (ke);
+}
+
+int editPlayers (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  int optionsRetVal;
+  // int rows = (global->screenHeight - 400) / 15;
+  int rows = (global->screenHeight - 2 * global->menuBeginY - 200) / 15;
+  int columns = (global->numPermanentPlayers / rows) + 1;
+  rows = (rows / columns) + 1;
+
+  MENUENTRY *playersOpts;
+  MENUDESC playersMenu;
+  // playersOpts = new MENUENTRY[1 + global->numPermanentPlayers];
+  playersOpts = (MENUENTRY *) calloc( global->numPermanentPlayers + 1, sizeof(MENUENTRY));
+  if (!playersOpts)
+    {
+      perror ( "atanks.cc: Failed allocating memory for playersOpts in editPlayers");
+      return 0;
+      // exit (1);
+    }
+  playersOpts[0].name = "Create New";
+  playersOpts[0].displayFunc = NULL;
+  playersOpts[0].color = WHITE;
+  playersOpts[0].value = (double*)createNewPlayer;
+  playersOpts[0].data = NULL;
+  playersOpts[0].type = OPTION_ACTIONTYPE;
+  playersOpts[0].viewonly = FALSE;
+  playersOpts[0].x = global->halfWidth - 3;
+  // playersOpts[0].y = global->halfHeight - 68 - 15;
+  playersOpts[0].y = global->menuBeginY + 117;
+
+  playersMenu.title = "Players";
+  playersMenu.numEntries = 1 + global->numPermanentPlayers;
+  playersMenu.entries = playersOpts;
+  playersMenu.quitButton = TRUE;
+  playersMenu.okayButton = FALSE;
+
+  for (int count = 0; count < global->numPermanentPlayers; count++)
+    {
+      MENUENTRY *opt = &playersOpts[1 + count];
+
+      opt->name = global->allPlayers[count]->getName ();
+      opt->displayFunc = displayPlayerName;
+      opt->data = global->allPlayers[count];
+      opt->color = global->allPlayers[count]->color;
+      opt->value = (double*)global->allPlayers[count]->menudesc;
+      opt->type = OPTION_MENUTYPE;
+      opt->viewonly = FALSE;
+      opt->x = global->halfWidth - (((count % columns) - (columns / 2)) * 90) - (((columns + 1) % 2) * 45);
+      // opt->y = global->halfHeight - 68 + ((count / columns) * 15);
+      opt->y = global->menuBeginY + 132 + ((count / columns) * 15);
+    }
+  optionsRetVal = options (global, env, &playersMenu);
+
+  // delete playersOpts;
+  free(playersOpts);
+
+  return (optionsRetVal);
+}
+
+int selectPlayers (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  MENUENTRY roundOpt = { global->ingame->complete_text[1], NULL, WHITE, (double*)&global->rounds, NULL, "%2.0f", 1, MAX_ROUNDS, 1, 5, NULL,
+                         OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->menuBeginY + 82
+                       };
+  MENUENTRY gamename = { global->ingame->complete_text[2], NULL, WHITE, (double *) global->game_name, NULL, "%s", 0, 0, 0, 0, NULL,
+                         OPTION_TEXTTYPE, FALSE, global->halfWidth - 3, global->menuBeginY + 100
+                       };
+  MENUENTRY loadgame, campaign;
+  int save_game_exists;
+
+  int optionsRetVal, z;
+  // int rows = (global->screenHeight - 400) / 15;
+  int rows = (global->screenHeight - 2 * global->menuBeginY - 200) / 15;
+  int columns = (global->numPermanentPlayers / rows) + 1;
+  int playerCount = 0;
+
+  int number_saved_games = 0;
+  struct dirent **saved_game_names;
+  char **game_list = NULL;
+  MENUENTRY *playersOpts;
+  MENUDESC playersMenu;
+  MENUENTRY load_game_entry;
+
+  // find saved games
+  saved_game_names = Find_Saved_Games(global, &number_saved_games);
+  if ( (saved_game_names) && ( number_saved_games ) )
+    {
+      int count;
+
+      // move the names into a char list
+      game_list = (char **) calloc( number_saved_games, sizeof(char *) );
+      for (count = 0; count < number_saved_games; count++)
+        {
+          game_list[count] = saved_game_names[count]->d_name;
+          // clear trailign extension
+          if ( strchr(game_list[count], '.') )
+            strchr(game_list[count], '.')[0] = '\0';
+        }
+
+      global->saved_game_list = game_list;
+      // set up menu for selecting saved games
+      load_game_entry.name = global->ingame->complete_text[3];
+      load_game_entry.displayFunc = NULL;
+      load_game_entry.color = WHITE;
+      load_game_entry.value = (double *) &global->saved_game_index;
+      load_game_entry.data = NULL;
+      load_game_entry.format = "%s";
+      load_game_entry.min = 0;
+      load_game_entry.max = number_saved_games - 1;
+      load_game_entry.increment = 1;
+      load_game_entry.defaultv = 0;
+      load_game_entry.specialOpts = global->saved_game_list;
+      load_game_entry.type = OPTION_SPECIALTYPE;
+      load_game_entry.viewonly = FALSE;
+      load_game_entry.x = global->halfWidth;
+      load_game_entry.y = global->menuBeginY + 120;
+    }
+
+  rows = (rows / columns) + 1;
+  // playersOpts = new MENUENTRY[global->numPermanentPlayers + 4];
+  playersOpts = (MENUENTRY *) calloc( global->numPermanentPlayers + 5, sizeof(MENUENTRY) );
+  if (!playersOpts)
+    {
+      perror ( "atanks.cc: Failed allocating memory for playersOpts in selectPlayers");
+      // exit (1);
+    }
+
+  loadgame.name = global->ingame->complete_text[4];
+  loadgame.displayFunc = NULL;
+  loadgame.data = &global->load_game;
+  loadgame.color = WHITE;
+  loadgame.value = (double *) &global->load_game;
+  loadgame.type = OPTION_TOGGLETYPE;
+  loadgame.viewonly = FALSE;
+  loadgame.x = global->halfWidth - 50;
+  loadgame.y = global->menuBeginY + 140;
+
+  campaign.name = global->ingame->complete_text[5];
+  campaign.displayFunc = NULL;
+  campaign.data = &global->campaign_mode;
+  campaign.color = WHITE;
+  campaign.value = (double *) &global->campaign_mode;
+  campaign.type = OPTION_TOGGLETYPE;
+  campaign.viewonly = FALSE;
+  campaign.x = global->halfWidth + 50;
+  campaign.y = global->menuBeginY + 140;
+
+  playersMenu.title = global->ingame->complete_text[0];
+  playersMenu.numEntries = global->numPermanentPlayers + 5;
+  playersMenu.entries = playersOpts;
+  playersMenu.quitButton = TRUE;
+  playersMenu.okayButton = TRUE;
+
+  for (int count = 0; count < global->numPermanentPlayers; count++)
+    {
+      MENUENTRY *opt = &playersOpts[count];
+
+      opt->name = global->allPlayers[count]->getName ();
+      opt->displayFunc = displayPlayerName;
+      opt->data = global->allPlayers[count];
+      opt->color = global->allPlayers[count]->color;
+      opt->value = (double*)&global->allPlayers[count]->selected;
+      opt->type = OPTION_TOGGLETYPE;
+      opt->viewonly = FALSE;
+      opt->x = global->halfWidth - (((count % columns) - (columns / 2)) * 90) - (((columns + 1) % 2) * 45);
+      // opt->y = 265 + ( (count / columns) * 15 );
+      opt->y = global->menuBeginY + 165 + ( (count / columns) * 15);
+    }
+  memcpy (&playersOpts[global->numPermanentPlayers], &roundOpt, sizeof (MENUENTRY));
+  memcpy (&playersOpts[global->numPermanentPlayers + 1], &gamename, sizeof (MENUENTRY));
+  memcpy (&playersOpts[global->numPermanentPlayers + 2], &loadgame, sizeof (MENUENTRY));
+  memcpy (&playersOpts[global->numPermanentPlayers + 3], &campaign, sizeof (MENUENTRY));
+  if ((number_saved_games) && (game_list) )
+    memcpy (&playersOpts[global->numPermanentPlayers + 4], &load_game_entry, sizeof(MENUENTRY));
+
+  do
+    {
+      optionsRetVal = options (global, env, &playersMenu);
+      if ( global->load_game )
+        {
+          if ( ( global->saved_game_list) && ( global->saved_game_list[ (int) global->saved_game_index ][0] ) )
+            {
+              memset(global->game_name, '\0', GAME_NAME_LENGTH);
+              strncpy(global->game_name, global->saved_game_list[ (int) global->saved_game_index ], 16);
+            }
+        }
+
+      if (optionsRetVal >> 8 == KEY_ENTER)
+        {
+          if (! global->load_game )    // trying to play a game
+            {
+              playerCount = 0;
+              global->numPlayers = 0;
+              for (z = 0; z < global->numPermanentPlayers; z++)
+                {
+                  if (global->allPlayers[z]->selected)
+                    {
+                      global->addPlayer (global->allPlayers[z]);
+                      playerCount++;
+                    }
+                }
+              if ((playerCount < 2) || (playerCount > MAXPLAYERS))
+                {
+                  if (playerCount < 2)
+                    errorMessage = global->ingame->complete_text[8];
+                  else if (playerCount > MAXPLAYERS)
+                    errorMessage = global->ingame->complete_text[9];
+                  errorX = global->halfWidth - text_length (font, errorMessage) / 2;
+                  errorY = global->menuBeginY + 70;
+                  optionsRetVal = 0;
+                }
+              else
+                {
+                  optionsRetVal = PLAY_GAME;
+                }
+            }    // end of trying to start a new game
+          else     // start to load an existing game
+            {
+              save_game_exists = Check_For_Saved_Game(global);
+              if (save_game_exists)
+                optionsRetVal = LOAD_GAME;
+              else
+                {
+                  optionsRetVal = 0;
+                  errorMessage = global->ingame->complete_text[39];
+                  errorX  = global->halfWidth - text_length(font, errorMessage) / 2;
+                  errorY = global->menuBeginY + 70;
+                }
+            }
+        }
+      // zero means an error occured.
+      // keep running the loop until ESC is pressed or a non-zero value appears
+    }
+  // while (optionsRetVal == 0);
+  while ( (optionsRetVal >> 8 != KEY_ESC) && (optionsRetVal != PLAY_GAME) &&
+          (optionsRetVal != LOAD_GAME) );
+
+  // delete playersOpts;
+  free(playersOpts);
+  if (optionsRetVal >> 8 == KEY_ESC)
+    optionsRetVal = ESC_MENU;
+
+  if (saved_game_names) free(saved_game_names);
+
+  return (optionsRetVal);
+}
+
+void title (GLOBALDATA *global)
+{
+  if (! global->os_mouse) show_mouse(NULL);
+  blit ((BITMAP *) global->title[0], screen, 0, 0, global->halfWidth - 320, global->halfHeight - 240, 640, 480);
+  if (! global->os_mouse) show_mouse (screen);
+  clear_keybuf ();
+
+  //wait_for_input();
+
+  if (! global->os_mouse) show_mouse (NULL);
+}
+
+
+
+
+int menu (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  int bf, bfdd, ban, anclock, lb, updateplayers, done, updaterounds, z, zz;
+  int move_text;
+  int seconds_idle = 0;
+  int current_index = 0, max_index = 7;
+  int my_key = 0;
+  int bn = 0;        // button number
+  int shift_menu = global->halfHeight - 240;
+  if (shift_menu < 0) shift_menu = -shift_menu;
+  else shift_menu = 0;
+
+  move_text = 75;
+  if (global->language == LANGUAGE_RUSSIAN)
+      bn += MENUBUTTONS * 2;
+
+  BUTTON but_play(global, env, global->halfWidth - move_text, global->halfHeight - 235 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
+  bn += 2;
+  BUTTON but_help(global, env, global->halfWidth - move_text, global->halfHeight - 185 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
+  bn += 2;
+  BUTTON but_options(global, env, global->halfWidth - move_text, global->halfHeight - 135 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
+  bn += 2;
+  BUTTON but_players(global, env, global->halfWidth - move_text, global->halfHeight - 85 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
+  bn += 2;
+  BUTTON but_credits(global, env, global->halfWidth - move_text, global->halfHeight - 35 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
+  bn += 2;
+  BUTTON but_quit(global, env, global->halfWidth - move_text, global->halfHeight + 65 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
+  bn += 2;
+  BUTTON but_network(global, env, global->halfWidth - move_text, global->halfHeight + 15 + shift_menu, NULL, (BITMAP*)global->button[bn], (BITMAP*)global->button[bn], (BITMAP*)global->button[bn+1]);
+
+  BUTTON *button[MENUBUTTONS] = {&but_play, &but_help, &but_options,
+                                 &but_players, &but_credits, &but_network, &but_quit
+                                };
+
+  ban = -1;
+  lock_cclock();
+  cclock = global->updateCount = lx = ly = anclock = env->mouseclock = 0;
+  unlock_cclock();
+  lb = updateplayers = done = updaterounds = 0;
+  fi = global->stopwindow = 1;
+  while (!done)
+    {
+      if ( global->Check_Time_Changed() )
+      {
+         seconds_idle++;
+         if (seconds_idle > DEMO_WAIT_TIME)
+         {
+            done = 1;
+            global->wr_lock_command();
+            global->command = GLOBAL_COMMAND_DEMO;
+            global->unlock_command();
+         }
+      }   
+
+      // LINUX_SLEEP;
+      LINUX_REST;
+      while (get_cclock() > 0)
+        {
+          lock_cclock();
+          cclock--;
+          unlock_cclock();
+          zz = 0;
+          for (z = 0; z < MENUBUTTONS; z++)
+            {
+              if (button[z]->isMouseOver ())
+                {
+                  if (ban > -1 && ban != z)
+                    {
+                      button[z]->draw (env->db);
+                      //env->make_update (button[ban]->location.x, button[ban]->location.y, button[ban]->location.w, button[ban]->location.h);
+                    }
+                  ban = z;
+                  zz = 1;
+                  break;
+                }
+            }
+          if (!zz)
+            {
+              bf = 0;
+              bfdd = 1;
+            }
+          if (!lb && mouse_b & 1)
+            env->mouseclock = 0;
+          lb = (mouse_b & 1) ? 1 : 0;
+          if (mouse_b & 1)
+            {
+              global->wr_lock_command();
+              for (z = 0; z < MENUBUTTONS; z++)
+                {
+                  if (button[z]->isPressed ())
+                    {
+                      if (z == 0)
+                        global->command = GLOBAL_COMMAND_PLAY;
+                      else if (z == 1)
+                        global->command = GLOBAL_COMMAND_HELP;
+                      else if (z == 2)
+                        global->command = GLOBAL_COMMAND_OPTIONS;
+                      else if (z == 3)
+                        global->command = GLOBAL_COMMAND_PLAYERS;
+                      else if (z == 4)
+                        global->command = GLOBAL_COMMAND_CREDITS;
+                      else if (z == 5)
+                        global->command = GLOBAL_COMMAND_NETWORK;
+                      else if (z == 6)
+                        global->command = GLOBAL_COMMAND_QUIT;
+                      done = 1;
+                    }
+                }
+              global->unlock_command();
+            }
+          env->mouseclock++;
+          if (env->mouseclock > 10)
+            env->mouseclock = 0;
+        }
+      if (updaterounds)
+        {
+          updaterounds = 0;
+          env->make_update (global->halfWidth + 27, global->halfHeight + 198, 32, 32);
+        }
+      if (! global->os_mouse) show_mouse (NULL);
+      if (fi)
+        {
+          draw_circlesBG (global, env->db, 0, 0, global->screenWidth, global->screenHeight, true);
+          //textout (env->db, font, (char *)"Rounds: ", global->halfWidth - 45, global->halfHeight + 200, BLACK);
+          //draw_sprite_v_flip (env->db, (BITMAP *) global->gfxData.M[6].dat, global->halfWidth - 60, global->halfHeight + 199);
+          //draw_sprite (env->db, (BITMAP *) global->gfxData.M[6].dat, global->halfWidth + 64, global->halfHeight + 199);
+          for (z = 0; z < MENUBUTTONS; z++)
+           {
+              button[z]->draw (env->db);
+              if (z == current_index)
+              {
+                // int delta_width = (global->language == LANGUAGE_RUSSIAN) ? 20 : 0;
+                // if (global->language == LANGUAGE_GERMAN) delta_width = 20;
+                // draw rectangle around selected option
+                rect(env->db, global->halfWidth - move_text - 8, 
+                     global->halfHeight - 240 + (50 * current_index) + shift_menu,
+                     global->halfWidth + move_text + 8, // - delta_width, 
+                     global->halfHeight - 190 + (50 * current_index) + shift_menu, YELLOW);
+              }
+           }
+        }
+      if (ban > -1)
+        {
+          button[ban]->draw (env->db);
+          //env->make_update (button[ban]->location.x, button[ban]->location.y, button[ban]->location.w, button[ban]->location.h);
+        }
+      //rectfill (env->db, global->halfWidth + 27, global->halfHeight + 198, global->halfWidth + 59, global->halfHeight + 210, WHITE);
+      //rect (env->db, global->halfWidth + 27, global->halfHeight + 198, global->halfWidth + 59, global->halfHeight + 210, BLACK);
+      //textprintf_centre (env->db, font, global->halfWidth + 43, global->halfHeight + 200, BLACK, (char *)"%d", global->rounds);
+      if (! global->os_mouse) show_mouse (env->db);
+      env->make_update (mouse_x, mouse_y, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
+      env->make_update (lx, ly, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
+      lx = mouse_x;
+      ly = mouse_y;
+
+      // check for key press
+      if ( keypressed() )
+      {
+          my_key = readkey();
+          my_key = my_key >> 8;
+          fi = 2;
+      }
+      
+      if ( ( my_key == KEY_DOWN ) || (my_key == KEY_S) )
+      {
+         current_index++;
+         if (current_index >= max_index)
+            current_index = 0;
+      }
+      else if ( (my_key == KEY_UP) || (my_key == KEY_W) )
+      {
+         current_index--;
+         if (current_index < 0)
+           current_index = max_index - 1;
+      }
+      else if ( (my_key == KEY_ENTER) || 
+                (my_key == KEY_ENTER_PAD) ||
+                (my_key == KEY_SPACE) )
+      {
+               done = 1;
+               global->wr_lock_command();
+               if (current_index == 0)
+                      global->command = GLOBAL_COMMAND_PLAY;
+               else if (current_index == 1)
+                        global->command = GLOBAL_COMMAND_HELP;
+               else if (current_index == 2)
+                        global->command = GLOBAL_COMMAND_OPTIONS;
+               else if (current_index == 3)
+                        global->command = GLOBAL_COMMAND_PLAYERS;
+               else if (current_index == 4)
+                        global->command = GLOBAL_COMMAND_CREDITS;
+               else if (current_index == 5)
+                        global->command = GLOBAL_COMMAND_NETWORK;
+               else if (current_index == 6)
+                        global->command = GLOBAL_COMMAND_QUIT;
+               global->unlock_command();
+
+      } 
+      else if ( (my_key == KEY_Q) || (my_key == KEY_ESC))
+      {
+          return SIG_QUIT_GAME;
+      }
+      my_key = 0;
+
+      if (fi > 0)
+        {
+          fi--;
+          change (global, env->db);
+        }
+      if (global->close_button_pressed) return SIG_QUIT_GAME;
+      if ( (global->update_string) && (global->update_string[0]) )
+      {  
+       textout_centre_ex (env->db, font, global->update_string, 
+                          global->halfWidth - 20, 500, WHITE, -1);
+       env->make_update(50, 450, 300, 50);
+      }
+      if (global->client_message)
+      {
+        textout_centre_ex(env->db, font, global->client_message,
+                          global->halfWidth - 20, 520, WHITE, -1);
+        env->make_update(50, 450, 300, 100);
+      }
+      env->do_updates ();
+    }
+  clear_keybuf ();
+  return SIG_OK;
+}
+
+void draw_text_in_box (ENVIRONMENT *env, BOX *region, char *text)
+{
+  char buffer[1024];
+  unsigned int lineBegin;
+  int lastSpace = 0;
+  int lineCount;
+  int charCount;
+  int buffCount ;
+
+  rectfill (env->db, region->x, region->y, region->w, region->h,
+            makecol (0,0,128));
+  rect     (env->db, region->x, region->y, region->w, region->h,
+            makecol (128,128,255));
+
+  lineBegin = 0;
+  lineCount = 0;
+  while (lineBegin < strlen (text))
+    {
+      charCount = 0;
+      buffCount = 0;
+      do
+        {
+          buffer[buffCount] = text[lineBegin + charCount];
+          buffer[buffCount+1] = 0;
+          if (buffer[buffCount] == ' ')
+            {
+              lastSpace = 0;
+            }
+          else if (buffer[buffCount] == '\n')
+            {
+              lineCount++;
+              charCount++;
+              break;
+            }
+          lastSpace++;
+          buffCount++;
+          charCount++;
+        }
+      while (text[lineBegin + charCount] && (text_length (font, buffer) < region->w - 20));
+      if ((lastSpace > 0) && (text_length (font, buffer) >= region->w - 20))
+        {
+          charCount -= lastSpace - 1;
+          buffer[buffCount - lastSpace] = 0;
+        }
+      else
+        {
+          buffer[buffCount] = 0;
+        }
+      textout_ex (env->db, font, buffer, region->x + 5,
+                  region->y + (lineCount * text_height (font)) + 5, WHITE, -1);
+      lineBegin = lineBegin + charCount;
+      charCount = 0;
+      lineCount++;
+    }
+  env->make_update (region->x, region->y, region->w, region->h);
+}
+
+void draw_buystuff(GLOBALDATA *global, ENVIRONMENT *env, PLAYER *pl)
+{
+  int z;
+  env->make_update (0, 0, global->screenWidth, global->screenHeight);
+  if (! global->os_mouse) show_mouse (NULL);
+
+  draw_circlesBG (global, env->db, 0, 0, global->screenWidth, global->screenHeight, false);
+  draw_sprite (env->db, (BITMAP *) global->misc[DONE_IMAGE], global->halfWidth - 100, global->screenHeight - 50);
+  draw_sprite (env->db, (BITMAP *) global->misc[FAST_UP_ARROW_IMAGE], global->screenWidth - STUFF_BAR_WIDTH - 30, global->halfHeight - 50);
+  draw_sprite (env->db, (BITMAP *) global->misc[UP_ARROW_IMAGE], global->screenWidth - STUFF_BAR_WIDTH - 30, global->halfHeight - 25);
+  draw_sprite (env->db, (BITMAP *) global->misc[DOWN_ARROW_IMAGE], global->screenWidth - STUFF_BAR_WIDTH - 30, global->halfHeight);
+  draw_sprite (env->db, (BITMAP *) global->misc[FAST_DOWN_ARROW_IMAGE], global->screenWidth - STUFF_BAR_WIDTH - 30, global->halfHeight + 25);
+  drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
+  env->current_drawing_mode = DRAW_MODE_TRANS;
+
+  for (z = 0; z < global->halfWidth - 200; z++)
+    {
+      set_trans_blender (0, 0, 0, (int)((double)((double)z / (global->halfWidth - 200)) * 240) + 15);
+      vline (env->db, z, 0, 29, pl->color);
+    }
+
+  for (z = 0; z < global->halfWidth - 200; z++)
+    {
+      set_trans_blender (0, 0, 0, (int)((double)((double)z / (global->halfWidth - 200)) * 240) + 15);
+      vline (env->db, (global->screenWidth-1) - z, 0, 29, pl->color);
+    }
+
+  solid_mode ();
+  env->current_drawing_mode = DRAW_MODE_SOLID;
+  textout_ex (env->db, font, global->ingame->complete_text[14], 20, 420, WHITE, -1);
+  textout_ex(env->db, font, global->ingame->complete_text[15], 20, 450, WHITE, -1);
+  textout_ex(env->db, font, global->ingame->complete_text[16], 20, 465, WHITE, -1);
+
+}
+
+int btps;
+void draw_weapon_list(GLOBALDATA *global, ENVIRONMENT *env, PLAYER *pl, int *trolley, int scroll, int pressed)
+{
+  int slot, zzz;
+  double tempbtps = (global->screenHeight - 55) / STUFF_BAR_HEIGHT;
+  int font_diff;
+
+  (font == global->unicode) ? font_diff = 8 : font_diff = 0;
+
+  // To be sure it rounds down
+  btps = (int)tempbtps;
+  if (tempbtps < btps)
+    btps--;
+
+
+  // go through all items and draw them on the screen with
+  // the amount of items in the trolly
+  for (slot = 1, zzz = scroll; (slot < btps) && (zzz < env->numAvailable); zzz++)
+    {
+      int itemNum = env->availableItems[zzz];
+      draw_sprite (env->db, (BITMAP *)global->gfxData.stuff_bar[(pressed == itemNum)?1:0], global->screenWidth - STUFF_BAR_WIDTH, slot * STUFF_BAR_HEIGHT);
+
+      draw_sprite(env->db, (BITMAP *) global->gfxData.stuff_icon_base, global->screenWidth - STUFF_BAR_WIDTH, (slot * STUFF_BAR_HEIGHT));
+      draw_sprite(env->db, (BITMAP *) global->stock[itemNum], global->screenWidth - STUFF_BAR_WIDTH, (slot * STUFF_BAR_HEIGHT) - 5);
+      env->make_update (global->screenWidth - STUFF_BAR_WIDTH, slot * STUFF_BAR_HEIGHT, STUFF_BAR_WIDTH, STUFF_BAR_HEIGHT + 5);
+
+      if (itemNum >= WEAPONS)  	/* Items part */
+        {
+
+          textout_ex (env->db, font,
+                      item[itemNum - WEAPONS].name, global->screenWidth - STUFF_BAR_WIDTH + 45, (slot * STUFF_BAR_HEIGHT) + 5 - font_diff, BLACK, -1);
+          // Amount in inventory
+          textprintf_ex (env->db, font, global->screenWidth - STUFF_BAR_WIDTH + 45, (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, BLACK, -1, "%s: %d", global->ingame->complete_text[40], pl->ni[itemNum - WEAPONS]);
+          // Anything in the trolley
+          if (trolley[itemNum] != 0)
+            {
+              int textCol;
+              if (trolley[itemNum] > 0)
+                textCol = makecol (255,255,0);
+              else
+                textCol = makecol (176,0,0);
+              textprintf_ex (env->db, font, global->screenWidth - STUFF_BAR_WIDTH + 45 + text_length (font, "Qty. in inventory: ddd"), (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, textCol, -1, "%+d", trolley[itemNum]);
+            }
+          sprintf (buf, "$%s", Add_Comma( item[itemNum - WEAPONS].cost ) );
+          textout_ex (env->db, font, buf,
+                      global->screenWidth - 45 - text_length (font, buf), (slot * STUFF_BAR_HEIGHT) + 5 - font_diff, BLACK, -1);
+          sprintf (buf, "for %d", item[itemNum - WEAPONS].amt);
+          textout_ex (env->db, font, buf,
+                      global->screenWidth - 45 - text_length (font, buf), (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, BLACK, -1);
+        }
+      else  			/* Weapons part */
+        {
+
+          textout_ex (env->db, font, weapon[itemNum].name, global->screenWidth - STUFF_BAR_WIDTH + 45, (slot * STUFF_BAR_HEIGHT) + 5 - font_diff, BLACK, -1);
+          textprintf_ex (env->db, font, global->screenWidth - STUFF_BAR_WIDTH + 45, (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, BLACK, -1, "%s: %d", global->ingame->complete_text[40], pl->nm[itemNum]);
+          // Anything in the trolley
+          if (trolley[itemNum] != 0)
+            {
+              int textCol;
+              if (trolley[itemNum] > 0)
+                textCol = makecol (255,255,0);
+              else
+                textCol = makecol (176,0,0);
+              textprintf_ex (env->db, font, global->screenWidth - STUFF_BAR_WIDTH + 45 + text_length (font, "Qty. in inventory: ddd"), (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, textCol, -1, "%+d", weapon[itemNum].delay ? trolley[itemNum] / weapon[itemNum].delay : trolley[itemNum]);
+            }
+          sprintf (buf, "$%s", Add_Comma( weapon[itemNum].cost ));
+          textout_ex (env->db, font, buf,
+                      global->screenWidth - 45 - text_length (font, buf), (slot * STUFF_BAR_HEIGHT) + 5 - font_diff, BLACK, -1);
+          sprintf (buf, "for %d", weapon[itemNum].amt);
+          textout_ex (env->db, font, buf, global->screenWidth - 45 - text_length (font, buf), (slot * STUFF_BAR_HEIGHT) + (STUFF_BAR_HEIGHT/2) - font_diff, BLACK, -1);
+        }
+      slot++;
+    }
+
+
+}
+
+bool buystuff (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  int pl, done; 
+  int updatew[THINGS];
+  int updatename, pressed, scroll, lb, lastMouse_b;
+  int hoverOver = 0, z, zz, zzz;
+  char buf[50];
+  int mouse_wheel_previous, mouse_wheel_current;
+  int performed_save_game = FALSE;
+  char description[1024];
+  BOX area = {20, 60, 300, 400};
+  int my_cclock;
+  int item_index = 1;
+  int my_key = 0;
+  int cost, amt, inInv;
+  int buy_count = 0;
+
+  strcpy(description, " ");
+  //avoid compiler warning via initalize
+  lastMouse_b = 0;
+
+  // check starting position of the mouse wheel
+  mouse_wheel_previous = mouse_z;
+
+  lock_cclock();
+  global->updateCount = cclock = lb = env->mouseclock = 0;
+  unlock_cclock();
+  fi = global->stopwindow = updatename = scroll = 1;
+
+  // before we do anything else, put a cap on money
+  for (z = 0; z < global->numPlayers; z++)
+  {
+     if (global->players[z]->money > 1000000000)
+            global->players[z]->money = 1000000000;
+     if (global->players[z]->money < 0)
+            global->players[z]->money = 0;
+  }
+
+ 
+  if (global->bIsGameLoaded)
+    // after the first shopping loop the game isn't fresh anymore
+#ifdef DEBUG
+    {
+      cout << endl << "===========================================" << endl;
+      cout << "==          New or Loaded Game!          ==" << endl;
+      cout << "===========================================" << endl << endl;
+#endif // DEBUG
+      global->bIsGameLoaded = false;
+#ifdef DEBUG
+    }
+#endif // DEBUG
+  else if (global->divide_money)
+    {
+      // This only applies if this is not a fresh/loaded game
+      // And if players want to divide the money
+      int iJediMoney = 0;
+      int iJediCount = 0;
+      int iSithMoney = 0;
+      int iSithCount = 0;
+      int iTeamFee	 = 0;
+      
+      for (z = 0; z < global->numPlayers; z++)
+        {
+          /*
+          if (global->players[z]->money > 1000000000)
+            global->players[z]->money = 1000000000;
+          if (global->players[z]->money < 0)
+            global->players[z]->money = 0;
+          */
+          // Sum up team money:
+          if (global->players[z]->team == TEAM_JEDI)
+            {
+              iTeamFee = (int)((double)global->players[z]->money * 0.25);
+              if (iTeamFee > MAX_TEAM_AMOUNT)
+                iTeamFee	=	MAX_TEAM_AMOUNT;
+              iJediMoney += iTeamFee;
+              global->players[z]->money -= iTeamFee;
+              iJediCount++;
+            }
+          if (global->players[z]->team == TEAM_SITH)
+            {
+              iTeamFee = (int)((double)global->players[z]->money * 0.25);
+              if (iTeamFee > MAX_TEAM_AMOUNT)
+                iTeamFee	=	MAX_TEAM_AMOUNT;
+              iSithMoney += iTeamFee;
+              global->players[z]->money -= iTeamFee;
+              iSithCount++;
+            }
+        }
+#ifdef DEBUG
+      cout << endl << "Jedi Count: " << iJediCount << " - SitH Count: " << iSithCount << endl;
+#endif // DEBUG
+      // Now apply the team money:
+      if (iJediCount || iSithCount)
+        {
+#ifdef DEBUG
+          if (iJediCount)
+            printf( (char *)"The Jedi summed up a pool of %13d bucks!\n", iJediMoney);
+          if (iSithCount)
+            printf( (char *)"The Sith summed up a pool of %13d bucks!\n", iSithMoney);
+#endif // DEBUG
+          if (iJediCount)
+            iJediMoney = (int)(((double)iJediMoney * 0.90) / (double)iJediCount);
+          if (iSithCount)
+            iSithMoney = (int)(((double)iSithMoney * 0.90) / (double)iSithCount);
+#ifdef DEBUG
+          if (iJediCount)
+            printf( (char *)"Every Jedi will receive %10d credits out of the pool!\n", iJediMoney);
+          if (iSithCount)
+            printf( (char *)"Every Sith will receive %10d credits out of the pool!\n", iSithMoney);
+#endif // DEBUG
+          for (z = 0; z < global->numPlayers; z++)
+            {
+              if (global->players[z]->team == TEAM_JEDI)
+                global->players[z]->money	+=	iJediMoney;
+              if (global->players[z]->team == TEAM_SITH)
+                global->players[z]->money	+=	iSithMoney;
+            }
+        }
+    }
+
+  env->generateAvailableItemsList ();
+  int iMaxBoost = 0;
+  int iMaxScore = 0; 
+  for (pl = 0; pl < global->numPlayers; pl++)
+    {
+      int iCurrentBoostLevel =	global->players[pl]->getBoostValue();
+      if (iCurrentBoostLevel > iMaxBoost)
+        iMaxBoost	=	iCurrentBoostLevel;
+      if (global->players[pl]->score > iMaxScore)
+        iMaxScore = global->players[pl]->score;
+    }
+
+  for (pl = 0; pl < global->numPlayers; pl++)
+    {
+      int money = global->players[pl]->money;
+      int trolley[THINGS];
+      memset (trolley, 0, sizeof (int) * THINGS);
+
+      //have computer players buy stuff
+      if ( (int) global->players[pl]->type != HUMAN_PLAYER)
+        {
+          int pressed = 0;
+          int moneyToSave = 0;	// How much money will the player save?
+          int numDmgWeaps = 0;	// How many damage dealing weapons apart from small missiles do they have=
+          int numPara			=	0;	// how many parachutes do we have?
+          int numProj			=	0;	// How many slick/dimpled projectiles do we have?
+#ifdef DEBUG
+          cout << "(" << global->players[pl]->getName() << ") Starting to buy:" << endl;
+          if (global->players[pl]->defensive < -0.9) cout << "(True Offensive)" << endl;
+          if ((global->players[pl]->defensive >=-0.9) && (global->players[pl]->defensive < -0.75)) cout << "(Very Offensive)" << endl;
+          if ((global->players[pl]->defensive >=-0.75) && (global->players[pl]->defensive < -0.25)) cout << "(Offensive)" << endl;
+          if ((global->players[pl]->defensive >=-0.25) && (global->players[pl]->defensive < 0.00)) cout << "(Slightly Offensive)" << endl;
+          if (global->players[pl]->defensive == 0.0)	cout << "(Neutral)" << endl;
+          if ((global->players[pl]->defensive >0.0) && (global->players[pl]->defensive <= 0.25)) cout << "(Slightly Defensive)"<< endl;
+          if ((global->players[pl]->defensive >0.25) && (global->players[pl]->defensive <= 0.75)) cout << "(Defensive)" << endl;
+          if ((global->players[pl]->defensive >0.75) && (global->players[pl]->defensive <= 0.9)) cout << "(Very Defensive)" << endl;
+          if (global->players[pl]->defensive > 0.9)	cout << "(True Defensive)" << endl;
+          cout << "Inventory:" << endl <<  "----------" << endl;
+          for (int i = 1; i < WEAPONS; i++)
+            {
+              if (global->players[pl]->nm[i])
+                cout << global->players[pl]->nm[i] << " x " << weapon[i].name << endl;
+            }
+          cout << " - - - - - - -" << endl;
+          for (int i = 1; i < ITEMS; i++)
+            {
+              if (global->players[pl]->ni[i])
+                cout << global->players[pl]->ni[i] << " x " << item[i].name << endl;
+            }
+          cout << "----------" << endl;
+#endif // DEBUG
+          // moneysaving will be made possible when:
+          // 1. It's not the first three rounds
+          // 2. It's not the last 5 rounds
+          // and, dynamically:
+          // 3. We have at least 10 parachutes  or no gravity
+          // 4. We have at least 5 damage dealing (not small missile) weapons
+          // 5. We have a sum of 50 slick/dimpled projectiles
+
+          if	( (global->currentround > 5)
+               && ( ( (int) global->rounds - global->currentround) > 3))
+            {
+              moneyToSave	=	global->players[pl]->getMoneyToSave();
+#ifdef DEBUG
+              cout << "Maximum Money to save: " << moneyToSave << " (I have: " << global->players[pl]->money << ")" << endl;
+#endif //DEBUG
+            }
+#ifdef DEBUG
+          else
+            cout << "No money to save this round!!!" << endl;
+#endif // DEBUG
+          // Check for a minimum of damage dealing weapons and parachutes, then buy until moneyToSave is reached
+          buy_count = 0;
+          do
+            {
+              numPara			=	global->players[pl]->ni[ITEM_PARACHUTE];
+              numProj			= global->players[pl]->ni[ITEM_SLICKP] + global->players[pl]->ni[ITEM_DIMPLEP];
+              numDmgWeaps	=	0;
+
+              for (int i = 1; i < WEAPONS; i++)
+                {
+                  // start from 1, as 0 is the small missile
+                  if (weapon[i].damage > 0)
+                    numDmgWeaps += global->players[pl]->nm[i];
+                }
+
+              if	( (global->players[pl]->money > moneyToSave)
+                   || ( (numPara			< 10) && (env->landSlideType > LANDSLIDE_NONE))
+                   || (numDmgWeaps	<	8)
+                   || (numProj			< 50))
+               {
+                pressed = global->players[pl]->chooseItemToBuy (iMaxBoost);
+               }
+              else
+                pressed	=	-1;
+
+#ifdef DEBUG
+              if (pressed > -1)
+                {
+                  cout << "I have bought: ";
+                  if (pressed < WEAPONS)
+                    cout << weapon[pressed].name;
+                  else
+                    cout << item[pressed - WEAPONS].name;
+                  cout << " (" << global->players[pl]->money << " bucks left)" << endl;
+                }
+              else
+                cout << "Finished, with " << global->players[pl]->money << " Credits left!" << endl;
+#endif // DEBUG
+            buy_count++;
+            }
+          while ( (pressed != -1) && (buy_count < 100) );
+
+#ifdef DEBUG
+          cout << "============================================" << endl << endl;
+#endif //DEBUG
+          continue;  //go to next player
+        }        // end of AI player
+
+      done = 0;
+      updatename = scroll = 1;
+      pressed = -1;
+
+      draw_buystuff (global, env, global->players[pl]);
+
+      for (z = 0; z < THINGS; z++)
+        updatew[z] = 1;
+      while (!done)
+        {
+
+          LINUX_SLEEP;
+          my_cclock = CLOCK_MAX;
+          while (my_cclock > 0)
+            {
+              LINUX_SLEEP;
+              if (global->close_button_pressed)
+                {
+                  clear_keybuf();
+                  return false;
+                }
+              my_cclock--;
+              if (!lb && mouse_b & 1 && mouse_x >= global->halfWidth - 100 && mouse_x < global->halfWidth + 100 && mouse_y >= global->screenHeight - 50 && mouse_y < global->screenHeight - 25)
+                done = 1;
+              if (!lb && mouse_b & 1)
+                env->mouseclock = 0;
+              lb = (mouse_b & 1) ? 1 : 0;
+
+              my_key = 0;
+              //Keyboard control
+              if ( keypressed() )
+              {
+                 my_key = readkey();
+                 my_key = my_key >> 8;
+              }
+
+              if  ( my_key == KEY_UP || my_key == KEY_W) // && (scroll > 1) 
+                //  && (!env->mouseclock))
+                {
+                  if (item_index > 1)
+                     item_index--;
+                  if (scroll > 1)
+                     scroll--;
+                  for (z = 0; z < THINGS; z++)
+                    updatew[z] = 1;
+                }
+              if (my_key == KEY_PGUP || my_key == KEY_R) // && (scroll > 1)
+                  // && (!env->mouseclock))
+                {
+                  item_index -= btps / 2;
+                  if (item_index < 1)
+                     item_index = 1;
+                  scroll -= btps / 2;
+                  if (scroll < 1)
+                    scroll = 1;
+                  for (z = 0; z < THINGS; z++)
+                    updatew[z] = 1;
+                }
+
+              if (my_key == KEY_DOWN || my_key == KEY_S)
+              //    && (scroll <= env->numAvailable - btps)
+              //    && (!env->mouseclock))
+                {
+                  if (item_index < (env->numAvailable - 1))
+                     item_index++;
+                 if (scroll <= env->numAvailable - btps)
+                     scroll++;
+                  for (z = 0; z < THINGS; z++)
+                    updatew[z] = 1;
+                }
+              if ((my_key == KEY_PGDN || my_key == KEY_F)
+                  && (scroll <= env->numAvailable - btps + 1) )
+                //  && (!env->mouseclock))
+                {
+                  item_index += btps / 2;
+                  if (item_index > env->numAvailable - btps)
+                     item_index = env->numAvailable - btps;
+                  scroll += btps / 2;
+                  if (scroll > env->numAvailable - btps + 1)
+                    scroll = env->numAvailable - btps + 1;
+                  for (z = 0; z < THINGS; z++)
+                    updatew[z] = 1;
+                }
+
+              // make sure the selected item is on the visible screen
+              if (item_index < scroll)
+                 item_index = scroll;
+              else if ( item_index > (scroll + btps + 3) )
+                 item_index = scroll + btps + 3;
+
+              // buy or sell an item
+              if (my_key == KEY_RIGHT || my_key == KEY_D) 
+              {
+                    pressed = env->availableItems[item_index];
+                    if (pressed >= WEAPONS)
+                    {
+                      cost = item[pressed - WEAPONS].cost;
+                      amt = item[pressed - WEAPONS].amt;
+                      inInv = global->players[pl]->ni[pressed - WEAPONS];
+                    }
+                  else
+                    {
+                      cost = weapon[pressed].cost;
+                      amt = weapon[pressed].amt;
+                      inInv = global->players[pl]->nm[pressed];
+                    }
+                     if ((money >= cost)
+                          && ( (inInv + trolley[pressed]) < (999 - amt)))
+                        {
+                          if (trolley[pressed] <= -amt)
+                            {
+                              if (global->sellpercent > 0.01)
+                                {
+                                  money -= (int)(cost * global->sellpercent);
+                                  trolley[pressed] += amt;
+                                  updatename = 1;
+                                }
+                            }
+                          else
+                            {
+                              money -= cost;
+                              trolley[pressed] += amt;
+                              updatename = 1;
+                              if (inInv + trolley[pressed] > 999)
+                                trolley[pressed] = 999;
+                            }
+                        }
+                   pressed = -1;
+              }         // end of buying
+
+              if ( my_key == KEY_LEFT || my_key == KEY_A)
+              {
+                  pressed = env->availableItems[item_index];
+                    if (pressed >= WEAPONS)
+                    {
+                      cost = item[pressed - WEAPONS].cost;
+                      amt = item[pressed - WEAPONS].amt;
+                      inInv = global->players[pl]->ni[pressed - WEAPONS];
+                    }
+                  else
+                    {
+                      cost = weapon[pressed].cost;
+                      amt = weapon[pressed].amt;
+                      inInv = global->players[pl]->nm[pressed];
+                    }
+                    if (inInv + trolley[pressed] >= amt)
+                    {
+                          if (trolley[pressed] >= amt)
+                          {
+                              money += cost;
+                              trolley[pressed] -= amt;
+                              updatename = 1;
+                          }
+                          else
+                          {
+                              if (global->sellpercent > 0.01)
+                                {
+                                  money += (int)(cost * global->sellpercent);
+                                  trolley[pressed] -= amt;
+                                  updatename = 1;
+                                }
+                          }
+                     }
+                   pressed = -1;
+              }           // end of selling
+
+
+              // check for adding or removing rounds
+              if ( (my_key == KEY_PLUS_PAD) || (my_key == KEY_EQUALS) )
+                {
+                  if ( (global->rounds < 999) && (! env->mouseclock) )
+                    {
+                      global->rounds++;
+                      global->currentround++;
+                      updatename = 1;
+                    }
+                }
+              if ( (my_key == KEY_MINUS_PAD) || (my_key == KEY_MINUS) )
+                {
+                  if ( (global->rounds > 1) && (global->currentround > 1)
+                       && (! env->mouseclock) )
+                    {
+                      global->rounds--;
+                      global->currentround--;
+                      updatename = 1;
+                    }
+                }
+
+              // check for saving the game
+              if ( my_key == KEY_F10 )
+                {
+                  int status;
+                  if (! performed_save_game)
+                    {
+                      status = Save_Game(global, env);
+                      performed_save_game = TRUE;
+                      if (status)
+                        snprintf(description, 64, "%s \"%s\".", global->ingame->complete_text[17], global->game_name);
+                      else
+                        strcpy(description, global->ingame->complete_text[41]);
+                      draw_text_in_box (env, &area, description);
+                    }
+                }
+
+              if ( my_key == KEY_ENTER)
+                 done = TRUE;
+
+              // Mouse control
+
+              // check mouse wheel
+              mouse_wheel_current = mouse_z;
+              if (mouse_wheel_current < mouse_wheel_previous)
+                {
+                  scroll++;
+                  if (scroll > env->numAvailable - btps + 1)
+                    scroll = env->numAvailable - btps + 1;
+                  if (scroll > item_index)
+                     item_index = scroll;
+                  for (z = 0; z < THINGS; z++)
+                    updatew[z] = 1;
+                }
+              else if (mouse_wheel_current > mouse_wheel_previous)
+                {
+                  scroll--;
+                  if (scroll < 1)
+                    scroll = 1;
+                  if (item_index > scroll + btps)
+                     item_index = scroll + btps - 3;
+                  for (z = 0; z < THINGS; z++)
+                    updatew[z] = 1;
+                }
+              mouse_wheel_previous = mouse_wheel_current;
+
+
+              if (mouse_x >= global->screenWidth - STUFF_BAR_WIDTH && mouse_x < global->screenWidth)
+                {
+                  int newlyOver;
+                  zz = 0;
+                  for (z = 1, zzz = scroll; z < btps; z++, zzz++)
+                    {
+                      if (mouse_y >= z * STUFF_BAR_HEIGHT && mouse_y < (z * STUFF_BAR_HEIGHT) + 30)
+                        {
+                          zz = 1;
+                          break;
+                        }
+                    }
+                  if (zz)
+                    newlyOver = env->availableItems[zzz];
+                  else
+                    newlyOver = -1;
+                  if (hoverOver != newlyOver)
+                    {
+                      // char description[1024];
+                      // BOX area = {20, 60, 300, 400};
+
+                      if (newlyOver > -1)
+                        {
+                          if (newlyOver < WEAPONS)
+                            {
+                              WEAPON *weap = &weapon[newlyOver];
+                              sprintf (description, "Radius: %d\nYield: %ld\n\n%s",
+                                       weap->radius, calcTotalPotentialDamage (newlyOver) * weap->spread, weap->description);
+                            }
+                          else
+                            {
+                              int itemNum = newlyOver - WEAPONS;
+                              ITEM *it = &item[itemNum];
+                              if (itemNum >= ITEM_VENGEANCE && itemNum <= ITEM_FATAL_FURY)
+                                {
+                                  sprintf (description, "Potential Damage: %ld\n\n%s",
+                                           calcTotalPotentialDamage ((int)it->vals[0]) * (int)it->vals[1],
+                                           it->description);
+                                }
+                              else
+                                {
+                                  sprintf (description, "%s", it->description);
+                                }
+                            }
+                        }
+                      else
+                        {
+                          description[0] = 0;
+                        }
+                      hoverOver = newlyOver;
+
+                      draw_text_in_box (env, &area, description);
+                    }
+                }
+              if (mouse_b & 1 && !env->mouseclock)
+                {
+                  int scrollArrowPos = global->screenWidth - STUFF_BAR_WIDTH - 30;
+                  if (mouse_x >= scrollArrowPos && mouse_x < scrollArrowPos + 24)
+                    {
+                      if ((mouse_y >= global->halfHeight - 50 && mouse_y < global->halfHeight - 25) && (scroll > 1))
+                        {
+                          scroll -= btps / 2;
+                          if (scroll < 1)
+                            scroll = 1;
+                          for (z = 0; z < THINGS; z++)
+                            updatew[z] = 1;
+                        }
+                      if ((mouse_y >= global->halfHeight - 24 && mouse_y < global->halfHeight) && (scroll > 1))
+                        {
+                          scroll--;
+                          for (z = 0; z < THINGS; z++)
+                            updatew[z] = 1;
+                        }
+                      if ((mouse_y >= global->halfHeight + 1 && mouse_y < global->halfHeight + 25) && (scroll <= env->numAvailable - btps))
+                        {
+                          scroll++;
+                          for (z = 0; z < THINGS; z++)
+                            updatew[z] = 1;
+                        }
+                      if ((mouse_y >= global->halfHeight + 25 && mouse_y < global->halfHeight + 50) && (scroll <= env->numAvailable - btps + 1))
+                        {
+                          scroll += btps / 2;
+                          if (scroll > env->numAvailable - btps + 1)
+                            scroll = env->numAvailable - btps + 1;
+                          for (z = 0; z < THINGS; z++)
+                            updatew[z] = 1;
+                        }
+                    }
+                    if (item_index < scroll)
+                       item_index = scroll;
+                    else if ( item_index > (scroll + btps) )
+                       item_index = scroll + btps - 3;
+                }
+              if (mouse_b & 1 || mouse_b & 2)
+                {
+                  int itemButtonClicked = 0;
+                  for (int buttonCount = 1, currItem = scroll; buttonCount < btps; buttonCount++, currItem++)
+                    {
+                      if (mouse_x >= global->screenWidth - STUFF_BAR_WIDTH && mouse_x < global->screenWidth && mouse_y >= buttonCount * STUFF_BAR_HEIGHT && mouse_y < (buttonCount * STUFF_BAR_HEIGHT) + 30)
+                        {
+                          itemButtonClicked = 1;
+                          // Remember which button was pressed
+                          if (pressed > -1)
+                            updatew[pressed] = 1;
+                          pressed = env->availableItems[currItem];
+                          updatew[env->availableItems[currItem]] = 1;
+                        }
+                    }
+                  if (!itemButtonClicked)
+                    {
+                      if (pressed > -1)
+                        updatew[pressed] = 1;
+                      pressed = -1;
+                    }
+                }
+              if (pressed > -1 && !(mouse_b & 1 || mouse_b & 2))
+                {
+                  // Cost, amount and in-inventory amount
+                  // of pressed item
+                  // int cost,amt,inInv;
+                  bool control_key = false;
+                  updatew[pressed] = 1;
+
+                  if ( ( key[KEY_LCONTROL] ) || ( key[KEY_RCONTROL] ) )
+                    control_key = true;
+
+                  if (pressed > WEAPONS - 1)
+                    {
+                      cost = item[pressed - WEAPONS].cost;
+                      amt = item[pressed - WEAPONS].amt;
+                      inInv = global->players[pl]->ni[pressed - WEAPONS];
+                    }
+                  else
+                    {
+                      cost = weapon[pressed].cost;
+                      amt = weapon[pressed].amt;
+                      inInv = global->players[pl]->nm[pressed];
+                    }
+
+                  if (control_key)
+                    {
+                      cost *= 10;
+                      amt *= 10;
+                    }
+
+                  if (lastMouse_b & 2)
+                    {
+                      if (inInv + trolley[pressed] >= amt)
+                        {
+                          if (trolley[pressed] >= amt)
+                            {
+                              money += cost;
+                              trolley[pressed] -= amt;
+                              updatename = 1;
+                            }
+                          else
+                            {
+                              if (global->sellpercent > 0.01)
+                                {
+                                  money += (int)(cost * global->sellpercent);
+                                  trolley[pressed] -= amt;
+                                  updatename = 1;
+                                }
+                            }
+                        }
+                    }
+                  else
+                    {
+                      if ((money >= cost)
+                          && ( (inInv + trolley[pressed]) < (999 - amt)))
+                        {
+                          if (trolley[pressed] <= -amt)
+                            {
+                              if (global->sellpercent > 0.01)
+                                {
+                                  money -= (int)(cost * global->sellpercent);
+                                  trolley[pressed] += amt;
+                                  updatename = 1;
+                                }
+                            }
+                          else
+                            {
+                              money -= cost;
+                              trolley[pressed] += amt;
+                              updatename = 1;
+                              if (inInv + trolley[pressed] > 999)
+                                trolley[pressed] = 999;
+                            }
+                        }
+                    }
+                  pressed = -1;
+                }
+              env->mouseclock++;
+              if (env->mouseclock > 5)
+                env->mouseclock = 0;
+              lastMouse_b = mouse_b;
+            }
+          if (! global->os_mouse) show_mouse (NULL);
+          if (fi)
+            {
+              for (int thing = 0; thing < THINGS; thing++)
+                updatew[thing] = 1;
+            }
+          if (updatename)
+            {
+              updatename = 0;
+              // env->make_update (global->halfWidth - 315, 0, 400, 30);
+              env->make_update (global->halfWidth - 315, 0, global->screenWidth - 1, 30);
+              draw_sprite (env->db, (BITMAP *) global->gfxData.stuff_bar[0], global->halfWidth - 200, 0);
+              textprintf_ex (env->db, font, global->halfWidth - 190, 5, BLACK, -1, "%s %d: %s", global->ingame->complete_text[10], pl + 1, global->players[pl]->getName ());
+              // textprintf_ex (env->db, font, global->halfWidth - 190, 17, BLACK, -1, "Money: $%d", money);
+              textprintf_ex(env->db, font, global->halfWidth - 190, 17, BLACK, -1, "%s: $%s", global->ingame->complete_text[11], Add_Comma(money));
+              sprintf (buf, "%s: %d/%d", global->ingame->complete_text[12], (int)(global->rounds - global->currentround) + 1, (int)global->rounds);
+              textout_ex (env->db, font, buf, global->halfWidth + 170 - text_length (font, buf), 5, BLACK, -1);
+              sprintf (buf, "%s: %d", global->ingame->complete_text[13], global->players[pl]->score);
+              textout_ex (env->db, font, buf, global->halfWidth + 155 - text_length (font, buf), 17, BLACK, -1);
+            }
+
+          draw_weapon_list(global, env, global->players[pl], trolley, scroll, (pressed < 0) ? env->availableItems[item_index] : pressed );
+          env->make_update (mouse_x, mouse_y, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
+          env->make_update (lx, ly, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
+          lx = mouse_x;
+          ly = mouse_y;
+          if (! global->os_mouse) show_mouse (env->db);
+          if (fi)
+            {
+              change (global, env->db);
+              fi = 0;
+            }
+
+          else
+            env->do_updates ();
+        }
+      for (int tItem = 0; tItem < WEAPONS; tItem++)
+        global->players[pl]->nm[tItem] += trolley[tItem];
+      for (int tItem = WEAPONS; tItem < THINGS; tItem++)
+        global->players[pl]->ni[tItem - WEAPONS] += trolley[tItem];
+      global->players[pl]->money = money;
+    }
+  // clear_keybuf ();
+
+  for (z = 0; z < global->numPlayers; z++)
+    {
+      int iMoney		= global->players[z]->money;
+      int iInterest = 0;
+      float fIntPerc= 0.0;
+      int iLevel		=	0;
+      int iInterSum = 0; // The summed up interest
+#ifdef DEBUG
+      cout << endl << "======================================================" << endl;
+      printf( (char *)"%2d.: %s enters the bank to get interest:\n", (z+1), global->players[z]->getName());
+      printf( (char *)"     Starting Account: %10d\n", global->players[z]->money);
+      cout << "------------------------------------------------------" << endl;
+#endif // DEBUG
+      while (iMoney && (iLevel < 5))
+        {
+          // Enter next level
+          iLevel++;
+          fIntPerc	=	(global->interest - 1.0) / iLevel;
+          iInterest = (int)((float)iMoney * fIntPerc);
+          // The limit is only applicable on the first four levels, in the fifth level interest is fully applied!
+          if ((iInterest > MAX_INTEREST_AMOUNT) && (iLevel < 5))
+            iInterest = MAX_INTEREST_AMOUNT;
+          // Now sum the interest up and substract the counted money!
+          iInterSum	+=	iInterest;
+          iMoney		-=	(int)((float)iInterest / fIntPerc);
+#ifdef DEBUG
+          printf( (char *)"     Level %1d:  %8d credits are rated,\n", iLevel, (int)(iInterest / fIntPerc));
+          printf( (char *)"     Interest: %8d credits. (%5.2f%%)\n", iInterest, (fIntPerc * 100));
+#endif // DEBUG
+          // To get rid of (possible) rounding errors, add a security check:
+          if ((iMoney < (4 * iLevel)) || (iInterest < 1))
+            iMoney = 0; // With less there won't be any more interest anyway!
+#ifdef DEBUG
+          printf( (char *)"     Unrated : %8d credits left.\n", iMoney);
+#endif // DEBUG
+        }
+      // Now giv'em their money:
+#ifdef DEBUG
+      printf( (char *)"     Sum:      %8d credits.\n", iInterSum);
+      cout << "------------------------------------------------------" << endl;
+#endif // DEBUG
+      global->players[z]->money += iInterSum;
+#ifdef DEBUG
+      printf( (char *)"     Final Account   : %10d\n", global->players[z]->money);
+      cout << "======================================================" << endl;
+#endif // DEBUG
+    }
+    return true;
+}
+
+
+
+#ifdef GETV_IS_EVER_USED
+double getv (int color)
+{
+  float h, s, v;
+  int r, g, b;
+
+  r = getr (color);
+  g = getg (color);
+  b = getb (color);
+  rgb_to_hsv (r, g, b, &h, &s, &v);
+
+  return (v);
+}
+#endif //GETV_IS_EVER_USED
+
+
+
+void set_level_settings (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  int taken[MAXPLAYERS];
+  BITMAP *sky_gradient_strip, *land_gradient_strip;
+  int chosen = 0, chosenCount = 0, peak_height = 0;
+  int z, zz; 
+  int objCount;
+  TANK *ltank;
+  int xoffset;
+
+  // srand (time (NULL));
+
+  if (! global->os_mouse) show_mouse (NULL);
+  draw_sprite (screen, (BITMAP *) global->misc[1], global->halfWidth - 120, global->halfHeight + 115);
+  textout_centre_ex (screen, font, global->ingame->complete_text[42], global->halfWidth, global->halfHeight + 120, WHITE, -1);
+
+  // Choose appropriate gradients for sky and land
+  while ((chosenCount < 60) && !chosen)
+    {
+      global->lock_curland();
+      global->curland = rand () % LANDS;
+      global->unlock_curland();
+      if (global->colour_theme == COLOUR_THEME_CRISPY)
+      {
+        global->lock_curland();
+        global->curland += LANDS;
+        global->unlock_curland();
+      }
+      global->lock_curland();
+      if (!global->gfxData.land_gradient_strips[global->curland])
+        global->gfxData.land_gradient_strips[global->curland] = create_gradient_strip (land_gradients[global->curland], (global->screenHeight - MENUHEIGHT));
+      land_gradient_strip = global->gfxData.land_gradient_strips[global->curland];
+      global->unlock_curland();
+
+      global->cursky = rand () % SKIES;
+      if (global->colour_theme == COLOUR_THEME_CRISPY)
+        global->cursky += SKIES;
+      if (!global->gfxData.sky_gradient_strips[global->cursky])
+        global->gfxData.sky_gradient_strips[global->cursky] = create_gradient_strip (sky_gradients[global->cursky], (global->screenHeight - MENUHEIGHT));
+      sky_gradient_strip = global->gfxData.sky_gradient_strips[global->cursky];
+
+      chosen = 1;
+      for (z = 0; z < global->screenWidth; z++)
+        if (peak_height < env->height[z])
+          peak_height = (int)env->height[z];
+      for (z = 0; z <= peak_height; z++)
+        {
+          int skyi, landi;
+          double distance;
+          skyi = getpixel (sky_gradient_strip, 0, (global->screenHeight - MENUHEIGHT - z));
+          landi = getpixel (land_gradient_strip, 0, z);
+
+          distance = colorDistance (skyi, landi);
+          if (distance < 30)
+            chosen = 0;
+        }
+      chosenCount++;
+    }
+
+  if (! global->os_mouse) show_mouse (NULL);
+  draw_sprite (screen, (BITMAP *) global->misc[1], global->halfWidth - 120, global->halfHeight + 155);
+  textout_centre_ex (screen, font, global->ingame->complete_text[43], global->halfWidth, global->halfHeight + 160, WHITE, -1);
+  // It looks like we do not use this anymore  xoffset = rand ();
+  //generate_sky (global, env, xoffset, 0, global->screenWidth, global->screenHeight);
+ 
+  if (env->sky)
+  {
+     destroy_bitmap(env->sky);
+     env->sky = NULL;
+  } 
+  // see if we want a custom background
+  if ( (env->custom_background) && (env->bitmap_filenames) )
+  {
+     // if ( env->sky) destroy_bitmap(env->sky);
+     env->sky = load_bitmap( env->bitmap_filenames[ rand() % env->number_of_bitmaps ], NULL);
+  }
+
+  // if we do not have a custom background (or do not want one) create a new background
+  if ( (! env->custom_background) || (! env->sky) )
+  {
+      // if ( env->sky ) destroy_bitmap(env->sky);
+#ifdef THREADS
+      // On Linux we will have a thread creating a sky for us in the background
+      // to avoid wait times. If there is not a pre-created sky waiting for us
+      // then fall back to generating one the regular way.
+      if (env->get_waiting_sky())
+      {
+           env->sky = env->get_waiting_sky();
+           env->lock(env->waiting_sky_lock);
+           env->waiting_sky = NULL;
+           env->unlock(env->waiting_sky_lock);
+      }
+      else
+      {
+#endif
+      env->sky = create_bitmap( global->screenWidth, global->screenHeight - MENUHEIGHT);
+      generate_sky (global, env->sky, sky_gradients[global->cursky],
+                   (global->ditherGradients ? GENSKY_DITHERGRAD : 0 ) |
+                   (global->detailedSky ? GENSKY_DETAILED : 0 )  );
+#ifdef THREADS
+      }
+#endif
+  }
+
+  if (! global->os_mouse) show_mouse (NULL);
+  draw_sprite (screen, (BITMAP *) global->misc[1], global->halfWidth - 120, global->halfHeight + 195);
+  textout_centre_ex (screen, font, global->ingame->complete_text[44], global->halfWidth, global->halfHeight + 200, WHITE, -1);
+
+  #ifdef THREADS
+  // we have threads, so check for pre-main terrain
+  if (env->get_waiting_terrain())
+  {
+      // we have one waiting, so destroy the current one
+      if (env->terrain) destroy_bitmap(env->terrain);
+      env->terrain = env->get_waiting_terrain();
+      env->lock(env->waiting_terrain_lock);
+      env->waiting_terrain = NULL;        // set this so a new one will be made
+      env->unlock(env->waiting_terrain_lock);
+  }
+  else      // one is not waiting, so we need to create one now
+  {
+  #endif
+
+  clear_to_color (env->terrain, PINK);
+
+  xoffset = rand ();
+  generate_land (global, env, env->terrain, xoffset, 0, global->screenHeight);
+  #ifdef THREADS
+  }         // end of else
+  #endif
+
+  for (z = 0; z < global->numTanks; z++)
+    {
+      taken[z] = 0;
+    }
+  for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
+    {
+      for (zz = rand () % global->numTanks; taken[zz]; zz = rand () % global->numTanks) { }
+      taken[zz] = objCount + 1;
+      ltank->x = (zz + 1) * (global->screenWidth / (global->numTanks + 1));
+      ltank->y = (global->screenHeight - (int)env->height[(int) ltank->x]) - (TANKHEIGHT - TANKSAG);
+      ltank->newRound ();
+    }
+  for (z = 0; z < MAXPLAYERS; z++)
+    env->order[z] = NULL;
+  global->maxNumTanks = global->numTanks;
+  for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
+    {
+      for (z = rand () % global->numTanks; env->order[z]; z = rand () % global->numTanks) { }
+      env->order[z] = ltank;
+    }
+  // if (global->turntype != TURN_RANDOM) {
+  if ( (global->turntype != TURN_RANDOM) &&
+       (global->turntype != TURN_SIMUL))
+    {
+      for (int index = 0; index < global->maxNumTanks - 1; index++)
+        {
+          int swap = FALSE;
+          if (global->turntype == TURN_HIGH)
+            {
+              if (env->order[index]->player->score <
+                  env->order[index + 1]->player->score)
+                {
+                  swap = TRUE;
+                }
+            }
+          else if (global->turntype == TURN_LOW)
+            {
+              if (env->order[index]->player->score >
+                  env->order[index + 1]->player->score)
+                {
+                  swap = TRUE;
+                }
+            }
+          if (swap)
+            {
+              TANK *tempTank = env->order[index];
+              env->order[index] =
+                env->order[index + 1];
+              env->order[index + 1] = tempTank;
+              index = -1;
+            }
+        }
+    }
+}
+
+
+char *do_winner (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  int maxscore = -1;
+  int winindex = -1;
+  int i, index, *order;
+  bool multiwinner = false;
+  int fonthgt = text_height(font)+10;
+  int jedi_index = -1, sith_index = -1, neutral_index = -1;
+  // char *my_quote;
+  char *return_string = NULL;
+
+  return_string = (char *) calloc(256, sizeof(char));
+  if (! return_string)
+     return NULL;
+
+  //find the maxscore and print out winner
+  for (i=0;i<global->numPlayers;i++)
+    {
+      if (global->players[i]->score == maxscore)
+        {
+          multiwinner=true;
+          if (global->players[i]->team == TEAM_NEUTRAL)
+            neutral_index = i;
+        }
+
+      else if (global->players[i]->score > maxscore)
+        {
+          maxscore = global->players[i]->score;
+          winindex=i;
+          multiwinner=false;
+          if (global->players[i]->team == TEAM_NEUTRAL)
+            neutral_index = i;
+        }
+      if (global->players[i]->team == TEAM_JEDI)
+        jedi_index = i;
+      else if (global->players[i]->team == TEAM_SITH)
+        sith_index = i;
+    }
+
+  //stop mouse during drawing
+  if (! global->os_mouse) show_mouse (NULL);
+
+  //draw background and winner bitmap
+  draw_circlesBG (global, env->db, 0, 0, global->screenWidth, global->screenHeight, false);
+  draw_sprite (env->db, (BITMAP *) global->misc[9], global->halfWidth - 150, global->halfHeight - 150);
+
+  //draw winner names and info about all players
+  int boxtop = global->halfHeight-40;
+  int boxleft = global->halfWidth-200;
+  int boxright = global->halfWidth+280;
+  int boxbottom = boxtop +4+(fonthgt*2)+(fonthgt*global->numPlayers);
+
+  rectfill (env->db, boxleft, boxtop, boxright, boxbottom, BLACK);
+  rect (env->db, boxleft, boxtop, boxright, boxbottom, WHITE);
+  if (multiwinner)
+    {
+      // check for team win
+      if ( global->players[winindex]->team == TEAM_JEDI )
+        {
+          if ( (sith_index >= 0) && ( (global->players[sith_index]->score == global->players[winindex]->score)) )
+            snprintf(return_string, 256, "%s", global->ingame->complete_text[48]);
+          else if ( (neutral_index >= 0) && ( (global->players[neutral_index]->score == global->players[winindex]->score) ) )
+            snprintf(return_string, 256, "%s", global->ingame->complete_text[48]);
+          else
+            snprintf(return_string, 256, "%s", global->ingame->complete_text[45]);
+        }
+      else if ( global->players[winindex]->team == TEAM_SITH )
+        {
+          if ((jedi_index >= 0) && ((global->players[jedi_index]->score == global->players[winindex]->score)))
+            snprintf(return_string, 256, "%s", global->ingame->complete_text[48]);
+          else if ( (neutral_index >= 0) && ( (global->players[neutral_index]->score == global->players[winindex]->score) ) )
+            snprintf(return_string, 256, "%s", global->ingame->complete_text[48]);
+          else
+            snprintf(return_string, 256, "%s", global->ingame->complete_text[46]);
+        }
+      else
+        snprintf(return_string, 256, "%s", global->ingame->complete_text[48]);
+    }
+  else
+     snprintf(return_string, 256, "%s: %s", global->ingame->complete_text[47],
+             global->players[winindex]->getName() );
+
+  textprintf_centre_ex(env->db, font, global->halfWidth, boxtop + 4,
+                       global->players[winindex]->color, -1,
+                       "%s", return_string);
+
+  textout_centre_ex (env->db, font, global->ingame->complete_text[49], global->halfWidth, boxtop+4+fonthgt, WHITE, -1);
+  order = Sort_Scores(global);
+  for (index = 0; index < global->numPlayers; index++)
+    {
+      int i = order[index];
+      int textypos = (index * 10) + boxtop+4+(fonthgt*2);
+      int money;
+
+      textprintf_ex (env->db, font, boxleft+10, textypos , global->players[i]->color, -1, "%s:", global->players[i]->getName ());
+
+      money = 0;
+      for (int weapNum = 0; weapNum < WEAPONS; weapNum++)
+        {
+          int individValue;
+          if (weapon[weapNum].amt)
+            individValue = weapon[weapNum].cost / weapon[weapNum].amt;
+          else
+            individValue = 0;
+          money += (int)(individValue * global->players[i]->nm[weapNum]);
+        }
+      for (int itemNum = 0; itemNum < ITEMS; itemNum++)
+        {
+          int individValue;
+          if (item[itemNum].amt)
+            individValue = item[itemNum].cost / item[itemNum].amt;
+          else
+            individValue = 0;
+          money += (int)(individValue * global->players[i]->ni[itemNum]);
+        }
+      textprintf_ex (env->db, font, boxleft+190, textypos, WHITE, -1, "%3d  $%s   %10d :%2d", global->players[i]->score, Add_Comma(money), global->players[i]->kills, global->players[i]->killed);
+    }
+
+  /*
+  my_quote = global->war_quotes->Get_Random_Line();
+  if (my_quote)
+  {
+     char *little_string;
+     int start_index = 0, to_index = 0;
+     int total_length = strlen(my_quote);
+     int quote_count = 1;
+
+     little_string = (char *) calloc( total_length + 1, sizeof(char));
+     if (little_string)
+     {
+        do
+        {
+           memset(little_string, '\0', total_length + 1);
+           while ((( my_quote[start_index] != ' ' ) || (to_index < 50) ) && (start_index < total_length) )
+           {
+               little_string[to_index] = my_quote[start_index];
+               to_index++;
+               start_index++;
+           }
+          
+           textprintf_ex(env->db,font,boxleft, boxbottom + (10 * quote_count), WHITE, -1,                          "%s", little_string);
+           to_index = 0;
+           quote_count++;
+           while ( (start_index < total_length) && (my_quote[start_index] == ' ') )
+                start_index++;
+        } while (start_index < total_length);
+        free(little_string);
+     }   
+  }
+  //do fade and wait for user keypress
+  change (global, env->db);
+  readkey ();
+  // for (i = 0; i < global->numPlayers; i++)
+  //  global->players[i]->type = global->players[i]->type_saved;
+  */
+  return return_string;
+}
+
+
+
+void do_quote(GLOBALDATA *global, ENVIRONMENT *env)
+{
+  char *my_quote;
+  int fonthgt = text_height(font)+10;
+  int boxleft = global->halfWidth-200;
+  int boxtop = global->halfHeight-40;
+  int boxbottom = boxtop +4+(fonthgt*2)+(fonthgt*global->numPlayers);
+
+  my_quote = global->war_quotes->Get_Random_Line();
+  if (my_quote)
+  {
+     char *little_string;
+     int start_index = 0, to_index = 0;
+     int total_length = strlen(my_quote);
+     int quote_count = 1;
+
+     little_string = (char *) calloc( total_length + 1, sizeof(char));
+     if (little_string)
+     {
+        do
+        {
+           memset(little_string, '\0', total_length + 1);
+           while ((( my_quote[start_index] != ' ' ) || (to_index < 50) ) && (start_index < total_length) )
+           {
+               little_string[to_index] = my_quote[start_index];
+               to_index++;
+               start_index++;
+           }
+
+           textprintf_ex(env->db,font,boxleft, boxbottom + (10 * quote_count), WHITE, -1,                          "%s", little_string);
+           to_index = 0;
+           quote_count++;
+           while ( (start_index < total_length) && (my_quote[start_index] == ' ') )
+                start_index++;
+        } while (start_index < total_length);
+        free(little_string);
+     }
+  }
+
+  //do fade and wait for user keypress
+  change (global, env->db);
+  readkey ();
+  for (int i = 0; i < global->numPlayers; i++)
+    global->players[i]->type = global->players[i]->type_saved;
+
+}
+
+
+
+
+//draws indicaation bar
+void graph_bar (ENVIRONMENT *env, int x, int y, long int col, int actual, int max)
+{
+  rect (env->db, x, y, x + max + 2, y + 8, BLACK);
+  rectfill (env->db, x + 1, y + 1, x + 1 + actual, y + 7, col);
+}
+
+
+//draws indication bar - centred
+void graph_bar_center (ENVIRONMENT *env, int x, int y, long int col, int actual, int max)
+{
+  rect (env->db, x, y, x + max + 2, y + 8, BLACK);
+  rectfill (env->db, x + 1 + max / 2, y + 1, x + 1 + actual + max / 2, y + 7, col);
+}
+
+
+//Some global parameters
+int ord;
+void loadshields (ENVIRONMENT *env)
+{
+  TANK *tank;
+  int objCount;
+
+  for (objCount = 0; (tank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && tank; objCount++)
+    tank->reactivate_shield ();
+}
+
+void change_wind_strength (ENVIRONMENT *env)
+{
+  if (env->windvariation == 0.0 || (int)env->windstrength == 0)
+    {
+      return;
+    }
+  else
+    {
+      env->wind = env->lastwind + (double)(rand () % (int)(env->windvariation * 100)) / 100 - (env->windvariation / 2);
+      if (env->wind > (env->windstrength / 2))
+        {
+          env->wind = env->windstrength / 2;
+        }
+      else if (env->wind < (-env->windstrength / 2))
+        {
+          env->wind = -env->windstrength / 2;
+        }
+
+      env->lastwind = env->wind;
+    }
+
+   // make sure game clients have up to date wind data
+   #ifdef NETWORK
+   char buffer[64];
+   sprintf(buffer, "WIND %f", env->wind);
+   env->_global->Send_To_Clients(buffer);
+   #endif
+}
+
+TANK *nextturn (GLOBALDATA *global, ENVIRONMENT *env, bool skippingComputerPlay)
+{
+  TANK *tank = NULL;
+  int ordCurrently = ord;
+  static int do_wind = 0;
+  static int next_wind = 0;
+  int index = 0, lowest_index = 0, lowest_shots = INT_MAX;
+
+  // check whether there currently *are* active tanks first
+  if (global->numTanks)
+    {
+      // find first tank with lowest number of shots fired
+      while ( index < global->maxNumTanks )
+        {
+          if ( env->order[index] )    // make sure tank exists
+            {
+              if ( env->order[index]->shots_fired < lowest_shots )
+                {
+                  lowest_shots = env->order[index]->shots_fired;
+                  lowest_index = index;
+                }
+            }
+          index++;
+        }     // end of looking for low index
+
+
+      do
+        {
+          ord++;
+          // coming around to the next turn
+          if (ord >= global->maxNumTanks)
+            {
+              ord = 0;
+              doLaunch(global, env);
+              // launch before we change the wind
+              next_wind = 1;
+            }
+
+        }
+      while ((!env->order[ord]) && (ord != ordCurrently));
+      tank = env->order[ord];
+      global->currTank = tank;
+
+      if ( tank->shots_fired > lowest_shots )
+        {
+          tank = env->order[lowest_index];
+          global->currTank = tank;
+        }
+
+      // Wind is blowing :-)
+      // change_wind_strength (env);
+      if ( (global->turntype != TURN_SIMUL) || (do_wind) )
+        {
+          change_wind_strength(env);
+          do_wind = next_wind = 0;
+        }
+      else
+        {
+          do_wind = next_wind;
+          next_wind = 0;
+        }
+    }
+
+  if (tank)
+    {
+      if (!skippingComputerPlay)
+        {
+          env->make_fullUpdate();
+          env->do_updates();
+        }
+      tank->reactivate_shield ();
+      clear_keybuf();
+      if (global->max_fire_time)
+        {
+          tank->player->time_left_to_fire = global->max_fire_time;
+          tank->player->skip_me = false;
+        }
+    }
+
+  return tank;
+}
+
+void showRoundEndScoresAt (GLOBALDATA *global, ENVIRONMENT *env, BITMAP *bitmap, int x, int y, int winner)
+{
+  int z;
+
+  env->make_update (x - 150, y - 100, 301, 301);
+  rectfill (bitmap, x - 150, y - 100, x + 100, y + 100, BLACK);
+  rect (bitmap, x - 150, y - 100, x + 100, y + 100, WHITE);
+  if (winner == JEDI_WIN)
+    textout_centre_ex (bitmap, font, "Jedi", x - 20, y - 90, WHITE, -1);
+  else if (winner == SITH_WIN)
+    textout_centre_ex (bitmap, font, "Sith", x - 20, y - 90, WHITE, -1);
+  else if (winner == -2)
+    textout_centre_ex (bitmap, font, "Draw", x - 20, y - 90, WHITE, -1);
+  else
+    textprintf_centre_ex (bitmap, font, x - 30, y - 90, global->players[winner]->color, -1, "%s: %s", global->ingame->complete_text[47], global->players[winner]->getName ());
+
+  textout_centre_ex (bitmap, font, global->ingame->complete_text[50], x - 30, y - 70, WHITE, -1);
+  for (z = 0; z < global->numPlayers; z++)
+    {
+      textprintf_ex (bitmap, font, x - 140, (z * 10) + y - 50, global->players[z]->color, -1, "%s:", global->players[z]->getName ());
+      textprintf_ex (bitmap, font, x + 60, (z * 10) + y - 50, WHITE, -1, "%d", global->players[z]->score);
+    }
+}
+
+int setSlideColumnDimensions (GLOBALDATA *global, ENVIRONMENT *env, int x, bool reset)
+{
+  int pixelHeight;
+  char	*done	= env->done;
+  int	*dropTo = env->dropTo;
+  int	*h	= env->h;
+  int	*fp	= env->fp;
+  double	*velocity = env->velocity;
+  double	*dropIncr = env->dropIncr;
+
+  if (x < 0 || x > (global->screenWidth-1))
+    {
+      return (0);
+    }
+
+  if (reset)
+    {
+      h[x] = 0;
+      fp[x] = 0;
+      dropTo[x] = global->screenHeight - 1;
+    }
+  done[x] = 0;
+
+  // Calc the top and bottom of the column to slide
+
+  // Find top-most non-PINK pixel
+  for (pixelHeight = h[x]; pixelHeight < dropTo[x]; pixelHeight++)
+    if (getpixel (env->terrain, x, pixelHeight) != PINK)
+      break;
+  h[x] = pixelHeight;
+  env->surface[x] = pixelHeight;
+
+  // Find bottom-most PINK pixel
+  for (pixelHeight = dropTo[x]; pixelHeight > h[x]; pixelHeight--)
+    if (getpixel (env->terrain, x, pixelHeight) == PINK)
+      break;
+  dropTo[x] = pixelHeight;
+
+  // Find bottom-most unsupported pixel
+  for (; pixelHeight >= h[x]; pixelHeight--)
+    if (getpixel (env->terrain, x, pixelHeight) != PINK)
+      break;
+
+  // If there's some processing to do
+  if ((pixelHeight >= h[x]) && (h[x] < dropTo[x]))
+    {
+      fp[x] = pixelHeight - (int)h[x] + 1;
+      return (0);
+    }
+  else
+    {
+      if (velocity[x])
+        play_sample ((SAMPLE *) global->sounds[10], (int)((velocity[x] / 10) * 255), (int)((double)(x - global->halfWidth) / global->halfWidth * 128 + 128), 1000 - (int)((double)fp[x] / global->screenHeight) * 1000, 0);
+      h[x] = 0;
+      fp[x] = 0;
+      done[x] = 1;
+      velocity[x] = 0;
+      dropIncr[x] = 0;
+      dropTo[x] = global->screenHeight - 1;
+      return (1);
+    }
+  return (0);
+}
+
+
+int drawFracture (GLOBALDATA *global, ENVIRONMENT *env, BITMAP *dest, BOX *updateArea, int x, int y, int angle, int width, int segmentLength, int maxRecurse, int recurseDepth)
+{
+  int branchCount;
+  int x1, x2, x3;
+  int y1, y2, y3;
+
+  x1 = (int)(x + global->slope[angle][0] * width);
+  y1 = (int)(y + global->slope[angle][1] * width);
+  x2 = (int)(x - global->slope[angle][0] * width);
+  y2 = (int)(y - global->slope[angle][1] * width);
+  x3 = (int)(x + global->slope[angle][1] * segmentLength);
+  y3 = (int)(y + global->slope[angle][0] * segmentLength);
+  triangle (dest, x1, y1, x2, y2, x3, y3, PINK);
+
+  if (recurseDepth == 0)
+    {
+      updateArea->x = x1;
+      updateArea->y = y1;
+      updateArea->w = x1;
+      updateArea->h = y1;
+    }
+  updateArea->x = MIN (MIN (MIN (x1, x2), x3), updateArea->x);
+  updateArea->y = MIN (MIN (MIN (y1, y2), y3), updateArea->y);
+  updateArea->w = MAX (MAX (MAX (x1, x2), x3), updateArea->w);
+  updateArea->h = MAX (MAX (MAX (y1, y2), y3), updateArea->h);
+
+  if (recurseDepth < maxRecurse)
+    {
+      for (branchCount = 0; branchCount < 3; branchCount++)
+        {
+          if ((branchCount == 0) || (Noise (x + y + branchCount) < 0))
+            {
+              int newAngle, reduction;
+              newAngle = (angle + (int)(Noise (x + y + 4) * 30));
+              while (newAngle < 0)
+                newAngle += 360;
+              newAngle %= 360;
+
+              reduction = 2;
+              if (branchCount == 1)
+                {
+                  newAngle = (int)(angle + 90 +
+                                   (Noise (x + y + 25 + branchCount) * 22.5)) % 360;
+                  reduction = abs ((int)Noise (x + y + 1 + branchCount) * 4 + 3);
+                }
+              else if (branchCount == 2)
+                {
+                  newAngle = (int)(angle + 270 +
+                                   (Noise (x + y + 32 + branchCount) * 22.5)) % 360;
+                  reduction = abs ((int)Noise (x + y + 2 + branchCount) * 4 + 3);
+                }
+              drawFracture (global, env, dest, updateArea, x3, y3, newAngle, width / reduction, segmentLength / reduction, maxRecurse, recurseDepth + 1);
+            }
+        }
+    }
+
+  // Calculate width and height, previously right and bottom
+  if (recurseDepth == 0)
+    {
+      updateArea->w -= updateArea->x;
+      updateArea->h -= updateArea->y;
+    }
+
+  return (0);
+}
+
+/*
+void initSurface (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  int pixelHeight;
+  for (int x = 0; x < global->screenWidth; x++)
+    {
+      for (pixelHeight = 0; pixelHeight < global->screenHeight; pixelHeight++)
+        if (getpixel (env->terrain, x, pixelHeight) != PINK)
+          break;
+      env->surface[x] = pixelHeight;
+    }
+}
+*/
+
+
+int slideLand (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  char	*done	= env->done;
+  int	*dropTo = env->dropTo;
+  int	*h	= env->h;
+  int	*fp	= env->fp;
+  double	*velocity = env->velocity;
+  double	*dropIncr = env->dropIncr;
+  int zz;
+  double land_slide_type = LANDSLIDE_INSTANT;
+
+  // land-slide, make it fall etc.
+  int allDone = 1;
+  if ( (env->landSlideType == LANDSLIDE_NONE) ||
+       (env->landSlideType == LANDSLIDE_TANK_ONLY) )
+    return (allDone);
+
+  else if (env->landSlideType == LANDSLIDE_CARTOON)
+    {
+      if (env->time_to_fall > 0)
+        land_slide_type = LANDSLIDE_CARTOON;
+      else
+        land_slide_type = LANDSLIDE_GRAVITY;
+    }
+
+  else if (env->landSlideType == LANDSLIDE_GRAVITY)
+    land_slide_type = LANDSLIDE_GRAVITY;
+
+  if (land_slide_type == LANDSLIDE_CARTOON)
+    return (allDone);
+
+  for (zz = 0; zz < global->screenWidth; zz++)
+    {
+      if (!done[zz])
+        {
+          allDone = 0;
+          if (land_slide_type == LANDSLIDE_GRAVITY)
+            {
+              if (fp[zz] > 0)
+                {
+                  velocity[zz] += env->gravity;
+                  dropIncr[zz] += velocity[zz];
+                  if (dropIncr[zz] >= 1)
+                    {
+                      if (dropIncr[zz] > dropTo[zz] - (h[zz] + fp[zz]))
+                        {
+                          dropIncr[zz] = dropTo[zz] - (h[zz] + fp[zz]) + 1;
+                        }
+                      blit (env->terrain, env->terrain, zz, h[zz] - (int)dropIncr[zz], zz, h[zz], 1, fp[zz] + (int)dropIncr[zz]);
+                      env->make_bgupdate (zz, h[zz] - (int)dropIncr[zz], 1, fp[zz] + ((int)dropIncr[zz] * 2) + 1);
+                      env->make_update (zz, h[zz] - (int)dropIncr[zz], 1, fp[zz] + ((int)dropIncr[zz] * 2) + 1);
+                      h[zz] += (int)dropIncr[zz];
+                      dropIncr[zz] -= (int)dropIncr[zz];
+                    }
+                  setSlideColumnDimensions (global, env, zz, FALSE);
+                }
+              else
+                {
+                  setSlideColumnDimensions (global, env, zz, FALSE);
+                }
+            }
+          else if (land_slide_type == LANDSLIDE_INSTANT)
+            {
+              if (fp[zz] > 0)
+                {
+                  env->make_bgupdate (zz, h[zz], 1, dropTo[zz] - h[zz] + 1);
+                  env->make_update (zz, h[zz], 1, dropTo[zz] - h[zz] + 1);
+                  done[zz] = 1;
+                  blit (env->terrain, env->terrain, zz, h[zz], zz, dropTo[zz] - fp[zz] + 1, 1, fp[zz]);
+                  vline (env->terrain, zz, h[zz], dropTo[zz] - fp[zz], PINK);
+                }
+              setSlideColumnDimensions (global, env, zz, FALSE);
+            }
+        }
+    }
+
+  return (allDone);
+}
+
+void drawTopBar (GLOBALDATA *global, ENVIRONMENT *env, BITMAP *dest)
+{
+  TANK *tank = global->currTank;
+  char *name = "";
+  int color = 0;
+  int wind_col1 = 0, wind_col2 = 0;
+  static int change_weapon_colour = RED;
+  char *team_name = "";
+  int time_to_fire = 0;
+  int minus_font = (font == global->unicode) ? 9 : 0;
+
+  if (tank)
+    {
+      name = global->currTank->player->getName ();
+      color = global->currTank->player->color;
+      team_name = global->currTank->player->Get_Team_Name();
+      time_to_fire = tank->player->time_left_to_fire;
+    }
+
+  global->updateMenu = 0;
+  blit (global->gfxData.topbar, dest, 0, 0, 0, 0, global->screenWidth, MENUHEIGHT);
+
+  if (tank)
+    {
+      textout_ex (dest, font, name, 2, 2 - minus_font, BLACK, -1);
+      textout_ex (dest, font, name, 1, 1 - minus_font, color, -1);
+      textprintf_ex (dest, font, 1, 11 - minus_font, BLACK, -1, "%s", global->ingame->complete_text[18]);
+      graph_bar_center (env, 50, 11, color, -(tank->a - 180) / 2, 180 / 2);
+      // 0 is directly left, 180 points directly right
+      textprintf_ex (dest, font, 150, 11 - minus_font, BLACK, -1, "%d", 180 - (tank->a - 90));
+
+      textprintf_ex (dest, font, 1, 21 - minus_font, BLACK, -1, "%s", global->ingame->complete_text[19]);
+      graph_bar (env, 50, 20, color, (tank->p) / (MAX_POWER/90), 90);
+      textprintf_ex (dest, font, 150, 21 - minus_font, BLACK, -1, "%d", tank->p);
+      textprintf_ex (dest, font, 200, 21 - minus_font, BLACK, -1, "%s: %s", global->ingame->complete_text[20], team_name);
+      if (tank->cw < WEAPONS)
+      {
+          int weapon_amount;
+
+          if (! weapon[tank->cw].delay )
+              weapon_amount = tank->player->nm[tank->cw];
+          else
+              weapon_amount = tank->player->nm[tank->cw] / weapon[tank->cw].delay;
+
+          if (tank->player->changed_weapon)
+            {
+              textprintf_ex (dest, font, 180, 1, change_weapon_colour, -1, "%s: %d",
+                             weapon[tank->cw].name, weapon_amount);
+              // tank->player->nm[tank->cw]);
+              if (change_weapon_colour == RED)
+                change_weapon_colour = WHITE;
+              else
+                change_weapon_colour = RED;
+
+
+            }
+
+          else
+            textprintf_ex (dest, font, 180, 1, BLACK, -1,"%s: %d",
+                           weapon[tank->cw].name, weapon_amount);
+
+        }      // end of less than WEAPONS
+      else
+        {
+          textprintf_ex (dest, font, 180, 1, BLACK, -1, "%s: %d",
+                         item[tank->cw - WEAPONS].name, tank->player->ni[tank->cw - WEAPONS]);
+        }
+      draw_sprite (env->db, (BITMAP *) global->stock[ (tank->cw) ? tank->cw : 1], 700, 1);
+      textprintf_ex (dest, font, 350, 1, BLACK, -1, "$%s", Add_Comma(tank->player->money));
+      textprintf_ex (dest, font, 350, 12, BLACK, -1, "%s: %d", global->ingame->complete_text[21], tank->player->ni[ITEM_FUEL]);
+    }
+
+  textprintf_ex ( dest, font, 500,  1 - minus_font, BLACK, -1, "%s %d/%d", 
+                  global->ingame->complete_text[12],
+                  (int)(global->rounds - global->currentround) + 1, (int)global->rounds);
+
+  if (global->tank_status[0])
+    textprintf_ex(dest, font, 350, 21, global->tank_status_colour, -1, "%s",
+                  global->tank_status);
+
+  if (env->windstrength > 0)
+    {
+      textprintf_ex (dest, font, 500, 11 - minus_font, BLACK, -1, "%s", global->ingame->complete_text[22]);
+      if (env->wind > 0)
+        {
+          wind_col1 = 1;
+          wind_col2 = 0;
+        }
+      if (env->wind < 0)
+        {
+          wind_col1 = 0;
+          wind_col2 = 1;
+        }
+      rect (dest, 540, 12, (int)(540 + env->windstrength * 4 + 2), 18, BLACK);
+      rectfill (dest, (int)(541 + env->windstrength * 2), 13,
+                (int) (541 + env->wind * 4 + env->windstrength * 2), 17,
+                makecol (200 * wind_col1, 200 * wind_col2, 0));
+    }
+
+  if (global->max_fire_time)
+    textprintf_ex( dest, font, 500, 20, BLACK, -1, "Time: %d", time_to_fire);
+
+  global->stopwindow = 1;
+  env->make_update (0, 0, global->screenWidth, MENUHEIGHT);
+  global->stopwindow = 0;
+}
+
+/*
+ *  Calculate the effective damage for a given weapon.
+ *  Recursively add the damage of sub-munitions, factor in chaos
+ *    and munition density.
+ */
+long int calcTotalEffectiveDamage (int weapNum)
+{
+  WEAPON *weap = &weapon[weapNum];
+  long int total = 0;
+
+  if (weap->submunition >= 0)
+    {
+      WEAPON *subm = &weapon[weap->submunition];
+
+      // How chaotic is this weapon?
+      double chaosVal=(weap->spreadVariation +
+                       weap->speedVariation +
+                       subm->countVariation) / 3;
+      double coverage = (weap->numSubmunitions *
+                         subm->radius) /
+                        (double)weap->radius;
+
+      total += calcTotalEffectiveDamage (weap->submunition) *
+               weap->numSubmunitions;
+      total = (long int)(total * coverage / weap->numSubmunitions);
+      total -= (long int)((total / 2) * (1.0 - chaosVal));
+    }
+  else
+    {
+      total += weap->damage;
+    }
+
+  return (total);
+}
+
+/*
+ *  Calculate the potential damage for a given weapon.
+ *  Recursively add the damage of sub-munitions.
+ */
+long int calcTotalPotentialDamage (int weapNum)
+{
+  WEAPON *weap = &weapon[weapNum];
+  long int total = 0;
+
+  if ( (weap->submunition >= 0) && (weap->numSubmunitions > 0) )
+    total += calcTotalPotentialDamage (weap->submunition) *
+             weap->numSubmunitions;
+  else
+    total += weap->damage;
+
+  return (total);
+}
+
+void doNaturals (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  int chance;
+
+  if (env->naturals_since_last_shot >= 5)
+    return;
+
+  if (env->lightning)
+    {
+      chance = (int)(600 / env->lightning) + 100;
+      if (!(rand () % chance))
+        {
+          BEAM *newbeam;
+          int ca = ((rand () % 160) + (360 - 80)) % 360;
+
+          newbeam = new BEAM (global, env,
+                              rand () % global->screenWidth, 0,
+                              ca, SML_LIGHTNING + (rand () % (int)env->lightning));
+          if (newbeam)
+          {
+            newbeam->player = NULL;
+            env->naturals_since_last_shot++;
+          }
+          else
+              perror ( "atanks.cc: Failed allocating memory for newbeam in doNaturals");
+        }
+    }      // end of lightning
+
+  // only create meteors  if we are not in aim mode on simul turn type
+  if ( (global->turntype == TURN_SIMUL) && (env->stage == STAGE_AIM) )
+    return;
+
+  if (env->meteors)
+    {
+      chance = (int)(600 / env->meteors) + 100;
+      if (!(rand () % chance))
+        {
+          MISSILE *newmis;
+          int ca = ((rand () % 160) + (360 - 80)) % 360;
+          double mxv = global->slope[ca][0] * 5;
+          double myv = global->slope[ca][1] * 5;
+
+          newmis = new MISSILE(global, env,
+                               rand () % global->screenWidth, 0,
+                               mxv, myv, SML_METEOR + (rand () % (int)env->meteors));
+          if (newmis)
+          {
+            newmis->player = NULL;
+            env->naturals_since_last_shot++;
+          }
+          else
+              perror ( "atanks.cc: Failed allocating memory for newmis in doNaturals");
+        }
+    }
+
+  if (env->falling_dirt_balls)
+    {
+      chance = (int) (600 / env->falling_dirt_balls) + 100;
+      if (! (rand() % chance) )
+        {
+          MISSILE *newmis;
+          int ca = ((rand() % 100) + (360 - 80) ) % 360;
+          double mxv = global->slope[ca][0] * 5;
+          double myv = global->slope[ca][1] * 5;
+
+          newmis = new MISSILE(global, env,
+                               rand() % global->screenWidth, 0,
+                               mxv, myv, DIRT_BALL + ( rand() % (int) env->falling_dirt_balls) );
+          if (newmis)
+          {
+            newmis->player = NULL;
+            env->naturals_since_last_shot++;
+          }
+          else
+              perror( "atanks.cc: Failed to allocate memory for falling dirt ball in doNaturals");
+        }
+    }
+}
+
+#ifdef OLD_GAMELOOP
+void game (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  int tanksfall;
+  int tanklife, tlt, dclock;
+  int lb, ca;
+  int allDone, anyExploding, anyTeleporting, anyLaserFiring;
+  int roundEndCount = 0;
+  bool nextTankSelected = false;
+  int humanPlayers = 0;
+  int skippingComputerPlay = FALSE;
+  int team_won = NO_WIN;
+  bool bWinnerIsCredited = false;
+  int my_class;
+  VIRTUAL_OBJECT *my_object;
+
+  TANK **tank, *ltank;
+  MISSILE *missile;
+  TELEPORT *teleport;
+  DECOR *decor;
+  BEAM *beam;
+  EXPLOSION *explosion;
+  FLOATTEXT *floattext;
+  static SATELLITE *satellite = NULL;
+
+  int bCount;
+  int z, zz, z4;
+  int objCount, count;
+  int AI_clock = 0;
+
+  global->computerPlayersOnly = FALSE;
+
+  tank = &global->currTank;
+
+  for (int doneCount = 0; doneCount < global->screenWidth; doneCount++)
+    env->done[doneCount] = 0;
+  // initSurface (global, env); // init surface[]
+
+  env->newRound ();
+  // set wall colour
+  switch (env->current_wallType)
+    {
+    case WALL_RUBBER:
+      env->wallColour = GREEN;
+      break;
+    case WALL_STEEL:
+      env->wallColour = RED;
+      break;
+    case WALL_SPRING:
+      env->wallColour = BLUE;
+      break;
+    case WALL_WRAP:
+      env->wallColour = YELLOW;
+      break;
+    }
+  if (env->dBoxedMode == 2.0)
+    {
+      if (rand() % 2)
+        global->bIsBoxed = true;
+      else
+        global->bIsBoxed = false;
+    }
+  else if (env->dBoxedMode == 1.0)
+    global->bIsBoxed = true;
+  else if (env->dBoxedMode == 0.0)
+    global->bIsBoxed = false;
+  // Set Max velocity
+  global->dMaxVelocity = (double)MAX_POWER * (100.0 / (double)global->frames_per_second) / 100.0;
+  if ((env->current_wallType == WALL_SPRING) && !global->bIsBoxed)
+    // In non-boxed the Spring Wall is allowed to have at least twice the normal velocity
+    global->dMaxVelocity *= 2.0;
+  if (global->bIsBoxed)
+    // In boxed Mode, there is four times the normal max velocity allowed (or it won't be fun!)
+    global->dMaxVelocity *= 4.0;
+  for (count = 0; count < global->numPlayers; count++)
+    global->players[count]->newRound ();
+
+  /* Unfortunately, ENVIRONMENT can't call uppon FLOATTEXT::newRound due to circular dependencies.
+     Thus we have to do that here: */
+
+  for (int objCount = 0; objCount < MAX_OBJECTS; objCount++)
+    {
+      if (env->objects[count] && (env->objects[count]->isSubClass(FLOATTEXT_CLASS)))
+        ((FLOATTEXT *)env->objects[count])->newRound();
+    }
+
+  buystuff (global, env);
+  if (global->close_button_pressed)
+    {
+      global->wr_lock_command();
+      global->command = GLOBAL_COMMAND_QUIT;
+      global->unlock_command();
+      return;
+    }
+
+  for (count = 0; count < global->numPlayers; count++)
+    global->players[count]->exitShop ();
+
+  set_level_settings (global, env);
+
+  for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
+    {
+      ltank->newRound ();
+      if ((int)ltank->player->type == HUMAN_PLAYER)
+        {
+          humanPlayers++;
+        }
+    }
+  if (!humanPlayers)
+    {
+      global->computerPlayersOnly = TRUE;
+      //if ((int)global->skipComputerPlay >= SKIP_AUTOPLAY)
+      //	skippingComputerPlay = TRUE;
+    }
+  lock_cclock();
+  cclock = lx = ly = tanksfall = 0;
+  unlock_cclock();
+  env->stage = STAGE_AIM;
+  tlt = global->updateCount = dclock = global->stopwindow = 0;
+  env->realm = env->am = 0;
+  ca = 0;
+  lb = env->mouseclock = env->pclock = 0;
+  ord = 0;
+
+  *tank = env->order[0];
+  for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
+    {
+      ltank->flashdamage = 0;
+      ltank->boost_up_shield ();
+    }
+  winner = tanklife = -1;
+  fi = global->updateMenu = 1;
+  global->window.x = 0;
+  global->window.y = 0;
+  global->window.w = (global->screenWidth-1);
+  global->window.h = (global->screenHeight-1);
+  bCount = 0;
+  if ((int)env->windstrength != 0)
+    env->wind = (float)(rand () % (int)env->windstrength) - (env->windstrength / 2);
+  else
+    env->wind = 0;
+  env->lastwind = env->wind;
+  if ( (env->satellite) && (! satellite) )
+    satellite = new SATELLITE(global, env);
+  if (satellite)
+    satellite->Init();
+
+  global->iHumanLessRounds = -1;
+#ifdef DEBUG_AIM_SHOW
+  global->bASD = false;
+#endif
+
+  global->background_music = global->Load_Background_Music();
+  if (global->background_music)
+     play_sample((SAMPLE *) global->background_music, 255, 128, 1000, TRUE);
+
+  while (1)
+    {
+      LINUX_SLEEP;
+      if (global->close_button_pressed)
+        {
+          global->wr_lock_command();
+          global->command = GLOBAL_COMMAND_QUIT;
+          global->wr_unlock_command();
+          return;
+        }
+
+      while (get_cclock() > 0 || skippingComputerPlay)
+        {
+          lock_cclock();
+          cclock--;
+          unlock_cclock();
+          if (!lb && mouse_b & 1)
+            env->mouseclock = 0;
+          lb = (mouse_b & 1) ? 1 : 0;
+          bCount += 360/32;
+          z4 = 0;
+          anyExploding    = 0;
+          anyTeleporting  = 0;
+          anyLaserFiring  = 0;
+
+          env->am = 0;
+          objCount = 0;
+          my_object = env->objects[objCount];
+          // keep track of how long we have been skipping AI
+          if (skippingComputerPlay)
+          {
+             // advance clock
+             if ( global->Check_Time_Changed() )
+                AI_clock++;
+             if (AI_clock > MAX_AI_TIME)
+             {
+                 int player_index = 0;
+                 // kill all remaining tanks
+                 while (player_index < global->numPlayers)
+                 {
+                    if ( ( global->players[player_index] ) &&
+                         ( global->players[player_index]->tank ) )
+                       global->players[player_index]->tank->l = 0;
+                    player_index++;
+                 }
+             }
+          }       // end of AI clock code
+
+          while (objCount < MAX_OBJECTS) 
+          {
+            if (my_object)
+            {
+            my_class = my_object->getClass();
+            //for (objCount = 0; (decor = (DECOR*)env->getNextOfClass (DECOR_CLASS, &objCount)) && decor; objCount++)
+            if (my_class == DECOR_CLASS)
+            {
+              decor = (DECOR *) my_object;
+              decor->applyPhysics ();
+              if (decor->destroy)
+                {
+                  decor->requireUpdate ();
+                  decor->update ();
+                  delete decor;
+                }
+            }
+          // for (objCount = 0; (explosion = (EXPLOSION*)env->getNextOfClass (EXPLOSION_CLASS, &objCount)) && explosion; objCount++)
+            else if (my_class == EXPLOSION_CLASS)
+            {
+              explosion = (EXPLOSION *) my_object;
+              if (explosion->bIsWeaponExplosion)
+                anyExploding++;
+              explosion->explode ();
+              explosion->applyPhysics ();
+              if (explosion->destroy)
+                {
+                  explosion->requireUpdate ();
+                  explosion->update ();
+                  delete explosion;
+                  anyExploding--;
+                }
+            }
+
+          // for (objCount = 0; (teleport = (TELEPORT*)env->getNextOfClass (TELEPORT_CLASS, &objCount)) && teleport; objCount++)
+            else if (my_class == TELEPORT_CLASS)
+            {
+              teleport = (TELEPORT *) my_object;
+              anyTeleporting++;
+              teleport->applyPhysics ();
+              if (teleport->destroy)
+                {
+                  teleport->requireUpdate ();
+                  teleport->update ();
+                  delete teleport;
+                  anyTeleporting--; // It's done!
+                  tanksfall = 1;
+                }
+            }
+          // env->am = 0;
+          // for (objCount = 0; (missile = (MISSILE*)env->getNextOfClass (MISSILE_CLASS, &objCount)) && missile; objCount++)
+            else if (my_class == MISSILE_CLASS)
+            {
+              TANK *shooting_tank = NULL;
+              BEAM *defense_beam = NULL;
+              int angle_to_fire;
+
+              missile = (MISSILE *) my_object;
+              env->am++;
+              missile->hitSomething = 0;
+              missile->applyPhysics ();
+              missile->triggerTest ();
+              shooting_tank = missile->Check_SDI(global);
+              if (shooting_tank)
+              {
+                  (shooting_tank->x < missile->x) ? angle_to_fire = 135 : angle_to_fire = 225;
+                  defense_beam = new BEAM(global, env, shooting_tank->x, shooting_tank->y - 10, angle_to_fire, SML_LAZER);
+                  missile->trigger();
+              }
+              if (missile->destroy)
+                {
+                  missile->requireUpdate ();
+                  missile->update ();
+                  delete missile;
+                  tanksfall = 1;
+                }
+            }
+          // for (objCount = 0; (beam = (BEAM*)env->getNextOfClass (BEAM_CLASS, &objCount)) && beam; objCount++)
+            else if (my_class == BEAM_CLASS)
+            {
+              beam = (BEAM *) my_object;
+              // As bots should not target while a laser is shot:
+              anyLaserFiring ++;
+              beam->applyPhysics ();
+              if (beam->destroy)
+                {
+                  beam->requireUpdate ();
+                  beam->update ();
+                  delete beam;
+                  anyLaserFiring--; // It's done!
+                  tanksfall = 1;
+                }
+            }
+          // for (objCount = 0; (floattext = (FLOATTEXT*)env->getNextOfClass (FLOATTEXT_CLASS, &objCount)) && floattext; objCount++)
+            else if (my_class == FLOATTEXT_CLASS)
+            {
+              floattext = (FLOATTEXT *) my_object;
+              floattext->applyPhysics ();
+              if (floattext->destroy)
+                {
+                  floattext->requireUpdate();
+                  floattext->update();
+                  delete floattext;
+                  env->make_fullUpdate(); // ...kill remaining texts!
+                }
+            }
+            }        // end of if we have an object
+            objCount++;
+            my_object = env->objects[objCount];
+          }   // end of going through virtual objects
+
+
+          #ifdef NETWORK
+          for (int counter = 0; counter < global->numPlayers; counter++)
+          {
+               if (global->players[counter]->type == NETWORK_CLIENT)
+               {
+                  global->players[counter]->Get_Network_Command();
+                  global->players[counter]->Execute_Network_Command(FALSE);
+               }
+          }
+          #endif
+
+          if (satellite)
+            satellite->Move();
+
+          if (!anyExploding)
+            {
+              doNaturals (global, env);
+              if (satellite)
+                satellite->Shoot();
+            }
+
+          allDone = slideLand (global, env);
+          if (tanksfall && (env->stage != STAGE_ENDGAME))
+            {
+              for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank;
+                   count--, objCount++)
+                {
+                  ltank->pen = 0;
+                  ltank->applyPhysics (global);
+                  if (ltank->l <= 0 && !anyExploding)
+                    {
+                      ltank->explode ();
+                      if (ltank->creditTo)
+                        {
+                          if (ltank->player != ltank->creditTo)  	//enemy destroyed
+                            {
+                              ltank->creditTo->money += (int)global->scoreUnitDestroyBonus;
+                            }
+                          else  	//self destroy - ugh foolish one :))
+                            {
+                              ltank->creditTo->money -= (int)global->scoreUnitSelfDestroy;
+                              if (ltank->creditTo->money < 0)
+                                ltank->creditTo->money = 0;
+                            }
+                          ltank->creditTo = NULL;
+                        }
+                      if (ltank->destroy)
+                        {
+                          if ((int)ltank->player->type == HUMAN_PLAYER)
+                            humanPlayers--;
+                          
+                          ltank->Destroy();
+                          delete(ltank);
+
+                          ltank = NULL; // should not be used anymore, setting NULL for later IF's to checks
+                          if ((!skippingComputerPlay) || (global->numTanks <= 1))
+                            env->make_fullUpdate();
+                          if (!humanPlayers)
+                            {
+                              int iMostIntelligentPlayer = 0;
+                              int iNumPlayers            = 0;
+
+                              for (int i = 0; i < global->numPlayers; i++)
+                                {
+                                  int iType = 0;
+
+                                  if (global->players[i]->tank)
+                                    {
+                                      if (global->players[i]->tank->l > 0)
+                                        {
+                                          iType = (int) global->players[i]->type;
+                                          iNumPlayers++;
+                                        }
+                                    }
+                                  if (iType > iMostIntelligentPlayer)
+                                    iMostIntelligentPlayer = iType;
+                                }
+                              // If the most intelligent player is more stupid than deadly, raise them all!
+                              if	( (iMostIntelligentPlayer < (int) DEADLY_PLAYER)
+                                   && (iMostIntelligentPlayer >= (int) USELESS_PLAYER)
+                                   && (iNumPlayers > 1))
+                                for (int i = 0; i < global->numPlayers; i++)
+                                  {
+                                    if (global->players[i]->tank)
+                                      {
+                                        if (global->players[i]->tank->l > 0)
+                                          global->players[i]->setComputerValues ( (int) DEADLY_PLAYER - iMostIntelligentPlayer);
+                                      }
+                                  }
+
+#ifdef DEBUG
+                              if ((iMostIntelligentPlayer >= (int)USELESS_PLAYER) && (iNumPlayers > 1))
+                                {
+                                  cout << endl << "===========================================================" << endl;
+                                  cout << "Round without human players!" << endl;
+                                  cout << "Most intelligent player has Skill level " << iMostIntelligentPlayer << endl;
+                                  cout << "Raised all players by " << ((int)DEADLY_PLAYER - iMostIntelligentPlayer) << " Skill Level(s)" << endl;
+                                  cout << "===========================================================" << endl << endl;
+                                }
+#endif //DEBUG
+                              // Initialize iHumanLessRounds if not done already
+                              if (global->iHumanLessRounds < 0)
+                                global->iHumanLessRounds = iNumPlayers * 16;
+                            }
+                          if (!*tank && global->numTanks)
+                            {
+                              *tank = nextturn (global, env, skippingComputerPlay);
+                              while (! *tank)
+                                *tank = nextturn (global, env, skippingComputerPlay);
+                              (*tank)->fs = 0;
+                              nextTankSelected = true;
+                            }
+                          team_won = Team_Won(global);
+                          if ( (global->numTanks <= 1) || ( team_won ) )
+                            {
+                              skippingComputerPlay = FALSE;
+                              lock_cclock();
+                              cclock = 0;
+                              unlock_cclock();
+                              env->stage = STAGE_ENDGAME;
+                              global->currTank = NULL;
+                              fi = 1;
+                              global->window.x = 0;
+                              global->window.y = 0;
+                              global->window.w = (global->screenWidth-1);
+                              global->window.h = (global->screenHeight-1);
+                              winner = -2;
+                              if (team_won)
+                                winner = team_won;
+                              else if (global->numTanks > 0)
+                                {
+                                  for (z = 0; z < global->numPlayers; z++)
+                                    {
+                                      if (global->players[z]->tank)
+                                        winner = z;
+                                    }
+                                }
+
+                              for (objCount = 0; (floattext = (FLOATTEXT*)env->getNextOfClass (FLOATTEXT_CLASS, &objCount)) && floattext; objCount++)
+                                {
+                                  floattext->newRound();
+                                }
+
+                              bCount = 0;
+                              global->updateMenu = 1;
+                              for (z = 0; z < global->numPlayers; z++)
+                                global->players[z]->played++;
+                            }
+                        }
+                    }
+
+                  // adjust chess style clock (only if tank wasn't destroyed)
+                  if ( ( global->max_fire_time > 0.0 ) &&
+                       ( ltank ) &&
+                       ( ltank->player->type == HUMAN_PLAYER ) &&
+                       (! env->stage ) )
+                    {
+                      if ( global->Check_Time_Changed() )
+                        {
+                          int ran_out_of_time;
+                          ran_out_of_time = ltank->player->Reduce_Time_Clock();
+                          if (ran_out_of_time && !nextTankSelected)
+                            {
+                              ltank->player->skip_me = true;
+                              *tank = nextturn (global, env, skippingComputerPlay);
+                              while (! *tank)
+                                *tank = nextturn (global, env, skippingComputerPlay);
+                              (*tank)->fs = 0;
+                              nextTankSelected = true;
+                            }
+                          global->updateMenu = 1;
+                        }
+                    }
+
+                  if ( ( ltank ) && ( ltank->fire_another_shot ) )
+                  {
+                      if (! (ltank->fire_another_shot % VOLLY_DELAY))
+                        ltank->activateCurrentSelection();
+                      ltank->fire_another_shot--;
+                      if (! ltank->fire_another_shot)
+                         env->stage = 0;
+                  }
+
+                }
+            }
+          if (env->stage == 1)
+            {
+              if ((env->am == 0) && allDone && !anyExploding)
+                {
+                  tanksfall = 0;
+                  env->stage = 2;
+                }
+            }
+          if (env->stage == 2)
+            {
+              zz = 0;
+
+              for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; count--, objCount++)
+                {
+                  zz += ltank->applyPhysics (global);
+                }
+              if (zz == global->numTanks)
+                {
+                  tanksfall = 1;
+                }
+              zz = 0;
+              if (tanksfall)
+                {
+                  for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
+                    {
+                      ltank->pen = 0;
+                      if (ltank->l > 0)
+                        zz++;
+                    }
+                }
+              if (zz == global->numTanks)
+                {
+                  if (((int)global->skipComputerPlay > SKIP_NONE) &&
+                      (!humanPlayers) && (!global->computerPlayersOnly))
+                    {
+                        skippingComputerPlay = TRUE;
+                        #ifdef NETWORK
+                        int index = 0, network_clients = 0;
+                        while ( (index < global->numPlayers) && (! network_clients) )
+                        {
+                            if (global->players[index]->type == NETWORK_CLIENT)
+                               network_clients++;
+                            else
+                               index++;
+                        }
+                        if (network_clients)
+                          skippingComputerPlay = FALSE;
+                        #endif
+                       if (skippingComputerPlay)
+                       {
+                         draw_sprite (env->db, (BITMAP *) global->misc[1], global->halfWidth - 120, global->halfHeight + 155);
+                         textout_centre_ex (env->db, font, global->ingame->complete_text[51], global->halfWidth, global->halfHeight + 160, WHITE, -1);
+                         draw_sprite (screen, (BITMAP *) global->misc[1], global->halfWidth - 120, global->halfHeight + 155);
+                         textout_centre_ex (screen, font, global->ingame->complete_text[51], global->halfWidth, global->halfHeight + 160, WHITE, -1);
+                       }
+                    }
+                    
+                  env->stage = STAGE_AIM;
+                  winner = -2;
+                  for (z = 0; z < global->numPlayers; z++)
+                    {
+                      if (global->players[z]->tank && winner >= 0)
+                        winner = -1;
+                      if (global->players[z]->tank && winner == -2)
+                        winner = z;
+                    }
+                  if (winner >= 0)
+                    {
+                      global->players[winner]->score++;
+                    }
+                  if (winner == -1)
+                    {
+                      if ((!nextTankSelected || !tank) && global->numTanks)
+                        {
+                          *tank = nextturn (global, env, skippingComputerPlay);
+                          while (! *tank)
+                            *tank = nextturn (global, env, skippingComputerPlay);
+                          (*tank)->fs = 0;
+                        }
+                      nextTankSelected = false;
+                    }
+                  if ((!humanPlayers) && (!global->computerPlayersOnly))
+                    {
+                      global->iHumanLessRounds--;
+#ifdef DEBUG
+                      cout << endl << global->iHumanLessRounds << " Rounds left for the bots to play... " << endl;
+#endif // DEBUG
+                      if ((!global->iHumanLessRounds) && (winner < 1))
+                        {
+#ifdef DEBUG
+                          cout << endl << "=======================" << endl;
+                          cout << "Bots have FINISHED!... " << endl;
+                          cout << "=======================" << endl << endl;
+#endif // DEBUG
+                          global->iHumanLessRounds = -1;
+                          team_won = NO_WIN; // will be determined later
+                          skippingComputerPlay = FALSE;
+                          lock_cclock();
+                          cclock = 0;
+                          unlock_cclock();
+                          winner = -2;
+                          if (global->numTanks > 0)
+                            {
+                              // The most healthy player wins
+                              int iMaxHealth = 1;
+                              int iHealth = 0;
+                              for (z = 0; z < global->numPlayers; z++)
+                                {
+#ifdef DEBUG
+                                  cout << z << ".: \"" << global->players[z]->getName() << "\" ";
+#endif // DEBUG
+                                  if (global->players[z]->tank)
+                                    {
+                                      iHealth = global->players[z]->tank->l + global->players[z]->tank->sh;
+                                      if (iHealth > iMaxHealth)
+                                        {
+#ifdef DEBUG
+                                          cout << "has most health! (" << iHealth << ")" << endl;
+#endif // DEBUG
+                                          iMaxHealth = iHealth;
+                                          winner = z;
+                                        }
+                                      else if (iHealth == iMaxHealth)
+                                        winner = -2; // Equal Health == draw!
+#ifdef DEBUG
+                                      else
+                                        cout << "is too weak! (" << iHealth << " max: " << iMaxHealth << ")" << endl;
+#endif // DEBUG
+                                    }
+#ifdef DEBUG
+                                  else
+                                    cout << "has no tank!" << endl;
+#endif //
+                                }
+#ifdef DEBUG
+                              cout << "winner is player " << winner << " - \"";
+                              if (winner > 0)
+                                cout << global->players[winner]->getName();
+                              else
+                                cout << "draw";
+                              cout << "\"" << endl;
+#endif // DEBUG
+                              if (winner > -1)
+                                {
+                                  if (global->players[winner]->team == TEAM_JEDI)
+                                    {
+                                      team_won = JEDI_WIN;
+                                      winner = JEDI_WIN;
+                                    }
+                                  if (global->players[winner]->team == TEAM_SITH)
+                                    {
+                                      team_won = SITH_WIN;
+                                      winner = SITH_WIN;
+                                    }
+                                }
+                            }
+#ifdef DEBUG
+                          cout << "Final Decision:" << endl;
+                          if (winner > -1)
+                            {
+                              cout << "\"";
+                              if (winner < 10)
+                                cout << global->players[winner]->getName();
+                              if (winner == JEDI_WIN)
+                                cout << "Team Jedi";
+                              if (winner == SITH_WIN)
+                                cout << "Team Sith";
+                              cout << "\" has won!" << endl;
+                            }
+                          else
+                            cout << "Round Draw!" << endl;
+#endif // DEBUG
+                        }
+                    }
+                  if (winner >= 0 || winner == -2)
+                    {
+                      env->stage = STAGE_ENDGAME;
+                      global->currTank = NULL;
+                      fi = 1;
+                      global->window.x = 0;
+                      global->window.y = 0;
+                      global->window.w = (global->screenWidth-1);
+                      global->window.h = (global->screenHeight-1);
+                    }
+                  bCount = 0;
+                  global->updateMenu = 1;
+                }
+            }
+          dclock++;
+          if (dclock > 2)
+            {
+              dclock = 0;
+              for (objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
+                {
+                  if (ltank->flashdamage)
+                    {
+                      if (ltank->flashdamage > 25 || ltank->l < 1)
+                        {
+                          ltank->damage = 0;
+                          ltank->flashdamage = 0;
+                          ltank->requireUpdate ();
+                        }
+                    }
+                }
+            }
+          env->pclock++;
+          if (env->pclock > 10)
+            env->pclock = 0;
+          if (*tank && !anyTeleporting && !anyLaserFiring)
+            {
+              // if ((*tank)->player->controlTank() == -1)
+              int status = (*tank)->player->controlTank();
+              if (status == -1)
+                return;
+              else if ( (status == -2) && (!humanPlayers) )
+              {
+                skippingComputerPlay = TRUE;
+              }
+            }
+          else if (global->computerPlayersOnly &&
+                   ((int)global->skipComputerPlay >= SKIP_HUMANS_DEAD))
+            {
+              if (env->stage == STAGE_ENDGAME)
+                return;
+            }
+          else if ((keypressed () || mouse_b) && !fi)
+            {
+              if (keypressed ())
+                k = readkey ();
+              else
+                k = 0;
+              if ((env->stage == STAGE_ENDGAME) && (roundEndCount >= WAIT_AT_END_OF_ROUND) &&
+                  (mouse_b || k >> 8 == KEY_ENTER || k >> 8 == KEY_ESC || k >> 8 == KEY_SPACE))
+                return;
+            }
+          env->mouseclock++;
+          if (env->mouseclock > 10)
+            env->mouseclock = 0;
+        }
+      frames++;
+      global->stopwindow = 1;
+      env->make_update (mouse_x, mouse_y, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
+      env->make_update (lx, ly, ((BITMAP *) (global->misc[0]))->w, ((BITMAP *) (global->misc[0]))->h);
+      global->stopwindow = 0;
+      lx = mouse_x;
+      ly = mouse_y;
+      set_clip_rect (env->db, 0, 0, (global->screenWidth-1), (global->screenHeight-1));
+      if (! global->os_mouse) show_mouse (NULL);
+      if (global->updateMenu)
+        {
+          set_clip_rect (env->db, 0, 0, (global->screenWidth-1), MENUHEIGHT - 1);
+          drawTopBar (global, env, env->db);
+        }
+      set_clip_rect (env->db, 0, MENUHEIGHT, (global->screenWidth-1), (global->screenHeight-1));
+      if (fi)
+        {
+          blit (env->sky, env->db, global->window.x, global->window.y - MENUHEIGHT, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 1);
+          masked_blit (env->terrain, env->db, global->window.x, global->window.y, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 2);
+        }
+      else
+        {
+          env->replaceCanvas ();
+        }
+
+      for (objCount = 0, count = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; count++, objCount++)
+        {
+          if (env->stage < STAGE_ENDGAME)
+            {
+              if (*tank == ltank)
+                {
+                  ltank->draw (env->db, (int)(global->slope[bCount % 360][0] * 4));
+                  ltank->requireUpdate ();
+                }
+              else
+                {
+                  ltank->draw (env->db, 0);
+                }
+              ltank->update ();
+            }
+          ltank->framelyAccounting ();
+        }
+
+      objCount = 0;
+      my_object = env->objects[objCount];
+      while (objCount < MAX_OBJECTS)
+      {
+          if (my_object)
+          {
+          my_class = my_object->getClass();
+      // for (objCount = 0; (missile = (MISSILE*)env->getNextOfClass (MISSILE_CLASS, &objCount)) && missile; objCount++)
+        if (my_class == MISSILE_CLASS)
+        {
+          missile = (MISSILE *) my_object;
+          missile->draw (env->db);
+          missile->update ();
+        }
+      // for (objCount = 0; (beam = (BEAM*)env->getNextOfClass (BEAM_CLASS, &objCount)) && beam; objCount++)
+        else if (my_class == BEAM_CLASS)
+        {
+          beam = (BEAM *) my_object;
+          beam->draw (env->db);
+          beam->update ();
+        }
+      // for (objCount = 0; (explosion = (EXPLOSION*)env->getNextOfClass (EXPLOSION_CLASS, &objCount)) && explosion; objCount++)
+        else if (my_class == EXPLOSION_CLASS)
+        {
+          explosion = (EXPLOSION *) my_object;
+          explosion->draw (env->db);
+          explosion->update ();
+        }
+      // for (objCount = 0; (teleport = (TELEPORT*)env->getNextOfClass (TELEPORT_CLASS, &objCount)) && teleport; objCount++)
+        else if (my_class == TELEPORT_CLASS)
+        {
+          teleport = (TELEPORT *) my_object;
+          if (teleport->object)
+            teleport->draw (env->db);
+          teleport->update ();
+        }
+      // for (objCount = 0; (decor = (DECOR*)env->getNextOfClass (DECOR_CLASS, &objCount)) && decor; objCount++)
+        else if (my_class == DECOR_CLASS)
+        {
+          decor = (DECOR *) my_object;
+          decor->draw (env->db);
+          decor->update ();
+        }
+      // for (objCount = 0; (floattext = (FLOATTEXT*)env->getNextOfClass (FLOATTEXT_CLASS, &objCount)) && floattext; objCount++)
+        else if (my_class == FLOATTEXT_CLASS)
+        {
+          floattext = (FLOATTEXT *) my_object;
+          floattext->draw (env->db);
+          floattext->requireUpdate ();
+          floattext->update ();
+        }
+        }        // end of if we have an object
+        objCount++;
+        my_object = env->objects[objCount];
+      }      // end of going through objects
+
+      if (satellite)
+        satellite->Draw(env->db);
+
+      if (env->stage == STAGE_ENDGAME)
+        {
+          if (roundEndCount < WAIT_AT_END_OF_ROUND + 1)
+            roundEndCount++;
+          if (roundEndCount >= WAIT_AT_END_OF_ROUND)
+            {
+              // check to see if the winner is still alive
+              int tank_index = 0;
+              int alive = false;
+              while ( (! alive) && (tank_index < global->numPlayers) )
+                {
+                  if ( ( global->players[tank_index]->tank )
+                       &&( global->players[tank_index]->tank->l > 0) )
+                  {
+                    alive = true;
+                  }
+                  tank_index++;
+                }
+
+                // moving this below so dead players lose credit
+//              if (! alive)
+//              {
+//                 winner = -2;
+//              }
+
+              if (! alive && bWinnerIsCredited)
+                {
+                  // The score needs to be reduced, of course:
+                  int count;
+                  int iTeamCount = 0;
+                  int iTeamBonus = 0;
+                  if (winner == JEDI_WIN)   // de-credit jedi team
+                    {
+                      for (count = 0; count < global->numPlayers; count++)
+                        {
+                          if (global->players[count]->team == TEAM_JEDI)
+                            {
+                              global->players[count]->score--;
+                              global->players[count]->won--;
+                              iTeamCount++;
+                            }
+                        }
+                    }
+                  else if (winner == SITH_WIN) // de-credit sith team
+                    {
+                      for (count = 0; count < global->numPlayers; count++)
+                        {
+                          if (global->players[count]->team == TEAM_SITH)
+                            {
+                              global->players[count]->score--;
+                              global->players[count]->won--;
+                              iTeamCount++;
+                            }
+                        }
+
+                    }
+                  else if (winner >= 0)    // de-credit the (ex-)winner
+                    {
+                      global->players[winner]->score--;
+                      global->players[winner]->won--;
+                      global->players[winner]->money -= (int)global->scoreRoundWinBonus;
+                    }
+                  // If it's a team, take away their money now!
+                  if (iTeamCount)
+                    {
+                      iTeamBonus = (int)(global->scoreRoundWinBonus / iTeamCount);
+                      for (count = 0; count < global->numPlayers; count++)
+                        if (	((winner==JEDI_WIN) && (global->players[count]->team == TEAM_JEDI))
+                             ||((winner==SITH_WIN) && (global->players[count]->team == TEAM_SITH))	)
+                          global->players[count]->money -= iTeamBonus;
+                    }
+                  winner = -2;
+                  bWinnerIsCredited = false; // Or it will be substracted on every loop...
+                }
+
+              if (! alive)
+              {
+                 winner = -2;
+              }
+
+
+              // if we have a winner, give them credit
+              if (alive && (winner >= 0) && (roundEndCount == WAIT_AT_END_OF_ROUND) && !bWinnerIsCredited)
+                {
+                  int count;
+                  int iTeamCount = 0;
+                  int iTeamBonus = 0;
+                  if (winner == JEDI_WIN)   // credit jedi team
+                    {
+                      for (count = 0; count < global->numPlayers; count++)
+                        {
+                          if (global->players[count]->team == TEAM_JEDI)
+                            {
+                              global->players[count]->score++;
+                              global->players[count]->won++;
+                              iTeamCount++;
+                            }
+                        }
+                    }
+                  else if (winner == SITH_WIN) // credit sith team
+                    {
+                      for (count = 0; count < global->numPlayers; count++)
+                        {
+                          if (global->players[count]->team == TEAM_SITH)
+                            {
+                              global->players[count]->score++;
+                              global->players[count]->won++;
+                              iTeamCount++;
+                            }
+                        }
+
+                    }
+                  else    // credit the winner
+                    {
+                      global->players[winner]->score++;
+                      global->players[winner]->won++;
+                      global->players[winner]->money += (int)global->scoreRoundWinBonus;
+                    }
+                  // If it's a team, do give them their money now!
+                  if (iTeamCount)
+                    {
+                      iTeamBonus = (int)(global->scoreRoundWinBonus / iTeamCount);
+                      for (count = 0; count < global->numPlayers; count++)
+                        if (	((winner==JEDI_WIN) && (global->players[count]->team == TEAM_JEDI))
+                             ||((winner==SITH_WIN) && (global->players[count]->team == TEAM_SITH))	)
+                          global->players[count]->money += iTeamBonus;
+                    }
+                  bWinnerIsCredited = true;
+                }
+
+              if ( roundEndCount >= WAIT_AT_END_OF_ROUND )
+                showRoundEndScoresAt (global, env, env->db, global->screenWidth/2, global->screenHeight/2, winner);
+                 // when we get here and it is a demo, we should bail out
+                 if (global->demo_mode)
+                    return;
+            }
+        }
+      // This four values are used to reduce access to global and increase readability (Easier to debug this way!)
+      int iLeft = 0;
+      int iRight = global->screenWidth - 1;
+      int iTop = MENUHEIGHT;
+      int iBottom = global->screenHeight - 1;
+      set_clip_rect (env->db, 0, 0, iRight, iBottom);
+      vline(env->db, iLeft, iTop, iBottom, env->wallColour);	// Left edge
+      vline(env->db, iRight, iTop, iBottom, env->wallColour);	// right edge
+      hline(env->db, iLeft, iBottom, iRight, env->wallColour);// bottom edge
+      if (global->bIsBoxed)
+        hline(env->db, iLeft, iTop, iRight, env->wallColour);// top edge
+      if (! global->os_mouse) show_mouse (env->db);
+      if (fi)
+        {
+          while (keypressed ())
+            {
+              readkey ();
+            }
+          fi = 0;
+
+          // if (env->fog) {
+          //	clear_to_color (screen, makecol (128,128,128));
+          // } else {
+          quickChange (global, env->db);
+          // }
+        }
+      else
+        {
+          env->do_updates ();
+          global->window.x = global->screenWidth;
+          global->window.y = global->screenHeight;
+          global->window.w = -1;
+          global->window.h = -1;
+        }
+#ifdef DEBUG_AIM_SHOW
+      if (!global->bASD)
+        global->bASD = true; // Now it is allowed to be true
+#endif
+    }
+}
+#endif // old gameloop
+
+
+void print_text_help()
+{
+  cout	<< "-h\tThis screen\n"
+       << "-fs\tFull screen\n"
+       << "--windowed\tRun in a window\n"
+       << "-w <width> or --width <width>\tSpecify the screen width in pixels\n"
+       << "-t <height> --tall <height>\tSpecify the screen height in pixels\n"
+       << "\tAdjust the screen size at your own risk (default is 800x600)\n"
+       << "-d <depth> or --depth <depth>\tCurrently either 16 or 32\n"
+       << "--datadir <data directory>\t Path to the data directory\n"
+       << "-c <config directory>\t Path to config and saved game directory\n"
+       << "--noconfig\t Do not load game settings from the config file.\n"
+       << "--nosound\t Disable sound\n"
+       << "--noname\t Do not show player name above tank\n"
+       << "--nonetwork\t Do not allow the game to accept network connection.\n"
+       << "--nobackground\t Do not display the green menu background.\n"
+       << "--nothread\t Do not use threads to perform background tasks.\n"
+       << "--thread\t Do use threads to perform background tasks.\n";
+}
+
+void print_text_initmsg()
+{
+  printf ( "Atomic Tanks Version %s (-h for help)\n", VERSION);
+  printf ( "Authors: \tTom Hudson (rewrite, additions, improvements)\n");
+  printf ( "\t\tStevante Software (original design)\n");
+  printf ( "\t\tKota543 Software (fixes and updates)\n");
+  printf ( "\t\tJesse Smith (additions, fixes and updates)\n");
+  printf ( "\t\tSven Eden (ai rewrite, additions, fixes and updates)\n\n");
+
+  // putchar ('\n');
+}
+
+void endgame_cleanup (GLOBALDATA *global, ENVIRONMENT *env)
+{
+  while (global->numPlayers > 0)
+    {
+      if (global->players[0]->tank)
+        delete(global->players[0]->tank);
+      // make sure networked clients say good-bye and return to old AI level
+      if (global->players[0]->type >= NETWORK_CLIENT)
+         global->players[0]->type = global->players[0]->previous_type;
+
+      global->players[0]->tank = NULL;
+      global->removePlayer(global->players[0]);
+    }
+  for (int objCount = 0; objCount < MAX_OBJECTS; objCount++)
+    {
+      if (env->objects[objCount])
+        {
+          delete(env->objects[objCount]);
+          env->objects[objCount] = NULL;
+        }
+    }
+}
+
+
+/*
+This function calls the functions which save data to a text file.
+The function requires the global data, environment and the path to
+the config file name.
+The function returns TRUE on success and FALSE on failure.
+-- Jesse
+*/
+int Save_Game_Settings_Text(GLOBALDATA *global, ENVIRONMENT *env, char *text_file)
+{
+  FILE *my_file;
+
+  my_file = fopen(text_file, (char *)"w");
+  if (! my_file)
+  {
+      perror ( "Error trying to open text file for writing.\n");
+      return FALSE;
+    }
+
+  global->saveToFile_Text (my_file);
+  env->saveToFile_Text (my_file);
+  savePlayers_Text (global, my_file);
+  fclose (my_file);
+  return TRUE;
+}
+
+/*
+This function detects changes to the global settings (mouse and sound)
+and, if a change has happened, makes the required changes to the
+game environment.
+The function returns TRUE.
+-- Jesse
+*/
+int Change_Settings(double old_mouse, double old_sound, double new_mouse, double new_sound, void *mouse_image)
+{
+  BITMAP *my_mouse_image = (BITMAP *) mouse_image;
+
+  // first, check for a change in the sound settings
+  if (old_sound != new_sound)
+    {
+      if (new_sound > 0.0)    // we turned ON sound
+      {
+            if (detect_digi_driver(DIGI_AUTODETECT))
+            {
+                if (install_sound (DIGI_AUTODETECT, MIDI_NONE, NULL) < 0)
+                    fprintf (stderr, "install_sound: failed turning on sound\n");
+            }
+            else
+                fprintf (stderr, "detect_digi_driver found no sound device\n");
+
+//          if (install_sound (DIGI_AUTODETECT, MIDI_NONE, NULL) < 0)
+//            {
+//              fprintf (stderr, "install_sound: %s", allegro_error);
+//            }
+      }
+      else if (new_sound == 0.0)  // we turned OFF sound
+        {
+          remove_sound();
+        }
+    }
+
+  // check for a change in mouse settings
+  if (old_mouse != new_mouse)
+    {
+      if (new_mouse > 0.0)   // use OS cursor
+        {
+          set_mouse_sprite(NULL);
+          show_os_cursor(MOUSE_CURSOR_ARROW);
+        }
+      else if (new_mouse == 0.0)     // use Allgero cursor
+        {
+          set_mouse_sprite (my_mouse_image);
+          set_mouse_sprite_focus (0, 0);
+        }
+    }
+  return TRUE;
+}
+
+
+
+
+
+
+/*
+This function catches the close command, usually given by
+the user pressing the close window button. We'll
+try to clean-up.
+
+Note: This function causes the app to hang in Windows.
+Make this compile on non-Windows systems only.
+*/
+void close_button_handler(void)
+{
+  // allegro_exit();
+  // exit(0);
+  my_global->close_button_pressed = true;
+}
+
+int main (int argc, char **argv)
+{
+  int signal;
+  int status;
+  string tmp;
+  ENVIRONMENT *env = NULL;
+  GLOBALDATA *global = NULL;
+  // ifstream configFile;
+  char fullPath[2048];
+  bool load_config_file = true;
+  bool bLoadingSuccess = false;
+  cmdTokens nextToken = ARGV_NOTHING_EXPECTED;
+  double temp_mouse, temp_sound;       // I wish I was not using these
+  int menu_action;
+  int playerCount, player_index;
+  #ifdef NETWORK
+  SEND_RECEIVE_TYPE *send_receive = NULL;
+  int client_socket = -1;
+  #endif
+  bool allow_network = true, allow_thread = false;
+  double music_place_holder;
+  double full_screen = FULL_SCREEN_EITHER;
+  init_cclock_lock();
+
+  quit_right_now = false;
+  global = new GLOBALDATA ();
+  if (!global)
+    {
+      perror ( "Allocating global");
+      exit (1);
+    }
+  my_global = global;
+  print_text_initmsg();
+
+  // try to find data dir
+  if (! global->Find_Data_Dir() )
+     printf("Could not find data dir.\n");
+
+  if (argc >= 2)  		/* Parse command-line switches */
+    {
+      for (int argument = 1; argument < argc; argument++)
+        {
+          tmp = argv[argument];
+
+          if (nextToken == ARGV_GFX_DEPTH)
+            {
+              global->colourDepth = strtol (tmp.c_str(), NULL, 10);
+              if (global->colourDepth != 16 &&
+                  global->colourDepth != 32)
+                {
+                  cout << "Invalid graphics depth, only 16 or 32 are valid\n";
+                  print_text_help();
+                  return 0;
+                }
+              nextToken = ARGV_NOTHING_EXPECTED;
+            }
+          else if (nextToken == ARGV_SCREEN_WIDTH)
+            {
+              global->screenWidth = strtol (tmp.c_str(), NULL, 10);
+              if (global->screenWidth < 512)
+                {
+                  cout << "Width too small (minimum 512)\n";
+                  return 0;
+                }
+              global->width_override = global->screenWidth;
+              global->halfWidth = global->screenWidth / 2;
+              nextToken = ARGV_NOTHING_EXPECTED;
+            }
+          else if (nextToken == ARGV_SCREEN_HEIGHT)
+            {
+              global->screenHeight = strtol (tmp.c_str(), NULL, 10);
+              if (global->screenHeight < 320)
+                {
+                  cout << "Height too small (minimum 320)\n";
+                  return 0;
+                }
+              global->height_override = global->screenHeight;
+              global->halfHeight = global->screenHeight / 2;
+              nextToken = ARGV_NOTHING_EXPECTED;
+            }
+          else if (nextToken == ARGV_DATA_DIR)
+            {
+              // Would use strndup, but the win compiler
+              //   doesn't know of it.
+              if (strlen (tmp.c_str()) > 2048)
+                {
+                  cout << "Datadir path too long:\n"
+                       << "\"" << tmp
+                       << "\"\n\n"
+                       << "Maximum length 2048 characters\n";
+                  return 0;
+                }
+              global->dataDir = strdup (tmp.c_str());
+              nextToken = ARGV_NOTHING_EXPECTED;
+            }
+          else if (nextToken == ARGV_CONFIG_DIR)
+            {
+              if (strlen (tmp.c_str()) > 2048)
+                {
+                  cout << "Configdir path too long:\n"
+                       << "\"" << tmp
+                       << "\"\n\n"
+                       << "Maximum length 2048 characters\n";
+                  return 0;
+                }
+              global->configDir = strdup ( tmp.c_str() );
+              nextToken = ARGV_NOTHING_EXPECTED;
+            }
+          if ( (tmp == SWITCH_HELP) || (tmp == "--help") )
+            {
+              print_text_help();
+              return 0;
+            }
+          else if (tmp == SWITCH_FULL_SCREEN)
+            {
+              screen_mode = GFX_AUTODETECT_FULLSCREEN;
+              full_screen = FULL_SCREEN_TRUE;
+            }
+          else if (tmp == SWITCH_WINDOWED)
+            {
+              screen_mode = GFX_AUTODETECT_WINDOWED;
+              full_screen = FULL_SCREEN_FALSE;
+            }
+          else if (tmp == "-d" || tmp == "--depth")
+            {
+              nextToken = ARGV_GFX_DEPTH;
+            }
+          else if (tmp == "-w" || tmp == "--width")
+            {
+              nextToken = ARGV_SCREEN_WIDTH;
+            }
+          else if (tmp == "-t" || tmp == "--tall")
+            {
+              nextToken = ARGV_SCREEN_HEIGHT;
+            }
+          else if (tmp == "--datadir")
+            {
+              nextToken = ARGV_DATA_DIR;
+            }
+          else if (tmp == "-c")
+            {
+              nextToken = ARGV_CONFIG_DIR;
+            }
+          else if (tmp == "--noconfig")
+            {
+              nextToken = ARGV_NOTHING_EXPECTED;
+              load_config_file = false;
+            }
+          else if (tmp == "--nosound")
+            {
+              nextToken = ARGV_NOTHING_EXPECTED;
+              global->sound = 0.0;
+            }
+          else if (tmp == "--noname")
+            {
+              nextToken = ARGV_NOTHING_EXPECTED;
+              global->name_above_tank = FALSE;
+            }
+          else if (tmp == "--nonetwork")
+          {
+             allow_network = false;
+             nextToken = ARGV_NOTHING_EXPECTED;
+          }
+          else if (tmp == "--nobackground")
+          {
+             global->draw_background = FALSE;
+             nextToken = ARGV_NOTHING_EXPECTED;
+          }
+          else if (tmp == "--nothread")
+          {
+             allow_thread = false;
+             nextToken = ARGV_NOTHING_EXPECTED;
+          }
+          else if (tmp == "--thread")
+          {
+             allow_thread = true;
+             nextToken = ARGV_NOTHING_EXPECTED;
+          }
+
+        }
+      if (nextToken != ARGV_NOTHING_EXPECTED)
+        {
+          cout << "Expecting an argument to follow " << tmp << endl;
+          return 0;
+        }
+    }
+
+  if (! global->configDir)
+    {
+      global->configDir = global->Get_Config_Path();
+
+      // copy the file over, if we did not yet
+      if (!Copy_Config_File(global))
+        {
+          // If it did not work, look whether the directory already exists:
+          DIR * pDestDir;
+          pDestDir = opendir(global->configDir);
+          if (!pDestDir)
+            printf( "An error has occured trying to set up Atomic Tank folders.\n");
+          else
+            {
+              closedir(pDestDir);
+              pDestDir = NULL;
+            }
+        }
+    }       // end of no config file on the command line
+
+
+
+  memset(fullPath, '\0', sizeof(fullPath));
+  FILE *old_config_file = NULL;
+  snprintf(fullPath, sizeof(fullPath) - 1, "%s/atanks-config.txt", global->configDir);
+     if (load_config_file)
+        old_config_file = fopen(fullPath, "r");
+     else
+        old_config_file = NULL;
+     if (old_config_file)
+     {
+         global->loadFromFile_Text(old_config_file);
+         // over-ride full screen setting with command line
+         if ( (full_screen == FULL_SCREEN_TRUE) || (full_screen == FULL_SCREEN_FALSE) )
+            global->full_screen = full_screen;
+         env = init_game_settings(global);
+         if (global->os_mouse)
+             show_os_cursor(MOUSE_CURSOR_ARROW); 
+         global->Load_Text_Files();
+         env->loadFromFile_Text(old_config_file);
+         loadPlayers_Text(global, env, old_config_file); 
+         fclose(old_config_file);
+         bLoadingSuccess = true;
+     }
+     
+
+  if (!bLoadingSuccess)         // no config file found or failed to load
+    {
+      global->numPermanentPlayers = 0;
+      if ( (full_screen == FULL_SCREEN_TRUE) || (full_screen == FULL_SCREEN_FALSE) )
+          global->full_screen = full_screen;
+      env = init_game_settings (global);  
+      global->Load_Text_Files();
+      if (global->os_mouse) show_os_cursor(MOUSE_CURSOR_ARROW);
+      char *defaultNames[] =
+      {
+        "Caesar",
+        "Alex",
+        "Hatshepsut",
+        "Patton",
+        "Napoleon",
+        "Attila",
+        "Catherine",
+        "Hannibal",
+        "Stalin",
+        "Mao"
+      };
+      PLAYER *tempPlayer;
+      tempPlayer = global->createNewPlayer (env);
+      tempPlayer->setName ( global->ingame->complete_text[52] );
+      options (global, env, (MENUDESC*)tempPlayer->menudesc);
+      for (int count = 0; count < 10; count++)
+        {
+          tempPlayer = global->createNewPlayer (env);
+          tempPlayer->type = rand () % (LAST_PLAYER_TYPE - 1) + 1;
+          tempPlayer->setName (defaultNames[count]);
+          tempPlayer->generatePreferences();
+        }
+    }
+
+  status = Load_Weapons_Text(global);
+  if (! status)
+  {
+      printf( "An error occured trying to read weapons file.\n");
+      exit(1);
+  }
+
+  snprintf(fullPath, sizeof(fullPath) - 1, "%s/atanks-config.txt", global->configDir); 
+  global->temp_screenWidth = global->screenWidth;
+  global->temp_screenHeight = global->screenHeight;
+  global->halfWidth = global->screenWidth / 2;
+  global->halfHeight = global->screenHeight / 2;
+  global->menuBeginY = (global->screenHeight - 400) / 2;
+  if (global->menuBeginY < 0) global->menuBeginY = 0;
+  global->menuEndY = global->screenHeight - global->menuBeginY;
+
+  title (global);
+  env->bitmap_filenames = Find_Bitmaps(global, & (env->number_of_bitmaps) );
+  env->my_sky_gradients = (const gradient **) sky_gradients;
+  env->my_land_gradients = (const gradient **) land_gradients;
+  Create_Music_Folder(global);
+#ifdef THREADS
+  if (allow_thread)
+  {
+  pthread_t sky_thread, terrain_thread;
+  pthread_create( &sky_thread, NULL, Generate_Sky_In_Background, (void *) env);
+  pthread_create( &terrain_thread, NULL, Generate_Land_In_Background, (void *) env);
+  }    // end of allowing threads
+#endif
+
+  // new networking area
+  #ifdef THREADS
+  #ifdef NETWORK
+  pthread_t network_thread;
+  if (global->check_for_updates)
+  {
+         global->update_string = Check_For_Update("projects.sourceforge.net",
+                 "version.txt", "atanks.sourceforge.net", VERSION);
+  }
+
+  if ( (global->enable_network) && (allow_network) )
+  {
+      send_receive = (SEND_RECEIVE_TYPE *) calloc(1, sizeof(SEND_RECEIVE_TYPE));
+      if (! send_receive)
+         printf("Could not create networking data.\n");
+  }
+  else
+      send_receive = NULL;
+  if (send_receive)
+  {
+     send_receive->listening_port = (int) global->listen_port;
+     send_receive->global = global;
+     // quit option already cleared by calloc call
+     pthread_create( &network_thread, NULL, Send_And_Receive, (void *) send_receive);
+  }
+  #endif
+  #endif
+   
+  do
+    {
+      //show the main menu
+      global->wr_lock_command();
+      global->command = GLOBAL_COMMAND_MENU;
+      global->unlock_command();
+      signal = menu (global, env);
+      if (global->client_message)
+      {
+         free(global->client_message);
+         global->client_message = NULL;
+      }
+
+      // did the user signal to quit the game
+      global->wr_lock_command();
+      if (signal == SIG_QUIT_GAME) global->command = GLOBAL_COMMAND_QUIT;
+      global->unlock_command();
+
+      //determine which menu item is selected
+      switch (global->get_command())
+        {
+        case GLOBAL_COMMAND_HELP:
+          scrollTextList (global, env, global->instructions);
+          break;
+        case GLOBAL_COMMAND_OPTIONS:
+          // save old settings
+          temp_mouse = global->os_mouse;
+          temp_sound = global->sound;
+
+          options(global, env, NULL);
+          if (! Save_Game_Settings_Text(global, env, fullPath))
+          {
+              perror ( "atanks.cpp: Failed to save game settings from atanks::main()!");
+          }
+
+          // check for changes to settings
+          Change_Settings(temp_mouse, temp_sound, global->os_mouse, global->sound, global->misc[0]);
+          global->Change_Font();
+          global->Update_Player_Menu();
+          break;
+        case GLOBAL_COMMAND_PLAYERS:
+          //loop until done editing players where return value is not ESC
+          do
+          {
+             status = editPlayers(global, env);
+          }
+          while ( (status != KEY_ESC << 8) && (status != KEY_ENTER << 8) );
+          break;
+        case GLOBAL_COMMAND_CREDITS:
+          credits(global, env);
+          break;
+        case GLOBAL_COMMAND_QUIT:
+          break;
+        case GLOBAL_COMMAND_NETWORK:
+          #ifdef NETWORK
+          client_socket = Setup_Client_Socket(global->server_name, global->server_port);
+          if (client_socket >= 0)
+          {
+             int keep_playing = TRUE;
+             printf("Ready to play networked\n");
+             while (keep_playing)
+             {
+                 keep_playing = Game_Client(global, env, client_socket);
+             }
+             Clean_Up_Client_Socket(client_socket);
+          }
+          else
+            printf("Unable to connect to server %s, port %s.\n", global->server_name, global->server_port);
+          #else
+            printf("This version of Atanks is not compiled to handle network games.\n");
+          #endif
+          break;
+        case GLOBAL_COMMAND_DEMO:
+           global->demo_mode = true;
+           global->load_game = false;
+           music_place_holder = global->play_music;
+           global->play_music = 0.0;
+
+           // set up a bunch of players (non-human, less than 10)
+           playerCount = 0;
+           global->numPlayers = 0;
+           for (player_index = 0; player_index < global->numPermanentPlayers; player_index++)
+           {
+               if ( (global->allPlayers[player_index]->type > HUMAN_PLAYER) && (playerCount < MAXPLAYERS) )
+               {
+                  global->addPlayer (global->allPlayers[player_index]);
+                  playerCount++;
+               }
+           }
+
+           player_index = (int) global->skipComputerPlay;
+           global->skipComputerPlay = SKIP_NONE;
+           global->currentround = 1;      // might add more later
+           while ( (global->currentround > 0) && (! global->close_button_pressed) )
+           {
+                game(global, env);
+                if ((global->get_command() == GLOBAL_COMMAND_QUIT) || (global->get_command() == GLOBAL_COMMAND_MENU))
+                      break;
+                global->currentround--;
+                // skipping winner screen for now
+           }
+           endgame_cleanup(global, env);
+           global->demo_mode = false;
+           global->skipComputerPlay = player_index;
+           global->play_music = music_place_holder;
+           break;
+
+        default: //must have commanded to play game
+          menu_action = selectPlayers(global, env);
+          if (menu_action == ESC_MENU)
+            break;
+
+          //selected players, start new game
+          else
+            {
+              // make sure the game has a name
+              if (! global->game_name[0])
+                strcpy(global->game_name,global->ingame->complete_text[53] );
+
+              newgame (global, env);
+
+              // play the game for the selected number of rounds
+              // for (global->currentround = (int)global->rounds; global->currentround > 0; global->currentround--)
+              if (! global->load_game) global->currentround = (int) global->rounds;
+              while ( (global->currentround > 0) && (! global->close_button_pressed) )
+                {
+                  game (global, env);      // play a round
+                  if (global->background_music)
+                  {
+                       stop_sample(global->background_music);
+                       destroy_sample(global->background_music);
+                       global->background_music = NULL;
+                  }
+                      
+                  // if user selected to quit or return to main menu during game play
+                  if ((global->get_command() == GLOBAL_COMMAND_QUIT) || (global->get_command() == GLOBAL_COMMAND_MENU))                 
+                  {
+                    #ifdef NETWORK
+                    global->Send_To_Clients("CLOSE");
+                    #endif
+                    break;
+                  }
+
+                  global->currentround--;
+                  #ifdef NETWORK
+                  if (global->currentround != 0)    // end of the round
+                     global->Send_To_Clients("ROUNDEND");
+                  #endif
+                }
+
+              // only show winner if finished all rounds
+              if ( (global->currentround == 0) && (! global->close_button_pressed) )
+              {
+                  char buffer[256], *my_player;
+                 
+                  // strcpy(buffer, "GAMEEND"); 
+                  // global->Send_To_Clients(buffer);
+                  my_player = do_winner (global, env);
+                  if (my_player)
+                  {
+                     snprintf(buffer, 256, "GAMEEND The game went to %s.", my_player);
+                     free(my_player);
+                  }
+                  else
+                     strcpy(buffer, "GAMEEND");
+                  #ifdef NETWORK
+                  global->Send_To_Clients(buffer);
+                  #endif
+                  do_quote(global, env);
+              }
+
+              endgame_cleanup (global, env);
+            }    // end of start new game
+
+          break;
+
+        }      // end of menu switch
+
+    }
+  while ( (global->get_command() != GLOBAL_COMMAND_QUIT) );
+
+  // print out if there is an update
+  if ( (global->update_string) && (global->update_string[0]) )
+  {
+      cout << global->update_string << endl;
+      free(global->update_string);
+      global->update_string = NULL;
+  }
+
+  #ifdef THREADS
+  #ifdef NETWORK
+  if (send_receive)
+  {
+     send_receive->shut_down = TRUE;
+     // sleep(1);
+     LINUX_REST;
+     // we should probably wait and do a join here, but if the network thread does not
+     // finish after a full second, then something has gone wrong anyway and we should move on....
+     free(send_receive);
+  }
+  #endif
+  #endif
+
+  if (! Save_Game_Settings_Text(global, env, fullPath))
+    {
+      // This is a very critical issue, but as we are ending here, we just report it
+      perror ( "atanks.cpp: Failed to save game settings from atanks::main()!");
+      allegro_exit ();
+      cout << "See http://atanks.sourceforge.net for the latest news and downloads." << endl;
+
+      return(1);
+    }
+  else
+    {
+      Save_Game_Settings_Text(global, env, fullPath);
+      allegro_exit ();
+      cout << "See http://atanks.sourceforge.net for the latest news and downloads." << endl;
+
+      return(0);
+    }
+}
+
+
+END_OF_MAIN ()
+
+
+
+
+/*
+Adding function here to avoid patch incompatibilties.
+This function should launch all items from all of
+the living tanks.
+*/
+void doLaunch(GLOBALDATA *global, ENVIRONMENT *env)
+{
+  // If we're in simultaneous mode, launch all selections
+  int i;
+  int savestage = env->stage;
+  TANK *tank;
+
+  if (global->turntype != TURN_SIMUL)
+    return;
+
+  for (i = 0; i < global->maxNumTanks; i++)
+    {
+       tank = env->order[i];
+       if (tank)
+        {
+          if (! tank->player->skip_me)
+            tank->activateCurrentSelection();
+          else
+            tank->player->skip_me = false;
+          tank->player->time_left_to_fire = global->max_fire_time;
+        }
+    }
+
+  env->stage = savestage;
+}
+
+
+// load a colour from a file
+bool popColo(int &aData, ifstream &ifsFile)
+{
+  bool bResult = false;
+  if (ifsFile.is_open())
+  {
+      int iColor = 0;
+      ifsFile >> iColor; // reads the next found number
+      if (ifsFile.good())
+      {
+          // Now transform to color:
+          aData = makecol((iColor & 0x00ff0000) >> 16,
+                          (iColor & 0x0000ff00) >>  8,
+                           iColor & 0x000000ff       );
+          bResult = true;
+       }
+  }
+  return bResult;
+}
+
+
+int *Sort_Scores(GLOBALDATA *global)
+{
+  static int order[MAXPLAYERS];
+  int counter;
+  bool made_change = true;
+  int temp;
+
+  for (counter = 0; counter < global->numPlayers; counter++)
+    order[counter] = counter;
+
+  // bubble sort
+  while (made_change)
+    {
+      made_change = false;
+      counter = 0;
+      // check for swap
+      while (counter < (global->numPlayers - 1) )
+        {
+          if ( global->players[ order[counter] ]->score < global->players[ order[counter + 1] ]->score )
+            {
+              temp = order[counter];
+              order[counter] = order[counter + 1];
+              order[counter + 1] = temp;
+              made_change = true;
+            }
+
+          counter++;
+        }    // end of check for swaps
+    }         // end of bubble sort
+
+  return order;
+}
+
+
+
+
+// Client version of the game
+// Really, this loop should do some basic things.
+// 1. Find out what the landscape should look like from the server.
+// 2. Place tanks on the battle field
+// 3. Create missiles, beam weapons and such when the server asks us to
+// 4. Get input from the player and forward it to the server.
+// 5. Clean up at the end of the round.
+//
+// Function return TRUE if everything went well or FALSE
+// if an error occured.
+#ifdef NETWORK
+
+int Game_Client(GLOBALDATA *global, ENVIRONMENT *env, int socket_number)
+{
+    int surface_x = 1, tank_position = 1, team_number = 1, name_number = 1;
+    int weapon_number = 1, item_number = 1, tank_health = 1;
+    int end_of_round = FALSE, keep_playing = FALSE;
+    int game_stage = CLIENT_VERSION;
+    char buffer[BUFFER_SIZE];
+    int incoming;
+    int my_key;
+    int time_clock = 0;
+    int screen_update = FALSE;
+    int count;      // generic counter
+    int stuff_going_down = FALSE;    // explosions, missiles etc on the screen
+    VIRTUAL_OBJECT *my_object;
+    BEAM *beam;
+    EXPLOSION *explosion;
+    MISSILE *missile;
+    TELEPORT *teleport;
+    FLOATTEXT *floattext;
+    int my_class, object_count;
+    bool fired = false;
+    
+
+    global->dMaxVelocity = (double)MAX_POWER * (100.0 / (double)global->frames_per_second) / 100.0;
+    clear_to_color (env->terrain, PINK);    // get terrain ready
+    clear_to_color(env->db, BLACK);
+
+    // clean up old text
+    for (count = 0; (floattext = (FLOATTEXT*)env->getNextOfClass (FLOATTEXT_CLASS, &count)) && floattext; count++)
+    {
+         floattext->newRound();
+         delete floattext;
+    }
+
+    Create_Sky(env, global);     // so we have a background
+    strcpy(buffer, "VERSION");
+    write(socket_number, buffer, strlen(buffer));
+
+    while (! end_of_round)
+    {
+        // check for waiting input from the server
+        incoming = Check_For_Incoming_Data(socket_number);
+        if (incoming)
+        {
+           int bytes_read;
+
+           memset(buffer, '\0', BUFFER_SIZE);
+           bytes_read = read(socket_number, buffer, BUFFER_SIZE);  
+           if (bytes_read > 0)
+           {
+                // do something with this input
+                if (! strncmp(buffer, "CLOSE", 5) )
+                {
+                   end_of_round = TRUE;
+                   keep_playing = FALSE;
+                   printf("Got close message.\n");
+                   global->client_message = global->ingame->complete_text[81];
+                }
+                else if (! strncmp(buffer, "NOROOM", 6) )
+                {
+                   end_of_round = TRUE;
+                   keep_playing = FALSE;
+                   printf("The server is full or the game has not started. Please try again later.\n");
+                   global->client_message = global->ingame->complete_text[80];
+                }
+                else if (! strncmp(buffer, "GAMEEND", 7) )
+                {
+                    end_of_round = TRUE;
+                    keep_playing = FALSE;
+                    printf("The game is over.\n");
+                    if ( strlen(buffer) > 7)
+                        global->client_message = strdup(& (buffer[8])) ;
+                    else
+                        global->client_message = strdup(global->ingame->complete_text[82]);
+                }
+                else if (! strncmp(buffer, "ROUNDEND", 8) )
+                {
+                   end_of_round = TRUE;
+                   keep_playing = TRUE;
+                   printf("Round is over.\n");
+                }
+                   
+                else         // not a special command, parse it
+                {
+                  if ( Parse_Client_Data(global, env, buffer) )
+                  {
+                      if (game_stage < CLIENT_PLAYING)
+                         game_stage++;
+                
+                      // Request more information
+                      if (game_stage < CLIENT_PLAYING)
+                      {
+                         switch (game_stage)
+                         {
+                            case CLIENT_SCREEN: strcpy(buffer, "SCREEN"); break;
+                            case CLIENT_WIND: strcpy(buffer, "WIND"); break;
+                            case CLIENT_NUMPLAYERS: strcpy(buffer, "NUMPLAYERS"); break;
+                            case CLIENT_TANK_POSITION: strcpy(buffer, "TANKPOSITION 0"); break;
+                            case CLIENT_SURFACE: strcpy(buffer, "SURFACE 0"); break;
+                            case CLIENT_WHOAMI: strcpy(buffer, "WHOAMI");
+                                                screen_update = TRUE; break;
+                            case CLIENT_WEAPONS: strcpy(buffer, "WEAPON 0"); break;
+                            case CLIENT_ITEMS:   strcpy(buffer, "ITEM 0"); break;
+                            case CLIENT_ROUNDS: strcpy(buffer, "ROUNDS"); break;
+                            case CLIENT_TEAMS: strcpy(buffer, "TEAMS 0"); 
+                                               global->updateMenu = TRUE; break;
+                            case CLIENT_WALL_TYPE: strcpy(buffer, "WALLTYPE"); break;
+                            case CLIENT_BOXED: strcpy(buffer, "BOXED"); break;
+                            case CLIENT_NAME: strcpy(buffer, "PLAYERNAME 0"); break;
+                            case CLIENT_TANK_HEALTH: strcpy(buffer, "HEALTH 0"); break;
+                            default: buffer[0] = '\0';
+                         }
+                         write(socket_number, buffer, strlen(buffer));
+                       }   // end of getting more info
+                   }    // our game stage went up
+                   else  // we got data, but our game stage did not go up
+                   {
+                       if (fired)
+                       {
+                           if ( (global->client_player) && (global->client_player->tank) )
+                           {
+                               fired = false;
+                               if (global->client_player->tank->cw < WEAPONS)
+                                   sprintf(buffer, "WEAPON %d", global->client_player->tank->cw);
+                               else
+                                   sprintf(buffer, "ITEM %d", global->client_player->tank->cw - WEAPONS);
+                               write(socket_number, buffer, strlen(buffer));
+                           }
+                       }
+                       else if (game_stage == CLIENT_SURFACE)
+                       {
+                           sprintf(buffer, "SURFACE %d", surface_x);
+                           write(socket_number, buffer, strlen(buffer));
+                           surface_x++;
+                       }
+                       else if (game_stage == CLIENT_ITEMS)
+                       {
+                            sprintf(buffer, "ITEM %d", item_number);
+                            write(socket_number, buffer, strlen(buffer));
+                            item_number++;
+                       }
+                       else if (game_stage == CLIENT_TANK_POSITION)
+                       {
+                            sprintf(buffer, "TANKPOSITION %d", tank_position);
+                            write(socket_number, buffer, strlen(buffer));
+                            tank_position++;
+                            if (tank_position >= global->numPlayers)
+                              tank_position = 0;
+                       }
+                       else if (game_stage == CLIENT_TANK_HEALTH)
+                       {
+                            sprintf(buffer, "HEALTH %d", tank_health);
+                            write(socket_number, buffer, strlen(buffer));
+                            tank_health++;
+                            if (tank_health >= global->numPlayers)
+                                tank_health = 0;
+                       }
+                       else if (game_stage == CLIENT_TEAMS)
+                       {
+                            sprintf(buffer, "TEAMS %d", team_number);
+                            write(socket_number, buffer, strlen(buffer));
+                            team_number++;
+                       }
+                       else if (game_stage == CLIENT_NAME)
+                       {
+                            sprintf(buffer, "PLAYERNAME %d", name_number);
+                            write(socket_number, buffer, strlen(buffer));
+                            name_number++;
+                       }
+                       else if (game_stage == CLIENT_WEAPONS)
+                       {
+                            sprintf(buffer, "WEAPON %d", weapon_number);
+                            write(socket_number, buffer, strlen(buffer));
+                            weapon_number++;
+                       }
+                       else if (game_stage == CLIENT_PLAYING)
+                       {
+                           time_clock++;
+                           if (time_clock > 1)   // check positions every few inputs
+                           {
+                               time_clock = 0;
+                               if (surface_x < global->screenWidth)
+                               {
+                                   game_stage = CLIENT_SURFACE;
+                                   sprintf(buffer, "SURFACE %d", surface_x);
+                                   write(socket_number, buffer, strlen(buffer));
+                                   surface_x++;
+                               }
+                               else
+                               {
+                                 game_stage = CLIENT_TANK_POSITION;
+                                 tank_position = 1;
+                                 strcpy(buffer, "TANKPOSITION 0");
+                                 write(socket_number, buffer, strlen(buffer));
+                               }    // game stage stuff
+                           }
+                       }        // end of playing commands
+                   }
+
+                }      // end of we got something besides the close command
+
+           }
+           else    // connection was broken
+           {
+              close(socket_number);
+              printf("Server closed connection.\n");
+              end_of_round = TRUE;
+           }
+        }
+
+        object_count = 0;
+        while (object_count < MAX_OBJECTS)
+        {
+            my_object = env->objects[object_count];
+            if (my_object)
+            {
+            my_class = my_object->getClass();
+            if (my_class == BEAM_CLASS)
+            {
+                beam = (BEAM *) my_object;
+                beam->applyPhysics();
+                if (beam->destroy)
+                {
+                    beam->requireUpdate();
+                    beam->update();
+                    delete beam;
+                }
+                stuff_going_down = TRUE;
+            }
+            else if (my_class == MISSILE_CLASS)
+            {
+                missile = (MISSILE *) my_object;
+                missile->hitSomething = 0;
+                missile->applyPhysics();
+                missile->triggerTest();
+                if (missile->destroy)
+                {
+                    missile->requireUpdate();
+                    missile->update();
+                    delete missile;
+                }
+                stuff_going_down = TRUE;
+            }
+            else if (my_class == EXPLOSION_CLASS)
+            {
+                explosion = (EXPLOSION *) my_object;
+                explosion->explode ();
+                explosion->applyPhysics ();
+                if (explosion->destroy)
+                {
+                  explosion->requireUpdate ();
+                  explosion->update ();
+                  delete explosion;
+                }
+                stuff_going_down = TRUE;
+            }
+            else if (my_class == TELEPORT_CLASS)
+            {
+                teleport = (TELEPORT *) my_object;
+                teleport->applyPhysics ();
+                if (teleport->destroy)
+                {
+                  teleport->requireUpdate ();
+                  teleport->update ();
+                  delete teleport;
+                  time_clock = 2;
+                }
+                stuff_going_down = TRUE;
+            }
+            else if (my_class == FLOATTEXT_CLASS)
+            {
+                floattext = (FLOATTEXT *) my_object;
+                floattext->applyPhysics ();
+                if (floattext->destroy)
+                {
+                  floattext->requireUpdate();
+                  floattext->update();
+                  delete floattext;
+                }
+            }
+            else if (my_class == DECOR_CLASS)
+            {
+                 DECOR *decor = (DECOR *) my_object;
+                 decor->applyPhysics ();
+                 if (decor->destroy)
+                 {
+                    decor->requireUpdate ();
+                    decor->update ();
+                    delete decor;
+                 }
+            }
+            }      // end of got valid object
+            object_count++;
+        }
+
+        slideLand(global, env);
+
+        // update everything on the screen
+        if (global->updateMenu)
+        {
+          set_clip_rect (env->db, 0, 0, (global->screenWidth-1), MENUHEIGHT - 1);
+          drawTopBar (global, env, env->db);
+        }
+
+        set_clip_rect (env->db, 0, MENUHEIGHT, (global->screenWidth-1), (global->screenHeight-1));
+        if (screen_update)
+        {
+          blit (env->sky, env->db, global->window.x, global->window.y - MENUHEIGHT, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 1);
+          masked_blit (env->terrain, env->db, global->window.x, global->window.y, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 2);
+          drawTopBar(global, env, env->db);
+          int iLeft = 0;
+          int iRight = global->screenWidth - 1;
+          int iTop = MENUHEIGHT;
+          int iBottom = global->screenHeight - 1;
+          set_clip_rect (env->db, 0, 0, iRight, iBottom);
+          vline(env->db, iLeft, iTop, iBottom, env->wallColour);    // Left edge
+          vline(env->db, iRight, iTop, iBottom, env->wallColour);   // right edge
+          hline(env->db, iLeft, iBottom, iRight, env->wallColour);// bottom edge
+          if (global->bIsBoxed)
+              hline(env->db, iLeft, iTop, iRight, env->wallColour);// top edge
+
+          env->make_update(0, 0, global->screenWidth, global->screenHeight);
+        }
+        else
+        {
+          env->replaceCanvas ();
+        }
+
+        for (count = 0; count < global->numPlayers; count++)
+        {
+             if ( (global->players[count]) && (global->players[count]->tank) )
+             {
+                global->players[count]->tank->draw(env->db, 0);
+                global->players[count]->tank->update();
+             }
+        }
+        // env->do_updates();
+        screen_update = TRUE;
+
+        object_count = 0;
+        while (object_count < MAX_OBJECTS)
+        {
+            my_object = env->objects[object_count];
+            if (my_object)
+            {
+               my_class = my_object->getClass();
+
+               if (my_class == BEAM_CLASS)
+               {
+                  beam = (BEAM *) my_object;
+                  beam->draw (env->db);
+                  beam->update ();
+                }
+                else if (my_class == MISSILE_CLASS)
+                {
+                    missile = (MISSILE *) my_object;
+                    missile->draw(env->db);
+                    missile->update();
+                }
+                else if (my_class == EXPLOSION_CLASS)
+                {
+                   explosion = (EXPLOSION *) my_object;
+                   explosion->draw (env->db);
+                   explosion->update ();
+                }
+                else if (my_class == TELEPORT_CLASS)
+                {
+                     teleport = (TELEPORT *) my_object;
+                     if (teleport->object)
+                        teleport->draw (env->db);
+                     teleport->update ();
+                }
+                else if (my_class == DECOR_CLASS)
+                {
+                     DECOR *decor = (DECOR *) my_object;
+                     decor->draw(env->db);
+                     decor->update();
+                }
+                else if (my_class == FLOATTEXT_CLASS)
+                {
+                     floattext = (FLOATTEXT *) my_object;
+                     floattext->draw (env->db);
+                     floattext->requireUpdate ();
+                     floattext->update ();
+               }
+            }       // end of valid object
+            object_count++;
+        }     // end of while updating objects
+        env->do_updates();
+
+        
+        // check for input from the user
+        if ( keypressed() )
+        {
+           my_key = readkey();
+           my_key = my_key >> 8;
+           if (my_key == KEY_SPACE)
+           {
+              Client_Fire(global->client_player, socket_number);
+              fired = true;
+           }
+           else if (my_key == KEY_ESC)
+           {
+              end_of_round = TRUE;
+              close(socket_number);
+           }
+           else if (my_key == KEY_UP)
+           {
+              Client_Power(global->client_player, CLIENT_UP);
+           }
+           else if (my_key == KEY_DOWN)
+           {
+              Client_Power(global->client_player, CLIENT_DOWN);
+           }
+           else if (my_key == KEY_LEFT)
+           {
+              Client_Angle(global->client_player, CLIENT_LEFT);
+           }
+           else if (my_key == KEY_RIGHT)
+           {
+              Client_Angle(global->client_player, CLIENT_RIGHT);
+           }
+           else if ( (my_key == KEY_Z) || (my_key == KEY_BACKSPACE) )
+           {
+               Client_Cycle_Weapon(global->client_player, CYCLE_BACK);
+           }
+           else if ( (my_key == KEY_C) || (my_key == KEY_TAB) )
+           {
+               Client_Cycle_Weapon(global->client_player, CYCLE_FORWARD);
+               global->updateMenu = TRUE;
+           }
+
+           screen_update = FALSE;
+           global->updateMenu = TRUE;
+        }
+
+        // pause for a moment
+        // if (game_stage < CLIENT_PLAYING)
+        if (stuff_going_down)
+        {
+            LINUX_SLEEP;
+            stuff_going_down = FALSE;
+        }
+    }
+
+    // we should clean up here
+    for (count = 0; count < global->numPlayers; count++)
+    {
+       if (global->players[count]->tank)
+       {
+           delete global->players[count]->tank;
+           global->players[count]->tank = NULL;
+       }
+    }
+ 
+    return keep_playing;
+}
+
+#endif
+
diff --git a/src/atanks.rc b/src/atanks.rc
new file mode 100644
index 0000000..52a074d
--- /dev/null
+++ b/src/atanks.rc
@@ -0,0 +1,37 @@
+/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */
+/* DO NOT EDIT! */
+
+#include <windows.h> // include for version info constants
+
+A ICON MOVEABLE PURE LOADONCALL DISCARDABLE "../atanks.ico"
+ALLEGRO_ICON ICON "../atanks.ico"
+
+//
+// TO CHANGE VERSION INFORMATION, EDIT PROJECT OPTIONS...
+//
+1 VERSIONINFO
+FILEVERSION 3,2,0,24
+PRODUCTVERSION 3,2,0,24
+FILETYPE VFT_APP
+{
+  BLOCK "StringFileInfo"
+     {
+         BLOCK "100904E4"
+         {
+             VALUE "CompanyName", ""
+             VALUE "FileVersion", ""
+             VALUE "FileDescription", "A fun tank game, which plays like Scorched Earth."
+             VALUE "InternalName", ""
+             VALUE "LegalCopyright", "See credits.txt and COPYING.txt"
+             VALUE "LegalTrademarks", ""
+             VALUE "OriginalFilename", "atanks.exe"
+             VALUE "ProductName", "Atomic Tanks"
+             VALUE "ProductVersion", ""
+         }
+     }
+  BLOCK "VarFileInfo"
+     {
+         VALUE "Translation", 0x1009, 1252
+     }
+}
+
diff --git a/src/beam.cpp b/src/beam.cpp
new file mode 100644
index 0000000..8cba4ef
--- /dev/null
+++ b/src/beam.cpp
@@ -0,0 +1,286 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+#include "environment.h"
+#include "globaldata.h"
+#include "physobj.h"
+#include "player.h"
+#include "decor.h"
+#include "tank.h"
+#include "beam.h"
+
+
+BEAM::~BEAM ()
+{
+  requireUpdate();
+  update();
+  _env->make_bgupdate (_current.x, _current.y, _current.w, _current.h);
+  _env->make_bgupdate (_old.x, _old.y, _old.w, _old.h);
+  _env->removeObject (this);
+  weap    = NULL;
+  _global = NULL;
+  _env    = NULL;
+   delete [] points;
+}
+
+void tracePath (int *targetX, int *targetY, GLOBALDATA *global, ENVIRONMENT *env, int minRange, double xpos, double ypos, int angle)
+{
+  double dx = global->slope[angle][0];
+  double dy = global->slope[angle][1];
+  double tx = xpos, ty = ypos;
+  int hitSomething = 0;
+  int range = 0;
+
+  while ((!hitSomething) && tx > -10 &&
+         tx < global->screenWidth + 10 && ty > -10 &&
+         ty < global->screenHeight &&
+         (getpixel (env->terrain, (int)tx, (int)ty) == PINK))
+    {
+      TANK *ltank;
+      for (int objCount = 0; (ltank = (TANK*)env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
+        {
+          if (range > minRange && tx > ltank->x - TANKWIDTH && tx < ltank->x + TANKWIDTH && ty > ltank->y && ty < ltank->y + TANKHEIGHT && ltank->l > 0)
+            {
+              hitSomething = 1;
+              ltank->requireUpdate ();
+            }
+        }
+      tx += dx;
+      ty += dy;
+      range++;
+    }
+  *targetX = (int)tx;
+  *targetY = (int)ty;
+}
+
+BEAM::BEAM (GLOBALDATA *global, ENVIRONMENT *env, double xpos, double ypos, int fireAngle,
+            int weaponType):PHYSICAL_OBJECT(),weap(NULL),points(NULL)
+{
+  player = NULL;
+  drag = 0.00;
+  mass = 0;
+  clock = 500;
+  age = 0;
+  setEnvironment (env);
+  _align = LEFT;
+  _global = global;
+  #ifdef NETWORK
+  char buffer[256];
+  sprintf(buffer, "BEAM %d %d %d %d", (int) xpos, (int) ypos, fireAngle, weaponType);
+  global->Send_To_Clients(buffer);
+  #endif
+  x = xpos;
+  y = ypos;
+  angle = fireAngle % 360;
+  type = weaponType;
+  if (type < WEAPONS)
+    weap = &(weapon[type]);
+  else
+    weap = &(naturals[type - WEAPONS]);
+  radius = weap->radius;
+
+
+  if (type >= SML_LIGHTNING && type <= LRG_LIGHTNING)
+    {
+      damage = (double)weap->damage / (10 * (type - SML_LIGHTNING + 1));
+      maxAge = 10 * (type - SML_LIGHTNING + 1);
+      numPoints = 4 + rand () % 10;
+      color = WHITE;
+      play_sample ((SAMPLE *) _global->sounds[LIGHTNING_SOUND], 128 + (radius * 10), 128, 500 + (radius * 50), 0);
+    }
+  else
+    {
+      numPoints = 2;
+      if (type >= SML_LAZER && type <= LRG_LAZER)
+        damage = (double)weap->damage / (10 * (type - SML_LAZER + 1));
+      maxAge = 10 * (type - SML_LAZER + 1);
+      color = makecol (255 - (type - SML_LAZER) * 64, 128, 64 + (type - SML_LAZER) * 64);
+    }
+  tracePath (&targetX, &targetY, global, env, radius + 2, x, y, angle);
+  xv = targetX - x;
+  yv = targetY - y;
+  points = new int[numPoints * 2];
+  if (!points)
+    {
+      perror ( "beam.cc: Failed allocating memory for points in BEAM::BEAM");
+      // exit (1);
+    }
+  setLightningPath ();
+}
+
+void BEAM::setLightningPath ()
+{
+  int point = 0;
+  double x1 = x, y1 = y;
+
+  do
+    {
+      double offX, offY;
+      if (point > 0 && point < numPoints - 1)
+        {
+          offX = (perlin2DPoint (1.0, 20, 12746 + x1, y1, 0.3, 6) + 1) * (radius * 10);
+          offY = (perlin2DPoint (1.0, 20, x1, 1273 + y1, 0.3, 6) + 1) * (radius * 10);
+        }
+      else
+        {
+          offX = 0;
+          offY = 0;
+        }
+      points[point * 2] = (int)(x1 + offX);
+      points[point * 2 + 1] = (int)(y1 + offY);
+
+      x1 += xv / (numPoints - 1);
+      y1 += yv / (numPoints - 1);
+      point++;
+    }
+  while (point < numPoints);
+}
+
+void BEAM::initialise ()
+{
+  PHYSICAL_OBJECT::initialise ();
+  drag = 0.00;
+  mass = 0;
+  clock = 500;
+  age = 0;
+}
+
+int BEAM::applyPhysics ()
+{
+  TANK *ltank;
+  DECOR *decor;
+
+  age++;
+  circlefill (_env->terrain, targetX, targetY, radius, PINK);
+  for (int col = targetX - radius - 1; col < targetX + radius + 1; col++)
+    setSlideColumnDimensions (_global, _env, col, true);
+
+  if (age > maxAge)
+    destroy = TRUE;
+
+  for (int objCount = 0; (ltank = (TANK*)_env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
+    {
+      if (targetX > ltank->x - TANKWIDTH - radius && targetX < ltank->x + TANKWIDTH + radius && targetY > ltank->y - radius && targetY < ltank->y + TANKHEIGHT + radius && ltank->l > 0)
+        {
+          // hitSomething = 1;
+          ltank->requireUpdate ();
+
+          // make sure a player is involved
+          if (player)
+            ltank->damage += damage * player->damageMultiplier;
+          else
+            ltank->damage += damage;
+
+          ltank->creditTo = player;
+          if (destroy)
+            ltank->applyDamage ();
+        }
+    }
+  decor = new DECOR (_global, _env, targetX, targetY, rand () % 6 - 3, rand () % 6 - 3, radius, DECOR_SMOKE);
+  if (!decor)
+    {
+      perror ( "beam.cc: Failed allocating memory for decor in applyPhysics");
+      // exit (1);
+    }
+  tracePath (&targetX, &targetY, _global, _env, radius + 2, x, y, angle);
+  setLightningPath ();
+
+  return (hitSomething);
+}
+
+int beamRadius;
+void lazerPoint (BITMAP *dest, int x1, int y1, int color)
+{
+  circlefill (dest, x1, y1, beamRadius, color);
+}
+
+void lightningPoint (BITMAP *dest, int x1, int y1, int age)
+{
+  double pointRad = (perlin2DPoint (1.0, 2, x1 + age, y1, 0.3, 6) + 1) / 2 * beamRadius + 1;
+  double offX = (perlin2DPoint (1.0, 20, 127846 + x1, y1 + age, 0.3, 6) + 1) * beamRadius;
+  double offY = (perlin2DPoint (1.0, 20, x1 + age, 12973 + y1, 0.3, 6) + 1) * beamRadius;
+
+  circlefill (dest, x1 + (int)offX, y1 + (int)offY, (int)pointRad, WHITE);
+}
+
+void BEAM::draw (BITMAP *dest)
+{
+  int x1, y1, x2, y2;
+  setUpdateArea ((int)x - radius, (int)y - radius, (int)x + radius * 2, (int)y + radius * 2);
+
+  drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+  _env->current_drawing_mode = DRAW_MODE_TRANS;
+  set_trans_blender (0, 0, 0, (int)50);
+  if (type >= SML_LIGHTNING && type <= LRG_LIGHTNING)
+    {
+      beamRadius = radius;
+      for (int point = 1; point < numPoints; point++)
+        {
+
+          x1 = points[(point - 1) * 2];
+          y1 = points[(point - 1) * 2 + 1];
+          x2 = points[point * 2];
+          y2 = points[point * 2 + 1];
+
+          do_line (dest, x1, y1, x2, y2, age, lightningPoint);
+          addUpdateArea (MIN(x1,x2) - radius * 6,
+                         MIN(y1,y2) - radius * 6,
+                         MAX(x1,x2) + radius * 2 * 6,
+                         MAX(y1,y2) + radius * 2 * 6);
+        }
+    }
+  else if (type >= SML_LAZER && type <= LRG_LAZER)
+    {
+      beamRadius = radius;
+      for (int point = 1; point < numPoints; point++)
+        {
+
+          x1 = points[(point - 1) * 2];
+          y1 = points[(point - 1) * 2 + 1];
+          x2 = points[point * 2];
+          y2 = points[point * 2 + 1];
+
+          do_line (dest, x1, y1, x2, y2, color, lazerPoint);
+          //do_line (dest, x1, y1, x2, y2, color, lightningPoint);
+          addUpdateArea (MIN(x1,x2) - radius * 2,
+                         MIN(y1,y2) - radius * 2,
+                         MAX(x1,x2) + radius * 2 * 2,
+                         MAX(y1,y2) + radius * 2 * 2);
+        }
+    }
+  drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+  _env->current_drawing_mode = DRAW_MODE_SOLID;
+  requireUpdate ();
+}
+
+/*void BEAM::update ()
+{
+	_env->combineUpdates = FALSE;
+	VIRTUAL_OBJECT::update ();
+	_env->combineUpdates = TRUE;
+}*/
+
+int BEAM::isSubClass (int classNum)
+{
+  if (classNum == BEAM_CLASS)
+    return (TRUE);
+  else
+    return (FALSE);
+  //return (PHYSICAL_OBJECT::isSubClass (classNum));
+}
diff --git a/src/beam.h b/src/beam.h
new file mode 100644
index 0000000..7bdfaa7
--- /dev/null
+++ b/src/beam.h
@@ -0,0 +1,74 @@
+#ifndef BEAM_DEFINE
+#define BEAM_DEFINE
+
+/*
+atanks - obliterate each other with oversize weapons
+Copyright (C) 2003  Thomas Hudson
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+*/
+
+#include "main.h"
+#include "virtobj.h"
+#include "physobj.h"
+
+#define LIGHTNING_SOUND 12
+
+enum beamType
+{
+  LIGHTNING_BEAM,
+  LAZER_BEAM
+};
+
+class BEAM: public PHYSICAL_OBJECT
+  {
+  public:
+    int	radius;
+    int	length;
+    double	damage;
+    int	clock;
+    int	type;
+    WEAPON	*weap;
+    int	*points;	// Allows jagged lines
+    int	numPoints;
+    int	color;
+    int	targetX;
+    int	targetY;
+
+    virtual ~BEAM ();
+    //BEAM (GLOBALDATA *global, ENVIRONMENT *env, double tX, double tY, double tXv, double tYv, int weaponType);
+    BEAM (GLOBALDATA *global, ENVIRONMENT *env, double xpos, double ypos, int angle, int weaponType);
+    void	setLightningPath();
+    void	initialise ();
+    void	draw (BITMAP *dest);
+    //void	update ();
+    int	applyPhysics ();
+    virtual int	isSubClass (int classNum);
+    inline virtual int	getClass ()
+    {
+      return (BEAM_CLASS);
+    }
+    inline virtual void setEnvironment(ENVIRONMENT *env)
+    {
+      if (!_env || (_env != env))
+        {
+          _env = env;
+          _index = _env->addObject (this);
+        }
+    }
+  };
+
+#endif
+
diff --git a/src/button.cpp b/src/button.cpp
new file mode 100644
index 0000000..fcd2da9
--- /dev/null
+++ b/src/button.cpp
@@ -0,0 +1,67 @@
+/*
+This file contains funcions for the BUTTON class. These
+are being moved out of the atanks.cc file.
+-- Jesse
+*/
+
+#include "button.h"
+
+BUTTON::BUTTON(GLOBALDATA *global, ENVIRONMENT *env, int x1, int y1,
+               char *text1, BITMAP *bmp1, BITMAP *hover1, BITMAP *depressed1):_global(NULL),_env(NULL),text(NULL),
+               bmp(NULL),hover(NULL),depressed(NULL),click(NULL)
+{
+  _global = global;
+  _env = env;
+  location.x = x1;
+  location.y = y1;
+  text = text1;
+  click = (SAMPLE *)_global->sounds[8];
+  bmp = bmp1;
+  hover = hover1;
+  depressed = depressed1;
+  location.w = bmp->w;
+  location.h = bmp->h;
+  xl = location.x + bmp->w;
+  yl = location.y + bmp->h;
+}
+
+
+
+void BUTTON::draw (BITMAP *dest)
+{
+  draw_sprite (dest, (BITMAP *)(isMouseOver())?((isPressed())?depressed:hover):bmp, location.x, location.y);
+  if (text)
+    textout_centre_ex (dest, font, text, location.x+75, location.y + 6, WHITE, -1);
+  _env->make_update (location.x, location.y, xl, yl);
+}
+
+
+int BUTTON::isMouseOver ()
+{
+  if ((mouse_x >= location.x) &&
+      (mouse_y >= location.y) &&
+      (mouse_x <= xl) &&
+      (mouse_y <= yl))
+    {
+      return (1);
+    }
+  else
+    {
+      return (0);
+    }
+}
+
+
+int BUTTON::isPressed()
+{
+  if ((mouse_b == 1) && isMouseOver ())
+    {
+      play_sample (click, 128, 128, 1000, 0);
+      return 1;
+    }
+  else
+    {
+      return 0;
+    }
+}
+
diff --git a/src/button.h b/src/button.h
new file mode 100644
index 0000000..6dfe362
--- /dev/null
+++ b/src/button.h
@@ -0,0 +1,30 @@
+#ifndef BUTTON_HEADER_
+#define BUTTON_HEADER_
+
+#include "globaldata.h"
+#include "environment.h"
+
+class BUTTON
+  {
+    GLOBALDATA *_global;
+    ENVIRONMENT *_env;
+
+  public:
+    BOX location;
+    int xl, yl;
+    char *text;
+    BITMAP *bmp;
+    BITMAP *hover;
+    BITMAP *depressed;
+    SAMPLE *click;
+
+    BUTTON (GLOBALDATA *global, ENVIRONMENT *env, int x1, int y1, char *text1,
+            BITMAP *bmp1, BITMAP *hover1, BITMAP *depressed1);
+
+    int     isPressed (); //if button pressed returns 1
+    int     isMouseOver (); //Cursor is over button
+    void    draw (BITMAP *dest);
+  };
+
+#endif
+
diff --git a/src/client.cpp b/src/client.cpp
new file mode 100644
index 0000000..c060e69
--- /dev/null
+++ b/src/client.cpp
@@ -0,0 +1,518 @@
+#ifdef NETWORK
+
+#include "menu.h"
+#include "button.h"
+#include "team.h"
+#include "files.h"
+#include "satellite.h"
+#include "update.h"
+#include "network.h"
+#include "client.h"
+#include "beam.h"
+#include "explosion.h"
+#include "missile.h"
+#include "teleport.h"
+#include "floattext.h"
+
+#include "sky.h"
+#ifdef THREADS
+#include <pthread.h>
+#endif
+
+
+
+
+
+// Here we try to match the buffer with an action. We then attempt to
+// perform the action. Remember, this is a command from the server, so
+// it is either giving us some info or telling us to create something.
+int Parse_Client_Data(GLOBALDATA *global, ENVIRONMENT *env, char *buffer)
+{
+   char args[CLIENT_ARGS][BUFFER_SIZE];
+   char letter;
+   int dest_string;
+   int line_length = strlen(buffer);
+   int source_index = 0, dest_index = 0;
+  
+   // clear buffers
+   for (dest_string = 0; dest_string < CLIENT_ARGS; dest_string++)
+       memset(args[dest_string], '\0', BUFFER_SIZE);
+
+   dest_string = 0; 
+   // copy buffer into cmd and argument variables
+   while ( ( source_index < line_length ) && (dest_string < CLIENT_ARGS) )
+   { 
+       letter = buffer[source_index];
+       if ( letter == ' ' )
+       {
+           letter = '\0';
+           args[dest_string][dest_index] = letter;
+           dest_index = 0;
+           dest_string++;
+       }
+       else
+       {
+          args[dest_string][dest_index] = letter;
+          dest_index++;
+       }
+       source_index++;
+   }
+  
+   // let us see what we have
+   if (! strcmp(args[0], "SERVERVERSION") )
+   {
+       if (! strcmp(args[1], VERSION) )
+          printf("Server version matchs us. OK.\n");
+       else
+          printf("Server version is %s, we are %s. This is likely to cause problems.\n",
+                 args[1], VERSION);
+       return TRUE;
+   }
+   else if (! strcmp(args[0], "CURRENTPOSITION") )
+   {
+      if ( (global->client_player) && (global->client_player->tank) )
+      {
+          sscanf(args[1], "%lf", &(global->client_player->tank->x));
+          sscanf(args[2], "%lf", &(global->client_player->tank->y));
+      }
+   }
+   else if (! strcmp(args[0], "BEAM") )
+   {
+      double my_x, my_y;
+      int my_angle, my_type;
+      BEAM *new_beam;
+      sscanf(args[1], "%lf", &my_x);
+      sscanf(args[2], "%lf", &my_y);
+      sscanf(args[3], "%d", &my_angle);
+      sscanf(args[4], "%d", &my_type);
+      new_beam = new BEAM(global, env, my_x, my_y, my_angle, my_type);
+   }
+   else if (! strcmp(args[0], "BOXED"))
+   {
+       int got_box;
+       sscanf(args[1], "%d", &got_box);
+       if (got_box)
+           global->bIsBoxed = true;
+       else
+           global->bIsBoxed = false;
+       return TRUE;
+   }
+   else if (! strcmp(args[0], "EXPLOSION") )
+   {
+        double my_x, my_y;
+        int my_type;
+        EXPLOSION *explosion;
+        sscanf(args[1], "%lf", &my_x);
+        sscanf(args[2], "%lf", &my_y);
+        sscanf(args[3], "%d", &my_type);
+        explosion = new EXPLOSION(global, env, my_x, my_y, my_type);
+        return FALSE;
+   }
+   else if (! strcmp(args[0], "ITEM"))
+   {
+       int item_index, amount;
+       sscanf(args[1], "%d", &item_index);
+       sscanf(args[2], "%d", &amount);
+       if ( (item_index >= 0) && (item_index < ITEMS) &&
+            (amount >= 0) && (amount <= 99) )
+       {
+          global->client_player->ni[item_index] = amount;
+       }
+       if (item_index == (ITEMS - 1) )
+          return TRUE;
+   }
+   else if (! strcmp(args[0], "HEALTH") )
+   {
+       int tank_index;
+       int health, shield, shield_type;
+       char some_text[32];
+
+       sscanf(args[1], "%d", &tank_index);
+       if (tank_index >= 0)
+       {
+          sscanf(args[2], "%d", &health );
+          sscanf(args[3], "%d", &shield );
+          sscanf(args[4], "%d", &shield_type);
+          global->players[tank_index]->tank->l = health;
+          global->players[tank_index]->tank->sh = shield;
+          global->players[tank_index]->tank->sht = shield_type;
+          // set the text over the tank
+          sprintf(some_text, "%d", health);
+          global->players[tank_index]->tank->healthText->set_text(some_text);
+          global->players[tank_index]->tank->healthText->set_color(global->players[tank_index]->color);
+          sprintf(some_text, "%d", shield);
+          global->players[tank_index]->tank->shieldText->set_text(some_text);
+          global->players[tank_index]->tank->healthText->set_color(global->players[tank_index]->color);
+       }
+       if (tank_index == (global->numPlayers - 1) )
+          return TRUE;
+       else
+          return FALSE;
+   }
+   else if (! strcmp(args[0], "WIND") )
+   {
+       sscanf(args[1], "%lf", & (env->wind) );
+       return TRUE;
+   }
+   else if (! strcmp(args[0], "MISSILE") )
+   {
+       int my_type;
+       double my_x, my_y, delta_x, delta_y;
+       MISSILE *missile;
+       sscanf(args[1], "%lf", &my_x);
+       sscanf(args[2], "%lf", &my_y);
+       sscanf(args[3], "%lf", &delta_x);
+       sscanf(args[4], "%lf", &delta_y);
+       sscanf(args[5], "%d", &my_type);
+       missile = new MISSILE(global, env, my_x, my_y, delta_x, delta_y, my_type);
+       if (! missile)
+         printf("Attempted to create missile failed in client code.\n");
+       return FALSE;
+   }
+   else if (! strcmp(args[0], "NUMPLAYERS") )
+   {
+      int counter;
+      sscanf(args[1], "%d", & (global->numPlayers) );
+      // create the players in question
+      for (counter = 0; counter < global->numPlayers; counter++)
+      {
+          global->players[counter] = new PLAYER(global, env);
+          global->players[counter]->tank = new TANK(global, env);
+          global->players[counter]->tank->player = global->players[counter];
+          global->players[counter]->tank->initialise();
+          global->players[counter]->tank->nameText->set_text("");
+      }
+      return TRUE;
+   }
+   // ping is a special case where we do not do anything it is just
+   // making sure we are still here because we are not talking
+   else if (! strcmp(args[0], "PING"))
+   {
+       return FALSE;
+   }
+   else if (! strcmp(args[0], "PLAYERNAME") )
+   {
+       int number;
+       sscanf(args[1], "%d", &number);
+       if ( (number < global->numPlayers) && (number >= 0) )
+           global->players[number]->setName(args[2]);
+       if (number == (global->numPlayers - 1) )
+          return TRUE;    
+   }
+   else if (! strcmp(args[0], "REMOVETANK") )
+   {
+       int index;
+       sscanf(args[1], "%d", &index);
+       if ( (index >= 0) && (index < global->numPlayers) )
+       {
+           // make sure this tank exists before we get rid of it
+           if ( global->players[index]->tank )
+           {
+               delete global->players[index]->tank;
+               global->players[index]->tank = NULL;
+           }
+       }
+   }
+   else if (! strcmp(args[0], "ROUNDS") )
+   {
+       sscanf(args[1], "%lf", &global->rounds);
+       sscanf(args[2], "%d", &global->currentround);
+       return TRUE;
+   }
+   else if (! strcmp(args[0], "SURFACE") )
+   {
+       int x, y;
+       int index;
+       int colour_change = 0;
+       int green = 150;
+       int my_height;
+
+       sscanf(args[1], "%d", &x);
+       sscanf(args[2], "%d", &y);
+       env->surface[x] = y;
+       my_height = global->screenHeight - y;
+       my_height = my_height / 50;      // ratio of change
+       // fill in terrain...
+       for (index = y; index < global->screenHeight; index++)
+       {
+           putpixel(env->terrain, x, index, makecol(0, green, 0));
+           colour_change++;
+           if (colour_change >= my_height)
+           {
+              colour_change = 0;
+              green--;
+           }
+       }
+       if (x >= (global->screenWidth - 1) )
+         return TRUE;
+   }
+   else if (! strcmp(args[0], "SCREEN") )
+   {
+       int width, height;
+
+       sscanf(args[1], "%d", &width);
+       sscanf(args[2], "%d", &height);
+       if ( (width == global->screenWidth) &&
+            (height == global->screenHeight) )
+           printf("Host's screen resolution matches ours.\n");
+       else
+       {
+           printf("Host's screen resolution is %d by %d.\n", width, height);
+           printf("Ours is %d by %d. This is going to cause problems!\n",
+                  global->screenWidth, global->screenHeight);
+        }
+       return TRUE;
+   }
+   else if (! strcmp(args[0], "TANKPOSITION") )
+   {
+       int player_number, x, y;
+       PLAYER *my_player;
+
+       sscanf(args[1], "%d", &player_number);
+       my_player = global->players[player_number];
+       if ( (my_player) && (my_player->tank) )
+       {
+           sscanf(args[2], "%d", &x);
+           sscanf(args[3], "%d", &y);
+           my_player->tank->x = x;
+           my_player->tank->y = y;
+       }
+       if (player_number == (global->numPlayers - 1))
+         return TRUE;
+   }
+   else if (! strcmp(args[0], "TEAM") )
+   {
+       int player_number, colour;
+       double the_team;
+       sscanf(args[1], "%d", &player_number);
+       sscanf(args[2], "%lf", & the_team);
+       if ( (the_team < global->numPlayers) && (the_team >= 0) )
+       {
+            global->players[player_number]->team = the_team;
+            if (the_team == TEAM_JEDI)
+                colour = makecol(0, 255, 0);
+            else if (the_team == TEAM_SITH)
+                colour = makecol(255, 0, 255);
+            else if (the_team == TEAM_NEUTRAL)
+                colour = makecol(0, 0, 255);
+            if (global->players[player_number] == global->client_player)
+                colour = makecol(255, 0, 0);
+            global->players[player_number]->color = colour;
+       }
+       if (player_number == (global->numPlayers - 1) )
+          return TRUE; 
+   }
+   else if (! strcmp(args[0], "TELEPORT") )
+   {
+       int player_num;
+       int new_x, new_y;
+       TELEPORT *my_teleport;
+
+       sscanf(args[1], "%d", &player_num);
+       sscanf(args[2], "%d", &new_x);
+       sscanf(args[3], "%d", &new_y);
+       if ( (player_num >= 0) && (player_num < global->numPlayers) &&
+            (global->players[player_num]->tank) )
+       {
+          my_teleport = new TELEPORT(global, env, global->players[player_num]->tank,
+                            new_x, new_y, TANKHEIGHT * 4 + GUNLENGTH, 120);
+       }
+           
+   }
+   else if (! strcmp(args[0], "WALLTYPE"))
+   {
+        sscanf(args[1], "%d", &(env->current_wallType));
+        switch (env->current_wallType)
+        {
+           case WALL_RUBBER:
+           env->wallColour = makecol(0, 255, 0); // GREEN;
+           break;
+           case WALL_STEEL:
+           env->wallColour = makecol(255, 0, 0); // RED;
+           break;
+           case WALL_SPRING:
+           env->wallColour = makecol(0, 0, 255); //BLUE;
+           break;
+           case WALL_WRAP:
+           env->wallColour = makecol(255, 255, 0); // YELLOW;
+           break;
+        }
+       return TRUE;
+   }
+   else if (! strcmp(args[0], "WEAPON") )
+   {
+       int weapon_index, amount;
+       sscanf(args[1], "%d", &weapon_index);
+       sscanf(args[2], "%d", &amount);
+       if ( (weapon_index >= 0) && (weapon_index < WEAPONS) &&
+            (amount >= 0) && (amount <= 99) )
+       {
+            global->client_player->nm[weapon_index] = amount;
+       }
+       if (weapon_index == (WEAPONS - 1))
+          return TRUE;
+   }
+   else if (! strcmp(args[0], "YOUARE") )
+   {
+       int index;
+       sscanf(args[1], "%d", &index );
+       if ( (index >= 0) && (index < global->numPlayers) )
+       {
+          global->client_player = global->players[index];
+          global->currTank = global->client_player->tank;
+       }
+       return TRUE;
+   }
+
+   return FALSE;
+}
+
+
+
+
+void Create_Sky(ENVIRONMENT *env, GLOBALDATA *global)
+{
+ if ( (env->custom_background) && (env->bitmap_filenames) )
+  {
+     if ( env->sky) destroy_bitmap(env->sky);
+     env->sky = load_bitmap( env->bitmap_filenames[ rand() % env->number_of_bitmaps ], NULL);
+  }
+
+    if ( (! env->custom_background) || (! env->sky) )
+    {
+      if ( env->sky ) destroy_bitmap(env->sky);
+#ifdef THREADS
+      if (env->get_waiting_sky())
+      {
+           env->sky = env->get_waiting_sky();
+           env->lock(env->waiting_sky_lock);
+           env->waiting_sky = NULL;
+           env->unlock(env->waiting_sky_lock);
+      }
+      else
+      {
+#endif
+      env->sky = create_bitmap( global->screenWidth, global->screenHeight - MENUHEIGHT);
+      generate_sky (global, env->sky, sky_gradients[global->cursky],
+                   (global->ditherGradients ? GENSKY_DITHERGRAD : 0 ) |
+                   (global->detailedSky ? GENSKY_DETAILED : 0 )  );
+#ifdef THREADS
+      }
+#endif
+  }
+
+}         // end of create sky function
+
+
+
+// Send a shot command to the server
+int Client_Fire(PLAYER *my_player, int my_socket)
+{
+   char buffer[256];
+
+   if (!my_player) return FALSE;
+   if (! my_player->tank) return FALSE;
+
+   sprintf(buffer, "FIRE %d %d %d", my_player->tank->cw, my_player->tank->a,
+                   my_player->tank->p);
+   write(my_socket, buffer, strlen(buffer));
+   return TRUE;
+}
+
+
+// Adjust our power on the client side
+int Client_Power(PLAYER *my_player, int more_or_less)
+{
+    if ( (my_player) && (my_player->tank) )
+    {
+        if ( (more_or_less == CLIENT_UP) && (my_player->tank->p < 1996) )
+           my_player->tank->p += 5;
+        else if ( (more_or_less == CLIENT_DOWN) && (my_player->tank->p > 5) )
+           my_player->tank->p -= 5;
+        return TRUE;
+    }
+    return FALSE;
+}
+
+
+
+int Client_Angle(PLAYER *my_player, int left_or_right)
+{
+    if (! my_player) return FALSE;
+    if (! my_player->tank) return FALSE;
+
+    if ( (left_or_right == CLIENT_LEFT) && (my_player->tank->a < 270) )
+         my_player->tank->a++;
+    else if ( (left_or_right == CLIENT_RIGHT) && (my_player->tank->a > 90) )
+         my_player->tank->a--;
+    return TRUE;
+}
+
+
+int Client_Cycle_Weapon(PLAYER *my_player, int forward_or_back)
+{
+   bool found = false;
+
+   if (! my_player->tank)
+       return FALSE;
+
+   while (! found)
+   {
+        if (forward_or_back == CYCLE_FORWARD)
+            my_player->tank->cw++;
+        else 
+            my_player->tank->cw--;
+
+        if (my_player->tank->cw >= THINGS)
+           my_player->tank->cw = 0;
+        else if (my_player->tank->cw < 0)
+           my_player->tank->cw = THINGS - 1;
+
+        // check if we have found a weapon
+        if (my_player->tank->cw < WEAPONS)
+        {
+             if (my_player->nm[my_player->tank->cw])
+                 found = true;
+        }
+        else      // an item
+        {
+             if ( (item[my_player->tank->cw - WEAPONS].selectable) &&
+                  (my_player->ni[my_player->tank->cw - WEAPONS]) )
+                 found = true;
+        }
+   }
+   return TRUE;
+}
+
+
+
+// This function takes an error number and returns a string
+// which contains useful information about that error.
+// On success, a pointer to char is returned.
+// On failure, a NULL is returned.
+// The returned pointer does NOT need to be freed.
+char *Explain_Error(GLOBALDATA *global, int error_code)
+{
+    char *my_message = NULL;
+
+    switch (error_code)
+    {
+       case CLIENT_ERROR_VERSION:
+           my_message = global->ingame->complete_text[77];
+       break;
+       case CLIENT_ERROR_SCREENSIZE:
+           my_message = global->ingame->complete_text[78];
+       break;
+       case CLIENT_ERROR_DISCONNECT:
+           my_message = global->ingame->complete_text[79];
+       break;
+    }
+
+    return my_message;
+}
+
+
+
+
+#endif
+
diff --git a/src/client.h b/src/client.h
new file mode 100644
index 0000000..488ed37
--- /dev/null
+++ b/src/client.h
@@ -0,0 +1,67 @@
+#ifndef CLIENT_HEADER_FILE__
+#define CLIENT_HEADER_FILE__
+
+#include "globaldata.h"
+#include "environment.h"
+
+#ifdef NETWORK
+
+#define CLIENT_VERSION 1
+#define CLIENT_SCREEN 2
+#define CLIENT_WIND 3
+#define CLIENT_NUMPLAYERS 4
+#define CLIENT_WHOAMI 5
+#define CLIENT_WEAPONS 6
+#define CLIENT_ITEMS 7
+#define CLIENT_ROUNDS 8
+#define CLIENT_NAME 9
+#define CLIENT_WALL_TYPE 10
+#define CLIENT_BOXED 11
+#define CLIENT_TEAMS 12
+#define CLIENT_SURFACE 13
+#define CLIENT_TANK_POSITION 14
+#define CLIENT_TANK_HEALTH 15
+#define CLIENT_PLAYING 16
+
+#define CLIENT_UP 1
+#define CLIENT_DOWN 2
+#define CLIENT_LEFT 3
+#define CLIENT_RIGHT 4
+#define CYCLE_BACK 10
+#define CYCLE_FORWARD 20
+
+#define CLIENT_ARGS 6
+
+#endif
+
+#define CLIENT_ERROR_VERSION 1
+#define CLIENT_ERROR_SCREENSIZE 2
+#define CLIENT_ERROR_DISCONNECT 3
+
+
+// This function takes some data from the server
+// and tries to figure out what to do with it.
+// The game stage is returned.
+int Parse_Client_Data(GLOBALDATA *global, ENVIRONMENT *env, char *buffer);
+
+
+// Draws a background
+void Create_Sky(ENVIRONMENT *env, GLOBALDATA *global);
+
+// Sends fire command to the server
+// Message must be in format "FIRE item angle power"
+int Client_Fire(PLAYER *my_player, int my_socket);
+
+
+int Client_Power(PLAYER *my_player, int up_or_down);
+
+int Client_Angle(PLAYER *my_player, int left_or_right);
+
+int Client_Cycle_Weapon(PLAYER *my_player, int forward_or_back);
+
+// Take an error code and return a string with readable info.
+// The returning string should NOT be freed after use.
+char *Explain_Error(GLOBALDATA *global, int error_code);
+
+#endif
+
diff --git a/src/decor.h b/src/decor.h
new file mode 100644
index 0000000..ff29a2f
--- /dev/null
+++ b/src/decor.h
@@ -0,0 +1,169 @@
+#ifndef DECOR_DEFINE
+#define DECOR_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "main.h"
+#include "physobj.h"
+#include "environment.h"
+#include "globaldata.h"
+
+enum	decorTypes
+{
+  DECOR_SMOKE
+};
+
+class DECOR: public PHYSICAL_OBJECT
+  {
+  public:
+    int	type;
+    int	radius;
+    int	color;
+
+    /* --- constructor --- */
+    inline DECOR (GLOBALDATA *global, ENVIRONMENT *env, double xpos, double ypos, double xvel, double yvel,
+                  int maxRadius, int decorType):PHYSICAL_OBJECT()
+    {
+      type = decorType;
+      initialise ();
+      setEnvironment (env);
+      player = NULL;
+      _align = LEFT;
+      _global = global;
+      x = xpos;
+      y = ypos;
+      xv = xvel;
+      yv = yvel;
+      if (maxRadius <= 3)
+        radius = 3;
+      else
+        radius = 3 + (rand () % (maxRadius - 3));
+    }
+
+    /* --- destructor --- */
+    inline virtual ~DECOR ()
+    {
+      _env->removeObject (this);
+      _global = NULL;
+      _env    = NULL;
+    }
+
+    /* --- non-inline methods --- */
+
+    /* --- inline methods --- */
+
+    inline virtual void	draw (BITMAP *dest)
+    {
+      if (!destroy)
+        {
+          int iCalcRadius = radius;
+          if (type == DECOR_SMOKE) iCalcRadius = (int)(iCalcRadius * (4.0 * age / maxAge)); // The older, the larger...
+          drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
+          set_trans_blender (0, 0, 0, 255 - (255 * age / maxAge));
+          circlefill (dest, (int)x, (int)y, iCalcRadius, color);
+          drawing_mode (DRAW_MODE_SOLID, NULL, 0, 0);
+          setUpdateArea ( (int)x - (iCalcRadius * 2) - 1,
+                          (int)y - (iCalcRadius * 2) - 1,
+                          iCalcRadius * 4 + 2,
+                          iCalcRadius * 4 + 2);
+          requireUpdate ();
+        }
+    }
+
+    inline virtual int	applyPhysics ()
+    {
+      /** Update: Smoke will age faster, if the wind is stronger! **/
+      int iAgeMod = 1;
+      if (_env->wind && (type == DECOR_SMOKE))
+        iAgeMod = (int)round(fabs(_env->wind / (_env->windstrength / 2.0))) + 1;
+      /* This produces: (with max wind = 8)
+       * wind = 1 : round(1 / (8 / 2)) + 1 = round(1 / 4) + 1 = 0 + 1 = 1 <-- normal aging
+       * wind = 4 : round(4 / (8 / 2)) + 1 = round(4 / 4) + 1 = 1 + 1 = 2 <-- raised aging
+       * wind = 6 : round(6 / (8 / 2)) + 1 = round(6 / 4) + 1 = 2 + 1 = 3 <-- fast aging
+       * wind = 8 : round(8 / (8 / 2)) + 1 = round(8 / 4) + 1 = 2 + 1 = 3 <-- fast aging */
+      age += iAgeMod;
+
+      if (!physics)
+        {
+          double xaccel = (_env->wind - xv) / mass * drag * _env->viscosity;
+          xv += xaccel;
+          x += xv;
+          if (x < 1 || x > (_global->screenWidth-1))
+            {
+              destroy = TRUE;
+            }
+          double yaccel = (-1 - yv) / mass * drag * _env->viscosity;
+          yv += yaccel;
+          if (y + yv >= _global->screenHeight)
+            {
+              yv = -yv * 0.5;
+              xv *= 0.95;
+            }
+          y += yv;
+        }
+      if (age > maxAge)
+        {
+          destroy = TRUE;
+        }
+
+      return (hitSomething);
+    }
+
+    inline virtual void	initialise ()
+    {
+      PHYSICAL_OBJECT::initialise ();
+      physics = 0;
+      age = 0;
+      if (type == DECOR_SMOKE)
+        {
+          int tempCol = 128 + (rand () % 64);
+          color = makecol (tempCol, tempCol, tempCol);
+          mass = 1 + ((double)(rand () % 5) / 10);
+          drag = 0.9 + ((double)(rand () % 90) / 100);
+          maxAge = 20 + (rand () % 90);
+        }
+    }
+
+    inline virtual int	isSubClass (int classNum)
+    {
+      if (classNum == DECOR_CLASS)
+        return (TRUE);
+      else
+        return (FALSE);
+    }
+
+    inline virtual int	getClass ()
+    {
+      return (DECOR_CLASS);
+    }
+
+    inline virtual void setEnvironment(ENVIRONMENT *env)
+    {
+      if (!_env || (_env != env))
+        {
+          _env = env;
+          _index = _env->addObject (this);
+        }
+    }
+
+  };
+
+#endif
diff --git a/src/environment.cpp b/src/environment.cpp
new file mode 100644
index 0000000..132069a
--- /dev/null
+++ b/src/environment.cpp
@@ -0,0 +1,1168 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "environment.h"
+#include "globaldata.h"
+#include "virtobj.h"
+#include "missile.h"
+#include "tank.h"
+#include "files.h"
+
+ENVIRONMENT::ENVIRONMENT (GLOBALDATA *global):_global(global),done(NULL),fp(NULL),h(NULL),surface(NULL),dropTo(NULL),
+    velocity(NULL),dropIncr(NULL),height(NULL),db(NULL),terrain(NULL),sky(NULL)
+{
+  gravity = 0.150;
+  viscosity = 0.5;
+  landSlideType = LANDSLIDE_GRAVITY;
+  landSlideDelay = MAX_GRAVITY_DELAY;
+  windstrength = 8;
+  windvariation = 1;
+  weapontechLevel = itemtechLevel = 5;
+  landType = LANDTYPE_RANDOM;
+  meteors = 0;
+  lightning = 0;
+  satellite = 0.0;
+  falling_dirt_balls = 0.0;
+  fog = 0;
+  wallType = 0.0;
+  dBoxedMode		=	0.0;	// default is 0 = off
+  dFadingText		=	0.0;	// defaults to 0 for backwards compatibilities sake
+  dShadowedText	=	0.0;	// defaults to 0 for backwards compatibilities sake
+  current_wallType = 0;
+  custom_background = 0.0;
+  bitmap_filenames = NULL;
+  number_of_bitmaps = 0;
+  current_drawing_mode = DRAW_MODE_SOLID;
+
+  done = new char[global->screenWidth];
+  fp = new int[global->screenWidth];
+  h = new int[global->screenWidth];
+  surface = new int[global->screenWidth];
+  dropTo = new int[global->screenWidth];
+  velocity = new double[global->screenWidth];
+  dropIncr = new double[global->screenWidth];
+  height = new double[global->screenWidth];
+
+  db = create_bitmap (global->screenWidth, global->screenHeight);
+  if (!db)
+    cout << "Failed to create db bitmap: " << allegro_error;
+  terrain = create_bitmap (global->screenWidth, global->screenHeight);
+  if (!terrain)
+    cout << "Failed to create terrain bitmap: " << allegro_error;
+  sky = create_bitmap (global->screenWidth, global->screenHeight - MENUHEIGHT);
+  if (!sky)
+    cout << "Failed to create sky bitmap: " << allegro_error;
+  waiting_sky = NULL;
+  waiting_terrain = NULL;
+  _global = global;
+  global_tank_index = 0;
+
+  initialise ();
+  waiting_sky_lock = init_lock(waiting_sky_lock);
+  waiting_terrain_lock = init_lock(waiting_terrain_lock);
+}
+
+
+
+/** @brief ~ENVIRONMENT default dtor
+ *  *   *
+ *   *     * Cleanly remove created objects
+ *    *       */
+ENVIRONMENT::~ENVIRONMENT()
+{
+  int count;
+
+  destroy_lock(waiting_sky_lock);
+  destroy_lock(waiting_terrain_lock);
+
+  if (db)      destroy_bitmap(db);      db      = NULL;
+  if (sky)     destroy_bitmap(sky);     sky     = NULL;
+  if (waiting_sky) destroy_bitmap(sky); waiting_sky = NULL;
+  if (terrain) destroy_bitmap(terrain); terrain = NULL;
+
+  _global = NULL;
+
+  if (done)     delete [] (done);     done = NULL;
+  if (fp)       delete [] (fp);       fp = NULL;
+  if (h)        delete [] (h);        h = NULL;
+  if (surface)  delete [] (surface);  surface = NULL;
+  if (dropTo)   delete [] (dropTo);   dropTo = NULL;
+  if (velocity) delete [] (velocity); velocity = NULL;
+  if (dropIncr) delete [] (dropIncr); dropIncr = NULL;
+  if (height)   delete [] (height);   height = NULL;
+  if (bitmap_filenames)
+  {
+     for (count = 0; count < number_of_bitmaps; count++)
+     {
+        if (bitmap_filenames[count]) 
+           free(bitmap_filenames[count]);
+     }
+     free(bitmap_filenames);
+  }
+}
+void ENVIRONMENT::destroy_lock(pthread_mutex_t* lock) {
+  #ifdef THREADS
+  if (lock)
+  {
+    int result = pthread_mutex_destroy(lock);
+    switch (result)
+    {
+      case 0:
+        //Successfully destroyed
+        break;
+      case EBUSY:
+        //Some thread forgot to unlock result
+        printf("%s:%i: Lock is still held.\n", __FILE__, __LINE__);
+        break;
+      case EINVAL:
+        //Invalid lock
+        printf("%s:%i: Lock is invalid.\n", __FILE__, __LINE__);
+        break;
+      default:
+        printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_destroy.\n", __FILE__, __LINE__, result);
+        break;
+    }
+    free(lock);
+  }
+  #endif
+}
+pthread_mutex_t* ENVIRONMENT::init_lock(pthread_mutex_t* lock) {
+  #ifdef THREADS
+  lock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
+  if (!lock)
+  {
+    printf("%s:%i: Could not allocate memory.\n", __FILE__, __LINE__);
+  }
+  int result = pthread_mutex_init(lock, NULL);
+  switch (result)
+  {
+    case 0:
+      //Succesfully initialized
+      break;
+    case EAGAIN:
+      //Not enough resources
+      printf("%s:%i: Not enough resources to create mutex.\n", __FILE__, __LINE__);
+      break;
+    case ENOMEM:
+      printf("%s:%i: Not enough memory to create mutex.\n", __FILE__, __LINE__);
+      break;
+    case EPERM:
+      printf("%s:%i: Not authorized.\n", __FILE__, __LINE__);
+      break;
+    case EBUSY:
+      printf("%s:%i: The mutex is already initialized.\n", __FILE__, __LINE__);
+      break;
+    case EINVAL:
+      printf("%s:%i: Invalid attribute.\n", __FILE__, __LINE__);
+      break;
+    default:
+      printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_init.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+  return lock;
+}
+void ENVIRONMENT::lock(pthread_mutex_t* lock)
+{
+  #ifdef THREADS
+  int result = pthread_mutex_lock(lock);
+  switch (result)
+  {
+    case 0:
+      //Got the lock.
+      break;
+    case EINVAL:
+      //Priority too high
+      printf("%s:%i: Either this thread's priority is higher than the mutex's priority, or the mutex is uninitialized.\n", __FILE__, __LINE__);
+      break;
+    case EAGAIN:
+      printf("%s:%i: Too many locks on the mutex.\n", __FILE__, __LINE__);
+      break;
+    case EDEADLK:
+      //We have the lock already
+      printf("%s:%i: Already have lock.\n", __FILE__, __LINE__);
+      break;
+    default:
+      //What error is this?
+      printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_lock.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+}
+void ENVIRONMENT::unlock(pthread_mutex_t* lock)
+{
+  #ifdef THREADS
+  int result = pthread_mutex_unlock(lock);
+  switch (result)
+  {
+    case 0:
+      //Released the lock
+      break;
+    case EPERM:
+      //Forgot to get a lock on the mutex
+      printf("%s:%i: Mutex isn't locked\n", __FILE__, __LINE__);
+      break;
+    case EINVAL:
+      //Uninitialized mutex
+      printf("%s:%i: waiting_sky_lock is uninitialized.\n", __FILE__, __LINE__);
+      break;
+    default:
+      //?
+      printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_unlock.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+}
+BITMAP* ENVIRONMENT::get_waiting_sky()
+{
+  lock(waiting_sky_lock);
+  BITMAP* w = waiting_sky;
+  unlock(waiting_sky_lock);
+  return w;
+}
+BITMAP* ENVIRONMENT::get_waiting_terrain()
+{
+  lock(waiting_terrain_lock);
+  BITMAP* w = waiting_terrain;
+  unlock(waiting_terrain_lock);
+  return w;
+}
+/*
+This function saves the environment settings to a text
+file. Each line has the format
+name=value\n
+
+The function returns TRUE on success and FALSE on failure.
+-- Jesse
+*/
+int ENVIRONMENT::saveToFile_Text (FILE *file)
+{
+  if (! file) return FALSE;
+
+  fprintf (file, "*ENV*\n");
+
+  fprintf (file, "WINDSTRENGTH=%f\n", windstrength);
+  fprintf (file, "WINDVARIATION=%f\n", windvariation);
+  fprintf (file, "VISCOSITY=%f\n", viscosity);
+  fprintf (file, "GRAVITY=%f\n", gravity);
+  fprintf (file, "WEAPONTECHLEVEL=%f\n", weapontechLevel);
+  fprintf (file, "ITEMTECHLEVEL=%f\n", itemtechLevel);
+  fprintf (file, "METEORS=%f\n", meteors);
+  fprintf (file, "LIGHTNING=%f\n", lightning);
+  fprintf (file, "SATELLITE=%f\n", satellite);
+  fprintf (file, "FOG=%f\n", fog);
+  fprintf (file, "LANDTYPE=%f\n", landType);
+  fprintf (file, "LANDSLIDETYPE=%f\n", landSlideType);
+  fprintf (file, "WALLTYPE=%f\n", wallType);
+  fprintf (file, "BOXMODE=%f\n", dBoxedMode);
+  fprintf (file, "TEXTFADE=%f\n", dFadingText);
+  fprintf (file, "TEXTSHADOW=%f\n", dShadowedText);
+  fprintf (file, "LANDSLIDEDELAY=%f\n", landSlideDelay);
+  fprintf (file, "FALLINGDIRTBALLS=%f\n", falling_dirt_balls);
+  fprintf (file, "CUSTOMBACKGROUND=%f\n", custom_background);
+  fprintf (file, "***\n");
+  return TRUE;
+}
+
+/*
+This function loads environment settings from a text
+file. The function returns TRUE on success and FALSE if
+any erors are encountered.
+-- Jesse
+*/
+int ENVIRONMENT::loadFromFile_Text (FILE *file)
+{
+  char line[MAX_CONFIG_LINE];
+  int equal_position, line_length;
+  char field[MAX_CONFIG_LINE], value[MAX_CONFIG_LINE];
+  char *result = NULL;
+  bool done = false;
+
+  // read until we hit line (char *)"*ENV*" or "***" or EOF
+  do
+    {
+      result = fgets(line, MAX_CONFIG_LINE, file);
+      if (! result)     // eof
+        return FALSE;
+      if (! strncmp(line, "***", 3) )     // end of record
+        return FALSE;
+    }
+  while ( strncmp(line, "*ENV*", 5) );     // read until we hit new record
+
+  while ( (result) && (!done) )
+    {
+      // read a line
+      memset(line, '\0', MAX_CONFIG_LINE);
+      result = fgets(line, MAX_CONFIG_LINE, file);
+      if (result)
+        {
+          // if we hit end of the record, stop
+          if (! strncmp(line, "***", 3) ) return TRUE;
+          // find equal sign
+          line_length = strlen(line);
+          // strip newline character
+          if ( line[line_length - 1] == '\n')
+            {
+              line[line_length - 1] = '\0';
+              line_length--;
+            }
+          equal_position = 1;
+          while ( ( equal_position < line_length) && (line[equal_position] != '=') )
+            equal_position++;
+          // make sure we have valid equal sign
+
+          if ( equal_position <= line_length )
+            {
+              // seperate field from value
+              memset(field, '\0', MAX_CONFIG_LINE);
+              memset(value, '\0', MAX_CONFIG_LINE);
+              strncpy(field, line, equal_position);
+              strcpy(value, & (line[equal_position + 1]));
+              // check for fields and values
+              if (! strcasecmp(field, "windstrength") )
+                sscanf(value, "%lf", &windstrength);
+              else if (! strcasecmp(field, "windvariation") )
+                sscanf(value, "%lf", &windvariation);
+              else if (! strcasecmp(field, "viscosity") )
+                sscanf(value, "%lf", &viscosity);
+              else if (! strcasecmp(field, "gravity") )
+                sscanf(value, "%lf", &gravity);
+              else if (! strcasecmp(field, "techlevel"))
+                {
+                  sscanf(value, "%lf", &weapontechLevel);
+                  itemtechLevel = weapontechLevel;    // for backward compatibility
+                }
+              else if (! strcasecmp(field, "weapontechlevel") )
+                sscanf(value, "%lf", &weapontechLevel);
+              else if (! strcasecmp(field, "itemtechlevel") )
+                sscanf(value, "%lf", &itemtechLevel);
+              else if (! strcasecmp(field, "meteors"))
+                sscanf(value, "%lf", &meteors);
+              else if (! strcasecmp(field, "lightning") )
+                sscanf(value, "%lf", &lightning);
+              else if (! strcasecmp(field, "satellite") )
+                sscanf(value, "%lf", &satellite);
+              else if (! strcasecmp(field, "fog") )
+                sscanf(value, "%lf", &fog);
+              else if (! strcasecmp(field, "landtype"))
+                sscanf(value, "%lf", &landType);
+              else if (! strcasecmp(field, "landslidetype"))
+                sscanf(value, "%lf", &landSlideType);
+              else if (! strcasecmp(field, "walltype"))
+                sscanf(value, "%lf", &wallType);
+              else if (! strcasecmp(field, "boxmode"))
+                sscanf(value, "%lf", &dBoxedMode);
+              else if (! strcasecmp(field, "textfade"))
+                sscanf(value, "%lf", &dFadingText);
+              else if (! strcasecmp(field, "textshadow"))
+                sscanf(value, "%lf", &dShadowedText);
+              else if (! strcasecmp(field, "landslidedelay"))
+                sscanf(value, "%lf", &landSlideDelay);
+              else if (! strcasecmp(field, "fallingdirtballs") )
+                sscanf(value, "%lf", &falling_dirt_balls);
+              else if (! strcasecmp(field, "custombackground") )
+                sscanf(value, "%lf", &custom_background);
+
+            }    // end of found field=value line
+
+        }     // end of read a line properly
+    }     // end of while not done
+
+  return TRUE;
+}
+
+
+
+void ENVIRONMENT::initialise ()
+{
+  for (int count = 0; count < _global->screenWidth; count++)
+    {
+      h[count] = 0;
+      fp[count] = 0;
+      done[count] = 1;
+      dropTo[count] = _global->screenHeight - 1;
+      surface[count] = 0;
+    }
+  for (int count = 0; count < MAX_OBJECTS; count++)
+    objects[count] = NULL;
+  for (int count = 0; count < MAXPLAYERS; count++)
+    order[count] = NULL;
+
+  clear_to_color (sky, PINK);
+  clear_to_color (db, WHITE);
+  clear_to_color (terrain, PINK);
+
+  // oldFogX = 0;
+  // oldFogY = 0;
+
+  combineUpdates = TRUE;
+}
+
+int ENVIRONMENT::isItemAvailable (int itemNum)
+{
+  if (itemNum < WEAPONS)
+    {
+      if ((weapon[itemNum].warhead) ||
+          (weapon[itemNum].techLevel > weapontechLevel))
+        return (FALSE);
+    }
+  else if (item[itemNum - WEAPONS].techLevel > itemtechLevel)
+    {
+      return (FALSE);
+    }
+  return (TRUE);
+}
+
+void ENVIRONMENT::generateAvailableItemsList ()
+{
+  int slot = 0;
+  for (int itemNum = 0; itemNum < THINGS; itemNum++)
+    {
+      if (!isItemAvailable (itemNum))
+        continue;
+      availableItems[slot] = itemNum;
+      slot++;
+    }
+  numAvailable = slot;
+}
+
+int ENVIRONMENT::addObject (VIRTUAL_OBJECT *object)
+{
+  int objCount = 0;
+
+  while ((objects[objCount] != NULL) && (objCount < MAX_OBJECTS))
+    objCount++;
+  if (objCount < MAX_OBJECTS)
+    objects[objCount] = object;
+
+  return (objCount);
+}
+
+int ENVIRONMENT::removeObject (VIRTUAL_OBJECT *object)
+{
+  int objCount  = object->getIndex();
+  int objClass  = object->getClass();
+
+  object->requireUpdate();
+  object->update();
+
+  if (objCount < MAX_OBJECTS)
+    {
+      objects[objCount] = NULL;
+      if (objClass == TANK_CLASS)
+        for (int ordCount = 0; ordCount < MAXPLAYERS; ordCount++)
+          if (order[ordCount] == object)
+            order[ordCount] = NULL;
+    }
+  else
+    {
+      return (objCount);
+    }
+
+  return (0);
+}
+
+VIRTUAL_OBJECT *ENVIRONMENT::getNextOfClass (int classNum, int *objCount)
+{
+  for (;*objCount < MAX_OBJECTS; (*objCount)++)
+    {
+      if ((objects[*objCount] != NULL) &&
+          ((classNum == ANY_CLASS) || (classNum == objects[*objCount]->getClass ())))
+        break;
+    }
+
+  if (*objCount < MAX_OBJECTS)
+    return (objects[*objCount]);
+  else
+    return (NULL);
+}
+
+void ENVIRONMENT::newRound ()
+{
+  for (int objCount = 0; objCount < MAX_OBJECTS; objCount++)
+    {
+      if (objects[objCount])
+        {
+          if ((!objects[objCount]->isSubClass (TANK_CLASS)) &&
+              (!objects[objCount]->isSubClass (FLOATTEXT_CLASS)))
+            {
+              delete objects[objCount];
+              objects[objCount] = NULL;
+            }
+          else if (objects[objCount]->isSubClass (TANK_CLASS))
+            ((TANK *)objects[objCount])->newRound();
+        }
+    }
+
+  naturals_since_last_shot = 0;
+  // set wall type
+  if (wallType == WALL_RANDOM)
+    current_wallType = rand() % 4;
+  else
+    current_wallType = (int) wallType;
+
+  // time_to_fall = (rand() % MAX_GRAVITY_DELAY) + 1;
+  time_to_fall = (rand() & (int)landSlideDelay) + 1;
+  global_tank_index = 0;
+}
+
+int ENVIRONMENT::ingamemenu ()
+{
+  int button[INGAMEBUTTONS];
+  int pressed = -1;
+  int updatew[INGAMEBUTTONS];
+  char *buttext[INGAMEBUTTONS];
+  buttext[0] = _global->ingame->complete_text[69];
+  buttext[1] =  _global->ingame->complete_text[70];
+  buttext[2] = _global->ingame->complete_text[71];
+  buttext[3] =  _global->ingame->complete_text[72];
+  // char buttext_de[INGAMEBUTTONS][32] = { "Zuruck", "Hauptmenu", "Verlassen", "Skip AI" };
+  int z, zz;
+
+  // Set/calcualte button size and positions
+  int button_width = 150;
+  int button_height = 20;
+  int button_space = 5;
+  int button_halfwidth = button_width / 2;
+  // int button_halfheight = button_height / 2;
+  int dialog_width = 200;
+  int dialog_height = ((INGAMEBUTTONS + 2) * button_height) + ((INGAMEBUTTONS + 1) * button_space);
+  int dialog_halfwidth = dialog_width / 2;
+  int dialog_halfheight = dialog_height / 2;
+
+  // Calculate button y values and set all button status to 0
+  int y = -dialog_halfheight + button_height + button_space;
+
+  for (z = 0; z < INGAMEBUTTONS; z++)
+  {
+    updatew[z] = 0;
+    button[z] = y;
+    y += button_height + button_space;
+  }
+
+  if (! _global->os_mouse) show_mouse (NULL);
+   make_update (_global->halfWidth - dialog_halfwidth, _global->halfHeight - dialog_halfheight, dialog_width, dialog_height);
+   rectfill (db, _global->halfWidth - dialog_halfwidth, _global->halfHeight - dialog_halfheight, _global->halfWidth + dialog_halfwidth - 1, _global->halfHeight + dialog_halfheight - 1, makecol (128, 128, 128));
+   rect (db, _global->halfWidth - dialog_halfwidth, _global->halfHeight - dialog_halfheight, _global->halfWidth + dialog_halfwidth - 1, _global->halfHeight + dialog_halfheight - 1, BLACK);
+
+
+  while (1)
+    {
+      LINUX_SLEEP;
+      if (keypressed ())
+        {
+          k = readkey ();
+          if ( (k >> 8 == KEY_ESC) || (k >> 8 == KEY_P) )
+            return (0);
+        }
+
+      if (mouse_b & 1)
+        {
+          zz = 0;
+          for (z = 0; z < INGAMEBUTTONS; z++)
+            {
+                if (mouse_x >= _global->halfWidth - button_halfwidth && mouse_x < _global->halfWidth + button_halfwidth && mouse_y >= button[z] + _global->halfHeight
+                   && mouse_y < button[z] + button_height + _global->halfHeight)
+                {
+                  zz = 1;
+                  if (pressed > -1)
+                    updatew[pressed] = 1;
+                  pressed = z;
+                  updatew[z] = 1;
+                }
+            }
+          if (!zz)
+            {
+              if (pressed > -1)
+                updatew[pressed] = 1;
+              pressed = -1;
+            }
+        }
+      if (pressed > -1 && !mouse_b & 1)
+        return (pressed);
+      for (z = 0; z < INGAMEBUTTONS; z++)
+        {
+          if (updatew[z])
+            {
+              updatew[z] = 0;
+              make_update (_global->halfWidth - button_halfwidth, _global->halfHeight + button[z], button_width, button_height);
+            }
+        }
+      make_update (mouse_x, mouse_y, ((BITMAP *) (_global->misc[0]))->w, ((BITMAP *) (_global->misc[0]))->h);
+      make_update (lx, ly, ((BITMAP *) (_global->misc[0]))->w, ((BITMAP *) (_global->misc[0]))->h);
+      lx = mouse_x;
+      ly = mouse_y;
+      if (! _global->os_mouse)  show_mouse (NULL);
+      for (z = 0; z < INGAMEBUTTONS; z++)
+        {
+          draw_sprite (db, (BITMAP *) _global->misc[(pressed == z) ? 8 : 7], _global->halfWidth - button_halfwidth, _global->halfHeight + button[z]);
+          textout_centre_ex (db, font, buttext[z], _global->halfWidth, _global->halfHeight + button[z] + 6, WHITE, -1);
+        }
+      if (! _global->os_mouse) show_mouse (db);
+      do_updates ();
+    }
+}
+
+void ENVIRONMENT::do_updates ()
+{
+  int count;
+
+  bool bIsBgUpdNeeded = false;
+  if (_global->lastUpdatesCount)
+    bIsBgUpdNeeded = true;
+
+  if (_global->updateCount >= MAXUPDATES)
+    make_fullUpdate();
+  else
+    {
+      for (count = 0; count < _global->updateCount && count < MAXUPDATES; count++)
+        {
+          blit (db, screen, _global->updates[count].x, _global->updates[count].y, _global->updates[count].x, _global->updates[count].y, _global->updates[count].w, _global->updates[count].h);
+          // Debug rectangle
+          //rect (screen, _global->updates[count].x, _global->updates[count].y, _global->updates[count].x + _global->updates[count].w, _global->updates[count].y + _global->updates[count].h, WHITE);
+          if (bIsBgUpdNeeded)
+            make_bgupdate(_global->updates[count].x, _global->updates[count].y, _global->updates[count].w, _global->updates[count].h);
+        }
+
+      if (!bIsBgUpdNeeded)
+        {
+          _global->lastUpdatesCount = _global->updateCount;
+          memcpy (_global->lastUpdates, _global->updates, sizeof (BOX) * _global->updateCount);
+        }
+      _global->updateCount = 0;
+    }
+}
+
+void ENVIRONMENT::replaceCanvas ()
+{
+  int count;
+
+  if (_global->lastUpdatesCount >= MAXUPDATES)
+    make_fullUpdate();
+  else
+    {
+      for (count = 0; count < _global->lastUpdatesCount && count < MAXUPDATES; count++)
+        {
+          blit (sky, db, _global->lastUpdates[count].x, _global->lastUpdates[count].y - MENUHEIGHT, _global->lastUpdates[count].x, _global->lastUpdates[count].y, _global->lastUpdates[count].w, _global->lastUpdates[count].h);
+          masked_blit (terrain, db, _global->lastUpdates[count].x, _global->lastUpdates[count].y, _global->lastUpdates[count].x, _global->lastUpdates[count].y, _global->lastUpdates[count].w, _global->lastUpdates[count].h);
+        }
+          #ifdef NEW_GAMELOOP
+          int iLeft = 0;
+          int iRight = _global->screenWidth - 1;
+          int iTop = MENUHEIGHT;
+          int iBottom = _global->screenHeight - 1;
+
+          vline(db, iLeft, iTop, iBottom, wallColour);    // Left edge
+          vline(db, iLeft + 1, iTop, iBottom, wallColour);    // Left edge
+          vline(db, iRight, iTop, iBottom, wallColour);   // right edge
+          vline(db, iRight - 1, iTop, iBottom, wallColour);   // right edge
+          hline(db, iLeft, iBottom, iRight, wallColour);// bottom edge
+          if (_global->bIsBoxed)
+              hline(db, iLeft, iTop, iRight, wallColour);// top edge
+          #endif
+      _global->lastUpdatesCount = 0;
+      // The menu needs to be redrawn:
+      make_update(0, 0, _global->screenWidth - 1, MENUHEIGHT);
+    }
+}
+
+void ENVIRONMENT::make_update (int x, int y, int w, int h)
+{
+  int combined = 0;
+  if (combineUpdates && _global->updateCount && _global->updateCount < MAXUPDATES)
+    {
+      BOX prev, next;
+      prev.x = _global->updates[_global->updateCount - 1].x;
+      prev.y = _global->updates[_global->updateCount - 1].y;
+      // .w = .x + .w = x2 (aka renamed to be the right x-position)
+      prev.w = _global->updates[_global->updateCount - 1].x + _global->updates[_global->updateCount - 1].w;
+      // .h = .y + .h = y2 (aka renamed to be the bottom y-position)
+      prev.h = _global->updates[_global->updateCount - 1].y + _global->updates[_global->updateCount - 1].h;
+
+      next.x = x;
+      next.y = y;
+      next.w = x + w; // same as above, becoming x2 and not the width!
+      next.h = y + h; // same as above, becoming y2 and not the height!
+
+      if (((next.w > prev.x - 3) && (prev.w > next.x - 3)) &&
+          ((next.h > prev.y - 3) && (prev.h > next.y - 3)))
+        {
+          next.x = (next.x < prev.x)?next.x:prev.x;
+          next.y = (next.y < prev.y)?next.y:prev.y;
+          next.w = (next.w > prev.w)?next.w:prev.w;
+          next.h = (next.h > prev.h)?next.h:prev.h;
+          _global->updates[_global->updateCount - 1].x = next.x;
+          _global->updates[_global->updateCount - 1].y = next.y;
+          _global->updates[_global->updateCount - 1].w = next.w - next.x;
+          _global->updates[_global->updateCount - 1].h = next.h - next.y;
+          combined = 1;
+        }
+    }
+  if (!combined)
+    {
+      _global->updates[_global->updateCount].x = x;
+      _global->updates[_global->updateCount].y = y;
+      _global->updates[_global->updateCount].w = w;
+      _global->updates[_global->updateCount].h = h;
+      if (_global->updateCount < MAXUPDATES)
+        _global->updateCount++;
+    }
+
+  if (_global->updateCount >= MAXUPDATES)
+    make_fullUpdate();
+  else if (!_global->stopwindow)
+    {
+      if (x < _global->window.x)
+        _global->window.x = x;
+      if (y < _global->window.y)
+        _global->window.y = y;
+      if (x + w > _global->window.w)
+        _global->window.w = (x + w) - 1;
+      if (y + h > _global->window.h)
+        _global->window.h = (y + h) - 1;
+      if (_global->window.x < 0)
+        _global->window.x = 0;
+      if (_global->window.y < MENUHEIGHT)
+        _global->window.y = MENUHEIGHT;
+      if (_global->window.w > (_global->screenWidth-1))
+        _global->window.w = (_global->screenWidth-1);
+      if (_global->window.h > (_global->screenHeight-1))
+        _global->window.h = (_global->screenHeight-1);
+    }
+}
+
+void ENVIRONMENT::make_bgupdate (int x, int y, int w, int h)
+{
+  int combined = 0;
+  if (_global && combineUpdates && _global->lastUpdatesCount && (_global->lastUpdatesCount < MAXUPDATES))
+    {
+      BOX prev, next;
+      prev.x = _global->lastUpdates[_global->lastUpdatesCount - 1].x;
+      prev.y = _global->lastUpdates[_global->lastUpdatesCount - 1].y;
+      prev.w = _global->lastUpdates[_global->lastUpdatesCount - 1].x + _global->lastUpdates[_global->lastUpdatesCount - 1].w;
+      prev.h = _global->lastUpdates[_global->lastUpdatesCount - 1].y + _global->lastUpdates[_global->lastUpdatesCount - 1].h;
+
+      next.x = x;
+      next.y = y;
+      next.w = x + w;
+      next.h = y + h;
+
+      if (((next.w > prev.x - 3) && (prev.w > next.x - 3)) &&
+          ((next.h > prev.y - 3) && (prev.h > next.y - 3)))
+        {
+          next.x = (next.x < prev.x)?next.x:prev.x;
+          next.y = (next.y < prev.y)?next.y:prev.y;
+          next.w = (next.w > prev.w)?next.w:prev.w;
+          next.h = (next.h > prev.h)?next.h:prev.h;
+          _global->lastUpdates[_global->lastUpdatesCount - 1].x = next.x;
+          _global->lastUpdates[_global->lastUpdatesCount - 1].y = next.y;
+          _global->lastUpdates[_global->lastUpdatesCount - 1].w = next.w - next.x;
+          _global->lastUpdates[_global->lastUpdatesCount - 1].h = next.h - next.y;
+          combined = 1;
+        }
+    }
+  if (_global && !combined)
+    {
+      _global->lastUpdates[_global->lastUpdatesCount].x = x;
+      _global->lastUpdates[_global->lastUpdatesCount].y = y;
+      _global->lastUpdates[_global->lastUpdatesCount].w = w;
+      _global->lastUpdates[_global->lastUpdatesCount].h = h;
+      if (_global->lastUpdatesCount < MAXUPDATES)
+        _global->lastUpdatesCount++;
+    }
+
+  if (_global && _global->lastUpdatesCount >= MAXUPDATES)
+    make_fullUpdate();
+}
+
+void ENVIRONMENT::make_fullUpdate()
+{
+  // Replace Updates with a full screen update:
+  int iOldCombUpd = combineUpdates;
+  combineUpdates = 0;
+
+  // They are splitted into 4 x 2 updates:
+  int iQuartWidth = _global->halfWidth / 2;
+  int iHalfHeight = _global->halfHeight;
+
+  _global->updateCount = 0;
+  for (int x = 0; x < 4; x++)
+    for (int y = 0; y < 2; y++)
+      make_update(iQuartWidth *		x		, iHalfHeight *		y,
+                  iQuartWidth * (x+1)	, iHalfHeight *	(y+1));
+
+  _global->lastUpdatesCount = 0;
+  for (int x = 0; x < 4; x++)
+    for (int y = 0; y < 2; y++)
+      make_bgupdate(iQuartWidth *		x		, iHalfHeight *		y,
+                    iQuartWidth * (x+1)	, iHalfHeight *	(y+1));
+
+  combineUpdates = iOldCombUpd;
+}
+
+
+
+
+
+int ENVIRONMENT::getAvgBgColor(int aTopLeftX, int aTopLeftY, int aBotRightX, int aBotRightY, double aVelX, double aVelY)
+    {
+      // Coordinate sets:
+      int iLeftX	= aTopLeftX;
+      int iRightX	= aBotRightX;
+      int iCentX;	// Will be calculated later
+      int iTopY		=	aTopLeftY;
+      int iBottomY=	aBotRightY;
+      int iCentY; // Will be calculated later!
+
+      // Colors:
+      int iColorToLe, iColorToCe, iColorToRi;	// top row
+      int iColorCeLe, iColorCeCe, iColorCeRi; // center row
+      int iColorBoLe, iColorBoCe, iColorBoRi; // bottom row
+      int iRed = 0;
+      int iGreen = 0;
+      int iBlue = 0;
+
+      // Get the coordinates into range:
+      if (aTopLeftX 	< 1)													iLeftX = 1;
+      if (aTopLeftX 	> (_global->screenWidth - 2))	iLeftX = _global->screenWidth - 2;
+      if (aBotRightX	<	1)													iRightX= 1;
+      if (aBotRightX	>	(_global->screenWidth - 2))	iRightX= _global->screenWidth	-	2;
+      iCentX = (iLeftX + iRightX) / 2;
+
+      if (aTopLeftY		< (MENUHEIGHT + 1))						 	iTopY			= MENUHEIGHT + 1;
+      if (aTopLeftY		> (_global->screenHeight - 2))	iTopY			= _global->screenHeight - 2;
+      if (aBotRightY	< (MENUHEIGHT + 1))						 	iBottomY	= MENUHEIGHT + 1;
+      if (aBotRightY	> (_global->screenHeight - 2))	iBottomY	= _global->screenHeight - 2;
+      iCentY = (iTopY + iBottomY) / 2;
+
+      // Get Sky color or bg color, whatever fits:
+      /*---------------------
+         --- Left side ---
+      ---------------------*/
+      if (surface[iLeftX] <= iTopY)
+        {
+          // All infront of the surface:
+          iColorBoLe	=	getpixel(terrain, iLeftX,		iBottomY);
+          iColorCeLe	=	getpixel(terrain, iLeftX,		iCentY);
+          iColorToLe	=	getpixel(terrain, iLeftX,		iTopY);
+        }
+      else
+        {
+          // look where we are going...
+          if (surface[iLeftX] > iBottomY)
+            {
+              // Left part is guaranteed to be in front of the sky, get all three colors at once:
+              iColorBoLe	=	getpixel(sky, iLeftX,		iBottomY - MENUHEIGHT);
+              iColorCeLe	=	getpixel(sky, iLeftX,		iCentY - MENUHEIGHT);
+              iColorToLe	=	getpixel(sky, iLeftX,		iTopY - MENUHEIGHT);
+            }
+          else
+            {
+              // At least the bottom color is infront of the terrain
+              iColorBoLe	=	getpixel(terrain, iLeftX,		iBottomY);
+              if (surface[iLeftX] > iCentY)
+                {
+                  // ...but the other two are in front of the sky:
+                  iColorCeLe	=	getpixel(sky, iLeftX,		iCentY - MENUHEIGHT);
+                  iColorToLe	=	getpixel(sky, iLeftX,		iTopY - MENUHEIGHT);
+                }
+              else
+                {
+                  // Nope, they are in front of the terrain
+                  iColorCeLe	=	getpixel(terrain, iLeftX,		iCentY);
+                  iColorToLe	=	getpixel(terrain, iLeftX,		iTopY);
+                }
+            }
+        }
+      /*---------------------
+         --- The Center ---
+      ---------------------*/
+      if (surface[iCentX] <= iTopY)
+        {
+          // All infront of the surface:
+          iColorBoCe =	getpixel(terrain, iCentX,		iBottomY);
+          iColorCeCe =	getpixel(terrain, iCentX,		iCentY);
+          iColorToCe =	getpixel(terrain, iCentX,		iTopY);
+        }
+      else
+        {
+          // look where we are going...
+          if (surface[iCentX] > iBottomY)
+            {
+              // Left part is guaranteed to be in front of the sky, get all three colors at once:
+              iColorBoCe =	getpixel(sky, iCentX,		iBottomY - MENUHEIGHT);
+              iColorCeCe =	getpixel(sky, iCentX,		iCentY - MENUHEIGHT);
+              iColorToCe =	getpixel(sky, iCentX,		iTopY - MENUHEIGHT);
+            }
+          else
+            {
+              // At least the bottom color is infront of the terrain
+              iColorBoCe =	getpixel(terrain, iCentX,		iBottomY);
+              if (surface[iCentX] > iCentY)
+                {
+                  // ...but the other two are in front of the sky:
+                  iColorCeCe =	getpixel(sky, iCentX,		iCentY - MENUHEIGHT);
+                  iColorToCe =	getpixel(sky, iCentX,		iTopY - MENUHEIGHT);
+                }
+              else
+                {
+                  // Nope, they are in front of the terrain
+                  iColorCeCe =	getpixel(terrain, iCentX,		iCentY);
+                  iColorToCe =	getpixel(terrain, iCentX,		iTopY);
+                }
+            }
+        }
+      /*----------------------
+         --- Right side ---
+      ----------------------*/
+      if (surface[iRightX] <= iTopY)
+        {
+          // All infront of the surface:
+          iColorBoRi =	getpixel(terrain, iRightX,		iBottomY);
+          iColorCeRi =	getpixel(terrain, iRightX,		iCentY);
+          iColorToRi =	getpixel(terrain, iRightX,		iTopY);
+        }
+      else
+        {
+          // look where we are going...
+          if (surface[iRightX] > iBottomY)
+            {
+              // Left part is guaranteed to be in front of the sky, get all three colors at once:
+              iColorBoRi =	getpixel(sky, iRightX,		iBottomY - MENUHEIGHT);
+              iColorCeRi =	getpixel(sky, iRightX,		iCentY - MENUHEIGHT);
+              iColorToRi =	getpixel(sky, iRightX,		iTopY - MENUHEIGHT);
+            }
+          else
+            {
+              // At least the bottom color is infront of the terrain
+              iColorBoRi =	getpixel(terrain, iRightX,		iBottomY);
+              if (surface[iRightX] > iCentY)
+                {
+                  // ...but the other two are in front of the sky:
+                  iColorCeRi =	getpixel(sky, iRightX,		iCentY - MENUHEIGHT);
+                  iColorToRi =	getpixel(sky, iRightX,		iTopY - MENUHEIGHT);
+                }
+              else
+                {
+                  // Nope, they are in front of the terrain
+                  iColorCeRi =	getpixel(terrain, iRightX,		iCentY);
+                  iColorToRi =	getpixel(terrain, iRightX,		iTopY);
+                }
+            }
+        }
+
+      // Fetch the rgb parts, according to movement:
+      /* --- X-Movement --- */
+      if (aVelX < 0.0)
+        {
+          // Movement to the left, weight left side color twice
+          iRed		+=	(_GET_R(iColorBoLe) * 2) + (_GET_R(iColorCeLe) * 2) + (_GET_R(iColorToLe) * 2);
+          iGreen	+=	(_GET_G(iColorBoLe) * 2) + (_GET_G(iColorCeLe) * 2) + (_GET_G(iColorToLe) * 2);
+          iBlue		+=	(_GET_B(iColorBoLe) * 2) + (_GET_B(iColorCeLe) * 2) + (_GET_B(iColorToLe) * 2);
+          // The others are counted once
+          iRed		+=	_GET_R(iColorBoCe) + _GET_R(iColorCeCe) + _GET_R(iColorToCe) + _GET_R(iColorBoRi) + _GET_R(iColorCeRi) + _GET_R(iColorToRi);
+          iGreen	+=	_GET_G(iColorBoCe) + _GET_G(iColorCeCe) + _GET_G(iColorToCe) + _GET_G(iColorBoRi) + _GET_G(iColorCeRi) + _GET_G(iColorToRi);
+          iBlue		+=	_GET_B(iColorBoCe) + _GET_B(iColorCeCe) + _GET_B(iColorToCe) + _GET_B(iColorBoRi) + _GET_B(iColorCeRi) + _GET_B(iColorToRi);
+        }
+      if (aVelX == 0.0)
+        {
+          // No X-Movement, weight center twice
+          iRed		+=	(_GET_R(iColorBoCe) * 2) + (_GET_R(iColorCeCe) * 2) + (_GET_R(iColorToCe) * 2);
+          iGreen	+=	(_GET_G(iColorBoCe) * 2) + (_GET_G(iColorCeCe) * 2) + (_GET_G(iColorToCe) * 2);
+          iBlue		+=	(_GET_B(iColorBoCe) * 2) + (_GET_B(iColorCeCe) * 2) + (_GET_B(iColorToCe) * 2);
+          // The others are counted once
+          iRed		+=	_GET_R(iColorBoLe) + _GET_R(iColorCeLe) + _GET_R(iColorToLe) + _GET_R(iColorBoRi) + _GET_R(iColorCeRi) + _GET_R(iColorToRi);
+          iGreen	+=	_GET_G(iColorBoLe) + _GET_G(iColorCeLe) + _GET_G(iColorToLe) + _GET_G(iColorBoRi) + _GET_G(iColorCeRi) + _GET_G(iColorToRi);
+          iBlue		+=	_GET_B(iColorBoLe) + _GET_B(iColorCeLe) + _GET_B(iColorToLe) + _GET_B(iColorBoRi) + _GET_B(iColorCeRi) + _GET_B(iColorToRi);
+        }
+      if (aVelX > 0.0)
+        {
+          // Movement to the right, weight right side color twice
+          iRed		+=	(_GET_R(iColorBoRi) * 2) + (_GET_R(iColorCeRi) * 2) + (_GET_R(iColorToRi) * 2);
+          iGreen	+=	(_GET_G(iColorBoRi) * 2) + (_GET_G(iColorCeRi) * 2) + (_GET_G(iColorToRi) * 2);
+          iBlue		+=	(_GET_B(iColorBoRi) * 2) + (_GET_B(iColorCeRi) * 2) + (_GET_B(iColorToRi) * 2);
+          // The others are counted once
+          iRed		+=	_GET_R(iColorBoCe) + _GET_R(iColorCeCe) + _GET_R(iColorToCe) + _GET_R(iColorBoLe) + _GET_R(iColorCeLe) + _GET_R(iColorToLe);
+          iGreen	+=	_GET_G(iColorBoCe) + _GET_G(iColorCeCe) + _GET_G(iColorToCe) + _GET_G(iColorBoLe) + _GET_G(iColorCeLe) + _GET_G(iColorToLe);
+          iBlue		+=	_GET_B(iColorBoCe) + _GET_B(iColorCeCe) + _GET_B(iColorToCe) + _GET_B(iColorBoLe) + _GET_B(iColorCeLe) + _GET_B(iColorToLe);
+        }
+      /* --- Y-Movement --- */
+      if (aVelY < 0.0)
+        {
+          // Movement upwards, weight upper side color twice
+          iRed		+=	(_GET_R(iColorToLe) * 2) + (_GET_R(iColorToCe) * 2) + (_GET_R(iColorToRi) * 2);
+          iGreen	+=	(_GET_G(iColorToLe) * 2) + (_GET_G(iColorToCe) * 2) + (_GET_G(iColorToRi) * 2);
+          iBlue		+=	(_GET_B(iColorToLe) * 2) + (_GET_B(iColorToCe) * 2) + (_GET_B(iColorToRi) * 2);
+          // The others are counted once
+          iRed		+=	_GET_R(iColorBoLe) + _GET_R(iColorCeLe) + _GET_R(iColorBoCe) + _GET_R(iColorCeCe) + _GET_R(iColorBoRi) + _GET_R(iColorCeRi);
+          iGreen	+=	_GET_G(iColorBoLe) + _GET_G(iColorCeLe) + _GET_G(iColorBoCe) + _GET_G(iColorCeCe) + _GET_G(iColorBoRi) + _GET_G(iColorCeRi);
+          iBlue		+=	_GET_B(iColorBoLe) + _GET_B(iColorCeLe) + _GET_B(iColorBoCe) + _GET_B(iColorCeCe) + _GET_B(iColorBoRi) + _GET_B(iColorCeRi);
+        }
+      if (aVelY == 0.0)
+        {
+          // No Y-Movement, weight center twice
+          iRed		+=	(_GET_R(iColorCeLe) * 2) + (_GET_R(iColorCeCe) * 2) + (_GET_R(iColorCeRi) * 2);
+          iGreen	+=	(_GET_G(iColorCeLe) * 2) + (_GET_G(iColorCeCe) * 2) + (_GET_G(iColorCeRi) * 2);
+          iBlue		+=	(_GET_B(iColorCeLe) * 2) + (_GET_B(iColorCeCe) * 2) + (_GET_B(iColorCeRi) * 2);
+          // The others are counted once
+          iRed		+=	_GET_R(iColorBoLe) + _GET_R(iColorToLe) + _GET_R(iColorBoCe) + _GET_R(iColorToCe) + _GET_R(iColorBoRi) + _GET_R(iColorToRi);
+          iGreen	+=	_GET_G(iColorBoLe) + _GET_G(iColorToLe) + _GET_G(iColorBoCe) + _GET_G(iColorToCe) + _GET_G(iColorBoRi) + _GET_G(iColorToRi);
+          iBlue		+=	_GET_B(iColorBoLe) + _GET_B(iColorToLe) + _GET_B(iColorBoCe) + _GET_B(iColorToCe) + _GET_B(iColorBoRi) + _GET_B(iColorToRi);
+        }
+      if (aVelY > 0.0)
+        {
+          // Movement downwards, weight lower side color twice
+          iRed		+=	(_GET_R(iColorBoRi) * 2) + (_GET_R(iColorBoCe) * 2) + (_GET_R(iColorBoLe) * 2);
+          iGreen	+=	(_GET_G(iColorBoRi) * 2) + (_GET_G(iColorBoCe) * 2) + (_GET_G(iColorBoLe) * 2);
+          iBlue		+=	(_GET_B(iColorBoRi) * 2) + (_GET_B(iColorBoCe) * 2) + (_GET_B(iColorBoLe) * 2);
+          // The others are counted once
+          iRed		+=	_GET_R(iColorToLe) + _GET_R(iColorCeLe) + _GET_R(iColorToCe) + _GET_R(iColorCeCe) + _GET_R(iColorToRi) + _GET_R(iColorCeRi);
+          iGreen	+=	_GET_G(iColorToLe) + _GET_G(iColorCeLe) + _GET_G(iColorToCe) + _GET_G(iColorCeCe) + _GET_G(iColorToRi) + _GET_G(iColorCeRi);
+          iBlue		+=	_GET_B(iColorToLe) + _GET_B(iColorCeLe) + _GET_B(iColorToCe) + _GET_B(iColorCeCe) + _GET_B(iColorToRi) + _GET_B(iColorCeRi);
+        }
+      /* I know this looks weird, but what we now have is some kind of summed matrix, which is always the same:
+       * Let's assume that dVelX and dVelY are both 0.0, so no movement is happening. The result is: (In counted times)
+       * 2|3|2  ( =  7)
+       * -+-+-
+       * 3|4|3  ( = 10)
+       * -+-+-
+       * 2|3|2  ( =  7)
+       *          = 24
+       * And it is always 24, no matter which movement combination you try. */
+      iRed 	/= 24;
+      if (iRed	> 0xff)	iRed	= 0xff;
+      iGreen/= 24;
+      if (iGreen> 0xff)	iGreen= 0xff;
+      iBlue /= 24;
+      if (iBlue	> 0xff)	iBlue	= 0xff;
+
+      return(makecol(iRed, iGreen, iBlue));
+    }
+
+
+
+
+/*
+ * This function puts all the of the environment settings back
+ * to their default values. These are settings which get written
+ * to the config file.
+ * -- Jesse
+ *  */ 
+void ENVIRONMENT::Reset_Options()
+{
+  windstrength = 8;
+  windvariation = 1;
+  viscosity = 0.5;
+  gravity = 0.150;
+  weapontechLevel = 5;
+  itemtechLevel = 5;
+  meteors = 0;
+  lightning = 0;
+  satellite = 0.0;
+  fog = 0;
+  landType = LANDTYPE_RANDOM;
+  landSlideType = LANDSLIDE_GRAVITY;
+  landSlideDelay = MAX_GRAVITY_DELAY;
+  falling_dirt_balls = 0.0;
+  wallType = 0.0;
+  dBoxedMode = 0.0;
+  dFadingText = 0.0;
+  dShadowedText = 0.0;
+  custom_background = 0.0;
+}
+
+
+/*
+This function checks to see which wall type we are using
+and sets the appropriate colour.
+*/
+void ENVIRONMENT::Set_Wall_Colour()
+{
+    switch (current_wallType)
+    {
+       case WALL_RUBBER:
+          wallColour = makecol(0, 255, 0); break;
+       case WALL_STEEL:
+          wallColour = makecol(255, 0, 0); break;
+       case WALL_SPRING:
+          wallColour = makecol(0, 0, 255); break;
+       case WALL_WRAP:
+          wallColour = makecol(255, 255, 0); break;
+    }
+}
+
+
+
+bool ENVIRONMENT::Get_Boxed_Mode(GLOBALDATA *global)
+{
+    if (dBoxedMode == 2.0)
+    {
+       if (rand() % 2)
+          global->bIsBoxed = true;
+       else
+          global->bIsBoxed = false;
+    }
+    else if (dBoxedMode == 1.0)
+         global->bIsBoxed = true;
+    else if (dBoxedMode == 0.0)
+         global->bIsBoxed = false;
+    return global->bIsBoxed;
+} 
+
+
+
+TANK *ENVIRONMENT::Get_Next_Tank(int *wrapped_around)
+{
+   int index;
+   int found = FALSE;
+   int old_index;
+   int wrapped = 0;
+
+   index = global_tank_index;
+   old_index = index;
+   index++;
+   while (!found)
+   {
+        if (index >= MAXPLAYERS)
+        {
+             index = 0;
+             *wrapped_around = TRUE;
+             wrapped++;
+        }
+        if ( (order[index]) && (index != old_index) )
+        {
+             found = TRUE;
+        }
+        else
+           index++;
+        if (wrapped > 1)
+           break;
+   }
+
+   /* 
+   if (! found)
+      *wrapped_around = TRUE;
+   else
+      *wrapped_around = FALSE;
+   */
+   global_tank_index = index;
+   return order[index];
+}
+
diff --git a/src/environment.h b/src/environment.h
new file mode 100644
index 0000000..f14f0aa
--- /dev/null
+++ b/src/environment.h
@@ -0,0 +1,180 @@
+#ifndef	ENVIRONMENT_DEFINE
+#define	ENVIRONMENT_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "main.h"
+
+enum landscapeTypes
+{
+  LANDTYPE_RANDOM,
+  LANDTYPE_CANYONS,
+  LANDTYPE_MOUNTAINS,
+  LANDTYPE_VALLEYS,
+  LANDTYPE_HILLS,
+  LANDTYPE_FOOTHILLS,
+  LANDTYPE_PLAIN,
+  LANDTYPE_NONE
+};
+
+enum landSlideTypes
+{
+  LANDSLIDE_NONE,       // gravity does not exist
+  LANDSLIDE_TANK_ONLY,  // dirt falls, tank does not
+  LANDSLIDE_INSTANT,    // dirt falls without you seeing it
+  LANDSLIDE_GRAVITY,    // normal
+  LANDSLIDE_CARTOON     // gravity is delayed
+};
+
+#ifndef MAX_GRAVITY_DELAY
+#define GRAVITY_DELAY 200
+#define MAX_GRAVITY_DELAY 3
+#endif
+
+enum wallTypes
+{
+  WALL_RUBBER,
+  WALL_STEEL,
+  WALL_SPRING,
+  WALL_WRAP,
+  WALL_RANDOM
+};
+
+
+// stages
+#define STAGE_AIM 0
+#define STAGE_FIRE 1
+#define STAGE_ENDGAME 3
+
+
+#define SPRING_CHANGE 1.25
+
+// size of satellite laser
+#define LASER_NONE 0.0
+#define LASER_WEAK 1.0
+#define LASER_STRONG 2.0
+#define LASER_SUPER 3.0
+
+#define _GET_R(x) ((x & 0xff0000) >> 16)
+#define _GET_G(x) ((x & 0x00ff00) >> 8)
+#define _GET_B(x) (x & 0x0000ff)
+
+#include "tank.h"
+//class TANK;
+//class MISSILE;
+//class FLOATTEXT;
+//class GLOBALDATA;
+//class VIRTUAL_OBJECT;
+class ENVIRONMENT
+  {
+  public:
+    GLOBALDATA	*_global;
+    TANK	*order[MAXPLAYERS * 3];
+    VIRTUAL_OBJECT	*objects[MAX_OBJECTS];
+    int	availableItems[THINGS];
+    int	numAvailable;
+    int	realm, am;
+    double	wind, lastwind;
+    double	windstrength, windvariation;
+    double	viscosity;
+    double	gravity;
+    double	weapontechLevel, itemtechLevel;
+    double	meteors;
+    double	lightning;
+    double  falling_dirt_balls;
+    double	fog;
+    // int	oldFogX, oldFogY;
+    double	landType;
+    double	landSlideType;
+    double  landSlideDelay;
+    char	*done;
+    int	*fp;
+    int	*h;
+    int	*surface;
+    int	*dropTo;
+    double	*velocity;
+    double	*dropIncr;
+    double	*height;
+    BITMAP	*db, *terrain, *sky;
+    BITMAP *waiting_sky, *waiting_terrain;     // sky saved in background
+    pthread_mutex_t* waiting_terrain_lock;
+    pthread_mutex_t* waiting_sky_lock;
+    void destroy_lock(pthread_mutex_t* lock);
+    pthread_mutex_t* init_lock(pthread_mutex_t* lock);
+    void lock(pthread_mutex_t* lock);
+    void unlock(pthread_mutex_t* lock);
+    BITMAP* get_waiting_sky();
+    BITMAP* get_waiting_terrain();
+    const gradient **my_sky_gradients, **my_land_gradients;
+    int	pclock, mouseclock;
+    int	stage;
+    int	combineUpdates;
+    double  wallType;
+    double	dBoxedMode;			// Can be 0.0 = off, 1.0 = on, 2.0 = random
+    double	dFadingText;		// 0.0 = off, 1.0 = on
+    double	dShadowedText;	// 0.0 = off, 1.0 = on
+    int     current_wallType, wallColour;
+    int     time_to_fall;    // amount of time dirt will hover
+    double  satellite;
+    int     naturals_since_last_shot;
+    double custom_background;
+    char **bitmap_filenames;
+    int number_of_bitmaps;
+    int current_drawing_mode;
+    int global_tank_index;
+
+    ENVIRONMENT (GLOBALDATA *global);
+    ~ENVIRONMENT ();
+    void initialise ();
+    void setGlobaldata (GLOBALDATA *global)
+    {
+      _global = global;
+    }
+    GLOBALDATA *Get_Globaldata()
+    {
+         return _global;
+    }
+    void generateAvailableItemsList ();
+    int isItemAvailable (int itemNum);
+    int addObject (VIRTUAL_OBJECT *object);
+    int removeObject (VIRTUAL_OBJECT *object);
+    VIRTUAL_OBJECT *getNextOfClass (int classNum, int *index);
+    void newRound ();
+    int ingamemenu ();
+    void make_fullUpdate();
+    int getAvgBgColor(int, int, int, int, double, double); 
+    void do_updates ();
+    void replaceCanvas ();
+    void make_update (int x, int y, int w, int h);
+    void make_bgupdate (int x, int y, int w, int h);
+
+    int saveToFile_Text (FILE *file);
+    int loadFromFile_Text (FILE *file);
+    int loadFromFile (ifstream &ifsFile);
+
+    void Reset_Options();
+    void Set_Wall_Colour();
+    bool Get_Boxed_Mode(GLOBALDATA *global);
+    TANK *Get_Next_Tank(int *wrapped_around);
+  };
+
+#endif
+
diff --git a/src/explosion.cpp b/src/explosion.cpp
new file mode 100644
index 0000000..29b02e9
--- /dev/null
+++ b/src/explosion.cpp
@@ -0,0 +1,439 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+#include "environment.h"
+#include "globaldata.h"
+#include "explosion.h"
+#include "missile.h"
+#include "decor.h"
+#include "tank.h"
+#include "player.h"
+
+
+EXPLOSION::~EXPLOSION ()
+{
+  /* the immediate destruction of the background creates a need for a second dirt slide,
+    or there are holes left
+  	(important for chain missiles to work properly!) */
+  for (int z = 0; z <= (radius + 2); z++)
+    {
+      setSlideColumnDimensions (_global, _env, x + z, true);
+      setSlideColumnDimensions (_global, _env, x - z, true);
+    }
+  _env->removeObject (this);
+  weap    = NULL;
+  _global = NULL;
+  _env    = NULL;
+}
+
+EXPLOSION::EXPLOSION (GLOBALDATA *global, ENVIRONMENT *env, double xpos, double ypos,
+                      int weaponType):PHYSICAL_OBJECT(),weap(NULL)
+{
+  drag = 0.95;
+  mass = 3;
+  a = 1;
+  peaked = 0;
+  exclock = 500;
+  bIsWeaponExplosion = true; // Exploding tanks set them to false themselves!
+  setEnvironment (env);
+  player = NULL;
+  _align = LEFT;
+  _global = global;
+  #ifdef NETWORK
+  /*
+  char buffer[256];
+  sprintf(buffer, "EXPLOSION %d %d %d", (int) xpos, (int) ypos, weaponType);
+  global->Send_To_Clients(buffer);
+  */
+  #endif
+  x = xpos;
+  y = ypos;
+  type = weaponType;
+  if (type < WEAPONS)
+    weap = &weapon[type];
+  else
+    weap = &naturals[type - WEAPONS];
+  radius = weap->radius;
+  etime = weap->etime;
+  damage = weap->damage;
+  eframes = weap->eframes;
+
+  // make sure dirt appears on the screen, not above the playing area
+  if ((type >= DIRT_BALL) && (type <= SMALL_DIRT_SPREAD))
+    {
+      if (y < DIRT_CEILING)
+        y = DIRT_CEILING + radius;
+    }
+}
+
+EXPLOSION::EXPLOSION (GLOBALDATA *global, ENVIRONMENT *env, double xpos, double ypos, double xvel, double yvel,
+                      int weaponType):PHYSICAL_OBJECT(),weap(NULL)
+{
+  initialise ();
+  setEnvironment (env);
+  _align = LEFT;
+  _global = global;
+  x = xpos;
+  y = ypos;
+  xv = xvel;
+  yv = yvel;
+  angle = (int)(atan2(xv, yv) / PI * 180);
+  while (angle < 0)
+    angle += 360;
+  while (angle > 360)
+    angle -= 360;
+
+  type = weaponType;
+  if (type < WEAPONS)
+    weap = &weapon[type];
+  else
+    weap = &naturals[type - WEAPONS];
+  radius = weap->radius;
+  etime = weap->etime;
+  damage = weap->damage;
+  eframes = weap->eframes;
+}
+
+void EXPLOSION::initialise ()
+{
+  PHYSICAL_OBJECT::initialise ();
+  drag = 0.95;
+  mass = 3;
+  a = 1;
+  peaked = 0;
+  exclock = 500;
+	bIsWeaponExplosion = true; // Exploding tanks set them to false themselves!
+}
+
+int EXPLOSION::applyPhysics ()
+{
+  if (type == NAPALM_JELLY)
+    {
+      if (rand () % 300 == 0)
+      {
+          DECOR *decor;
+          decor = new DECOR (_global, _env, x, y, xv, yv, radius / 2, DECOR_SMOKE);
+          if (!decor)
+            {
+              perror ( "explosion.cc: Failed allocating memory for decor in applyPhysics");
+              // exit (1);
+            }
+        // If the dirt below is falling away, napalm can fall, too:
+        if (getpixel(_env->terrain, x, y + 1) == PINK)
+        {
+           // yv = _env->gravity * (100.0 / FRAMES_PER_SECOND);
+           yv = _env->gravity * (100.0 / _global->frames_per_second);
+           PHYSICAL_OBJECT::applyPhysics();
+        }
+        else
+          yv = 0.0;
+      }
+    }
+  /*	if (dispersing)
+  	{
+  		double accel = (_env->wind - xv) / mass * drag * _env->viscosity;
+  		xv += accel;
+  		x += xv;
+  		y += yv;
+  	}
+  */
+  return (hitSomething);
+}
+
+
+void EXPLOSION::explode ()
+{
+  int calcblow;
+  double distance;
+  int z;
+  calcblow = 1;
+
+	/* to allow synchronous tank explosions, explosions need to know what they are */
+	if (player && player->tank && (type < WEAPONS))
+		bIsWeaponExplosion = true;
+	else
+		bIsWeaponExplosion = false;
+
+  if (peaked == 1 && a <= EXPLOSIONFRAMES + 1)
+    {
+      exclock++;
+      if (exclock > weap->etime)
+        {
+          exclock = 0;
+          a++;
+          requireUpdate ();
+        }
+      if (a > EXPLOSIONFRAMES + 1)
+        {
+          destroy = TRUE;
+        }
+    }
+  if (a <= EXPLODEFRAMES + 1)
+    {
+      TANK *tank;
+      if (a == 1)
+        {
+          for (int index = 0; (tank = (TANK*)_env->getNextOfClass (TANK_CLASS, &index)) && tank; index++)
+            {
+              // is tank directly above explosion?
+              if ((fabs (x - tank->x) < radius) && (y - tank->y >= 0))
+                tank->creditTo = player;
+            }
+        }
+      if ((a == 1) && (type <= TECTONIC || type >= WEAPONS || type == PERCENT_BOMB || type == REDUCER))
+        {
+          for (int index = 0; (tank = (TANK*)_env->getNextOfClass (TANK_CLASS, &index)) && tank; index++)
+            {
+              if (type >= SHAPED_CHARGE && type <= CUTTER)
+                {
+                  double dXDistance = fabs (x - tank->x);
+                  double dYDistance;
+                  if (y > tank->y)
+                    dYDistance     = fabs (y - tank->y) - (TANKHEIGHT * (3.0 / 4.0)); // To include the bottom of the tank
+                  else
+                    dYDistance     = fabs (y - tank->y) - (TANKHEIGHT * (3.0 / 8.0)); // The top has to be hit, but not only brushed
+
+                  if (dYDistance < 0) dYDistance = 0;
+
+                  if ( (dYDistance  <= (radius / 20))
+                       && (dXDistance  >= (TANKWIDTH / 2)))
+                    distance = ABSDISTANCE(dXDistance, dYDistance, 0, 0);
+                  else
+                    distance = 2 * radius; // clear outside the explosion!
+#ifdef DEBUG
+                  if ((dXDistance < (radius + TANKHEIGHT / 2)) && (dYDistance < 25))
+                    {
+                      cout << endl << "Shape: " << radius << " x " << (radius / 20) << endl;
+                      printf( "Tank  X = % 4d, Tank  Y = % 4d\n", (int)tank->x, (int)tank->y);
+                      printf( "Explo X = % 4d, Explo Y = % 4d\n", (int)x, (int)y);
+                      printf( "Dist  X = % 4d, Dist  Y = % 4d\n", (int)dXDistance, (int)dYDistance);
+                      cout << "Distance: " << distance << endl;
+                    }
+#endif // DEBUG
+                }
+              else
+                distance = ABSDISTANCE(x, y, tank->x, tank->y);
+
+              if (distance <= (radius + TANKHEIGHT/2) && tank->l > 0)
+                {
+                  _global->updateMenu = 1;
+
+                  if (type == PERCENT_BOMB)
+                    tank->damage = (int) ( (tank->l + tank->sh) / 2) + 1;
+                  else if ( type == REDUCER )
+                  {
+                    if (tank->player->damageMultiplier > 0.1)
+                       tank->player->damageMultiplier *= 0.75;
+                  }
+                  else if (player)
+                    tank->damage = (int) ((float) damage * ((float) 1 - ((fabs (distance) / (float)radius) / 2)) * player->damageMultiplier);
+                  // player is not used in weather attacks
+                  else
+                    tank->damage = (int) (float) damage * ((float) 1 - ((fabs (distance) / (float)radius) / 2));
+                  tank->creditTo = player;
+                  tank->applyDamage ();
+                }
+            }
+          if (type >= TREMOR && type <= TECTONIC)
+            {
+              angle = (int)(atan2 (yv, xv) / PI * 180);
+              if (angle < 0)
+                angle = angle + 360;
+              angle = angle % 360;
+            }
+        }
+      exclock++;
+      if (exclock > weap->etime)
+        {
+          exclock = 0;
+          a++;
+          requireUpdate ();
+        }
+      if (a >= EXPLODEFRAMES + 1 && !peaked)
+        {
+          calcblow = 0;
+        }
+    }
+  if (!calcblow)
+    {
+      if (type >= SHAPED_CHARGE && type <= CUTTER)
+        {
+          ellipsefill (_env->terrain, (int)x, (int)y, radius, radius / 20, PINK);
+          setUpdateArea ((int)x - (radius + 1), (int)y - (radius / 20 + 1), (radius + 1) * 2, (radius / 20 + 1) * 2);
+
+        }
+      
+      else if (type == DRILLER)
+      {
+           ellipsefill (_env->terrain, (int) x, (int) y, radius / 20, radius, PINK);
+           setUpdateArea( (int) x - (radius + 1), (int) y - (radius + 1), (radius + 1) * 2, (radius + 1) * 2);
+      }
+      
+      else if (type <= LAST_EXPLOSIVE || type >= WEAPONS || type == PERCENT_BOMB)
+        {
+
+          if (type != NAPALM_JELLY)
+            {
+              circlefill (_env->terrain, (int)x, (int)y, radius, PINK);
+// too much?  setUpdateArea ((int)x - (radius + 1), (int)y - (radius + 1), (radius + 1) * 2, (radius + 1) * 2);
+// still too much! setUpdateArea ((int)x - radius, (int)y - radius, radius * 2, radius * 2);
+              setUpdateArea ((int)x - radius, (int)y - radius, (radius * 2) - 2, (radius * 2) - 2);
+            }
+        }
+      else  if ((type >= RIOT_BOMB) && (type <= HVY_RIOT_BOMB))
+        {
+          circlefill (_env->terrain, (int)x, (int)y, radius, PINK);
+          setUpdateArea ((int)x - (radius + 1), (int)y - (radius + 1), (radius + 1) * 2, (radius + 1) * 2);
+        }
+      else if ((type >= RIOT_CHARGE) && (type <= RIOT_BLAST))
+        {
+          double sx = x - _global->slope[angle][0] * 15;
+          double sy = y - _global->slope[angle][1] * 15;
+          triangle (_env->terrain,
+                    (int)sx,
+                    (int)sy,
+                    (int)(sx + _global->slope[(angle + 45) % 360][0] * radius),
+                    (int)(sy + _global->slope[(angle + 45) % 360][1] * radius),
+                    (int)(sx + _global->slope[(angle + 315) % 360][0] * radius),
+                    (int)(sy + _global->slope[(angle + 315) % 360][1] * radius), PINK);
+          setUpdateArea ((int)sx - (radius + 1), (int)sy - (radius + 1), (radius + 1) * 2, (radius + 1) * 2);
+        }
+      else if ((type >= DIRT_BALL) && (type <= SMALL_DIRT_SPREAD))
+        {
+          BITMAP *tmp;		//for mixing
+
+          tmp = create_bitmap(radius * 2, radius * 2);
+          clear_to_color(tmp, PINK);
+          for (int count = 0; count < radius ; count++)
+            {
+              circle (tmp, radius, radius, count, (player)?player->color: makecol (0, 255, 0) );
+            }
+          setUpdateArea ((int)x - (radius + 1), (int)y - (radius + 1), (radius + 1) * 2, (radius + 1) * 2);
+
+          //copy terrain over explosion
+          masked_blit(_env->terrain, tmp, (int)x - radius, (int)y - radius, 0, 0, radius*2, radius*2);
+
+          //blit back exploded terrain
+          masked_blit(tmp, _env->terrain, 0, 0,(int)x - radius, (int)y - radius, radius*2, radius*2);
+
+          destroy_bitmap(tmp);
+        }
+
+      for (z = 0; z < (_current.w + 2); z++)
+        setSlideColumnDimensions (_global, _env, _current.x + z, TRUE);
+      calcblow = 1;
+      peaked = 1;
+      dispersing = 1;
+    }
+}
+
+void EXPLOSION::draw (BITMAP *dest)
+{
+  if (type >= SHAPED_CHARGE && type <= CUTTER)
+    {
+      if (a > 1 && a <= EXPLOSIONFRAMES + 1)
+        {
+          rotate_scaled_sprite (dest, (BITMAP *) _global->gfxData.flameFront[(a + (EXPLOSIONFRAMES * weap->eframes)) - 2],
+                                (int)x - radius, (int)y - (radius / 20), itofix (0), ftofix ((double) radius / 300));
+          setUpdateArea ((int)x - (radius + 1), (int)y - (radius / 20 + 1), (radius + 1) * 2, (radius / 20 + 1) * 2);
+        }
+    }
+  else if (type == DRILLER)
+  {
+     if (a > 1 && a <= EXPLOSIONFRAMES + 1)
+     {
+        rotate_scaled_sprite(dest, (BITMAP *) _global->gfxData.flameFront[(a + (EXPLOSIONFRAMES * weap->eframes)) - 2], (int) x - (radius), (int) y - (radius / 20), itofix(192), ftofix(radius / 300));
+        // rotate_scaled_sprite (dest, (BITMAP *) _global->gfxData.flameFront[(a + (EXPLOSIONFRAMES * weap->eframes)) - 2], (int)x - radius, (int)y - (radius / 20), itofix (0), ftofix ((double) radius / 300));
+
+        setUpdateArea( (int) x - (radius + 1), (int) y - (radius + 1), (radius + 1) * 2, (radius + 1) * 2);
+     }
+  }
+  else if (type == NAPALM_JELLY)
+    {
+      int blobSize = (int)(radius - ((double)a / EXPLOSIONFRAMES) * radius + 1);
+      if (blobSize < 2) blobSize = 2;       // avoid circle size crash
+      circlefill (_env->db, (int)x, (int)y, blobSize - 2, makecol (255, 0, 0));
+      circle(_env->db, (int)x, (int)y, blobSize - 1, makecol(255, 150, 0));
+      circle(_env->db, (int)x, (int)y, blobSize, makecol(255, 150, 0));
+      setUpdateArea ((int)x - (radius + 1), (int)y - (radius + 1), (radius + 1) * 2, (radius + 1) * 2);
+    }
+  else if (type <= LAST_EXPLOSIVE || type >= WEAPONS || type == PERCENT_BOMB)
+    {
+      if (a > 1 && a <= EXPLOSIONFRAMES + 1)
+        {
+          /*  - background needs to be cleard immediately to allow chain missiles to work
+          		  (and horizontal spreads look *far* better, too! ;) )
+          		Note: Shaped charges are always shot alone, and they live off their visual effect.
+          					Adding the immediate destruction on them, too, would cut off some of the effect... */
+          if	(a <= EXPLODEFRAMES)
+            circlefill (_env->terrain, (int)x, (int)y, (int)((radius / EXPLODEFRAMES) * a), PINK);
+          rotate_scaled_sprite(dest, (BITMAP *) _global->gfxData.explosions[(a + (EXPLOSIONFRAMES * weap->eframes)) - 2],
+                               (int)x - radius, (int)y - radius, itofix (0), ftofix ((double) radius / 107));
+          setUpdateArea ((int)x - (radius + 1), (int)y - (radius + 1), (radius + 1) * 2, (radius + 1) * 2);
+        }
+    }
+  else if ( (type <= TECTONIC) && (type >= TREMOR) )
+    {
+      if (a > 1 && a <= EXPLODEFRAMES + 1)
+        {
+          drawFracture (_global, _env, _env->terrain, &_current, (int)x, (int)y, angle, (int)(((double)a / EXPLODEFRAMES) * (radius / 4)), radius, 5, 0);
+        }
+    }
+  else if ((type >= RIOT_BOMB) && (type <= HVY_RIOT_BOMB))
+    {
+      if (a > 1 && a <= EXPLODEFRAMES + 1)
+        {
+          int startCirc = (radius / EXPLODEFRAMES) * a;
+          int colour = (player) ? player->color : makecol(0, 0, 255);
+          circlefill (_env->terrain, (int)x, (int)y, startCirc, PINK);
+          circle (dest, (int)x, (int)y, startCirc, colour);
+          setUpdateArea ((int)x - (radius + 1), (int)y - (radius + 1), (radius + 1) * 2, (radius + 1) * 2);
+        }
+    }
+  else if ((type >= RIOT_CHARGE) && (type <= RIOT_BLAST))
+    {
+      if (a > 1 && a <= EXPLODEFRAMES + 1)
+        {
+          double sx = x - _global->slope[angle][0] * 15;
+          double sy = y - _global->slope[angle][1] * 15;
+          int startCirc = (radius / EXPLODEFRAMES) * a;
+          triangle (dest, (int)sx, (int)sy, (int)(sx + _global->slope[(angle + 45) % 360][0] * startCirc), (int)(sy + _global->slope[(angle + 45) % 360][1] * startCirc),(int)(sx + _global->slope[(angle + 315) % 360][0] * startCirc),(int)(sy + _global->slope[(angle + 315) % 360][1] * startCirc), player->color);
+          setUpdateArea ((int)sx - (startCirc + 1), (int)sy - (startCirc + 1), (startCirc + 1) * 2, (startCirc + 1) * 2);
+        }
+    }
+  else
+    {
+      if (a > 1 && a <= EXPLODEFRAMES + 1)
+        {
+          int startCirc = (radius / EXPLODEFRAMES) * a;
+          circlefill (dest, (int)x, (int)y, startCirc, (player)?player->color: makecol (0, 255, 0) );
+          startCirc += (radius / EXPLODEFRAMES) * 2;
+          setUpdateArea ((int)x - startCirc, (int)y - startCirc, startCirc * 2, startCirc * 2);
+        }
+    }
+}
+
+int EXPLOSION::isSubClass (int classNum)
+{
+  if (classNum == EXPLOSION_CLASS)
+    return (TRUE);
+  else
+    return (FALSE);
+  //return (PHYSICAL_OBJECT::isSubClass (classNum));
+}
diff --git a/src/explosion.h b/src/explosion.h
new file mode 100644
index 0000000..f7c9b19
--- /dev/null
+++ b/src/explosion.h
@@ -0,0 +1,68 @@
+#ifndef EXPLOSION_DEFINE
+#define EXPLOSION_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "main.h"
+#include "physobj.h"
+
+#define DIRT_CEILING 50
+
+
+class EXPLOSION: public PHYSICAL_OBJECT
+  {
+  public:
+    int	etime;
+    int	damage;
+    int	eframes;
+    int	radius;
+    int	sound;
+    int	exclock;
+    int	type, a;
+    int	peaked;
+    int	dispersing;
+    WEAPON	*weap;
+		/* to allow synchronous tank explosions, explosions need to know what they are */
+		bool bIsWeaponExplosion;
+
+    virtual ~EXPLOSION ();
+    EXPLOSION (GLOBALDATA *global, ENVIRONMENT *env, double xpos, double ypos, int weaponType);
+    EXPLOSION (GLOBALDATA *global, ENVIRONMENT *env, double xpos, double ypos, double xvel, double yvel, int weaponType);
+    void	draw (BITMAP *dest);
+    void	initialise ();
+    int	applyPhysics ();
+    void	explode ();
+    int	isSubClass (int classNum);
+    inline virtual int	getClass ()
+    {
+      return (EXPLOSION_CLASS);
+    }
+    inline virtual void setEnvironment(ENVIRONMENT *env)
+    {
+      if (!_env || (_env != env))
+        {
+          _env = env;
+          _index = _env->addObject (this);
+        }
+    }
+  };
+
+#endif
diff --git a/src/externs.h b/src/externs.h
new file mode 100644
index 0000000..2a6a692
--- /dev/null
+++ b/src/externs.h
@@ -0,0 +1,59 @@
+#ifndef EXTERNS_DEFINE
+#define	EXTERNS_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+extern char	*errorMessage;
+extern int	errorX, errorY;
+
+extern int	WHITE, BLACK, PINK, COLOR[];
+
+extern int	k;
+extern int	ctrlUsedUp;
+
+extern int	cclock,
+  fps, frames,
+  fi, lx, ly,
+  order[];
+
+//extern char	cacheCirclesBG;
+//extern char	ditherGradients;
+//extern int	startmoney;
+//extern int	turntype;
+
+extern double	height[];
+//extern int	landtable[];
+
+//extern int	steep, mheight, mbase;
+//extern double	msteep, smooth;
+//extern double	gravity;
+//extern double	windstrength, windvariation;
+//extern double	interest;
+//extern char	name[][11];
+
+extern int winner;
+
+extern WEAPON	weapon[];
+extern WEAPON	naturals[];
+extern ITEM	item[];
+
+#endif
+
diff --git a/src/fade.cpp b/src/fade.cpp
new file mode 100644
index 0000000..eb6da5a
--- /dev/null
+++ b/src/fade.cpp
@@ -0,0 +1,235 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+fade.cc
+
+Provides graphical transitions via change and quickChange, as prototyped in
+main.h
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/*
+TODO
+ + Add more faders
+ + Improve/complete documentation
+*/
+
+
+
+#include "globaldata.h"
+#include "main.h"
+
+
+
+/*****************************************************************************
+Internal fades
+
+The following section of code defines the internal fade routines.  These
+routines are used by the change function to perform transitions.  To add a
+new fader, simply implement a function as seen below and then add it to
+change's function pointer array.
+*****************************************************************************/
+/*
+static void spiralPixelFade (GLOBALDATA *global, BITMAP *target)
+{
+  int blockSize = 8;
+  int spiralSize = 20;
+  int length = spiralSize, x = 0, y = 0;
+  int stepSize = (spiralSize + 1) * blockSize;
+  int x2, y2;
+  int count;
+
+  for (count = 0, y = stepSize - blockSize; count < length; count++, y -= blockSize)
+    for (x2 = 0; x2 <= global->screenWidth; x2 += stepSize)
+      for (y2 = 0; y2 <= global->screenHeight; y2 += stepSize)
+        blit (target, screen, x2+x, y2+y, x2+x, y2+y, blockSize, blockSize);
+  while (length)
+    {
+      for (count = 0; count < length; count++, x += blockSize)
+        for (x2 = 0; x2 <= global->screenWidth; x2 += stepSize)
+          for (y2 = 0; y2 <= global->screenHeight; y2 += stepSize)
+            blit (target, screen, x2+x, y2+y, x2+x, y2+y, blockSize, blockSize);
+      for (count = 0; count < length; count++, y += blockSize)
+        for (x2 = 0; x2 <= global->screenWidth; x2 += stepSize)
+          for (y2 = 0; y2 <= global->screenHeight; y2 += stepSize)
+            blit (target, screen, x2+x, y2+y, x2+x, y2+y, blockSize, blockSize);
+      length--;
+      for (count = 0; count < length; count++, x -= blockSize)
+        for (x2 = 0; x2 <= global->screenWidth; x2 += stepSize)
+          for (y2 = 0; y2 <= global->screenHeight; y2 += stepSize)
+            blit (target, screen, x2+x, y2+y, x2+x, y2+y, blockSize, blockSize);
+      for (count = 0; count < length; count++, y -= blockSize)
+        for (x2 = 0; x2 <= global->screenWidth; x2 += stepSize)
+          for (y2 = 0; y2 <= global->screenHeight; y2 += stepSize)
+            blit (target, screen, x2+x, y2+y, x2+x, y2+y, blockSize, blockSize);
+      length--;
+    }
+  for (x2 = 0; x2 <= global->screenWidth; x2 += stepSize)
+    for (y2 = 0; y2 <= global->screenHeight; y2 += stepSize)
+      blit (target, screen, x2+x, y2+y, x2+x, y2+y, blockSize, blockSize);
+}
+
+static void topDownMultiWipeFade (GLOBALDATA *global, BITMAP *target)
+{
+  int z, zz ;
+
+  for (zz = 0; zz < 8; zz++)
+    {
+      int lineCount = 0;
+      for (z = zz; z < global->screenHeight; z += 8)
+        {
+          blit (target, screen, 0, z, 0, z, global->screenWidth, 1);
+          if (lineCount == 10)
+            {
+              lineCount = 0;
+              rest (1);
+            }
+          lineCount++;
+        }
+    }
+}
+
+static void topDownWipeFade (GLOBALDATA *global, BITMAP *target)
+{
+  int z;
+
+  for (z = 0; z <= global->screenHeight / 8; z++)
+    {
+      blit (target, screen, 0, z * 8, 0, z * 8, global->screenWidth, 8);
+      rest (1);
+    }
+}
+
+static void bottomUpWipeFade (GLOBALDATA *global, BITMAP *target)
+{
+  int z;
+
+  for (z = global->screenHeight / 8; z >= 0; z--)
+    {
+      blit (target, screen, 0, z * 8, 0, z * 8, global->screenWidth, 8);
+      rest (1);
+    }
+}
+
+static void rightLeftWipeFade (GLOBALDATA *global, BITMAP *target)
+{
+  int z;
+
+  for (z = global->screenWidth / 8; z >= 0; z--)
+    {
+      blit (target, screen, z * 8, 0, z * 8, 0, 8, global->screenHeight);
+      rest (1);
+    }
+}
+
+static void leftRightWipeFade (GLOBALDATA *global, BITMAP *target)
+{
+  int z;
+
+  for (z = 0; z <= global->screenWidth / 8; z++)
+    {
+      blit (target, screen, z * 8, 0, z * 8, 0, 8, global->screenHeight);
+      rest (1);
+    }
+}
+
+static void crossLinesFade (GLOBALDATA *global, BITMAP *target)
+{
+  int z;
+
+  for (z = 0; z < (global->screenWidth/4+4) / 4; z++)
+    {
+      blit (target, screen, z * 8, 0, z * 8, 0, 4, global->screenHeight);
+      blit (target, screen, (global->screenWidth-1) - (z * 8), 0, (global->screenWidth-1) - (z * 8), 0, 4, global->screenHeight);
+      blit (target, screen, 0, (z * 6), 0, (z * 6), global->screenWidth, 4);
+      blit (target, screen, 0, (global->screenHeight - (z * 6)), 0, (global->screenHeight - (z * 6)), global->screenWidth, 4);
+      rest (1);
+    }
+  for (z = (global->screenWidth/4+4) / 4; z != 0; z--)
+    {
+      blit (target, screen, z * 8 + 4, 0, z * 8 + 4, 0, 4, global->screenHeight);
+      blit (target, screen, (global->screenWidth-1) - (z * 8) + 4, 0, (global->screenWidth-1) - (z * 8) + 4, 0, 4, global->screenHeight);
+      blit (target, screen, 0, (z * 6) + 4, 0, (z * 6) + 4, global->screenWidth, 4);
+      blit (target, screen, 0, (global->screenHeight - (z * 6)) + 4, 0, (global->screenHeight - (z * 6)) + 4, global->screenWidth, 4);
+      rest (1);
+    }
+}
+
+*/
+
+/*****************************************************************************
+changeHandleError
+
+Used internally by change and quickChange.  Prints out error messages.
+*****************************************************************************/
+static void changeHandleError (GLOBALDATA *global, BITMAP *target)
+{
+  if (! global->os_mouse) show_mouse (NULL);
+  if (errorMessage)
+    {
+      textout_ex (target, font, errorMessage, errorX, errorY, makecol (255, 0, 0), -1);
+      errorMessage = NULL;
+    }
+}
+
+
+/*****************************************************************************
+change
+
+Selects and executes a random transition.
+*****************************************************************************/
+/*
+void change(GLOBALDATA *global, BITMAP *target)
+{
+  static void (* const procs[])(GLOBALDATA*,BITMAP*) =
+  {
+    crossLinesFade,			spiralPixelFade,
+    leftRightWipeFade,		rightLeftWipeFade,
+    bottomUpWipeFade,		topDownWipeFade,
+    topDownMultiWipeFade,
+  } ;
+  static const int cprocs = sizeof( procs ) / sizeof( procs[0] );
+
+  if (! global->os_mouse) show_mouse (NULL);
+  changeHandleError (global, target);
+
+  (procs[rand() % cprocs]) (global, target);
+
+  clear_keybuf ();
+}
+*/
+
+void change(GLOBALDATA *global, BITMAP *target)
+{
+    quickChange(global, target);
+}
+
+/*****************************************************************************
+quickChange
+
+Executes a fast and simple transition.
+
+*****************************************************************************/
+void quickChange (GLOBALDATA *global, BITMAP *target)
+{
+  changeHandleError (global, target);
+  blit (target, screen, 0, 0, 0, 0, global->screenWidth, global->screenHeight);
+  rest (1);
+}
+
diff --git a/src/files.cpp b/src/files.cpp
new file mode 100644
index 0000000..a7074ce
--- /dev/null
+++ b/src/files.cpp
@@ -0,0 +1,1106 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+
+// basically all UNIX-like OSes should use stat
+#ifndef WIN32
+#include <sys/stat.h>
+#endif
+
+#include "player.h"
+#include "files.h"
+#include "main.h"
+#include "text.h"
+
+/*
+This function saves the game in progress.
+All data is saved in a text file for flexiblity.
+Returns TRUE on success and FALSE on failure.
+*/
+int Save_Game(GLOBALDATA *global, ENVIRONMENT *env)
+{
+  FILE *game_file = NULL;
+  char *file_path = NULL;
+  int player_count = 0;
+  PLAYER *my_player = NULL;
+  int count;
+  int global_player_number;
+
+  // figure out file name
+  file_path = (char *) calloc( strlen(global->configDir) +
+                               strlen(global->game_name) + 24,
+                               sizeof(char) );
+  if (! file_path)
+    return FALSE;
+
+  sprintf(file_path, "%s/%s.sav", global->configDir, global->game_name);
+
+  game_file = fopen(file_path, "w");
+  free(file_path);
+  if (!game_file)
+    return FALSE;
+
+  // write global data
+  fprintf(game_file, "GLOBAL\n");
+  fprintf(game_file, "ROUNDS=%f\n", global->rounds);
+  fprintf(game_file, "CURRENTROUND=%d\n", global->currentround);
+  fprintf(game_file, "CAMPAIGNMODE=%f\n", global->campaign_mode);
+  fprintf(game_file, "***\n");
+
+  // write envrionment data
+  fprintf(game_file, "ENVIRONMENT\n");
+  fprintf(game_file, "***\n");
+
+  // write player data
+  fprintf(game_file, "PLAYERS\n");
+  while ( player_count < global->numPlayers )
+  {
+      my_player = global->players[player_count];
+      global_player_number = 0;
+      while ( strcmp(global->allPlayers[global_player_number]->getName(), my_player->getName() ) )
+        global_player_number++;
+      fprintf(game_file, "PLAYERNUMBER=%d\n", global_player_number);
+      fprintf(game_file, "SCORE=%d\n", my_player->score);
+      fprintf(game_file, "MONEY=%d\n", my_player->money);
+      fprintf(game_file, "TYPE=%f\n", my_player->type);
+      fprintf(game_file, "TYPESAVED=%f\n", my_player->type_saved);
+      for (count = 0; count < WEAPONS; count++)
+        fprintf(game_file, "WEAPON=%d %d\n", count, my_player->nm[count]);
+      for (count = 0; count < ITEMS; count++)
+        fprintf(game_file, "ITEM=%d %d\n", count, my_player->ni[count]);
+      fprintf(game_file, "***\n");
+      player_count++;
+    }
+
+  fclose(game_file);
+
+  // save the current config
+  file_path = (char *) calloc( strlen(global->configDir) +
+                               strlen(global->game_name) + 24,
+                               sizeof(char) );
+  if (! file_path)
+    return FALSE;
+  sprintf(file_path, "%s/%s.txt", global->configDir, global->game_name);
+  Save_Game_Settings_Text(global, env, file_path);
+  free(file_path);
+
+  return TRUE;
+}
+
+
+
+/*
+This function attempts to load a saved
+game.
+The function returns TRUE on success and
+FALSE is an error occures.
+-- Jesse
+*/
+int Load_Game(GLOBALDATA *global, ENVIRONMENT *env)
+{
+  char line[512];
+  char *field, *value;
+  int index, amount, player_count = 0;
+  FILE *my_file;
+  char *file_path;
+  int stage = NO_STAGE;
+  char *got_line;
+  int global_player_number;
+
+  // load config settings
+  /*
+  file_path = (char *) calloc( strlen(homedir) +
+                               strlen(global->game_name) + 24,
+                               sizeof(char) );
+  if (! file_path)
+    return FALSE;
+  sprintf(file_path, "%s/.atanks/%s.txt", homedir, global->game_name);
+  my_file = fopen(file_path, "r");
+  free(file_path);
+  if (! my_file)
+    return FALSE;
+  global->loadFromFile_Text(my_file);
+  env->loadFromFile_Text(my_file);
+  fclose(my_file);
+  */
+
+  file_path = (char *) calloc( strlen(global->configDir) +
+                               strlen(global->game_name) + 24,
+                               sizeof(char) );
+  if (! file_path)
+    return FALSE;
+
+  sprintf(file_path, "%s/%s.sav", global->configDir, global->game_name);
+
+  my_file = fopen(file_path, "r");
+  free(file_path);
+  if (! my_file)
+    return FALSE;
+
+  // read a line from the file
+  got_line = fgets(line, 512, my_file);
+  // keep reading until we hit EOF or error
+  while ( (got_line) && (player_count < MAXPLAYERS) )
+  {
+      // clear end of line
+      if ( strchr(line, '\n') )
+        strchr(line, '\n')[0] = '\0';
+      if ( strchr(line, '\r') )
+        strchr(line, '\r')[0] = '\0';
+
+      // check to see if we found a new stage
+      if (! strcasecmp(line, "global") )
+        stage = GLOBAL_STAGE;
+      else if (! strcasecmp(line, "environment") )
+        stage = ENVIRONMENT_STAGE;
+      else if (! strcasecmp(line, "players") )
+        stage = PLAYER_STAGE;
+
+      // not a new stage, seperate field and value
+      else
+        {
+          value = strchr(line, '=');
+          if (value)        // valid line
+            {
+              field = line;
+              value[0] = '\0';   // seperate field and value;
+              value++;           // go to first place after =
+              // interpret data
+              switch (stage)
+                {
+                case GLOBAL_STAGE:
+                  if (! strcasecmp(field, "rounds") )
+                    sscanf(value, "%lf", &global->rounds);
+                  else if (! strcasecmp(field, "currentround") )
+                    sscanf(value, "%d", &global->currentround);
+                  else if (! strcasecmp(field, "campaignmode") )
+                    sscanf(value, "%lf", &global->campaign_mode);
+
+                  break;
+                case ENVIRONMENT_STAGE:
+
+                  break;
+                case PLAYER_STAGE:
+                  if (! strcasecmp(field, "playernumber") )
+                    {
+                      sscanf(value, "%d", &global_player_number);
+                      global->addPlayer( global->allPlayers[global_player_number] );
+                      /*  the loading of the preferences is (unfortunately) disabled and I do not know why.
+                          As long as they *are* disabled, PerPlay-Config bots have to get a new config here,
+                          or they use the global config, rendering PerPlay-Config useless. */
+                      if	( (global->players[player_count]->preftype	==	PERPLAY_PREF)
+                           && (global->players[player_count]->type			!=	HUMAN_PLAYER))
+                        global->players[player_count]->generatePreferences();
+                      global->players[player_count]->initialise();
+                    }
+                  else if (! strcasecmp(field, "score") )
+                    sscanf(value, "%d", &(global->players[player_count]->score) );
+                  else if (! strcasecmp(field, "money") )
+                    sscanf(value, "%d", &(global->players[player_count]->money) );
+                  else if (! strcasecmp(field, "type") )
+                    sscanf(value, "%lf", &(global->players[player_count]->type) );
+                  else if (! strcasecmp(field, "typesaved") )
+                    sscanf(value, "%lf", &(global->players[player_count]->type_saved) );
+                  else if (! strcasecmp(field, "weapon") )
+                    {
+                      sscanf(value, "%d %d", &index, &amount);
+                      global->players[player_count]->nm[index] = amount;
+                    }
+                  else if (! strcasecmp(field, "item") )
+                    {
+                      sscanf(value, "%d %d", &index, &amount);
+                      global->players[player_count]->ni[index] = amount;
+                    }
+                  break;
+                }    // end of stage
+
+            }       //     end of valid line
+          else if ( (! strcmp(line, "***") ) && (stage == PLAYER_STAGE) )
+            player_count++;
+
+        }     // end of field value area
+
+      // read next line of file
+      got_line = fgets(line, 512, my_file);
+
+    }    // end of reading file
+  fclose(my_file);
+  return TRUE;
+}
+
+
+
+/*
+Check to see if a saved game exists with the given name.
+*/
+int Check_For_Saved_Game(GLOBALDATA *global)
+{
+  FILE *my_file;
+  char *path_name;
+
+  path_name = (char *) calloc( strlen(global->configDir) + strlen(global->game_name) + 24,
+                               sizeof(char) );
+  if (! path_name)
+    return FALSE;
+
+  sprintf(path_name, "%s/%s.sav", global->configDir, global->game_name);
+
+  my_file = fopen(path_name, "r");
+  free(path_name);
+  if (my_file)
+  {
+     fclose(my_file);
+     return TRUE;
+  }
+  else
+    return FALSE;
+
+}
+
+
+
+/*
+This function copies the atanks config file
+from the HOME_DIR folder to HOME_DIR/.atanks
+If the .atanks folder does not exist, this
+function will create it.
+Returns TRUE on success and FALSE on error.
+*/
+
+int Copy_Config_File(GLOBALDATA *global)
+{
+  FILE *source_file, *dest_file;
+  char source_path[1024], dest_path[1024];
+  char buffer[1024];
+  char *my_home_folder;
+  int status;
+
+  // figure out where home is
+  my_home_folder = getenv(HOME_DIR);
+  if (! my_home_folder)
+    my_home_folder = (char *)".";
+
+  // check to see if the config file has already been copied
+  snprintf(source_path, 1024, "%s/atanks-config.txt", global->configDir);
+  source_file = fopen(source_path, "r");
+  if (source_file)     // config file is in the right place
+    {
+      fclose(source_file);
+      return TRUE;
+    }
+
+  /*
+  // check to make sure we have a source file
+  snprintf(source_path, 1024, "%s/.atanks-config.txt", my_home_folder);
+  source_file = fopen(source_path, "r");
+  if (! source_file)
+     return TRUE;
+  */
+
+  // file not copied yet, create the required directory
+  snprintf(buffer, 1024, "%s/.atanks", my_home_folder);
+#ifdef WIN32
+  status = mkdir(buffer);
+#else
+  status = mkdir(buffer, 0700);
+#endif
+  if (status == -1)
+    {
+      printf( (char *)"Error occured. Unable to create sub directory.\n");
+      return FALSE;
+    }
+
+  // check to make sure we have a source file
+  snprintf(source_path, 1024, "%s/.atanks-config.txt", my_home_folder);
+  source_file = fopen(source_path, "r");
+  if (! source_file)
+    return TRUE;
+
+  // we already have an open source file, create destination file
+  snprintf(dest_path, 1024, "%s/atanks-config.txt", global->configDir);
+  dest_file = fopen(dest_path, "wb");
+  if (! dest_file)
+    {
+      printf( (char *)"Unable to create destination file.\n");
+      fclose(source_file);
+      return FALSE;
+    }
+
+  // we have open files, let's copy
+  status = fread(buffer, 1, 1024, source_file);
+  while (status)
+    {
+      status = fwrite(buffer, 1, 1024, dest_file);
+      status = fread(buffer, 1, 1024, source_file);
+    }
+
+  fclose(source_file);
+  fclose(dest_file);
+  return TRUE;
+}
+
+
+
+// Make sure we have a music folder
+// Returns TRUE on success or FALSE
+// if an error occures.
+int Create_Music_Folder(GLOBALDATA *global)
+{
+   DIR *music_folder;
+   char *folder_path;
+   
+   folder_path = (char *) calloc( strlen(global->configDir) + 32, sizeof(char) );
+   if (! folder_path)
+      return FALSE;
+
+   sprintf(folder_path, "%s/music", global->configDir);
+   music_folder = opendir(folder_path);
+   if (! music_folder)
+   {
+     #ifdef WIN32
+     mkdir(folder_path);
+     #else
+     mkdir(folder_path, 0700);
+     #endif
+   }
+   else    // it already exists
+     closedir(music_folder);
+
+   free(folder_path);
+   return TRUE;
+}
+
+
+
+
+
+/*
+Displays lines of text.
+*/
+void renderTextLines (GLOBALDATA *global, ENVIRONMENT *env,
+                      TEXTBLOCK *lines, int scrollOffset,
+                      const FONT* fnt, const int spacing )
+{
+  const int textheight = text_height (fnt) ;
+  const int textheight_s = textheight * spacing ;
+  int yOffset = scrollOffset;
+  char *text;
+  int tLen, count;
+
+  for (count = 0;
+       (count < lines->total_lines) && (yOffset < global->screenHeight);
+       count++)
+    {
+      text = lines->complete_text[count];
+      tLen = text_length (fnt, text);
+
+          textout_centre_ex (env->db, fnt, text,
+                             global->halfWidth + 2, global->halfHeight + yOffset + 2, BLACK, -1);
+          textout_centre_ex (env->db, fnt, text,
+                             global->halfWidth, global->halfHeight + yOffset, WHITE, -1);
+      yOffset += textheight_s;
+    }
+}
+
+
+
+
+/*
+Scroll text in a box
+*/
+void scrollTextList (GLOBALDATA *global, ENVIRONMENT *env,
+                     TEXTBLOCK *lines)
+{
+  /* Justin says: this function, along with renderTextLines, aren't
+  exactly efficient.  I think they could use rewrite. */
+  static const int numItemsSrc[] = { 100, 30 } ;
+
+  // DATAFILE *dffont ;
+  const FONT* fnt = font;
+  int spacing = 2;
+  int tOffset = rand ();
+  int itemType = rand () / (RAND_MAX/2 + 1) ;
+  int numItems = numItemsSrc[itemType];
+  int my_key, done = FALSE;
+  int moving = TRUE;
+
+  draw_circlesBG (global, env->db, 0, 0, global->screenWidth, global->screenHeight, false);
+  drawMenuBackground (global, env, BACKGROUND_BLANK, abs (tOffset), numItems);
+  quickChange (global, env->db);
+  //set_clip_rect (env->db, global->halfWidth - 300 + 1, 100 + 1,
+  //               global->halfWidth + 300 - 1, global->screenHeight - 100 - 1);
+  set_clip_rect(env->db, global->halfWidth - 300 + 1, global->menuBeginY + 1,
+                global->halfWidth + 300 - 1, global->menuEndY - 1);
+  int scrollOffset = 0;
+  flush_inputs ();
+  if (! global->os_mouse) show_mouse (NULL);
+
+  // lines->Display_All(TRUE);
+  do
+    {
+      drawMenuBackground (global, env, BACKGROUND_BLANK, abs (tOffset), numItems);
+
+      renderTextLines (global, env, lines, scrollOffset,
+                       fnt, spacing );
+      //blit (env->db, screen, global->halfWidth - 300, 100, global->halfWidth - 300, 100,
+      //      601, global->screenHeight - 199);
+      blit(env->db, screen, global->halfWidth - 300, global->menuBeginY,
+           global->halfWidth - 300, global->menuBeginY, 601, 
+           global->screenHeight - 2 * global->menuBeginY);
+      LINUX_REST;
+      if (moving)
+      {
+         tOffset++;
+         scrollOffset--;
+      }
+
+      if (scrollOffset < -(global->halfHeight - 100 + lines->total_lines * 30))
+        scrollOffset = global->halfHeight - 100;
+      if (global->close_button_pressed)
+        break;
+      if ( keypressed() )
+      {
+          my_key = (readkey()) >> 8;
+          switch (my_key)
+          {
+             case KEY_ESC: done = TRUE;
+                       break;
+             case KEY_SPACE: 
+                       moving = TRUE; 
+                       break;
+             case KEY_UP:
+                       tOffset--;
+                       scrollOffset++;
+                       moving = FALSE;
+                       break;
+             case KEY_DOWN:
+                       tOffset++;
+                       scrollOffset--;
+                       moving = FALSE;
+                       break;
+          }      // end of switch
+      }       // end of key pressed
+    }
+  while ( (! done) && (!mouse_b) );
+
+  if (! global->os_mouse) show_mouse (screen);
+  set_clip_rect (env->db, 0, 0, (global->screenWidth-1), (global->screenHeight-1));
+  flush_inputs ();
+}
+
+
+
+/* Flush key buffer and waits for button releases */
+void flush_inputs()
+{
+  do { }
+  while (mouse_b);
+  clear_keybuf();
+}
+
+
+
+// This file loads weapons, naturals and items
+// from a text file
+// Returns TRUE on success and FALSE on failure
+int Load_Weapons_Text(GLOBALDATA *global)
+{
+  FILE *wfile;
+  char *path_to_file;
+  char *status;
+  char line[512];
+  int file_stage = 0;     // weapons, natruals, items
+  int data_stage = 0;         // name, descrption, data
+  int item_count = 0, weapon_count = 0, natural_count = 0;
+
+  setlocale(LC_NUMERIC, "C");
+  // get path name
+  path_to_file = (char *) calloc( strlen(global->dataDir) + 64, sizeof(char) );
+  if (! path_to_file)
+    {
+      printf( "Memory error occured while loading weapons.\n");
+      return FALSE;
+    }
+
+  if (global->language == LANGUAGE_ENGLISH)
+    sprintf(path_to_file, "%s/text/weapons.txt", global->dataDir);
+  else if (global->language == LANGUAGE_PORTUGUESE)
+    sprintf(path_to_file, "%s/text/weapons.pt_BR.txt", global->dataDir);
+  else if (global->language == LANGUAGE_FRENCH)
+    sprintf(path_to_file, "%s/text/weapons_fr.txt", global->dataDir);
+  else if (global->language == LANGUAGE_GERMAN)
+    sprintf(path_to_file, "%s/text/weapons_de.txt", global->dataDir);
+  else if (global->language == LANGUAGE_SLOVAK)
+    sprintf(path_to_file, "%s/text/weapons_sk.txt", global->dataDir);
+  else if (global->language == LANGUAGE_RUSSIAN)
+    sprintf(path_to_file, "%s/text/weapons_ru.txt", global->dataDir);
+  else if (global->language == LANGUAGE_SPANISH)
+    sprintf(path_to_file, "%s/text/weapons_ES.txt", global->dataDir);
+  else if (global->language == LANGUAGE_ITALIAN)
+    sprintf(path_to_file, "%s/text/weapons_it.txt", global->dataDir);
+
+  // open file
+  wfile = fopen(path_to_file, "r");
+  // free memory
+  // free(path_to_file);
+  if (! wfile)
+    {
+      printf( "Unable to open weapons file. (%s)\n", path_to_file);
+      free(path_to_file);
+      return FALSE;
+    }
+  free(path_to_file);
+
+  Clear_Weapons();            // make sure arrays are cleared before loading data
+  // read line
+  status = fgets(line, 512, wfile);
+  while (status)
+    {
+      // clear end of line
+      if ( strchr(line, '\n') )
+        strchr(line, '\n')[0] = '\0';
+      if ( strchr(line, '\r') )
+        strchr(line, '\r')[0] = '\0';
+
+      // skip # and empty lines
+      if ( (! (line[0] == '#') ) && ( strlen(line) > 2 ) )
+        {
+          // check for header
+          if (! strcasecmp(line, "*WEAPONS*") )
+            {
+              file_stage = 0;
+              data_stage = 0;
+            }
+          else if (! strcasecmp(line, "*NATURALS*") )
+            {
+              file_stage = 1;
+              data_stage = 0;
+            }
+          else if (! strcasecmp(line, "*ITEMS*") )
+            {
+              file_stage = 2;
+              data_stage = 0;
+            }
+
+          // not a special line, let's read some data
+          else
+            {
+              // weapon
+              if ( (file_stage == 0) && (weapon_count < WEAPONS) )
+                {
+                  if (data_stage == 0)   // name
+                    strcpy(weapon[weapon_count].name, line);
+                  else if (data_stage == 1)
+                    strcpy(weapon[weapon_count].description, line);
+                  else if (data_stage == 2)
+                    {
+                      sscanf(line, "%d %d %lf %lf %d %d %d %d %d %d %d %d %d %d %d %d %d %lf %d %lf %lf %lf %d %lf",
+                             &(weapon[weapon_count].cost),
+                             &(weapon[weapon_count].amt),
+                             &(weapon[weapon_count].mass),
+                             &(weapon[weapon_count].drag),
+                             &(weapon[weapon_count].radius),
+                             &(weapon[weapon_count].sound),
+                             &(weapon[weapon_count].etime),
+                             &(weapon[weapon_count].damage),
+                             &(weapon[weapon_count].eframes),
+                             &(weapon[weapon_count].picpoint),
+                             &(weapon[weapon_count].spread),
+                             &(weapon[weapon_count].delay),
+                             &(weapon[weapon_count].noimpact),
+                             &(weapon[weapon_count].techLevel),
+                             &(weapon[weapon_count].warhead),
+                             &(weapon[weapon_count].numSubmunitions),
+                             &(weapon[weapon_count].submunition),
+                             &(weapon[weapon_count].impartVelocity),
+                             &(weapon[weapon_count].divergence),
+                             &(weapon[weapon_count].spreadVariation),
+                             &(weapon[weapon_count].launchSpeed),
+                             &(weapon[weapon_count].speedVariation),
+                             &(weapon[weapon_count].countdown),
+                             &(weapon[weapon_count].countVariation) );
+                    }
+                  data_stage++;
+                  if (data_stage > 2)
+                    {
+                      data_stage = 0;
+                      weapon_count++;
+                    }
+                }       // end of weapon section
+
+              // naturals
+              else if ( (file_stage == 1) && (natural_count < NATURALS) )
+                {
+                  if (data_stage == 0)   // name
+                    strcpy(naturals[natural_count].name, line);
+                  else if (data_stage == 1)
+                    strcpy(naturals[natural_count].description, line);
+                  else if (data_stage == 2)
+                    {
+                      sscanf(line, "%d %d %lf %lf %d %d %d %d %d %d %d %d %d %d %d %d %d %lf %d %lf %lf %lf %d %lf",
+                             &(naturals[natural_count].cost),
+                             &(naturals[natural_count].amt),
+                             &(naturals[natural_count].mass),
+                             &(naturals[natural_count].drag),
+                             &(naturals[natural_count].radius),
+                             &(naturals[natural_count].sound),
+                             &(naturals[natural_count].etime),
+                             &(naturals[natural_count].damage),
+                             &(naturals[natural_count].eframes),
+                             &(naturals[natural_count].picpoint),
+                             &(naturals[natural_count].spread),
+                             &(naturals[natural_count].delay),
+                             &(naturals[natural_count].noimpact),
+                             &(naturals[natural_count].techLevel),
+                             &(naturals[natural_count].warhead),
+                             &(naturals[natural_count].numSubmunitions),
+                             &(naturals[natural_count].submunition),
+                             &(naturals[natural_count].impartVelocity),
+                             &(naturals[natural_count].divergence),
+                             &(naturals[natural_count].spreadVariation),
+                             &(naturals[natural_count].launchSpeed),
+                             &(naturals[natural_count].speedVariation),
+                             &(naturals[natural_count].countdown),
+                             &(naturals[natural_count].countVariation) );
+                    }
+
+                  data_stage++;
+                  if (data_stage > 2)
+                    {
+                      data_stage = 0;
+                      natural_count++;
+                    }
+
+                }       // end of naturals
+
+              // item section
+              else if ( (file_stage == 2) && (item_count < ITEMS) )
+                {
+                  if (data_stage == 0)   // name
+                    strcpy(item[item_count].name, line);
+                  else if (data_stage == 1)
+                    strcpy(item[item_count].description, line);
+                  else if (data_stage == 2)
+                    {
+                      sscanf(line, "%d %d %d %d %d %lf %lf %lf %lf %lf %lf",
+                             &(item[item_count].cost),
+                             &(item[item_count].amt),
+                             &(item[item_count].selectable),
+                             &(item[item_count].techLevel),
+                             &(item[item_count].sound),
+                             &(item[item_count].vals[0]),
+                             &(item[item_count].vals[1]),
+                             &(item[item_count].vals[2]),
+                             &(item[item_count].vals[3]),
+                             &(item[item_count].vals[4]),
+                             &(item[item_count].vals[5]) );
+                    }
+
+                  data_stage++;
+                  if (data_stage > 2)
+                    {
+                      data_stage = 0;
+                      item_count++;
+                    }
+                }         // end of items
+
+            }       // end of reading data from a valid line
+
+        }     // end of valid line
+
+      // read in data
+      status = fgets(line, 512, wfile);
+    }
+
+  // close file
+  fclose(wfile);
+  // go home
+  return TRUE;
+}
+
+
+
+
+/*
+Filter out files that do not have .sav in the name.
+*/
+#ifndef MACOSX
+int Filter_File( const struct dirent *my_file )
+#else
+int Filter_File( struct dirent *my_file )
+#endif
+{
+  if ( strstr(my_file->d_name, ".sav") )
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/*
+This function finds a list of saved games on your profile.
+On error, NULL is returned. If all goes well, a list of file names
+are returned.
+After use, the return value should be freed.
+*/
+#ifndef WIN32
+struct dirent ** Find_Saved_Games(GLOBALDATA *global, int *num_files_found)
+  {
+    struct dirent **my_list;
+    int status;
+
+    status = scandir(global->configDir, &my_list, Filter_File, alphasort);
+    if (status < 0)
+      {
+        printf( (char *)"Error trying to find saved games.\n");
+        return NULL;
+      }
+
+    *num_files_found = status;
+    return my_list;
+  }
+#endif
+
+
+
+/*
+This function hunts for saved games. If games are found, the
+function returns an array of filenames. If an error occures
+or no files are found, NULL is returned.
+*/
+#ifdef WIN32
+struct dirent ** Find_Saved_Games(GLOBALDATA *global, int *num_files_found)
+  {
+    struct dirent **my_list;
+    struct dirent *one_file;
+    int file_count = 0;
+    DIR *game_dir;
+
+    my_list = (struct dirent **) calloc(256, sizeof(struct dirent *));
+    if (! my_list)
+      return NULL;
+
+    game_dir = opendir(global->configDir);
+    if (! game_dir)
+    {
+      free(my_list);
+      return NULL;
+    }
+
+    one_file = readdir(game_dir);
+    while ( (one_file) && (file_count < 256) )
+      {
+        // check to see if this is a save game file
+        if ( strstr( one_file->d_name, ".sav" ) )
+          {
+            my_list[file_count] = (struct dirent *) calloc(1, sizeof(struct dirent) );
+            if ( my_list[file_count] )
+              {
+                memcpy(my_list[file_count], one_file, sizeof(struct dirent) );
+                file_count++;
+              }
+          }
+
+        one_file = readdir(game_dir);
+      }
+
+    closedir(game_dir);
+    *num_files_found = file_count;
+    return my_list;
+  }
+#endif
+
+
+
+
+/*
+ * This function grabs a random quote from the war_quotes.txt file.
+ * This file is held in the data directory (dataDir) and contains
+ * one-line quotes.
+ * The function returns a pointer to the quote on success and a NULL
+ * on failure. The line should be free()ed after use.
+ * -- Jesse
+ *  */
+/*
+char *Get_Random_Quote(GLOBALDATA *global)
+{
+    char *path_to_file = NULL;
+    char *line, *result;
+    FILE *quote_file = NULL;
+    int line_count = 0;
+    int index = 0;
+    int random_number;
+
+    line = (char *) calloc(1024, sizeof(char));
+    if (! line)
+       return NULL;
+    path_to_file = (char *) calloc( strlen(global->dataDir) + 32, sizeof(char) );
+    if (! path_to_file)
+    {
+       free(line);
+       return NULL;
+    }
+
+    if (global->language == LANGUAGE_RUSSIAN)
+       sprintf(path_to_file, "%s/war_quotes_ru.txt", global->dataDir);
+    else
+       sprintf(path_to_file, "%s/war_quotes.txt", global->dataDir);
+    quote_file = fopen(path_to_file, "r");
+    free(path_to_file);
+    if (! quote_file)
+    {
+       free(line);
+       return NULL;
+    }
+
+    // search through file getting the number of lines
+    result = fgets(line, 1024, quote_file);
+    while (result)
+    {
+        line_count++;
+        result = fgets(line, 1024, quote_file);
+    }
+
+    // return to the start of the file
+    rewind(quote_file);
+
+    // generate a random number based on the size of the file
+    random_number = rand() % line_count;
+
+    // search through and find the line we want
+    result = fgets(line, 1024, quote_file);
+    while ( (result) && (index < random_number) )
+    {
+        index++;
+        result = fgets(line, 1024, quote_file);
+    }
+
+    fclose(quote_file);
+    if (! result)
+    {
+       free(line);
+       return NULL;
+    }
+
+    // trim trailing newline character
+    if ( strchr(line, '\n') )
+       strchr(line, '\n')[0] = '\0';
+    return line;
+}
+*/
+
+
+
+
+/*
+ * This function searches for bitmap files (.bmp) in the config folder.
+ * The function returns an array of bitmap file names. If no files
+ * are found, or an error occures, then NULL is returned.
+ * */
+char ** Find_Bitmaps(GLOBALDATA *global, int *bitmaps_found)
+{
+    char **my_list;
+    struct dirent *one_file;
+    int file_count = 0;
+    DIR *game_dir;
+
+    my_list = (char **) calloc(256, sizeof(struct dirent *));
+    if (! my_list)
+      return NULL;
+
+    
+    game_dir = opendir(global->configDir);
+    if (! game_dir)
+    {
+      free(my_list);
+      return NULL;
+    }
+
+    one_file = readdir(game_dir);
+    while ( (one_file) && (file_count < 256) )
+    {
+         // check to see if this is a save game file
+         #ifdef LINUX
+         if ( strcasestr( one_file->d_name, ".bmp" ) )
+         #else
+         if ( (strstr(one_file->d_name, ".bmp")) || (strstr(one_file->d_name, ".BMP") ) )
+         #endif
+         {
+            my_list[file_count] = (char *) calloc( strlen(global->configDir) + strlen(one_file->d_name) + 16, sizeof(char) );
+            if ( my_list[file_count] )
+            {
+               sprintf(my_list[file_count], "%s/%s", global->configDir, one_file->d_name);
+               file_count++;
+            }
+         }
+
+         one_file = readdir(game_dir);
+     }
+        
+     closedir(game_dir);
+     *bitmaps_found = file_count;
+     if (file_count < 1)
+     {
+         free(my_list);
+         my_list = NULL;
+     }
+     return my_list;
+}
+
+
+
+
+
+BITMAP *create_gradient_strip (const gradient *grad, int length)
+{
+  BITMAP *strip;
+  int color;
+  int currLine;
+
+  strip = create_bitmap (1, length);
+  if (! strip)
+     return NULL;
+
+  clear_to_color (strip, BLACK);
+
+  for (currLine = 0;currLine < length; currLine++)
+    {
+      color = gradientColorPoint (grad, length, currLine);
+      putpixel (strip, 0, currLine, color);
+    }
+
+  return (strip);
+}
+
+
+
+
+int gradientColorPoint (const gradient *grad, double length, double line)
+{
+  int pointCount = 0;
+  double point = line / length;
+  int color;
+
+  for (pointCount = 0; (point >= grad[pointCount].point) && (grad[pointCount].point != -1); pointCount++) { }
+  pointCount--;
+
+  if (pointCount == -1)
+    {
+      color = makecol (grad[0].color.r, grad[0].color.g, grad[0].color.b);
+    }
+  else if (grad[pointCount + 1].point == -1)
+    {
+      color = makecol (grad[pointCount].color.r, grad[pointCount].color.g, grad[pointCount].color.b);
+    }
+  else
+    {
+      double i = (point - grad[pointCount].point) / (grad[pointCount + 1].point - grad[pointCount].point);
+      int r = (int)(interpolate (grad[pointCount].color.r, grad[pointCount + 1].color.r, i));
+      int g = (int)(interpolate (grad[pointCount].color.g, grad[pointCount + 1].color.g, i));
+      int b = (int)(interpolate (grad[pointCount].color.b, grad[pointCount + 1].color.b, i));
+
+      color = makecol (r, g, b);
+    }
+
+  return (color);
+}
+
+
+
+
+
+/*****************************************************************************
+ * colorDistance
+ *
+ * Treat two color values as 3D vectors of the form <r,g,b>.
+ * Compute the scalar size of the difference between the two vectors.
+ * *****************************************************************************/
+double colorDistance (int col1, int col2)
+{
+  double distance;
+  int col1r, col1g, col1b;
+  int col2r, col2g, col2b;
+
+  col1r = getr (col1);
+  col1g = getg (col1);
+  col1b = getb (col1);
+  col2r = getr (col2);
+  col2g = getg (col2);
+  col2b = getb (col2);
+
+  // Treat the colour-cube as a space
+  distance = vector_length_f ((float)(col1r - col2r), (float)(col1g - col2g), (float)(col1b - col2b));
+  
+  return (distance);
+}
+
+
+
+
+void Clear_Weapons()
+{
+    memset(weapon, 0, WEAPONS * sizeof(WEAPON));
+    memset(naturals, 0, NATURALS * sizeof(WEAPON));
+    memset(item, 0, ITEMS * sizeof(ITEM));   
+
+}
+
+
+
+int Display_Tank_Bitmap(ENVIRONMENT *env, int xpos, int ypos, void *image_number)
+{
+    double *temp_number = (double *) image_number;
+    int my_number = (int) *temp_number;
+    int use_tank_bitmap, use_turret_bitmap;
+    BITMAP *dest = env->db;
+    GLOBALDATA *global = env->_global;
+
+    switch (my_number)
+    {
+         case CLASSIC_TANK:
+          use_tank_bitmap = 8;
+          use_turret_bitmap = 1;
+          break;
+        case BIGGREY_TANK:
+          use_tank_bitmap = 9;
+          use_turret_bitmap = 2;
+          break;
+        case T34_TANK:
+          use_tank_bitmap = 10;
+          use_turret_bitmap = 3;
+          break;
+        case HEAVY_TANK:
+          use_tank_bitmap = 11;
+          use_turret_bitmap = 4;
+          break;
+        case FUTURE_TANK:
+          use_tank_bitmap = 12;
+          use_turret_bitmap = 5;
+          break;
+        case UFO_TANK:
+          use_tank_bitmap = 13;
+          use_turret_bitmap = 6;
+          break;
+        case SPIDER_TANK:
+          use_tank_bitmap = 14;
+          use_turret_bitmap = 7;
+          break;
+        case BIGFOOT_TANK:
+          use_tank_bitmap = 15;
+          use_turret_bitmap = 8;
+          break;
+        default:
+          use_tank_bitmap = 0;
+          use_turret_bitmap = 0;
+          break;
+
+    }
+
+    draw_sprite(dest, global->tank[use_tank_bitmap], xpos, ypos);
+    draw_sprite(dest, global->tankgun[use_turret_bitmap], xpos, ypos - TANKHEIGHT + 5);
+    
+    return TRUE;
+
+
+}
+
diff --git a/src/files.h b/src/files.h
new file mode 100644
index 0000000..5fbd485
--- /dev/null
+++ b/src/files.h
@@ -0,0 +1,90 @@
+#ifndef FILE_HANDLING_HEADER_
+#define FILE_HANDLING_HEADER_
+
+#define MAX_CONFIG_LINE 128
+#define MAX_INSULT_LINE 256
+
+#define NO_STAGE 0
+#define GLOBAL_STAGE 1
+#define ENVIRONMENT_STAGE 2
+#define PLAYER_STAGE 3
+
+#include <dirent.h>
+#include "globaldata.h"
+#include "environment.h"
+#include "text.h"
+
+
+int Save_Game(GLOBALDATA *global, ENVIRONMENT *env);
+int Load_Game(GLOBALDATA *global, ENVIRONMENT *env); 
+int Check_For_Saved_Game(GLOBALDATA *global);
+/*
+Copy the atanks config file from HOME_DIR to
+HOME_DIR/.atanks
+*/
+int Copy_Config_File(GLOBALDATA *global);
+
+// Make sure there is a music folder in .atanks
+int Create_Music_Folder(GLOBALDATA *global);
+
+
+void renderTextLines (GLOBALDATA *global, ENVIRONMENT *env,
+                      TEXTBLOCK *lines, int scrollOffset,
+                      const FONT* fnt, const int spacing );
+
+void scrollTextList (GLOBALDATA *global, ENVIRONMENT *env,
+                     TEXTBLOCK *lines);
+
+int draw_circlesBG (GLOBALDATA *global, BITMAP *dest, int x, int y, int width, int height, bool image);
+
+void drawMenuBackground (GLOBALDATA *global, ENVIRONMENT *env, int itemType, int tOffset, int numItems);
+
+void flush_inputs();
+
+int Load_Weapons_Text(GLOBALDATA *global);
+
+// char *Get_Random_Quote(GLOBALDATA *global);
+
+#ifdef MACOSX
+int Filter_File( struct dirent *my_file );
+#else
+int Filter_File( const struct dirent *my_file );
+#endif
+
+struct dirent ** Find_Saved_Games(GLOBALDATA *global, int *num_files_found);
+
+
+
+char ** Find_Bitmaps(GLOBALDATA *global, int *bitmaps_found);
+
+BITMAP *create_gradient_strip (const gradient *gradient, int length);
+
+int gradientColorPoint (const gradient *grad, double length, double line);
+
+double colorDistance(int col1, int col2);
+
+
+// This function removes all weapon, natural and item data.
+// Should be called before re-loading weapon file.
+void Clear_Weapons();
+
+
+// Draw a tank bitmap on the screen at the given location'
+int Display_Tank_Bitmap(ENVIRONMENT *env, int xpos, int ypos, void *image_number);
+
+// cause natural events to happen
+void doNaturals(GLOBALDATA *global, ENVIRONMENT *env);
+
+// give people the chance to buy items
+bool buystuff (GLOBALDATA *global, ENVIRONMENT *env);
+
+// display the bar at the top of the game screen
+void drawTopBar(GLOBALDATA *global, ENVIRONMENT *env, BITMAP *dest);
+
+int slideLand(GLOBALDATA *global, ENVIRONMENT *env);
+
+void set_level_settings(GLOBALDATA *global, ENVIRONMENT *env);
+
+void showRoundEndScoresAt (GLOBALDATA *global, ENVIRONMENT *env, BITMAP *bitmap, int x, int y, int winner);
+
+#endif
diff --git a/src/floattext.cpp b/src/floattext.cpp
new file mode 100644
index 0000000..94ad909
--- /dev/null
+++ b/src/floattext.cpp
@@ -0,0 +1,273 @@
+#include "floattext.h"
+
+FLOATTEXT::FLOATTEXT (GLOBALDATA *global, ENVIRONMENT *env, char *text, int xpos, int ypos, int color, alignType alignment)
+{
+      initialise ();
+      setEnvironment (env);
+      _text = NULL;
+      x = (double)xpos;
+      y = (double)ypos;
+      _current.x = (int)x;
+      _current.y = (int)y;
+      _current.w = 0;
+      _current.h = 0;
+      set_pos (xpos, ypos);
+      if (text)
+        set_text (text);
+      else
+        set_text( "");
+      set_color (color);
+      _align = alignment;
+      _global = global;
+      _halfColor = color;
+      sway = NO_SWAY;
+      original_x = xpos;
+      delta_x = 0;
+}
+
+
+FLOATTEXT::~FLOATTEXT()
+{
+      if (_env)
+        {
+          /* To be sure to really remove the full text (might fail due to font differences),
+             we "enlarge" the text by 25%: */
+          if (_current.w)
+            {
+              _current.x -= (int)((double)_current.w * 1.125);
+              _current.w  = (int)((double)_current.w * 1.250);
+            }
+          if (_current.h)
+            {
+              _current.y -= (int)((double)_current.h * 1.125);
+              _current.h  = (int)((double)_current.h * 1.250);
+            }
+
+          switch (_align)
+            {
+            case LEFT:
+              _env->make_bgupdate (_current.x, _current.y, _current.w, _current.h);
+              _env->make_bgupdate (_old.x, _old.y, _old.w, _old.h);
+              break;
+            case RIGHT:
+              _env->make_bgupdate (_current.x - _current.w, _current.y - _current.h, _current.w, _current.h);
+              _env->make_bgupdate (_old.x - _old.w, _old.y - _old.h, _old.w, _old.h);
+              break;
+            case CENTRE:
+              _env->make_bgupdate (_current.x - (_current.w / 2), _current.y - (_current.h / 2), _current.w + 2, _current.h + 2);
+              _env->make_bgupdate (_old.x - (_old.w / 2), _old.y - (_old.h / 2), _old.w + 2, _old.h + 2);
+              break;
+            default:
+              _env->make_bgupdate (_current.x - _current.w, _current.y - _current.h, 2 * _current.w, 2 * _current.h);
+              _env->make_bgupdate (_old.x - _old.w, _old.y - _old.h, 2 * _old.w, 2 * _old.h);
+            }
+          _env->removeObject (this);
+        }
+      _global = NULL;
+      _env    = NULL;
+      if (_text)
+      {
+         free(_text);
+         _text = NULL;
+      }
+}
+
+
+int FLOATTEXT::applyPhysics()
+{
+      VIRTUAL_OBJECT::applyPhysics ();
+
+      if ( (!delta_x) && (sway) )
+         delta_x = -1;
+
+      x += delta_x;
+      if (x < original_x - sway)
+         delta_x = -delta_x;
+      else if (x > original_x + sway)
+         delta_x = -delta_x;
+
+      set_pos ((int)x, (int)y);
+
+      age++;
+      if ( (maxAge != -1) && (age > maxAge) )
+        destroy = TRUE;
+
+      return (0);
+}
+
+
+void FLOATTEXT::setEnvironment(ENVIRONMENT *env)
+{
+      if (!_env || (_env != env))
+        {
+          _env = env;
+          _index = _env->addObject (this);
+        }
+}     
+
+
+
+void FLOATTEXT::draw(BITMAP *dest)
+  {
+      if (_current.w)
+        {
+          double dFrontFade		=	1.0;
+          double dShadFade		= 0.75;
+          int iFrontCol				=	_color;
+          int iShadCol				=	_halfColor;
+          int iBackCol				=	_color;
+
+          // get Background color:
+          if (  (_env->dShadowedText > 0.0) || (_env->dFadingText > 0.0)  )
+          {
+            switch (_align)
+              {
+              case LEFT:
+                iBackCol = _env->getAvgBgColor(	_current.x,								_current.y,
+                                                _current.x + _current.w,	_current.y + _current.h,
+                                                xv,												yv);
+                break;
+              case RIGHT:
+                iBackCol = _env->getAvgBgColor(	_current.x - _current.w,	_current.y - _current.h,
+                                                _current.x,								_current.y,
+                                                xv,												yv);
+                break;
+              case CENTRE:
+                iBackCol = _env->getAvgBgColor(	_current.x - (_current.w / 2),		_current.y - (_current.h / 2),
+                                                _current.x + (_current.w / 2) + 2,_current.y + (_current.h / 2) + 2,
+                                                xv,																yv);
+                break;
+              }
+          }
+          if ((maxAge > 0) && (age >= (maxAge / 2)) && (_env->dFadingText > 0.0))
+            {
+              double dCalcAge = (double)age - (double)(maxAge / 2);
+              double dCalcMax = (double)(maxAge / 2);
+              dFrontFade	= 1.0 - (dCalcAge / dCalcMax);
+              dShadFade		=	0.75 - (0.75 * (dCalcAge / dCalcMax));
+              if (dFrontFade	< 0.0) dFrontFade		= 0.0;
+              if (dFrontFade	> 1.0) dFrontFade		= 1.0;
+              if (dShadFade < 0.0) dShadFade	= 0.0;
+              if (dShadFade >	1.0) dShadFade	= 1.0;
+              iFrontCol = newmakecol((getr(iFrontCol) * dFrontFade) + (getr(iBackCol) * (1.0 - dFrontFade)),
+                                  (getg(iFrontCol) * dFrontFade) + (getg(iBackCol) * (1.0 - dFrontFade)),
+                                  (getb(iFrontCol) * dFrontFade) + (getb(iBackCol) * (1.0 - dFrontFade)));
+            }
+          if (_env->dShadowedText > 0.0)
+            iShadCol = newmakecol(	(getr(iShadCol) * dShadFade) + (getr(iBackCol) * (1.0 - dShadFade)),
+                                (getg(iShadCol) * dShadFade) + (getg(iBackCol) * (1.0 - dShadFade)),
+                                (getb(iShadCol) * dShadFade) + (getb(iBackCol) * (1.0 - dShadFade)));
+          if (_align == LEFT)
+            {
+              if (_env->dShadowedText > 0.0)
+                textout_ex (dest, font, _text,
+                            _current.x + 1, _current.y + 1, iShadCol, -1);
+              textout_ex (dest, font, _text,
+                          _current.x, _current.y, iFrontCol, -1);
+            }
+          else if (_align == RIGHT)
+            {
+              if (_env->dShadowedText > 0.0)
+                textout_ex (dest, font, _text,
+                            _current.x - _current.w + 1,
+                            _current.y - _current.h + 1, iShadCol, -1);
+              textout_ex (dest, font, _text,
+                          _current.x - _current.w,
+                          _current.y - _current.h, iFrontCol, -1);
+            }
+          else
+            {
+              if (_env->dShadowedText > 0.0)
+                textout_centre_ex (dest, font, _text,
+                                   _current.x + 1, _current.y + 1, iShadCol, -1);
+              textout_centre_ex (dest, font, _text,
+                                 _current.x, _current.y, iFrontCol, -1);
+            }
+        }
+}
+
+
+/*
+This is too limiting, creating a more flexible text setting function below.
+-- Jesse
+void FLOATTEXT::set_text(char *text)
+ {
+      strncpy (_text, text, 80);
+      if (strlen (text) > 0)
+        {
+          _current.w = text_length (font, _text) + 3;
+          _text[79] = '\0';
+        }
+      else
+        _current.w = 0;
+      _current.h = text_height (font) + 15;
+}
+*/
+
+// Returns TRUE on success or FALSE on failure.
+int FLOATTEXT::set_text(char *text)
+{
+   int my_length = strlen(text);
+
+   // clean up old text
+   if (_text)
+      free(_text);
+    
+   _text = (char *) calloc( my_length + 1, sizeof(char));
+   if (! _text)
+      return FALSE;
+
+   strcpy(_text, text);
+   if (my_length)
+        _current.w = text_length(font, _text) + 3;
+   else
+       _current.w = 0;
+   _current.h = text_height(font) + 15;
+   return TRUE;
+}
+
+
+void FLOATTEXT::set_color(int color)
+{
+      int red		=	getr(color);
+      int green	=	getg(color);
+      int blue	=	getb(color);
+      int iAverage = (red + green + blue) / 3;
+
+      _color = color;
+
+      if (!(red & 0xc0) && !(green & 0xc0) && !(blue & 0xc0))
+        _halfColor = makecol(red | 0x80, green | 0x80, blue | 0x80); // Color is too dark, shadow should be bright
+      else
+        _halfColor = makecol(	red		> iAverage?(red		/ 4):(red		/ 6),
+                              green	> iAverage?(green	/ 4):(green	/ 6),
+                              blue	> iAverage?(blue	/ 4):(blue	/ 6));
+}
+
+
+void FLOATTEXT::newRound()
+{
+   age = maxAge + 1;
+}
+
+void FLOATTEXT::set_pos(int x, int y)
+{
+   _current.x = x;
+   _current.y = y;
+}
+
+
+
+void FLOATTEXT::set_speed(double x_speed, double y_speed)
+{
+     double mix_it_up;       // avoid over-lapping text
+
+     mix_it_up = rand() % SPEED_RANGE;      // (0-5)
+     mix_it_up -= 3.0;                      // -3 to +2
+     mix_it_up /= 10.0;                     // -0.3 to + 0.2
+     xv = x_speed;
+     yv = y_speed + mix_it_up;
+     if ( (yv == 0.0) && (y_speed < 0.0) )
+        yv = -0.1;       // avoid text that does not move
+}
+
diff --git a/src/floattext.h b/src/floattext.h
new file mode 100644
index 0000000..027dbe6
--- /dev/null
+++ b/src/floattext.h
@@ -0,0 +1,95 @@
+#ifndef	FLOATTEXT_DEFINE
+#define	FLOATTEXT_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "virtobj.h"
+#include "main.h"
+#include "environment.h"
+
+#define newmakecol(r,g,b) makecol((int)(r),(int)(g),(int)(b))
+
+#define NO_SWAY 0
+#define NORMAL_SWAY 42
+
+#define SPEED_RANGE 6
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+class FLOATTEXT: public VIRTUAL_OBJECT
+  {
+  private:
+    // empty ctor, copy-ctor and assign operator are private, so the compiler won't create implicit ones!
+    // inline const FLOATTEXT& operator= (const FLOATTEXT &sourceText) { return(sourceText); }
+
+    char *_text;
+    int	_color;
+    int _halfColor; // for shadowd text!
+    int original_x;
+    int delta_x;
+
+  public:
+    int sway;
+
+    /* --- constructor --- */
+    FLOATTEXT (GLOBALDATA *global, ENVIRONMENT *env, char *text, int xpos, int ypos, int color, alignType alignment);
+   
+    /* --- destructor --- */
+    ~FLOATTEXT ();
+    void setEnvironment(ENVIRONMENT *env);
+   
+    inline virtual void		initialise ()
+    {
+      VIRTUAL_OBJECT::initialise ();
+    }
+
+    int	applyPhysics ();
+    void draw (BITMAP *dest);
+    int set_text (char * text);
+    void set_pos (int x, int y);
+    void set_color (int color);
+    void set_speed(double x_speed, double y_speed);
+    
+
+    inline virtual int		isSubClass (int classNum)
+    {
+      if (classNum != FLOATTEXT_CLASS)
+        return (FALSE);
+      //return (VIRTUAL_OBJECT::isSubClass (classNum));
+      else
+        return (TRUE);
+    }
+
+    inline virtual int		getClass ()
+    {
+      return (FLOATTEXT_CLASS);
+    }
+
+    void newRound();
+
+  };
+
+#endif
diff --git a/src/gameloop.cpp b/src/gameloop.cpp
new file mode 100644
index 0000000..3b0ec55
--- /dev/null
+++ b/src/gameloop.cpp
@@ -0,0 +1,590 @@
+#include <stdio.h>
+#include "main.h"
+#include "team.h"
+#include "files.h"
+#include "satellite.h"
+#include "update.h"
+#include "network.h"
+#include "land.h"
+
+#include "floattext.h"
+#include "explosion.h"
+#include "beam.h"
+#include "missile.h"
+#include "decor.h"
+#include "teleport.h"
+#include "sky.h"
+
+#include "gameloop.h"
+
+#ifdef NEW_GAMELOOP
+
+int game (GLOBALDATA *global, ENVIRONMENT *env)
+{
+    int humanPlayers = 0;
+    int skippingComputerPlay = FALSE;
+    int team_won = NO_WIN;
+    int my_class;
+    int screen_update = TRUE;
+    int text_bounce = 0, text_delta = 1;
+    VIRTUAL_OBJECT *my_object;
+    TANK *my_tank, *a_tank;
+    MISSILE *missile;
+    TELEPORT *teleport;
+    DECOR *decor;
+    BEAM *beam;
+    EXPLOSION *explosion;
+    FLOATTEXT *floattext;
+    SATELLITE *satellite = NULL;
+    int count;
+    int winner = -1, done = FALSE;
+    int stuff_happening = FALSE;
+    int AI_clock;
+    int fire = FALSE;
+    int roundEndCount = 0;
+    int game_speed = (int) global->frames_per_second * GAME_SPEED / 60;
+    int explosion_in_progress = FALSE;
+    
+    // adjust for Windows
+    #ifdef WIN32
+    game_speed /= 1000;
+    #endif
+
+    global->computerPlayersOnly = FALSE;
+    // clear surface
+    for (count = 0; count < global->screenWidth; count++)
+       env->done[count] = 0;
+
+    env->newRound();
+    env->Set_Wall_Colour();
+    global->bIsBoxed = env->Get_Boxed_Mode(global);
+    global->dMaxVelocity = global->Calc_Max_Velocity();
+   
+    for (count = 0; count <global->numPlayers; count++)
+        global->players[count]->newRound();
+
+    // clear floating text
+    for (count = 0; count < MAX_OBJECTS; count++)
+    {
+         if (env->objects[count] && (env->objects[count]->isSubClass(FLOATTEXT_CLASS)))
+        ((FLOATTEXT *)env->objects[count])->newRound();
+    }
+
+    // everyone gets to buy stuff
+    buystuff(global, env);
+    set_level_settings(global, env);
+
+    for (count = 0; count < global->numPlayers; count++)
+    {
+        global->players[count]->exitShop();
+        if ( (global->players[count]->type == HUMAN_PLAYER) ||
+             (global->players[count]->type == NETWORK_CLIENT) )
+           humanPlayers++;
+        if (global->players[count]->tank)
+        {
+              // global->players[count]->tank->newRound();
+              global->players[count]->tank->flashdamage = 0;
+              global->players[count]->tank->boost_up_shield();
+         }
+        
+    }
+
+    // set_level_settings(global, env);
+    env->stage = STAGE_AIM;
+    fi = global->updateMenu = TRUE;
+    global->window.x = 0;
+    global->window.y = 0;
+    global->window.w = global->screenWidth - 1;
+    global->window.h = global->screenHeight - 1;
+
+    // set wind
+    if ( (int) env->windstrength != 0)
+       env->wind = (float) (rand() % (int)env->windstrength) - (env->windstrength / 2);
+    else
+       env->wind = 0;
+    env->lastwind = env->wind;
+
+    // create satellite
+    if (env->satellite)
+        satellite = new SATELLITE(global, env);
+    if (satellite)
+       satellite->Init();
+
+    // get some mood music
+    global->background_music = global->Load_Background_Music();
+    if (global->background_music)
+       play_sample( (SAMPLE *) global->background_music, 255, 128, 1000, TRUE);
+
+    my_tank = env->order[0];
+    // init stuff complete. Get down to playing
+    while ( (! done) && (global->get_command() != GLOBAL_COMMAND_QUIT) )
+    {
+        // see how long we have been skipping
+        if (skippingComputerPlay)
+        {
+            // advance clock
+            if (global->Check_Time_Changed() )
+                AI_clock++;
+            if ( (AI_clock > MAX_AI_TIME) && (winner == -1) )
+            {
+                // in over-time, kill all tanks
+                count = 0;
+                while (count < global->numPlayers)
+                {
+                    if ( (global->players[count]) &&
+                         (global->players[count]->tank) )
+                       global->players[count]->tank->l = 0;
+                    count++;
+                }
+            }
+        }
+
+
+        global->currTank = my_tank;
+        // move through all objects, updating them
+        explosion_in_progress = FALSE;
+        count = 0;
+        while (count < MAX_OBJECTS)
+        {
+            my_object = env->objects[count];
+            if (my_object)
+            {
+            my_class = my_object->getClass();
+            if (my_class == DECOR_CLASS)
+            {
+              decor = (DECOR *) my_object;
+              decor->applyPhysics ();
+              if (decor->destroy)
+                {
+                  decor->requireUpdate ();
+                  decor->update ();
+                  delete decor;
+                }
+            }
+            else if (my_class == EXPLOSION_CLASS)
+            {
+              explosion = (EXPLOSION *) my_object;
+              if (explosion->bIsWeaponExplosion)
+                 stuff_happening = TRUE;
+              explosion->explode ();
+              explosion_in_progress = TRUE;
+              explosion->applyPhysics ();
+              if (explosion->destroy)
+                {
+                  explosion->requireUpdate ();
+                  explosion->update ();
+                  delete explosion;
+                }
+            }
+
+            else if (my_class == TELEPORT_CLASS)
+            {
+              teleport = (TELEPORT *) my_object;
+              stuff_happening = TRUE;
+              teleport->applyPhysics ();
+              if (teleport->destroy)
+                {
+                  teleport->requireUpdate ();
+                  teleport->update ();
+                  delete teleport;
+                }
+            }
+            else if (my_class == MISSILE_CLASS)
+            {
+              TANK *shooting_tank = NULL;
+              BEAM *defense_beam;
+              int angle_to_fire;
+
+              missile = (MISSILE *) my_object;
+              stuff_happening = TRUE;
+              env->am++;
+              missile->hitSomething = 0;
+              missile->applyPhysics ();
+              missile->triggerTest ();
+              shooting_tank = missile->Check_SDI(global);
+              if (shooting_tank)
+              {
+                  // (shooting_tank->x < missile->x) ? angle_to_fire = 135 : angle_to_fire = 225;
+                  angle_to_fire = atan2(labs(shooting_tank->y - 10 - missile->y), (missile->x - shooting_tank->x)) * 180 / 3.14159265 + 90;
+                  defense_beam = new BEAM(global, env, shooting_tank->x, shooting_tank->y - 10, angle_to_fire, SML_LAZER);
+                  missile->trigger();
+              }
+              if (missile->destroy)
+              {
+                  missile->requireUpdate ();
+                  missile->update ();
+                  delete missile;
+              }
+            }
+            else if (my_class == BEAM_CLASS)
+            {
+              beam = (BEAM *) my_object;
+              // As bots should not target while a laser is shot:
+              stuff_happening = TRUE;
+              beam->applyPhysics ();
+              if (beam->destroy)
+                {
+                  beam->requireUpdate ();
+                  beam->update ();
+                  delete beam;
+                }
+            }
+            else if (my_class == FLOATTEXT_CLASS)
+            {
+              floattext = (FLOATTEXT *) my_object;
+              floattext->applyPhysics ();
+              if (floattext->destroy)
+                {
+                  floattext->requireUpdate();
+                  floattext->update();
+                  delete floattext;
+                  env->make_fullUpdate(); // ...kill remaining texts!
+                }
+            }
+            }        // end of if we have an object
+
+            count++;
+        }       // end of updating envirnoment objects
+
+    if (satellite)
+       satellite->Move();
+
+    // move land
+    slideLand(global, env);
+
+    // seems like a good place to update tanks
+    for (count = 0; count < global->numPlayers; count++)
+    {
+        a_tank = global->players[count]->tank;
+        if (a_tank)
+        {
+           // see if we are doing a volly
+           if (a_tank->fire_another_shot)
+           {
+              if (! (a_tank->fire_another_shot % VOLLY_DELAY) )
+                 a_tank->activateCurrentSelection();
+              a_tank->fire_another_shot--;
+           }
+
+           if (a_tank->flashdamage)
+           {
+              if (a_tank->flashdamage > 25 || a_tank->l < 1)
+              {
+                 a_tank->damage = 0;
+                 a_tank->flashdamage = 0;
+                 a_tank->requireUpdate();
+              }
+           }
+
+           // update position
+           a_tank->pen = 0;
+           a_tank->applyPhysics(global);
+
+           if ( (a_tank->l <= 0) && (! explosion_in_progress) )    // dead tank
+           {
+               a_tank->explode();
+               a_tank->Give_Credit(global);
+               if (a_tank->destroy)
+               {
+                   if ( (a_tank->player) && 
+                        ( (a_tank->player->type == HUMAN_PLAYER) ||
+                          (a_tank->player->type == NETWORK_CLIENT) ) )
+                   {
+                       humanPlayers--;
+                       if ( (! humanPlayers) && (global->skipComputerPlay) )
+                           skippingComputerPlay = TRUE;
+                   }
+
+                   a_tank->Destroy();
+                   if (my_tank == a_tank)
+                     my_tank = NULL;
+                   delete a_tank;
+                   a_tank = NULL;
+               }
+           }
+          
+           // if the tank is still alive, adjust its chess-style clock
+           if ( (global->max_fire_time > 0.0) &&
+                (a_tank == my_tank) &&
+                (a_tank) && (a_tank->player->type == HUMAN_PLAYER) &&
+                (! env->stage) )
+           {
+               if (global->Check_Time_Changed() )
+               {
+                    int ran_out_of_time;
+                    ran_out_of_time = a_tank->player->Reduce_Time_Clock();
+                    if (ran_out_of_time)
+                    {
+                        a_tank->player->skip_me = true;
+                        a_tank = NULL;
+                        fire = FALSE;
+                        my_tank = env->Get_Next_Tank(&fire);
+                    }
+                    global->updateMenu = TRUE;
+               }
+           }
+                
+        }
+    }
+    
+    #ifdef NETWORK
+    // check for input from network
+    for (count = 0; count < global->numPlayers; count++)
+    {
+         if (global->players[count]->type == NETWORK_CLIENT)
+         {
+             global->players[count]->Get_Network_Command();
+             global->players[count]->Execute_Network_Command(FALSE);
+         }
+    }   
+    #endif
+ 
+    // drop some naturals
+    if (! stuff_happening)
+    {
+        env->stage = STAGE_AIM;
+        doNaturals(global, env);
+        if (satellite)
+            satellite->Shoot();
+    }
+
+    // draw top bar
+    if (global->updateMenu)
+    {
+         set_clip_rect(env->db, 0, 0, global->screenWidth - 1,
+                       MENUHEIGHT - 1);
+         drawTopBar(global, env, env->db);
+         global->updateMenu = FALSE;
+    }
+
+
+        set_clip_rect (env->db, 0, MENUHEIGHT, 
+                       (global->screenWidth-1), (global->screenHeight-1));
+        if (screen_update)
+        {
+          blit (env->sky, env->db, global->window.x, global->window.y - MENUHEIGHT, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 1);
+          masked_blit (env->terrain, env->db, global->window.x, global->window.y, global->window.x, global->window.y, (global->window.w - global->window.x) + 1, (global->window.h - global->window.y) + 2);
+          // drawTopBar(global, env, env->db);
+          int iLeft = 0;
+          int iRight = global->screenWidth - 1;
+          int iTop = MENUHEIGHT;
+          int iBottom = global->screenHeight - 1;
+          set_clip_rect (env->db, 0, 0, iRight, iBottom);
+          vline(env->db, iLeft, iTop, iBottom, env->wallColour);    // Left edge
+          vline(env->db, iLeft + 1, iTop, iBottom, env->wallColour);    // Left edge
+          vline(env->db, iRight, iTop, iBottom, env->wallColour);   // right edge
+          vline(env->db, iRight - 1, iTop, iBottom, env->wallColour);   // right edge
+          hline(env->db, iLeft, iBottom, iRight, env->wallColour);// bottom edge
+          if (global->bIsBoxed)
+              hline(env->db, iLeft, iTop, iRight, env->wallColour);// top edge
+
+          env->make_update(0, 0, global->screenWidth, global->screenHeight);
+        }
+        else
+        {
+          env->replaceCanvas ();
+          screen_update = TRUE;
+        }
+        for (count = 0; count < global->numPlayers; count++)
+        {
+           if ( (global->players[count]) && (global->players[count]->tank) )
+           {
+              global->players[count]->tank->framelyAccounting();
+              if ( my_tank == global->players[count]->tank )
+              {
+                 text_bounce += text_delta;
+                 global->players[count]->tank->draw(env->db, text_bounce / 4);
+                 if ( (text_bounce > MAX_TEXT_BOUNCE) ||
+                      (text_bounce < 1) )
+                    text_delta = -text_delta;
+              }
+                 
+              else
+                 global->players[count]->tank->draw(env->db, 0);
+              global->players[count]->tank->update();
+           }
+        }
+
+
+    // draw all this cool stuff
+    count = 0;
+    while (count < MAX_OBJECTS)
+    {
+       my_object = env->objects[count];
+       if (my_object)
+       {
+         my_class = my_object->getClass();
+         if (my_class == MISSILE_CLASS)
+         {
+           missile = (MISSILE *) my_object;
+           missile->draw (env->db);
+           missile->update ();
+         }
+        else if (my_class == BEAM_CLASS)
+        {
+          beam = (BEAM *) my_object;
+          beam->draw (env->db);
+          beam->update ();
+        }
+        else if (my_class == EXPLOSION_CLASS)
+        {
+          explosion = (EXPLOSION *) my_object;
+          explosion->draw (env->db);
+          explosion->update ();
+        }
+        else if (my_class == TELEPORT_CLASS)
+        {
+           teleport = (TELEPORT *) my_object;
+           if (teleport->object)
+             teleport->draw (env->db);
+           teleport->update ();
+        }
+        else if (my_class == DECOR_CLASS)
+         {
+           decor = (DECOR *) my_object;
+           decor->draw (env->db);
+           decor->update ();
+         }
+         else if (my_class == FLOATTEXT_CLASS)
+         {
+           floattext = (FLOATTEXT *) my_object;
+           floattext->draw (env->db);
+           floattext->requireUpdate ();
+           floattext->update ();
+         }
+        }        // end of if we have an object
+        count++;
+    }       // end of while drawing objects
+    if (satellite)
+       satellite->Draw(env->db);
+    env->do_updates();
+
+     // it is possible our tank is dead, make sure we have one
+     if (! my_tank)
+     {
+        my_tank = env->Get_Next_Tank(&fire);
+        fire = FALSE;
+     }
+
+     // get user input
+     if ( (my_tank) && (env->stage < STAGE_ENDGAME) )
+     {
+        PLAYER *my_player;
+        int control_result;
+
+        global->updateMenu = FALSE;
+        my_player = my_tank->player;
+        // my_tank->reactivate_shield();
+        control_result = my_player->controlTank();
+        if (control_result == CONTROL_QUIT)
+           done = TRUE;
+        else if (control_result == CONTROL_FIRE)
+        {
+           my_tank = env->Get_Next_Tank(&fire);
+           if (global->turntype != TURN_SIMUL)
+              fire = TRUE;
+        }
+        else if ( (control_result == CONTROL_SKIP) && (! humanPlayers) )
+            skippingComputerPlay = TRUE;
+
+        // if ( (fire) && (env->stage == STAGE_AIM) )
+        if (fire)
+        {
+           env->stage = STAGE_FIRE;
+           if (my_tank)
+                my_tank->reactivate_shield();
+           doLaunch(global, env);
+           fire = FALSE;
+           // screen_update = TRUE;
+        }
+        // else
+           // screen_update = FALSE;
+
+        screen_update = FALSE;
+        if (control_result)
+           global->updateMenu = TRUE;
+     }     // end of controling my tank
+
+     if ( (! skippingComputerPlay) && (env->stage != STAGE_ENDGAME) )
+     {
+         #ifdef LINUX
+         usleep(game_speed);
+         #endif
+         #ifdef MACOSX
+         usleep(game_speed);
+         #endif
+         #ifdef WIN32
+         Sleep(game_speed);
+         #endif
+     }
+         stuff_happening = FALSE;
+         // check for winner
+         if (env->stage < STAGE_ENDGAME)
+         {
+            team_won = Team_Won(global);
+            if (team_won == NO_WIN)
+               winner = global->Check_For_Winner();
+
+            if ( (winner >= 0) || (winner == -2) || (team_won != NO_WIN) )
+               env->stage = STAGE_ENDGAME;
+         }
+
+         if (env->stage == STAGE_ENDGAME)
+         {
+             roundEndCount++;
+             if (roundEndCount >= WAIT_AT_END_OF_ROUND)
+                done = TRUE;
+             screen_update = FALSE;
+         }
+         if (global->close_button_pressed)
+             done = TRUE;
+    }    // end of game loop
+
+    // credit winners
+    if (team_won != NO_WIN)
+       winner = team_won;
+    global->Credit_Winners(winner);
+
+    // display winning results
+    while ( keypressed() )
+         readkey();     // clear the buffer
+
+    // check to see if we have a winner or we just bailed out early
+    if ( (winner != -1) && (! global->demo_mode) && 
+         (! global->close_button_pressed) )
+    {
+          showRoundEndScoresAt(global, env, env->db, global->screenWidth / 2,
+                               global->screenHeight / 2, winner);
+          env->do_updates();
+
+          while ( (! keypressed() ) && (! global->demo_mode) )
+              LINUX_SLEEP;
+          readkey();
+    }
+    // else
+    // {
+        global->window.x = global->window.y = 0;
+        global->window.w = global->screenWidth - 1;
+        global->window.h = global->screenHeight - 1;
+        set_clip_rect(env->db, 0, 0, global->window.w, global->window.h);
+    // }
+
+    // clean up
+    if (satellite)
+       delete satellite;
+
+    // remove existing tanks etc
+    for (count = 0; count < global->numPlayers; count++)
+    {
+       if (global->players[count]->tank)
+       {
+          global->players[count]->Reclaim_Shield();
+          delete global->players[count]->tank;
+       }
+    }
+
+    return done;
+}
+
+#endif
+
diff --git a/src/gameloop.h b/src/gameloop.h
new file mode 100644
index 0000000..934f118
--- /dev/null
+++ b/src/gameloop.h
@@ -0,0 +1,16 @@
+#ifndef GAMELOOP_HEADER_FILE__
+#define GAMELOOP_HEADER_FILE__
+
+#include "globaldata.h"
+#include "environment.h"
+
+#define MAX_TEXT_BOUNCE 40
+
+// The massive game loop, re-wrrite here for
+// all sorts of reasons.
+#ifdef NEW_GAMELOOP
+int game(GLOBALDATA *global, ENVIRONMENT *env);
+#endif
+
+#endif
+
diff --git a/src/globaldata.cpp b/src/globaldata.cpp
new file mode 100644
index 0000000..9014a03
--- /dev/null
+++ b/src/globaldata.cpp
@@ -0,0 +1,1389 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+#include <time.h>
+#include "player.h"
+#include "globaldata.h"
+#include "files.h"
+#include "network.h"
+#include "team.h"
+
+GLOBALDATA::GLOBALDATA ():dataDir(NULL),configDir(NULL),updates(NULL),lastUpdates(NULL),allPlayers(NULL),
+    players(NULL),currTank(NULL),saved_game_list(NULL)
+{
+  init_curland_lock();
+
+  command_lock = (pthread_rwlock_t*) malloc(sizeof(pthread_rwlock_t));
+  if (command_lock == NULL)
+  {
+    printf("%s:%i: Could not allocate memory for command_lock.\n", __FILE__, __LINE__);
+  }
+  int result = pthread_rwlock_init(command_lock, NULL);
+  switch (result)
+  {
+    case 0:
+       //Successfully initialized
+       break;
+    case EAGAIN:
+       //resource lack
+       printf("%s:%i: Not enough resources to initialize read-write lock.\n", __FILE__, __LINE__);
+       break;
+    case ENOMEM:
+       //out of memory
+       printf("%s:%i: Not enough memory to initialize read-write lock.\n", __FILE__, __LINE__);
+       break;
+    case EPERM:
+       //not authorized
+       printf("%s:%i: Not authorized.\n", __FILE__, __LINE__);
+       break;
+    default:
+       //If the switch ever gets to here, something very wrong happened and pthread_rwlock_init returned
+       //a random value
+       printf("%s:%i: Unknown error code (%i) returned by pthread_rwlock_init.\n", __FILE__, __LINE__, result);
+       break;
+  }
+  tank_status = (char *)calloc(128, sizeof(char));
+  if (!tank_status)
+    {
+      perror ( "globaldata.cpp: Failed allocating memory for tank_status in GLOBALDATA::GLOBALDATA");
+      // exit (1);
+    }
+
+  initialise ();
+  language = LANGUAGE_ENGLISH;
+  sound = 1.0;
+  name_above_tank = TRUE;
+  colourDepth = 0;
+  client_player = NULL;
+  screenWidth = DEFAULT_SCREEN_WIDTH;
+  screenHeight = DEFAULT_SCREEN_HEIGHT;
+  width_override = height_override = 0;
+  temp_screenWidth = screenWidth;
+  temp_screenHeight = screenHeight;
+  halfWidth = screenWidth / 2;
+  halfHeight = screenHeight / 2;
+  menuBeginY = (screenHeight - 400) / 2;
+  if (menuBeginY < 0) menuBeginY = 0;
+  menuEndY = screenHeight - menuBeginY;
+  frames_per_second = FRAMES_PER_SECOND;
+  numPermanentPlayers = 10;
+  violent_death = FALSE;
+/*
+#ifndef DOS
+  cacheCirclesBG = 1;
+#endif
+
+#ifdef DOS
+  cacheCirclesBG = 0;
+#endif
+*/
+  ditherGradients = 1;
+  detailedLandscape = 0;
+  detailedSky = 0;
+  colour_theme = COLOUR_THEME_CRISPY;
+  startmoney = 15000;
+  turntype = TURN_RANDOM;
+  skipComputerPlay = SKIP_HUMANS_DEAD;
+  // dataDir = DATA_DIR;
+  Find_Data_Dir();
+  os_mouse = 1.0;
+  full_screen = FULL_SCREEN_FALSE;
+  interest = 1.25;
+  scoreHitUnit = 75;
+  scoreSelfHit = 0;
+  scoreUnitDestroyBonus = 5000;
+  scoreUnitSelfDestroy = 0;
+  scoreRoundWinBonus = 10000;
+  sellpercent = 0.80;
+  game_name[0] = '\0';
+  load_game = 0.0;
+  campaign_mode = 0.0;
+  saved_game_index = 0;
+  saved_game_list = NULL;
+  max_fire_time = 0.0;
+  close_button_pressed = false;
+  divide_money = 0.0;
+  sound_driver = SOUND_AUTODETECT;
+  update_string = NULL;
+  check_for_updates = 1.0;
+  demo_mode = false;
+  env = NULL;
+  war_quotes = instructions = ingame = NULL;
+  gloat = revenge = retaliation = kamikaze = suicide = NULL;
+  client_message= NULL;
+
+  updates = new BOX[MAXUPDATES];
+  if (!updates)
+    {
+      perror ( "globaldata.cc: Failed allocating memory for updates in GLOBALDATA::GLOBALDATA");
+      // exit (1);
+    }
+  lastUpdates = new BOX[MAXUPDATES];
+  if (!lastUpdates)
+    {
+      perror ( "globaldata.cc: Failed allocating memory for lastUpdates in GLOBALDATA::GLOBALDATA");
+      // exit (1);
+    }
+  updateCount = 0;
+  lastUpdatesCount = 0;
+
+  // players = new PLAYER*[MAXPLAYERS];
+  players = (PLAYER **) calloc( MAXPLAYERS, sizeof(PLAYER *) );
+  if (!players)
+    {
+      perror ( "globaldata.cc: Failed allocating memory for players in GLOBALDATA::GLOBALDATA");
+      // exit (1);
+    }
+  numPlayers = 0;
+  rounds = 5;
+
+  if (allPlayers) free(allPlayers);   // avoid potential leak
+  allPlayers = (PLAYER**) calloc (1, sizeof (PLAYER*));
+  if (!allPlayers)
+    {
+      fprintf (stderr, "Failed allocating memory for players in globaldata.cc\n");
+      // exit (1);
+    }
+
+  for (int count = 0; count < 360; count++)
+    {
+      slope[count][0] = sin (count / (180 / PI));
+      slope[count][1] = cos (count / (180 / PI));
+    }
+  slope[270][1] = 0;
+  configDir = NULL;
+  bIsGameLoaded = true;
+  bIsBoxed = false;
+  iHumanLessRounds = -1;
+  dMaxVelocity = 0.0;	// Will be set in game()
+#ifdef DEBUG_AIM_SHOW
+  bASD = false; // will be set to true after the first drawing of the map
+#endif
+  enable_network = 0.0;
+#ifdef NETWORK
+  listen_port = DEFAULT_LISTEN_PORT;
+#endif
+  strcpy(server_name, "127.0.0.1");
+  strcpy(server_port, "25645");
+  play_music = 1.0;
+  background_music = NULL;
+  music_dir = NULL;
+  unicode = NULL;
+  regular_font = font;
+  draw_background = TRUE;
+}
+
+
+
+GLOBALDATA::~GLOBALDATA()
+{
+  int index;
+
+  if (tank_status)
+  {
+      tank_status[0] = 0;
+      free(tank_status);
+  }
+
+  index = 0;
+  while (sounds[index])
+  {
+     destroy_sample(sounds[index]);
+  }
+  free(sounds);
+
+  if (music_dir)
+     closedir(music_dir);
+  if (unicode)
+     destroy_font(unicode);
+
+  if (war_quotes) delete war_quotes;
+  if (instructions) delete instructions;
+  if (ingame) delete ingame;
+  if (gloat) delete gloat;
+  if (revenge) delete revenge;
+  if (retaliation) delete retaliation;
+  if (kamikaze) delete kamikaze;
+  if (suicide) delete suicide;
+  if (allPlayers) free(allPlayers);
+  if (command_lock)
+  {
+    int result = pthread_rwlock_destroy(command_lock);
+    switch (result)
+    {
+      case 0:
+         //Successfully destroyed
+         break;
+      case EBUSY:
+         //Some thread forgot to unlock the read-write lock
+         printf("%s:%i: Can't destroy because command_lock is still locked.\n", __FILE__, __LINE__);
+         break;
+      case EINVAL:
+         //Invalid lock
+         printf("%s:%i: The lock is invalid.\n", __FILE__, __LINE__);
+         break;
+      default:
+         //Something went wrong
+         printf("%s:%i: Unknown error code (%i) returned by pthread_rwlock_destroy.\n", __FILE__, __LINE__, result);
+         break;
+    }
+    free(command_lock);
+  }
+  destroy_curland_lock();
+}
+//Destroys curland_lock and frees it. If the lock is NULL or an error occurs, a diagnostic message will be printed.
+void GLOBALDATA::destroy_curland_lock() {
+  #ifdef THREADS
+  if (curland_lock != NULL)
+  {
+    int result = pthread_mutex_destroy(curland_lock);
+    switch (result)
+    {
+      case 0:
+        //Successfully destroyed
+        break;
+      case EBUSY:
+        //Some thread forgot to unlock result
+        printf("%s:%i: Lock is still held.\n", __FILE__, __LINE__);
+        break;
+      case EINVAL:
+        //Invalid lock
+        printf("%s:%i: Lock is invalid.\n", __FILE__, __LINE__);
+        break;
+      default:
+        printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_destroy.\n", __FILE__, __LINE__, result);
+        break;
+    }
+    free(curland_lock);
+  }
+  else
+  {
+    printf("%s:%i: Cannot destroy a null mutex.\n", __FILE__, __LINE__);
+  }
+  #endif
+}
+//init_curland_lock() allocates space for curland_lock and then calls pthread_mutex_init to initialize the lock. If the call fails, then this function will print diagnostic messages.
+void GLOBALDATA::init_curland_lock() {
+  #ifdef THREADS
+  curland_lock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));
+  if (!curland_lock)
+  {
+    printf("%s:%i: Could not allocate memory for curland_lock.\n", __FILE__, __LINE__);
+  }
+  int result = pthread_mutex_init(curland_lock, NULL);
+  switch (result)
+  {
+    case 0:
+      //Succesfully initialized
+      break;
+    case EAGAIN:
+      //Not enough resources
+      printf("%s:%i: Not enough resources to create mutex.\n", __FILE__, __LINE__);
+      break;
+    case ENOMEM:
+      printf("%s:%i: Not enough memory to create mutex.\n", __FILE__, __LINE__);
+      break;
+    case EPERM:
+      printf("%s:%i: Not authorized.\n", __FILE__, __LINE__);
+      break;
+    case EBUSY:
+      printf("%s:%i: The mutex is already initialized.\n", __FILE__, __LINE__);
+      break;
+    case EINVAL:
+      printf("%s:%i: Invalid attribute.\n", __FILE__, __LINE__);
+      break;
+    default:
+      printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_init.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+}
+//lock_curland() locks curland and prints diagnostic messages if the lock operation fails.
+//Use get_curland() to read the value instead of directly using lock_curland()/unlock_curland() pairs.
+void GLOBALDATA::lock_curland()
+{
+  #ifdef THREADS
+  int result = pthread_mutex_lock(curland_lock);
+  switch (result)
+  {
+    case 0:
+      //Got the lock.
+      break;
+    case EINVAL:
+      //Priority too high
+      printf("%s:%i: Either this thread's priority is higher than the mutex's priority, or the mutex is uninitialized.\n", __FILE__, __LINE__);
+      break;
+    case EAGAIN:
+      printf("%s:%i: Too many locks on the mutex.\n", __FILE__, __LINE__);
+      break;
+    case EDEADLK:
+      //We have the lock already
+      printf("%s:%i: Already have lock.\n", __FILE__, __LINE__);
+      break;
+    default:
+      //What error is this?
+      printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_lock.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+}
+//unlock_curland() will unlock curland and print diagnostic messages if the unlock operation fails.
+void GLOBALDATA::unlock_curland()
+{
+  #ifdef THREADS
+  int result = pthread_mutex_unlock(curland_lock);
+  switch (result)
+  {
+    case 0:
+      //Released the lock
+      break;
+    case EPERM:
+      //Forgot to get a lock on the mutex
+      printf("%s:%i: Mutex isn't locked\n", __FILE__, __LINE__);
+      break;
+    case EINVAL:
+      //Uninitialized mutex
+      printf("%s:%i: waiting_sky_lock is uninitialized.\n", __FILE__, __LINE__);
+      break;
+    default:
+      //?
+      printf("%s:%i: Unknown error code (%i) returned by pthread_mutex_unlock.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+}
+//get_curland() locks curland, reads the value, unlocks curland, then returns the value. The value returned cannot be assigned to.
+//Use this only for reading the value of curland, not for writing.
+//For writing, use lock_curland()/unlock_curland().
+int GLOBALDATA::get_curland()
+{
+  lock_curland();
+  int c = curland;
+  unlock_curland();
+  return c;
+}
+
+//Locks global->command for writing. Unlock with GLOBALDATA::unlock_command().
+void GLOBALDATA::wr_lock_command()
+{
+  #ifdef THREADS
+  int result = pthread_rwlock_wrlock(command_lock);
+  switch (result)
+  {
+    case 0:
+      //Got the lock.
+      break;
+    case EINVAL:
+      //No lock has been created yet
+      printf("%s:%i: Read-write lock is uninitialized.\n", __FILE__, __LINE__);
+      break;
+    case EDEADLK:
+      //We have the lock already
+      printf("%s:%i: Can't lock for writing because the lock is already locked for either reading or writing.\n", __FILE__, __LINE__);
+      break;
+    default:
+      //What error is this?
+      printf("%s:%i: Unknown error code (%i) returned by pthread_rwlock_wrlock.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+}
+//Unlocks a read or a write lock. Do not try to use this function to unlock a lock acquired by calling get_command().
+void GLOBALDATA::unlock_command()
+{
+  #ifdef THREADS
+  int result = pthread_rwlock_unlock(command_lock);
+  switch (result)
+  {
+    case 0:
+      //Released the lock
+      break;
+    case EPERM:
+      //We have released all locks
+      printf("%s:%i: Can't unlock because no read or write lock is currently being held.\n", __FILE__, __LINE__);
+      break;
+    case EINVAL:
+      //Uninitialized read-write lock
+      printf("%s:%i: global->command_lock is uninitialized.\n", __FILE__, __LINE__);
+      break;
+    default:
+      //Something went wrong
+      printf("%s:%i: Unknown error code (%i) returned by pthread_rwlock_unlock.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+}
+//Locks global->command for reading, reads value, then unlocks the variable and returns the value.
+int GLOBALDATA::get_command()
+{
+  #ifdef THREADS
+  int result = pthread_rwlock_rdlock(command_lock);
+  switch (result)
+  {
+    case 0:
+      //Got the lock
+      break;
+    case EINVAL:
+      //No lock has been created.
+      printf("%s:%i: *global->command_lock is uninitialized.\n", __FILE__, __LINE__);
+      break;
+    case EAGAIN:
+      //Can't read since already trying to read
+      //Maybe locks are not being unlocked?
+      printf("%s:%i: Too many read locks already held.\n", __FILE__, __LINE__);
+      break;
+    case EDEADLK:
+      //Obtaining read locks while possessing a write lock is forbidden with read-write locks.
+      printf("%s:%i: Already own write lock; can't get read lock.\n", __FILE__, __LINE__);
+      break;
+    default:
+      //What error is this?
+      printf("%s:%i: Unknown error code (%i) returned by pthread_rwlock_rdlock.\n", __FILE__, __LINE__, result);
+      break;
+  }
+  #endif
+  int c = command;
+  unlock_command();
+  return c;
+}
+
+/*
+This function saves the global data to a text file. If all goes
+well, TRUE is returned, on error, FALSE is returned.
+-- Jesse
+*/
+int GLOBALDATA::saveToFile_Text( FILE *file)
+{
+  if (! file) return FALSE;
+
+  setlocale(LC_NUMERIC, "C");
+
+  screenWidth = (int) temp_screenWidth;
+  screenHeight = (int) temp_screenHeight;
+
+  fprintf (file, "*GLOBAL*\n");
+
+  fprintf (file, "NUMPLAYERS=%d\n", numPlayers);
+  fprintf (file, "ROUNDS=%f\n", rounds);
+  fprintf (file, "DITHER=%f\n", ditherGradients);
+  fprintf (file, "DETAILEDSKY=%f\n", detailedSky);
+  fprintf (file, "DETAILEDLAND=%f\n", detailedLandscape);
+  fprintf (file, "STARTMONEY=%f\n", startmoney);
+  fprintf (file, "TURNTYPE=%f\n", turntype);
+  fprintf (file, "INTEREST=%f\n", interest);
+  fprintf (file, "SCOREROUNDWINBONUS=%f\n", scoreRoundWinBonus);
+  fprintf (file, "SCOREHITUNIT=%f\n", scoreHitUnit);
+  fprintf (file, "SCOREUNITDESTROYBONUS=%f\n", scoreUnitDestroyBonus);
+  fprintf (file, "SCOREUNITSELFDESTROY=%f\n", scoreUnitSelfDestroy);
+  fprintf (file, "ACCELERATEDAI=%f\n", skipComputerPlay);
+  fprintf (file, "SELLPERCENT=%f\n", sellpercent);
+  fprintf (file, "ENABLESOUND=%f\n", sound);
+  fprintf (file, "SCREENWIDTH=%d\n", screenWidth);
+  fprintf (file, "SCREENHEIGHT=%d\n", screenHeight);
+  fprintf (file, "OSMOUSE=%f\n", os_mouse);
+  fprintf (file, "NUMPERMANENTPLAYERS=%d\n", numPermanentPlayers);
+  fprintf (file, "LANGUAGE=%f\n", language);
+  fprintf (file, "COLOURTHEME=%f\n", colour_theme);
+  fprintf (file, "FRAMES=%f\n", frames_per_second);
+  fprintf (file, "VIOLENTDEATH=%f\n", violent_death);
+  fprintf (file, "MAXFIRETIME=%f\n", max_fire_time);
+  fprintf (file, "DIVIDEMONEY=%f\n", divide_money);
+  fprintf (file, "CHECKUPDATES=%f\n", check_for_updates);
+  fprintf (file, "NETWORKING=%f\n", enable_network);
+  fprintf (file, "LISTENPORT=%f\n", listen_port);
+  fprintf (file, "SOUNDDRIVER=%f\n", sound_driver);
+  fprintf (file, "PLAYMUSIC=%f\n", play_music);
+  fprintf (file, "FULLSCREEN=%f\n", full_screen);
+  fprintf (file, "***\n");
+  return TRUE;
+}
+
+/*
+This function loads global settings from a text
+file. The function returns TRUE on success and FALSE if
+any erors are encountered.
+-- Jesse
+*/
+
+int GLOBALDATA::loadFromFile_Text (FILE *file)
+{
+  char line[MAX_CONFIG_LINE];
+  int equal_position, line_length;
+  char field[MAX_CONFIG_LINE], value[MAX_CONFIG_LINE];
+  char *result = NULL;
+  bool done = false;
+  double sound_bookmark = 1.0;
+
+  setlocale(LC_NUMERIC, "C");
+  if (! sound)
+    sound_bookmark = sound;
+
+ // read until we hit line "*ENV*" or "***" or EOF
+  do
+    {
+      result = fgets(line, MAX_CONFIG_LINE, file);
+      if (! result)     // eof
+        return FALSE;
+      if (! strncmp(line, (char *)"***", 3) )     // end of record
+        return FALSE;
+    }
+  while ( strncmp(line, (char *)"*GLOBAL*", 5) );     // read until we hit new record
+
+  while ( (result) && (!done) )
+    {
+      // read a line
+      memset(line, '\0', MAX_CONFIG_LINE);
+      result = fgets(line, MAX_CONFIG_LINE, file);
+      if (result)
+        {
+          // if we hit end of the record, stop
+          if (! strncmp(line, (char *)"***", 3) )
+            {
+              return TRUE;
+            }
+          // find equal sign
+          line_length = strlen(line);
+          // strip newline character
+          if ( line[line_length - 1] == '\n')
+            {
+              line[line_length - 1] = '\0';
+              line_length--;
+            }
+          equal_position = 1;
+          while ( ( equal_position < line_length) && (line[equal_position] != '=') )
+            equal_position++;
+          // make sure we have valid equal sign
+
+          if ( equal_position <= line_length )
+            {
+              // seperate field from value
+              memset(field, '\0', MAX_CONFIG_LINE);
+              memset(value, '\0', MAX_CONFIG_LINE);
+              strncpy(field, line, equal_position);
+              strcpy(value, & (line[equal_position + 1]));
+              if (! strcasecmp(field, "numplayers") )
+                sscanf(value, "%d", &numPlayers);
+              else if (! strcasecmp(field, "rounds") )
+                sscanf(value, "%lf", &rounds);
+              else if (! strcasecmp(field, "dither"))
+                sscanf(value, "%lf", &ditherGradients);
+              else if (! strcasecmp(field, "detailedsky"))
+                sscanf(value, "%lf", &detailedSky);
+              else if (! strcasecmp(field, "detailedland"))
+                sscanf(value, "%lf", &detailedLandscape);
+              else if (! strcasecmp(field, "startmoney"))
+                sscanf(value, "%lf", &startmoney);
+              else if (! strcasecmp(field, "turntype"))
+                sscanf(value, "%lf", &turntype);
+              else if (! strcasecmp(field, "interest"))
+                sscanf(value, "%lf", &interest);
+              else if (! strcasecmp(field, "scoreroundwinbonus"))
+                sscanf(value, "%lf", &scoreRoundWinBonus);
+              else if (! strcasecmp(field, "scorehitunit"))
+                sscanf(value, "%lf", &scoreHitUnit);
+              else if (! strcasecmp(field, "scoreunitdestroybonus"))
+                sscanf(value, "%lf", &scoreUnitDestroyBonus);
+              else if (! strcasecmp(field, "scoreunitselfdestroy"))
+                sscanf(value, "%lf", &scoreUnitSelfDestroy);
+              else if (! strcasecmp(field, "acceleratedai"))
+                sscanf(value, "%lf", &skipComputerPlay);
+              else if (! strcasecmp(field, "sellpercent"))
+                sscanf(value, "%lf", &sellpercent);
+              else if (! strcasecmp(field, "enablesound"))
+                sscanf(value, "%lf", &sound);
+              else if (! strcasecmp(field, "screenwidth"))
+                sscanf(value, "%d", &screenWidth);
+              else if (! strcasecmp(field, "screenheight"))
+                sscanf(value, "%d", &screenHeight);
+              else if (! strcasecmp(field, "OSMOUSE"))
+                sscanf(value, "%lf", &os_mouse);
+              else if (! strcasecmp(field, "numpermanentplayers"))
+                sscanf(value, "%d", &numPermanentPlayers);
+              else if (! strcasecmp(field, "language") )
+                sscanf(value, "%lf", &language);
+              else if (! strcasecmp(field, "colourtheme") )
+                sscanf(value, "%lf", &colour_theme);
+              else if (! strcasecmp(field, "frames") )
+                sscanf(value, "%lf", &frames_per_second);
+              else if (! strcasecmp(field, "violentdeath") )
+                sscanf(value, "%lf", &violent_death);
+              else if (! strcasecmp(field, "maxfiretime") )
+                sscanf(value, "%lf", &max_fire_time);
+              else if (! strcasecmp(field, "dividemoney") )
+                sscanf(value, "%lf", &divide_money);
+              else if (!strcasecmp(field, "checkupdates")) 
+                sscanf(value, "%lf", &check_for_updates);
+              else if (!strcasecmp(field, "networking"))
+                sscanf(value, "%lf", &enable_network);
+              else if (!strcasecmp(field, "listenport"))
+                sscanf(value, "%lf", &listen_port);
+              else if (!strcasecmp(field, "sounddriver"))
+                sscanf(value, "%lf", &sound_driver);
+              else if (!strcasecmp(field, "playmusic"))
+                sscanf(value, "%lf", &play_music);
+              else if (!strcasecmp(field, "fullscreen"))
+                sscanf(value, "%lf", &full_screen);
+      
+            }    // end of found field=value line
+
+        }     // end of read a line properly
+    }     // end of while not done
+  if (! sound_bookmark)
+    sound = sound_bookmark;
+
+  if (width_override)
+    screenWidth = width_override;
+  if (height_override)
+    screenHeight = height_override;
+
+  halfWidth = screenWidth / 2;
+  halfHeight = screenHeight / 2;
+
+  menuBeginY = (screenHeight - 400) / 2;
+  if (menuBeginY < 0) menuBeginY = 0;
+  menuEndY = screenHeight - menuBeginY;
+
+  if (skipComputerPlay > SKIP_HUMANS_DEAD)
+    skipComputerPlay = SKIP_HUMANS_DEAD;
+
+  return TRUE;
+}
+
+
+
+
+
+void GLOBALDATA::initialise ()
+{
+  numTanks = 0;
+}
+
+void GLOBALDATA::addPlayer (PLAYER *player)
+{
+  if (numPlayers < MAXPLAYERS)
+    {
+      players[numPlayers] = player;
+      numPlayers++;
+      if ((int)player->type == HUMAN_PLAYER)
+        {
+          numHumanPlayers++;
+          computerPlayersOnly = FALSE;
+        }
+    }
+}
+
+void GLOBALDATA::removePlayer (PLAYER *player)
+{
+  int fromCount = 0;
+  int toCount = -1;
+
+  if ((int)player->type == HUMAN_PLAYER)
+    {
+      numHumanPlayers--;
+      if (numHumanPlayers == 0)
+        {
+          computerPlayersOnly = TRUE;
+        }
+    }
+
+  while (fromCount < numPlayers)
+    {
+      if (player != players[fromCount])
+        {
+          if ((toCount >= 0) && (fromCount > toCount))
+            {
+              players[toCount]    = players[fromCount];
+              players[fromCount]  = NULL;
+              toCount++;
+            }
+        }
+      else
+        // Position found,1G now move the remaining players down!
+        toCount = fromCount;
+      fromCount++;
+    }
+  numPlayers--;
+}
+
+PLAYER *GLOBALDATA::getNextPlayer (int *playerCount)
+{
+  (*playerCount)++;
+  if (*playerCount >= numPlayers)
+    *playerCount = 0;
+  return (players[*playerCount]);
+}
+
+PLAYER *GLOBALDATA::createNewPlayer (ENVIRONMENT *env)
+{
+  PLAYER **reallocatedPlayers;
+  PLAYER *player;
+
+  reallocatedPlayers = (PLAYER**)realloc (allPlayers, sizeof (PLAYER*) * (numPermanentPlayers + 1));
+  if (reallocatedPlayers != NULL)
+    {
+      allPlayers = reallocatedPlayers;
+    }
+  else
+    {
+      perror ( (char *)"atanks.cc: Failed allocating memory for reallocatedPlayers in GLOBALDATA::createNewPlayer");
+      // exit (1);
+    }
+  player = new PLAYER (this, env);
+  if (!player)
+    {
+      perror ( (char *)"globaldata.cc: Failed allocating memory for player in GLOBALDATA::createNewPlayer");
+      // exit (1);
+    }
+  allPlayers[numPermanentPlayers] = player;
+  numPermanentPlayers++;
+
+  return (player);
+}
+
+void GLOBALDATA::destroyPlayer (PLAYER *player)
+{
+  int fromCount = 0;
+  int toCount = 0;
+
+  for (; fromCount < numPermanentPlayers; fromCount++)
+    {
+      if (allPlayers[fromCount] != player)
+        {
+          allPlayers[toCount] = allPlayers[fromCount];
+          toCount++;
+        }
+    }
+  numPermanentPlayers--;
+}
+
+
+
+// This function returns the path to the
+// config directory used by Atanks
+char *GLOBALDATA::Get_Config_Path()
+{
+  char *my_config_dir;
+  char *homedir;
+
+  // figure out file name
+  homedir = getenv(HOME_DIR);
+  if (! homedir)
+    homedir = (char *)".";
+  my_config_dir = (char *) calloc( strlen(homedir) + 24,
+                                   sizeof(char) );
+  if (! my_config_dir)
+    return NULL;
+
+  sprintf (my_config_dir, "%s/.atanks", homedir);
+  return my_config_dir;
+
+}
+
+
+
+// This function checks to see if one full second has passed since the
+// last time the function was called.
+// The function returns true if time has passed. The function
+// returns false if time hasn't passed or it was unable to tell
+// how much time has passed.
+bool GLOBALDATA::Check_Time_Changed()
+{
+  static time_t last_second = 0;
+  time_t current_second;
+
+  current_second = time(NULL);
+  if ( current_second == last_second )
+    return false;
+
+  // time has changed
+  last_second = current_second;
+  return true;
+}
+
+
+
+/*
+ * This function Loads a music file (if there is one available.
+ * A pointer to the music file is returned. If no music can
+ * be found, then NULL is returned.
+*/
+SAMPLE *GLOBALDATA::Load_Background_Music()
+{
+    SAMPLE *my_sample = NULL;;
+    struct dirent *folder_entry;
+
+    // see if we should bother
+    if (! play_music)
+       return NULL;
+
+    // see if we have the music folder open
+    if (! music_dir)
+    {
+        char *buffer = (char *) calloc( strlen(configDir) + 32, sizeof(char) );
+        if (! buffer)
+           return NULL;
+
+        sprintf(buffer, "%s/music", configDir);
+        music_dir = opendir(buffer);
+        free(buffer);
+        if (! music_dir)
+           return NULL;
+    }
+
+    // at this point we should have an open music folder
+    // the music folder is closed by global's deconstructor
+    // search for files ending in .wav
+    folder_entry = readdir(music_dir);
+    while ( (folder_entry) && (! my_sample) )
+    {
+        // we have something, see if it is a wav file
+        if ( strstr(folder_entry->d_name, ".wav") )
+        {
+            char *filename = (char *) calloc( strlen(configDir) + strlen(folder_entry->d_name) + 64, sizeof(char));
+            if (filename)
+            {
+               sprintf(filename, "%s/music/%s", configDir, folder_entry->d_name);
+               my_sample = load_sample(filename);
+               free(filename);
+            }
+        }
+        if (! my_sample)
+           folder_entry = readdir(music_dir);
+    }
+
+    if (! folder_entry)  // hit end of folder
+    {
+       closedir(music_dir);
+       music_dir = NULL;
+    }
+
+    return my_sample;
+}
+
+
+
+
+/*
+ * This function sets all variables, which get written to the
+ * config file, back to their defaults.
+ * -- Jesse
+ *  */
+void GLOBALDATA::Reset_Options()
+{
+  ditherGradients = 1;
+  detailedLandscape = 0;
+  detailedSky = 0;
+  interest = 1.25;
+  scoreRoundWinBonus = 10000;
+  scoreHitUnit = 75;
+  scoreUnitDestroyBonus = 5000;
+  scoreUnitSelfDestroy = 0;
+  sellpercent = 0.80;
+  startmoney = 15000;
+  turntype = TURN_RANDOM;
+  skipComputerPlay = SKIP_HUMANS_DEAD;
+  sound = 1.0;
+  screenWidth = DEFAULT_SCREEN_WIDTH;
+  screenHeight = DEFAULT_SCREEN_HEIGHT;
+  os_mouse = 1.0;
+  language = LANGUAGE_ENGLISH;
+  colour_theme = COLOUR_THEME_CRISPY;
+  frames_per_second = FRAMES_PER_SECOND;
+  violent_death = FALSE;
+  max_fire_time = 0.0;
+  divide_money = 0.0;
+  check_for_updates = 1.0;
+  enable_network = 0.0;
+  #ifdef NETWORK
+  listen_port = DEFAULT_LISTEN_PORT;
+  #endif
+  play_music = 1.0;
+} 
+
+
+
+
+/*
+ * This function loads all sounds from the data folder and saves them
+ * in an array.
+ * The function returns TRUE on success or FALSE if an error happens.
+*/
+int GLOBALDATA::Load_Sounds()
+{
+   int file_count = 0, array_size = 10;
+   char *file_name;
+   FILE *my_file;
+   SAMPLE *temp_sample;
+
+   file_name = (char *) calloc( strlen(dataDir) + 128, sizeof(char) );
+   if (! file_name)
+     return FALSE;
+
+   // allocate space for sound samples
+   sounds = (SAMPLE **) calloc(10, sizeof(SAMPLE *) );
+   if (! sounds)
+   {
+       free(file_name);
+       printf("Unable to create sound array.\n");
+       return FALSE;
+   }
+
+   // read from directory
+   sprintf(file_name, "%s/sound/%d.wav", dataDir, file_count);
+   my_file = fopen(file_name, "r");
+   while ( (my_file) && (sounds) )
+   {
+       fclose(my_file);
+       temp_sample = load_sample(file_name);
+       if (! temp_sample )
+         printf("An error occured loading sound file %s\n", file_name);
+       sounds[file_count] = temp_sample;
+       file_count++; 
+   
+       // make sure we have enough memory for more samples
+       if (file_count >= array_size)
+       {
+            array_size += 10;
+            sounds = (SAMPLE**) realloc(sounds, sizeof(SAMPLE*) * (array_size + 1));
+            if (! sounds)
+              printf("We just ran out of memory loading sound files.\n");
+            else
+            {
+              // zero out new memory pointers
+              int counter;
+              for (counter = file_count; counter <= array_size; counter++)
+                 sounds[counter] = NULL;
+            }
+       }
+       sprintf(file_name, "%s/sound/%d.wav", dataDir, file_count);
+       my_file = fopen(file_name, "r");
+   }
+
+   free(file_name);
+   return TRUE;
+}
+
+
+
+/*
+ * This function loads all the bitmaps needed by th game.
+ * Bitmaps are found in a series of sub-folders under the
+ * dataDir. The function returns TRUE on success and FALSE
+ * if an error occures.
+*/
+int GLOBALDATA::Load_Bitmaps()
+{
+   int file_group = 0;
+   int array_size, file_count;
+   char *file_name;
+   char sub_folder[64];
+   FILE *my_file;
+   BITMAP *new_bitmap, **bitmap_array;
+
+   file_name = (char *) calloc( strlen(dataDir) + 128, sizeof(char) );
+   if (!file_name)
+      return FALSE;
+
+   while (file_group < 7)
+   {
+     // set the folder we're looking at
+     switch (file_group)
+     {
+        case 0: strcpy(sub_folder, "title"); break;
+        case 1: strcpy(sub_folder, "button"); break;
+        case 2: strcpy(sub_folder, "misc"); break;
+        case 3: strcpy(sub_folder, "missile"); break;
+        case 4: strcpy(sub_folder, "stock"); break;
+        case 5: strcpy(sub_folder, "tank"); break;
+        case 6: strcpy(sub_folder, "tankgun"); break;
+     }
+
+     // set up empty array
+     array_size = 10;
+     bitmap_array = (BITMAP **) calloc(10, sizeof(BITMAP *) );
+     if (! bitmap_array)
+     {
+         printf("Ran out of memory, loading bitmaps.\n");
+         free(file_name);
+         return FALSE;
+     }
+
+     // search for files
+     file_count = 0;
+     sprintf(file_name, "%s/%s/%d.bmp", dataDir, sub_folder, file_count);
+     my_file = fopen(file_name, "r");
+     while ( (my_file) && (bitmap_array) )
+     {
+         fclose(my_file);
+         new_bitmap = load_bitmap(file_name, NULL);
+         if (! new_bitmap)
+           printf("An error occured loading bitmap %s\n", file_name);
+         bitmap_array[file_count] = new_bitmap;
+         file_count++;
+
+         // make sure array is large enough
+         if ( file_count >= array_size)
+         {
+            array_size += 10;
+            bitmap_array = (BITMAP **) realloc(bitmap_array, sizeof(BITMAP *) * (array_size + 1) );
+            if (! bitmap_array)
+               printf("Unable to increase array size while loading bitmaps.\n");
+            else
+            {
+               // clear memory
+               int count;
+               for (count = file_count; count <= array_size; count++)
+                  bitmap_array[count] = NULL;
+            }
+         }
+
+         // get next file
+         sprintf(file_name, "%s/%s/%d.bmp", dataDir, sub_folder, file_count);
+         my_file = fopen(file_name, "r");
+     }
+ 
+     // save the new array
+     switch (file_group)
+     {
+        case 0: title = bitmap_array; break;
+        case 1: button = bitmap_array; break;
+        case 2: misc = bitmap_array; break;
+        case 3: missile = bitmap_array; break;
+        case 4: stock = bitmap_array; break;
+        case 5: tank = bitmap_array; break;
+        case 6: tankgun = bitmap_array; break;
+     }
+
+     file_group++;
+   }
+
+   free(file_name);
+   return TRUE;
+}
+
+
+
+// This file loads in extra fonts the game requires.
+// Fonts should be stored in the datafolder. On
+// success the function returns TRUE. When an
+// error occures, it returns FALSE.
+int GLOBALDATA::Load_Fonts()
+{
+   char *filename;
+
+   filename = (char *) calloc( strlen(dataDir) + 32, sizeof(char));
+   if (!filename)
+     return FALSE;
+
+   sprintf(filename, "%s/unicode.dat", dataDir);
+   unicode = load_font(filename, NULL, NULL);
+   if (! unicode)
+      printf("Unable to load font %s\n", filename);
+   free(filename);
+
+   if (unicode)
+   {
+      Change_Font();
+      return TRUE;
+   }
+   else return FALSE;  
+}
+
+
+// This function selects the font to use. This should be called
+// right after a language change.
+void GLOBALDATA::Change_Font()
+{
+    // FONT *temp_font = font;
+
+    if ( (language == LANGUAGE_RUSSIAN) || (language == LANGUAGE_GERMAN) )
+       font = unicode;
+    else
+       font = regular_font;
+
+    // if (temp_font != font)     // font has changed
+    // {
+       Load_Weapons_Text(this);
+       Load_Text_Files();
+    // }
+}
+
+
+
+void GLOBALDATA::Update_Player_Menu()
+{
+   int index;
+
+   for (index = 0; index < numPermanentPlayers; index++)
+   {
+       if (allPlayers[index])
+          allPlayers[index]->initMenuDesc();
+   }
+}
+
+
+
+
+// This function loads all needed text files, based on
+// language, into memory. If a previous text was loaded, it is
+// removed from memory first.
+int GLOBALDATA::Load_Text_Files()
+{
+    char *filename;
+    char suffix[32];
+
+    filename = (char *) calloc( strlen(dataDir) + 64, sizeof(char) );
+    if (! filename)
+       return FALSE;
+
+    if (war_quotes) delete war_quotes;
+    if (instructions) delete instructions;
+    if (gloat) delete gloat;
+    if (revenge) delete revenge;
+    if (retaliation) delete retaliation;
+    if (suicide) delete suicide;
+    if (kamikaze) delete kamikaze;
+    if (ingame) delete ingame;
+
+    if (language == LANGUAGE_RUSSIAN)
+       sprintf(filename, "%s/text/war_quotes_ru.txt", dataDir);
+    else if (language == LANGUAGE_SPANISH)
+       sprintf(filename, "%s/text/war_quotes_ES.txt", dataDir);
+    else
+       sprintf(filename, "%s/text/war_quotes.txt", dataDir);
+    war_quotes = new TEXTBLOCK(filename);
+
+     if (language == LANGUAGE_PORTUGUESE)
+        strcpy(suffix, ".pt_BR.txt");
+     else if (language == LANGUAGE_FRENCH)
+        strcpy(suffix, "_fr.txt");
+     else if (language == LANGUAGE_GERMAN)
+        strcpy(suffix, "_de.txt");
+     else if (language == LANGUAGE_SLOVAK)
+        strcpy(suffix, "_sk.txt");
+     else if (language == LANGUAGE_RUSSIAN)
+        strcpy(suffix, "_ru.txt");
+     else if (language == LANGUAGE_SPANISH)
+        strcpy(suffix, "_ES.txt");
+     else if (language == LANGUAGE_ITALIAN)
+        strcpy(suffix, "_it.txt");
+     else
+        strcpy(suffix, ".txt");       // default to english
+
+    sprintf(filename, "%s/text/instr%s", dataDir, suffix);
+    instructions = new TEXTBLOCK(filename);
+
+    sprintf(filename, "%s/text/gloat%s", dataDir, suffix);
+    gloat = new TEXTBLOCK(filename);
+    sprintf(filename, "%s/text/revenge%s", dataDir, suffix);
+    revenge = new TEXTBLOCK(filename);
+    sprintf(filename, "%s/text/retaliation%s", dataDir, suffix);
+    retaliation = new TEXTBLOCK(filename);
+    sprintf(filename, "%s/text/suicide%s", dataDir, suffix);
+    suicide = new TEXTBLOCK(filename);
+    sprintf(filename, "%s/text/kamikaze%s", dataDir, suffix);
+    kamikaze = new TEXTBLOCK(filename);
+    sprintf(filename, "%s/text/ingame%s", dataDir, suffix);
+    ingame = new TEXTBLOCK(filename);
+
+    free(filename);
+    return TRUE;
+}
+
+
+#ifdef NETWORK
+// This function sends a message to all connected game clients.
+// Returns TRUE on success or FALSE if the message could not be sent
+int GLOBALDATA::Send_To_Clients(char *message)
+{
+   int index;
+   int message_length;
+
+   if (! message) return FALSE;
+   message_length = strlen(message);
+   for (index = 0; index < numPlayers; index++)
+   {
+       if ( (players[index]) && (players[index]->type == NETWORK_CLIENT) )
+          write(players[index]->server_socket, message, message_length);
+   }     // done all players
+   return TRUE;
+}
+#endif
+
+
+
+// This function tries to figure out where the dataDir is. It
+// first checks the current working directory, ".". If the
+// proper files are not found, then we try the defined value of
+// DATA_DIR.
+// On success, TRUE is returned. If no usable directory is
+// found, then FALSE is returned.
+int GLOBALDATA::Find_Data_Dir()
+{
+     char *current_dir = NULL;
+     FILE *my_phile;
+
+     current_dir = (char *) calloc( strlen(DATA_DIR) + 32, sizeof(char));
+     if (! current_dir)
+        return FALSE;
+
+     // try current dir
+     strcpy(current_dir, "./unicode.dat");   // local dir
+     my_phile = fopen(current_dir, "r");
+     if (my_phile)
+     {
+         fclose(my_phile);
+         free(current_dir);
+         dataDir = ".";
+         return TRUE;
+     }
+
+    // try system dir
+    sprintf(current_dir, "%s/unicode.dat", DATA_DIR);
+    my_phile = fopen(current_dir, "r");
+    if (my_phile)
+    {
+        fclose(my_phile);
+        free(current_dir);
+        dataDir = DATA_DIR;
+        return TRUE;
+    }
+
+    dataDir = DATA_DIR;    // fall back
+    free(current_dir);
+    return FALSE;
+}
+
+
+
+/*
+Find the max velocity of a missile
+*/
+double GLOBALDATA::Calc_Max_Velocity()
+{
+   dMaxVelocity = (double) MAX_POWER * (100.0 / (double) frames_per_second) / 100.0;
+   return dMaxVelocity; 
+}
+
+
+
+/* See how many humans and networked players we have */
+int GLOBALDATA::Count_Humans()
+{
+     int count;
+     int humans = 0;
+
+     for (count = 0; count < numPlayers; count++)
+     {
+        if (players[count]->type == HUMAN_PLAYER)
+           humans++;
+        else if (players[count]->type == NETWORK_CLIENT)
+           humans++;
+     }
+
+     return humans;
+}
+
+
+/*
+This function checks to see if there is a single player left standing.
+If there is, that player's index is returned. If there is no winner, then
+-1 is returned. If all tanks have been destroyed, then -2 is returned.
+*/
+int GLOBALDATA::Check_For_Winner()
+{
+    int index = 0, tank_count = 0;
+    int last_alive = -1;
+    
+    while ( (index < numPlayers) && (tank_count < 2) )
+    {
+         if (players[index]->tank)
+         {
+            last_alive = index;
+            tank_count++;
+         }
+         index++;
+    }
+
+    if ( (last_alive >= 0) && (tank_count == 1) )
+       return last_alive;
+    else if (tank_count > 1)
+       return -1;
+    else      // all dead
+       return -2;
+}
+
+
+/*
+This function gives credits, score and money to the winner(s).
+*/
+void GLOBALDATA::Credit_Winners(int winner)
+{
+   int team_members = 0;
+   int index;
+
+   if (winner < 0)    // no winner
+      return;
+
+   if (winner == JEDI_WIN)
+   {
+      for (index = 0; index < numPlayers; index++)
+      {
+          if (players[index]->team == TEAM_JEDI)
+          {
+             players[index]->score++;
+             players[index]->won++;
+             team_members++;
+          }
+      }
+
+   }
+
+   else if (winner == SITH_WIN)
+   {
+       for (index = 0; index < numPlayers; index++)
+       {
+          if (players[index]->team == TEAM_SITH)
+          {
+             players[index]->score++;
+             players[index]->won++;
+             team_members++;
+          }
+       }
+   }
+   else // credit single winner
+   {
+      players[winner]->score++;
+      players[winner]->won++;
+      players[winner]->money += (int) scoreRoundWinBonus; 
+   }
+
+   // team gets their money too
+   if (team_members)
+   {
+       int team_bonus = (int) scoreRoundWinBonus / team_members;
+       for (index = 0; index < numPlayers; index++)
+       {
+           if ( ((winner == JEDI_WIN) && (players[index]->team == TEAM_JEDI) ) ||
+                ((winner == SITH_WIN) && (players[index]->team == TEAM_SITH) ) )
+                players[index]->money += team_bonus;
+       }
+   }
+}
+
diff --git a/src/globaldata.h b/src/globaldata.h
new file mode 100644
index 0000000..0227d08
--- /dev/null
+++ b/src/globaldata.h
@@ -0,0 +1,234 @@
+#ifndef GLOBALDATA_DEFINE
+#define GLOBALDATA_DEFINE
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "main.h"
+#include "text.h"
+
+#define DEFAULT_SCREEN_WIDTH 800
+#define DEFAULT_SCREEN_HEIGHT 600
+
+#define LANGUAGE_ENGLISH 0.0
+#define LANGUAGE_PORTUGUESE 1.0
+#define LANGUAGE_FRENCH 2.0
+#define LANGUAGE_GERMAN 3.0
+#define LANGUAGE_SLOVAK 4.0
+#define LANGUAGE_RUSSIAN 5.0
+#define LANGUAGE_SPANISH 6.0
+#define LANGUAGE_ITALIAN 7.0
+
+#define COLOUR_THEME_REGULAR 0.0
+#define COLOUR_THEME_CRISPY 1.0
+
+#define GAME_NAME_LENGTH 64
+
+#define VIOLENT_DEATH_OFF 0
+#define VIOLENT_DEATH_LIGHT 1
+#define VIOLENT_DEATH_MEDIUM 2
+#define VIOLENT_DEATH_HEAVY 3
+
+#define MAX_INTEREST_AMOUNT 100000
+#define MAX_TEAM_AMOUNT 500000
+
+#define DEMO_WAIT_TIME 60
+
+#define SOUND_AUTODETECT 0
+#define SOUND_OSS 1
+#define SOUND_ESD 2
+#define SOUND_ARTS 3
+#define SOUND_ALSA 4
+#define SOUND_JACK 5
+
+#define FULL_SCREEN_EITHER 10.0
+#define FULL_SCREEN_TRUE  1.0
+#define FULL_SCREEN_FALSE 0.0
+
+#define MAX_AI_TIME 10
+
+#define ALL_SOCKETS -1
+
+
+enum skipComputerPlayType
+{
+  SKIP_NONE, SKIP_HUMANS_DEAD// , SKIP_AUTOPLAY
+};
+
+class PLAYER;
+class TANK;
+class GLOBALDATA
+  {
+  private:
+  DIR *music_dir;
+  public:
+    ~GLOBALDATA();
+    int	WHITE, BLACK, PINK;
+    double	slope[360][2];
+
+    char	*dataDir;
+    char    *configDir;
+    BOX	*updates, *lastUpdates, window;
+    int	updateCount, lastUpdatesCount;
+    int	stopwindow;
+    int	command;
+    double  frames_per_second;
+
+    PLAYER	**allPlayers;
+    int	numPermanentPlayers;
+    pthread_rwlock_t* command_lock;
+    void wr_lock_command ();
+    void unlock_command ();
+    int get_command ();
+    PLAYER	**players;
+    int	numPlayers;
+    int	numHumanPlayers;
+    int	computerPlayersOnly;
+    double	skipComputerPlay;	/* options requires doubles - grr */
+    /* It's a lot simpler than having
+     * special cases for each type */
+    int	numTanks;
+    int	maxNumTanks;
+    TANK	*currTank;
+
+    int	updateMenu;
+
+    int	curland, cursky;
+    int get_curland();
+    void unlock_curland();
+    void lock_curland();
+    void destroy_curland_lock();
+    void init_curland_lock();
+    pthread_mutex_t* curland_lock;
+
+    int	colourDepth;
+    int	screenWidth, screenHeight;
+    int menuBeginY, menuEndY;
+    int	halfWidth, halfHeight;
+    int     width_override, height_override;
+    double  temp_screenWidth, temp_screenHeight;
+    PLAYER *client_player;     // the index we use to know which one is the player on the client side
+    gfxDataStruct	gfxData;
+    // DATAFILE	*SOUND;
+    ENVIRONMENT *env;
+
+    // bool            full_screen;
+    // int		cacheCirclesBG ;	// This is just a flag, so it need only be
+						// 		an integer, not a double 
+    void Reset_Options();
+
+    /* Logically, these three variables should be ints.  However, converting
+    them to ints (or even an enumerated type) would require some rewritting
+    of the options function - and that's a lot of work. 2003.09.05 */
+    /* Hence being double. 2004.01.05 */
+    double ditherGradients;
+    double detailedLandscape;
+    double detailedSky;
+    double os_mouse;          // whether we should use the OS or custom mouse
+    double colour_theme;     // land and sky gradiant theme
+    double sound_driver;
+
+    /* All this money data; couldn't it be moved into some separate data
+    structure or object */
+    /* It could, but it's not a problem */
+    double	startmoney;
+    double	interest;
+    double	scoreHitUnit;
+    double	scoreSelfHit;
+    double	scoreUnitDestroyBonus;
+    double	scoreUnitSelfDestroy;
+    double	scoreRoundWinBonus;
+    double  sellpercent;
+    double  divide_money;
+    double  play_music;
+    double full_screen;
+    char server_name[128], server_port[128];
+
+    /* double? */
+    /* double for options() reasons, no messing about with casting or
+     * special cases. */
+    double	turntype;
+    double	rounds;
+    int     currentround;
+    double  sound;
+    double  language;
+    int     name_above_tank;
+    int     tank_status_colour;
+    char   *tank_status;
+    char    game_name[GAME_NAME_LENGTH];
+    double  load_game;
+    double  campaign_mode;
+    double  violent_death;
+    double  saved_game_index;
+    char    **saved_game_list;
+    double  max_fire_time;
+    bool close_button_pressed;
+    char *update_string;
+    double check_for_updates;
+    bool demo_mode;
+    double enable_network, listen_port;
+    int draw_background;
+    BITMAP **button, **misc, **missile, **stock, **tank, **tankgun, **title;
+    SAMPLE **sounds;
+    SAMPLE *background_music;
+    FONT *unicode, *regular_font;
+    TEXTBLOCK *war_quotes, *instructions, *ingame;
+    TEXTBLOCK *gloat, *revenge, *retaliation, *suicide, *kamikaze;
+    char *client_message;   // message sent from client to main menu
+
+
+    GLOBALDATA ();
+    void	initialise ();
+    int     saveToFile_Text (FILE *file);
+    int     loadFromFile_Text (FILE *file);
+    int     loadFromFile(ifstream &my_file);
+    void	addPlayer (PLAYER *player);
+    void	removePlayer (PLAYER *player);
+    PLAYER	*getNextPlayer (int *playerCount);
+    PLAYER	*createNewPlayer (ENVIRONMENT *env);
+    void	destroyPlayer (PLAYER *player);
+    char    *Get_Config_Path();
+    bool    Check_Time_Changed();      // check to see if one second has passed
+    bool		bIsGameLoaded;
+    bool		bIsBoxed;
+    int			iHumanLessRounds;
+    double	dMaxVelocity;
+    int Load_Sounds();
+    int Load_Bitmaps();
+    SAMPLE *Load_Background_Music();
+    int Load_Fonts();
+    void Change_Font();
+    void Update_Player_Menu();
+    int Load_Text_Files();
+    #ifdef NETWORK
+    int Send_To_Clients(char *message);        // send a short message to all network clients
+    #endif
+#ifdef DEBUG_AIM_SHOW
+    bool bASD;
+#endif
+    int Find_Data_Dir();
+    double Calc_Max_Velocity();
+    int Count_Humans();
+    int Check_For_Winner();    // returns winner index or -1 for no winner
+    void Credit_Winners(int winner);
+  };
+
+#endif
diff --git a/src/globals.h b/src/globals.h
new file mode 100644
index 0000000..2f128a8
--- /dev/null
+++ b/src/globals.h
@@ -0,0 +1,295 @@
+#ifndef GLOBALS_DEFINE
+#define GLOBALS_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+/*
+#include "virtobj.h"
+#include "floattext.h"
+#include "physobj.h"
+#include "tank.h"
+#include "missile.h"
+#include "explosion.h"
+#include "player.h"
+#include "environment.h"
+*/
+#include "globaldata.h"
+/*
+#include "teleport.h"
+#include "decor.h"
+#include "beam.h"
+*/
+using namespace std;
+
+char	*errorMessage;
+int	errorX, errorY;
+
+int	WHITE, BLACK, PINK, RED, GREEN, DARK_GREEN, BLUE, PURPLE, YELLOW;
+
+int	k;
+int	ctrlUsedUp;
+
+const gradient topbar_gradient[] =
+{
+  {{200,200,200,0}, 0.0},
+  {{255,255,255,0}, 0.5},
+  {{128,128,128,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient stuff_bar_gradient[] =
+{
+  {{  0,120,  0,0}, 0.0},
+  {{ 10,210, 50,0}, 0.1},
+  {{100,150,150,0}, 0.28},
+  {{100,170,170,0}, 0.31},
+  {{200,200,200,0}, 0.33},
+  {{120,150,120,0}, 0.35},
+  {{180,190,180,0}, 0.5},
+  {{210,210,210,0}, 0.55},
+  {{200,220,200,0}, 0.57},
+  {{255,255,255,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient circles_gradient[] =
+{
+  {{100, 75, 50,0}, 0.0},
+  {{  0,100,  0,0}, 0.5},
+  {{255,255,255,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Explosion gradient
+const gradient explosion_gradient1[] =
+{
+  {{150, 75, 30,0}, 0.0},
+  {{255,255,255,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Explosion gradient
+const gradient explosion_gradient2[] =
+{
+  {{255,255,102,0}, 0.0}, // ff6
+  {{255,136, 0,0}, 1.0}, // f80
+  {{0,0,0,0}, -1}
+};
+
+const gradient * const explosion_gradients[] =
+{
+  explosion_gradient1,
+  explosion_gradient2
+};
+
+/*
+// Sky gradients, first line is top of screen
+const gradient sky_gradient1[] =
+{
+  {{255,255,255,0}, 0.0},
+  {{100,100,100,0}, 0.1},
+  {{ 80,100,100,0}, 0.5},
+  {{0,0,0,0}, -1}
+};
+
+const gradient sky_gradient2[] =
+{
+  {{  0,  0, 40,0}, 0.0},
+  {{ 40, 40,100,0}, 0.5},
+  {{ 80,80,100,0}, 0.75},
+  {{0,0,0,0}, -1}
+};
+
+const gradient sky_gradient3[] =
+{
+  {{240,  0, 40,0}, 0.0},
+  {{140, 40,100,0}, 0.15},
+  {{ 80, 80,100,0}, 0.75},
+  {{0,0,0,0}, -1}
+};
+
+const gradient sky_gradient4[] =
+{
+  {{ 40, 40, 40,0}, 0.0},
+  {{100, 40,100,0}, 0.2},
+  {{ 80, 80,100,0}, 0.75},
+  {{0,0,0,0}, -1}
+};
+
+const gradient sky_gradient5[] =
+{
+  {{  0, 90, 40,0}, 0.0},
+  {{  0,120,100,0}, 0.2},
+  {{ 40,200,100,0}, 0.75},
+  {{0,0,0,0}, -1}
+};
+
+// Sunset
+const gradient sky_gradient6[] =
+{
+  {{ 70,240,240,0}, 0.0},
+  {{ 70,200,200,0}, 0.3},
+  {{ 70,200,160,0}, 0.35},
+  {{255,200, 70,0}, 0.6},
+  {{255,255,128,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Burning sky
+const gradient sky_gradient7[] =
+{
+  {{ 20, 20, 20,0}, 0.0},
+  {{255,200,  0,0}, 0.08},
+  {{255,255,  0,0}, 0.13},
+  {{ 20, 20, 20,0}, 0.16},
+  {{255,200,  0,0}, 0.5},
+  {{255,255,  0,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Burning landscape, black skies
+const gradient sky_gradient8[] =
+{
+  {{  0,  0,  0,0}, 0.0},
+  {{100,  0,  0,0}, 0.4},
+  {{255,255,255,0}, 0.8},
+  {{0,0,0,0}, -1}
+};
+
+// Sky gradients, first line is top of screen
+// dark blue to darker blue
+const gradient sky_gradient9[] =
+{
+  {{ 90, 90,255,0}, 0.0},
+  {{ 60, 60,200,0}, 0.3},
+  {{ 30, 30,150,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// dark blue to blue-grey
+const gradient sky_gradient10[] =
+{
+  {{110,110,255,0}, 0.0},
+  {{150,150,255,0}, 0.3},
+  {{200,200,255,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// white to grey-blue to dark blue
+const gradient sky_gradient11[] =
+{
+  {{255,255,255,0}, 0.0},
+  {{200,200,255,0}, 0.3},
+  {{ 80, 80,180,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// simple purple: dark to light
+const gradient sky_gradient12[] =
+{
+  {{133, 33,133,0}, 0.0},
+  {{220,120,220,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// night sky: black to dark purple
+const gradient sky_gradient13[] =
+{
+  {{  0,  0,  0,0}, 0.0},
+  {{ 50,  0, 50,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Sunset
+const gradient sky_gradient14[] =
+{
+  {{  0,  0,  0,0}, 0.0},
+  {{ 50,  0, 50,0}, 0.1},
+  {{ 90, 20,  0,0}, 0.3},
+  {{180, 50,  0,0}, 0.7},
+  {{255,150,150,0}, 0.9},
+  {{255,255,100,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Burning sky
+const gradient sky_gradient15[] =
+{
+  {{185, 60, 60,0}, 0.0},
+  {{240,110,110,0}, 0.5},
+  {{255,110,110,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Burning landscape, black skies
+const gradient sky_gradient16[] =
+{
+  {{  0,  0,  0,0}, 0.0},
+  {{170, 50, 50,0}, 0.5},
+  {{220,110,110,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+
+const gradient * const sky_gradients[] =
+{
+  sky_gradient1,
+  sky_gradient2,
+  sky_gradient3,
+  sky_gradient4,
+  sky_gradient5,
+  sky_gradient6,
+  sky_gradient7,
+  sky_gradient8,
+  sky_gradient9,
+  sky_gradient10,
+  sky_gradient11,
+  sky_gradient12,
+  sky_gradient13,
+  sky_gradient14,
+  sky_gradient15,
+  sky_gradient16
+};
+*/
+
+int		cclock,
+fps, frames,
+fi, lx, ly;
+#define CLOCK_MAX 10
+
+int		steep=2, mheight=200, mbase=0;
+double		msteep=.2, smooth=.00;
+
+int winner;
+
+char buf[100];
+
+bool quit_right_now;
+
+WEAPON  weapon[WEAPONS];
+WEAPON  naturals[NATURALS];
+ITEM    item[ITEMS];
+
+GLOBALDATA *my_global;
+
+
+#endif
+
diff --git a/src/imagedefs.h b/src/imagedefs.h
new file mode 100644
index 0000000..f09fa5c
--- /dev/null
+++ b/src/imagedefs.h
@@ -0,0 +1,29 @@
+#ifndef IMAGEDEFS_DEFINE
+#define IMAGEDEFS_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License 
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+#define	DONE_IMAGE		11
+#define	FAST_UP_ARROW_IMAGE	12
+#define	UP_ARROW_IMAGE		13
+#define	DOWN_ARROW_IMAGE	14
+#define	FAST_DOWN_ARROW_IMAGE	15
+
+#endif // IMAGEDEFS_DEFINE
diff --git a/src/land.cpp b/src/land.cpp
new file mode 100644
index 0000000..2db0c57
--- /dev/null
+++ b/src/land.cpp
@@ -0,0 +1,209 @@
+#include "land.h"
+#include "files.h"
+
+#ifdef THREADS
+#include <pthread.h>
+#endif
+
+// Define how the land will look.
+
+void generate_land (GLOBALDATA *global, ENVIRONMENT *env, BITMAP *land, int xoffset, int yoffset, int heightx)
+{
+  const int land_height = heightx * 5 / 6;
+  double        smoothness = 100;
+  int   octaves = 8;
+  double        lambda = 0.25;
+  double * depthStrip[2];
+  //Ignore updates from other threads by using a temporary variable.
+  int curland_temp=global->get_curland();
+
+  depthStrip[0] = (double *)calloc(global->screenHeight, sizeof(double));
+  depthStrip[1] = (double *)calloc(global->screenHeight, sizeof(double));
+
+  if (!depthStrip[0] || !depthStrip[1])
+    {
+      cerr << "ERROR: Unable to allocate " << (global->screenHeight * 2) << " bytes in generate_land() !!!" << endl;
+    }
+
+  int landType = (env->landType == LANDTYPE_RANDOM)? (rand () % LANDTYPE_PLAIN) + 1 : (int)env->landType;
+
+  switch (landType)
+    {
+    case LANDTYPE_MOUNTAINS:
+      smoothness = 200;
+      octaves = 8;
+      lambda = 0.65;
+      break;
+    case LANDTYPE_CANYONS:
+      smoothness = 50;
+      octaves = 8;
+      lambda = 0.25;
+      break;
+    case LANDTYPE_VALLEYS:
+      smoothness = 200;
+      octaves = 8;
+      lambda = 0.25;
+      break;
+    case LANDTYPE_HILLS:
+      smoothness = 600;
+      octaves = 6;
+      lambda = 0.40;
+      break;
+    case LANDTYPE_FOOTHILLS:
+      smoothness = 1200;
+      octaves = 3;
+      lambda = 0.25;
+      break;
+    case LANDTYPE_PLAIN:
+      smoothness = 4000;
+      octaves = 2;
+      lambda = 0.2;
+      break;
+    case LANDTYPE_NONE:
+      break;
+    default:
+      break;
+    }
+
+  if (global->detailedLandscape)
+    memset (depthStrip[1], 0, global->screenHeight * sizeof (double));
+
+ for (int x = 0; x < global->screenWidth; x++)
+    {
+      int depth = 0;
+      if (landType == LANDTYPE_NONE)
+        env->height[x] = 1;
+      else
+        env->height[x] = ((perlin2DPoint (1.0, smoothness, xoffset + x, yoffset, lambda, octaves) + 1) / 2);
+
+      if (global->detailedLandscape)
+        {
+          memcpy (depthStrip[0], depthStrip[1], global->screenHeight * sizeof(double));
+          for (depth = 1; depth < global->screenHeight; depth++)
+            {
+              depthStrip[1][depth] = ((perlin2DPoint (1.0, smoothness, xoffset + x, yoffset + depth, lambda, octaves) + 1) / 2 * land_height - (global->screenHeight - depth));
+              if (depthStrip[1][depth] > env->height[x] * land_height)
+                depthStrip[1][depth] = env->height[x] * land_height;
+            }
+          depthStrip[1][0] = 0;
+          depth = 1;
+        }
+
+      if (landType == LANDTYPE_NONE)
+        env->height[x] = 1;
+      else
+        env->height[x] *= land_height;
+
+     for (int y = 0; y <= env->height[x]; y++)
+        {
+          double offset = 0;
+          int color = 0;
+          double shade = 0;
+
+          if (global->detailedLandscape)
+            {
+              double bot; // top, 
+              double minBot, maxTop, btdiff, i;
+              double a1, a2, angle;
+              while ((depthStrip[1][depth] <= y) && (depth < global->screenHeight))
+                depth++;
+              bot = (depthStrip[0][depth - 1] + depthStrip[1][depth - 1]) / 2;
+              // top = (depthStrip[0][depth] + depthStrip[1][depth]) / 2;
+              minBot = MIN (depthStrip[0][depth - 1], depthStrip[1][depth - 1]);
+              maxTop = MAX (depthStrip[0][depth], depthStrip[1][depth]);
+              btdiff = maxTop - minBot;
+              i = (y - bot) / btdiff;
+              a1 = atan2 (depthStrip[0][depth - 1] - depthStrip[1][depth - 1], 1.0) * 180 / PI + 180;
+              a2 = atan2 (depthStrip[0][depth] - depthStrip[1][depth], 1.0) * 180 / PI + 180;
+
+              angle = interpolate (a1, a2, i);
+              shade = global->slope[(int)angle][0];
+            }
+
+          if (global->ditherGradients)
+            offset += rand () % 10 - 5;
+
+          if (global->detailedLandscape)
+            offset += (global->screenHeight - depth) * 0.5;
+
+          while (y + offset < 0)
+            offset /= 2;
+          while (y + offset > global->screenHeight)
+            offset /= 2;
+
+          color = gradientColorPoint (land_gradients[curland_temp], env->height[x], y + offset);
+          if (global->detailedLandscape)
+            {
+              float h, s, v;
+              int r, g, b;
+
+              r = getr (color);
+              g = getg (color);
+              b = getb (color);
+              rgb_to_hsv (r, g, b, &h, &s, &v);
+              shade += (double)(rand () % 1000 - 500) * (1.0/10000);
+              if (shade < 0)
+                v += v * shade * 0.5;
+              else
+                v += (1 - v) * shade * 0.5;
+              hsv_to_rgb (h, s, v, &r, &g, &b);
+              color = makecol (r, g, b);
+            }
+
+          #ifdef THREADS
+          solid_mode();
+          #endif
+          putpixel (land, x, global->screenHeight - y, color);
+          #ifdef THREADS
+          drawing_mode(global->env->current_drawing_mode, NULL, 0, 0);
+          #endif
+        }
+    }
+
+  free(depthStrip[0]);
+  free(depthStrip[1]);
+
+}
+
+
+
+#ifdef THREADS
+// This function should be called as a separate thread. Its sole purpose
+// is to generate terrain images in the background. Then pass them
+// to the main program.
+void *Generate_Land_In_Background(void *new_env)
+{
+    ENVIRONMENT *env = (ENVIRONMENT *) new_env;
+    GLOBALDATA *global = env->Get_Globaldata();
+    BITMAP *land = NULL;
+    int xoffset;
+
+   while (global->get_command() != GLOBAL_COMMAND_QUIT)
+   {
+      if (! env->get_waiting_terrain())
+      {
+          // The sky thread runs around the same time. We will wait a few seconds
+          LINUX_DREAMLAND;
+          land = create_bitmap(global->screenWidth, global->screenHeight);
+          if (! land)
+          {
+             printf("Memory error while creating land in background.\n");
+          }
+          else
+          {
+              clear_to_color(land, PINK);
+              xoffset = rand();
+              generate_land(global, env, land, xoffset, 0, global->screenHeight);
+          }
+          env->lock(env->waiting_terrain_lock);
+          env->waiting_terrain = land;
+          env->unlock(env->waiting_terrain_lock);
+      }
+      LINUX_SLEEP;        // avoid taxing the CPU
+   }        // while still running program
+ 
+   pthread_exit(NULL);
+   return NULL;         // keeps the compiler happy
+}
+#endif
+
diff --git a/src/land.h b/src/land.h
new file mode 100644
index 0000000..3c9158c
--- /dev/null
+++ b/src/land.h
@@ -0,0 +1,169 @@
+#ifndef LAND_HEADER_FILE__
+#define LAND_HEADER_FILE__
+
+#include "globaldata.h"
+#include "environment.h"
+
+const gradient land_gradient1[] =
+{
+  {{ 20, 40, 20,0}, 0.0},
+  {{ 80,100, 80,0}, 0.5},
+  {{ 80,120,100,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient2[] =
+{
+  {{100,200,100,0}, 0.0},
+  {{ 80,100, 80,0}, 0.5},
+  {{ 80,120,100,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient3[] =
+{
+  {{200,100,100,0}, 0.0},
+  {{100, 70, 80,0}, 0.5},
+  {{120, 80,100,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient4[] =
+{
+  {{ 80, 50, 60,0}, 0.0},
+  {{100, 70, 80,0}, 0.25},
+  {{150,120, 80,0}, 0.75},
+  {{200,180,150,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient5[] =
+{
+  {{ 20, 20, 20,0}, 0.0},
+  {{100,100,100,0}, 0.7},
+  {{250,250,250,0}, 0.75},
+  {{250,250,250,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient6[] =
+{
+  {{200,180, 70,0}, 0.0},
+  {{100, 90, 30,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient7[] =
+{
+  {{ 50,200,150,0}, 0.0},
+  {{130,120,180,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient8[] =
+{
+  {{  0,  0,  0,0}, 0.0},
+  {{ 50, 40, 50,0}, 0.4},
+  {{100,  0,  0,0}, 0.8},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient9[] =
+{
+  {{100,100,100,0}, 0.0},
+  {{ 50, 50, 50,0}, 0.7},
+  {{255,255,255,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient10[] =
+{
+  {{100, 50, 50,0}, 0.0},
+  {{ 50,  0,  0,0}, 0.25},
+  {{100, 10, 10,0}, 0.5},
+  {{100,  0,  0,0}, 0.95},
+  {{  0,  0,  0,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient11[] =
+{
+  {{ 50,100, 50,0}, 0.0},
+  {{  0, 50,  0,0}, 0.7},
+  {{  0,100,  0,0}, 0.95},
+  {{  0,  0,  0,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient12[] =
+{
+  {{ 90, 90, 90,0}, 0.0},
+  {{ 30, 30, 30,0}, 0.4},
+  {{ 60, 60, 60,0}, 0.95},
+  {{  0,  0,  0,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient13[] =
+{
+  {{ 90, 90, 90,0}, 0.0},
+  {{  0, 60,  0,0}, 0.95},
+  {{  0,  0,  0,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient14[] =
+{
+  {{  0,175,  0,0}, 0.0},
+  {{  0, 50,  0,0}, 0.95},
+  {{  0,  0,  0,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient15[] =
+{
+  {{100, 50, 50,0}, 0.0},
+  {{ 50,  0,  0,0}, 0.95},
+  {{  0,  0,  0,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient land_gradient16[] =
+{
+  {{200,  0,  0,0}, 0.0},
+  {{200,200,  0,0}, 0.25},
+  {{  0,200,  0,0}, 0.5},
+  {{  0,  0,200,0}, 0.75},
+  {{200,  0,200,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+const gradient * const land_gradients[] =
+{
+  land_gradient1,
+  land_gradient2,
+  land_gradient3,
+  land_gradient4,
+  land_gradient5,
+  land_gradient6,
+  land_gradient7,
+  land_gradient8,
+  land_gradient9,
+  land_gradient10,
+  land_gradient11,
+  land_gradient12,
+  land_gradient13,
+  land_gradient14,
+  land_gradient15,
+  land_gradient16,
+};
+
+
+void generate_land(GLOBALDATA *global, ENVIRONMENT *env, BITMAP *land, int xoffest, int yoffset, int heightx);
+
+#ifdef THREADS
+void *Generate_Land_In_Background(void *new_env);
+#endif
+
+#endif
+
diff --git a/src/main.h b/src/main.h
new file mode 100644
index 0000000..9f92836
--- /dev/null
+++ b/src/main.h
@@ -0,0 +1,474 @@
+#ifndef MAIN_DEFINE
+#define MAIN_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+#ifndef VERSION
+#define VERSION "5.5"
+#endif
+
+#ifdef GENTOO
+#ifndef DATA_DIR
+#define DATA_DIR "/usr/share/games/atanks"
+#endif
+#endif
+
+#ifndef BUFFER_SIZE
+#define BUFFER_SIZE 256
+#endif
+
+#ifndef _UNUSED
+#define _UNUSED __attribute__ ((unused))
+#endif // _UNUSED
+#ifndef _WARNUNUSED
+#define _WARNUNUSED __attribute__ ((warn_unused_result))
+#endif // _WARNUNUSED
+
+#include <allegro.h>
+#ifdef WIN32
+#include <winalleg.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <time.h>
+#include "imagedefs.h"
+
+#include <iostream>
+#include <fstream>
+
+#ifdef LINUX
+#include <unistd.h>
+#endif /* LINUX */
+
+#include <string>
+
+#define GAME_SPEED 14000
+
+#ifdef LINUX
+#define LINUX_SLEEP usleep(10000)
+#define LINUX_REST usleep(40000)
+#define LINUX_DREAMLAND sleep(5)
+#endif
+
+#ifdef MACOSX
+#define LINUX_SLEEP usleep(10000)
+#define LINUX_REST usleep(40000)
+#define LINUX_DREAMLAND sleep(5)
+#endif
+
+#ifdef WIN32
+#include <windows.h>
+#include <winbase.h>
+#define LINUX_SLEEP Sleep(10)
+#define LINUX_REST Sleep(40)
+#define LINUX_DREAMLAND Sleep(500)
+#endif
+
+using namespace std;
+
+// place to save config and save games
+#ifdef WIN32
+#define HOME_DIR "AppData"
+#endif
+#ifdef LINUX
+#define HOME_DIR "HOME"
+#endif
+#ifdef MACOSX
+#define HOME_DIR "HOME"
+#endif
+
+#ifndef	DATA_DIR
+#define DATA_DIR "."
+#endif
+#define SCREEN_WIDTH	800
+#define SCREEN_HEIGHT	600
+#define HALF_WIDTH	(SCREEN_WIDTH/2)
+#define HALF_HEIGHT	(SCREEN_HEIGHT/2)
+#define	STUFF_BAR_WIDTH		400
+#define	STUFF_BAR_HEIGHT	35
+
+#define	GFILE_KEY	0x14233241
+
+#define	FRAMES_PER_SECOND	60
+#ifndef PI
+#define PI 3.1415926535897932384626433832795029L
+#endif // PI
+// #define PI 3.14
+#define MAXUPDATES 256 // This one needs to be watched! If the display goes bye bye, reduce the value!
+#define MAX_OVERSHOOT 10000
+#define ABSDISTANCE(x1,y1,x2,y2) abs((int)sqrt((long double)pow(((long double)x2) - ((long double)x1), 2) + (long double)pow(((long double)y2) - ((long double)y1), 2)))
+#define FABSDISTANCE(x1,y1,x2,y2) fabs(sqrt((long double)pow(((long double)x2) - ((long double)x1), 2) + (long double)pow(((long double)y2) - ((long double)y1), 2)))
+#define MAXPLAYERS 10
+#define MAX_POWER  2000
+#define MAX_OBJECTS 400
+#define	MAX_ROUNDS 1000
+#define TANKHEIGHT 20
+#define TANKWIDTH 15
+#define GUNLENGTH 16
+#define MENUHEIGHT 30
+#define SKIES 8
+#define LANDS 8
+#define ALL_SKIES 16
+#define ALL_LANDS 16
+#define	BALLISTICS 52
+#define	BEAMWEAPONS 3
+#define WEAPONS (BALLISTICS + BEAMWEAPONS)
+#define ITEMS 24
+#define THINGS (WEAPONS + ITEMS)
+#define	NATURALS 6
+#define RADII 6
+#define MAXRADIUS 200
+#define BUTTONFRAMES 2
+#define EXPLODEFRAMES 18
+#define	DISPERSEFRAMES 10
+#define	EXPLOSIONFRAMES	(EXPLODEFRAMES + DISPERSEFRAMES)
+#define TANKSAG 10
+#define MENUBUTTONS 7
+#define MISSILEFRAMES 1
+#define ACHANGE 256/360
+#define INGAMEBUTTONS 4
+#define MAX_MISSILES 10
+#define SPREAD 10
+#define SHIELDS 6
+#define WEAPONSOUNDS 4
+#define NAME_LENGTH 24
+#define ADDRESS_LENGTH 16
+
+//Score coeficients
+
+#define SCORE_DESTROY_UNIT_BONUS	5000
+#define SCORE_UNIT_SELF_DESTROY		0
+#define SCORE_HIT_UNIT			50
+#define SCORE_SELF_HIT			0
+
+//Wind
+#define WIND_COEF			0.3
+#define	MAX_WIND			3
+
+
+
+// bitmaps for tanks
+#define NORMAL_TANK 0
+#define CLASSIC_TANK 1     // really 8 in the .dat file
+#define BIGGREY_TANK 2
+#define T34_TANK 3
+#define HEAVY_TANK 4
+#define FUTURE_TANK 5
+#define UFO_TANK 6
+#define SPIDER_TANK 7
+#define BIGFOOT_TANK 8
+
+
+// background images
+#define BACKGROUND_CIRCLE 0
+#define BACKGROUND_LINE 1
+#define BACKGROUND_BLANK 2
+
+#ifdef NEW_GAMELOOP
+#define WAIT_AT_END_OF_ROUND 300
+#else
+#define WAIT_AT_END_OF_ROUND 100
+#endif
+
+// time between volly shots
+#define VOLLY_DELAY 50
+
+
+// defines for teams
+#define TEAM_SITH 0
+#define TEAM_NEUTRAL 1
+#define TEAM_JEDI 2
+
+
+//turns
+enum turnTypes
+{
+  TURN_HIGH, TURN_LOW, TURN_RANDOM, TURN_SIMUL
+};
+
+class BOX
+  {
+  public:
+    int 	x, y, w, h;
+  };
+
+
+typedef struct gradient_struct
+  {
+    RGB	color;
+    float	point;
+  } gradient;
+
+class WEAPON
+  {
+  public:
+    char		name[128];		//name of weapon
+    char		description[512];
+    int             cost;		//$ :))
+    int		amt;		//number of weapons in one buying package
+    double		mass;
+    double		drag;
+    int		radius;        // of the explosion
+    int		sound;
+    int		etime;
+    int		damage;		//damage power
+    int		eframes;
+    int		picpoint;       // which picture do we show in flight?
+    int		spread;         // number of weapons in the shot
+    int		delay;		// volleys etc.
+    int		noimpact;
+    int		techLevel;
+    int		warhead;	// Is it a warhead?
+    int		numSubmunitions;// Number of submunitions
+    int		submunition;	// The next stage
+    double		impartVelocity;	// Impart velocity 0.0-1.0 to subs
+    int		divergence;	// Total angle for submunition spread
+    double		spreadVariation;// Uniform or random distribution
+    //   0-1.0 (0=uniform, 1.0=random)
+    //   divergence at centre of range
+    double		launchSpeed;	// Speed given to submunitions
+    double		speedVariation;	// Uniform or random speed
+    //   0-1.0 (0=uniform, 1.0=random)
+    //   launchSpeed at centre of range
+    int		countdown;	// Set the countdown to this
+    double		countVariation;	// Uniform or random countdown
+    //   0-1.0 (0=uniform, 1.0=random)
+    //   countdown at centre of range
+  };
+
+#define	MAX_ITEMVALS	10
+class ITEM
+  {
+  public:
+    char		name[128];
+    char		description[256];
+    int		cost;
+    int		amt;
+    int		selectable;
+    int		techLevel;
+    int		sound;
+    double		vals[MAX_ITEMVALS];
+  };
+
+
+enum shieldVals
+{
+  SHIELD_ENERGY,
+  SHIELD_REPULSION,
+  SHIELD_RED,
+  SHIELD_GREEN,
+  SHIELD_BLUE,
+  SHIELD_THICKNESS
+};
+enum selfDestructVals
+{
+  SELFD_TYPE,
+  SELFD_NUMBER
+};
+
+enum weaponType
+{
+  SML_MIS, MED_MIS, LRG_MIS, SML_NUKE, NUKE, DTH_HEAD,
+  SML_SPREAD, MED_SPREAD, LRG_SPREAD, SUP_SPREAD, DTH_SPREAD, ARMAGEDDON,
+  CHAIN_MISSILE, CHAIN_GUN, JACK_HAMMER,
+  SHAPED_CHARGE, WIDE_BOY, CUTTER,
+  SML_ROLLER, LRG_ROLLER, DTH_ROLLER,
+  SMALL_MIRV,
+  ARMOUR_PIERCING,
+  CLUSTER, SUP_CLUSTER,
+  FUNKY_BOMB, FUNKY_DEATH,
+  FUNKY_BOMBLET, FUNKY_DEATHLET,
+  BOMBLET, SUP_BOMBLET,
+  BURROWER, PENETRATOR,
+  SML_NAPALM, MED_NAPALM, LRG_NAPALM,
+  NAPALM_JELLY,
+  DRILLER,
+  TREMOR, SHOCKWAVE, TECTONIC,
+  RIOT_BOMB, HVY_RIOT_BOMB,
+  RIOT_CHARGE, RIOT_BLAST,
+  DIRT_BALL, LRG_DIRT_BALL, SUP_DIRT_BALL,
+  SMALL_DIRT_SPREAD,
+  CLUSTER_MIRV,
+  PERCENT_BOMB,
+  REDUCER,
+  SML_LAZER, MED_LAZER, LRG_LAZER, 
+  SML_METEOR, MED_METEOR, LRG_METEOR,
+  SML_LIGHTNING, MED_LIGHTNING, LRG_LIGHTNING
+};
+
+// #define LAST_EXPLOSIVE	NAPALM_JELLY
+#define LAST_EXPLOSIVE DRILLER
+
+#define ITEM_NO_SHIELD			-1
+enum itemType
+{
+  ITEM_TELEPORT,
+  ITEM_SWAPPER,
+  ITEM_MASS_TELEPORT,
+  ITEM_FAN,
+  ITEM_VENGEANCE,
+  ITEM_DYING_WRATH,
+  ITEM_FATAL_FURY,
+  ITEM_LGT_SHIELD,
+  ITEM_MED_SHIELD,
+  ITEM_HVY_SHIELD,
+  ITEM_LGT_REPULSOR_SHIELD,
+  ITEM_MED_REPULSOR_SHIELD,
+  ITEM_HVY_REPULSOR_SHIELD,
+  ITEM_ARMOUR,
+  ITEM_PLASTEEL,
+  ITEM_INTENSITY_AMP,
+  ITEM_VIOLENT_FORCE,
+  ITEM_SLICKP,
+  ITEM_DIMPLEP,
+  ITEM_PARACHUTE,
+  ITEM_REPAIRKIT,
+  ITEM_FUEL,
+  ITEM_ROCKET,
+  ITEM_SDI
+};
+
+#define SHIELD_COUNT		6
+
+//signals
+#define	SIG_QUIT_GAME		-1
+#define SIG_OK			0
+#define GLOBAL_COMMAND_QUIT		-1
+#define GLOBAL_COMMAND_MENU		0
+#define GLOBAL_COMMAND_OPTIONS		 1
+#define GLOBAL_COMMAND_PLAYERS		 2
+#define GLOBAL_COMMAND_CREDITS		 3
+#define	GLOBAL_COMMAND_HELP		     4
+#define GLOBAL_COMMAND_PLAY        5
+#define GLOBAL_COMMAND_DEMO        6
+#define GLOBAL_COMMAND_NETWORK     7
+
+
+// Classes
+#define	ANY_CLASS		-1
+#define	VIRTUAL_OBJECT_CLASS	0
+#define	FLOATTEXT_CLASS		1
+#define	PHYSICAL_OBJECT_CLASS	2
+#define	MISSILE_CLASS		3
+#define	TANK_CLASS		4
+#define	EXPLOSION_CLASS		5
+#define	TELEPORT_CLASS		6
+#define	BEAM_CLASS		7
+#define	DECOR_CLASS		8
+
+
+typedef struct
+  {
+    // DATAFILE	*M, *T, *TITLE, *S, *E, *B, *L,
+    // *TG, *MI, *STOCK_IMAGE;
+
+    BITMAP		*sky_gradient_strips[ALL_SKIES];
+    BITMAP		*land_gradient_strips[ALL_LANDS];
+    // BITMAP		*circle_gradient_strip;
+    BITMAP		*stuff_bar_gradient_strip;
+    BITMAP		*topbar_gradient_strip;
+    BITMAP		*explosion_gradient_strip;
+    BITMAP		*stuff_bar[2];
+    BITMAP		*stuff_icon_base;
+    // BITMAP		*circlesBG;
+    BITMAP		*topbar;
+    BITMAP		*explosions[EXPLOSIONFRAMES];
+    BITMAP		*flameFront[EXPLOSIONFRAMES];
+  } gfxDataStruct;
+
+
+
+class GLOBALDATA;
+class ENVIRONMENT;
+int drawFracture (GLOBALDATA *global, ENVIRONMENT *env, BITMAP *dest, BOX *updateArea, int x, int y, int angle, int width, int segmentLength, int maxRecurse, int recurseDepth);
+int setSlideColumnDimensions (GLOBALDATA *global, ENVIRONMENT *env, int x, bool reset);
+double Noise (int x);
+double Noise2D (int x, int y);
+double interpolate (double x1, double x2, double i);
+double perlin1DPoint (double amplitude, double scale, double xo, double lambda, int octaves);
+double perlin2DPoint (double amplitude, double scale, double xo, double yo, double lambda, int octaves);
+
+void quickChange (GLOBALDATA *global, BITMAP *target) ;
+void change(GLOBALDATA *global, BITMAP *target);
+
+int checkPixelsBetweenTwoPoints (GLOBALDATA *global, ENVIRONMENT *env, double *startX, double *startY, double endX, double endY);
+long int calcTotalPotentialDamage (int weapNum);
+long int calcTotalEffectiveDamage (int weapNum);
+
+void close_button_handler(void);
+
+void doLaunch(GLOBALDATA *gd, ENVIRONMENT *env);
+
+#define GENSKY_DETAILED		1
+#define GENSKY_DITHERGRAD	2
+void generate_sky (GLOBALDATA *global, BITMAP* bmp, const gradient* grad, int flags ) ;
+
+// load all game settings
+bool Load_Game_Settings(GLOBALDATA *global, ENVIRONMENT *env, char *text_file) _WARNUNUSED;
+bool loadPlayers(GLOBALDATA *global, ENVIRONMENT *env, ifstream &ifsFile) _WARNUNUSED;
+// save all game settings
+bool Save_Game_Settings(GLOBALDATA *global, ENVIRONMENT *env, char *text_file, bool bIsSaveGame = false) _WARNUNUSED;
+bool savePlayers (GLOBALDATA *global, ofstream &ofsFile) _WARNUNUSED;
+int Save_Game_Settings_Text(GLOBALDATA *global, ENVIRONMENT *env, char *path_to_file);
+
+// These defines are needed to identify parts of the binary save files.
+#define FILEPART_ENVIRON "[Environment]"
+#define FILEPART_GLOBALS "[Global]"
+#define FILEPART_PLAYERS "[Players]"
+#define FILEPART_ENDSECT "[EndSection]"
+#define FILEPART_ENDPLYR "[EndPlayer]"
+#define FILEPART_ENDFILE "[EndFile]"
+
+// methods to handle loading and saving of data
+
+/*  --- take data out of filestream -- */
+bool popColo(int    &aData, ifstream &ifsFile) _WARNUNUSED;
+bool popData(int    &aData, ifstream &ifsFile) _WARNUNUSED;
+bool popData(double &aData, ifstream &ifsFile) _WARNUNUSED;
+bool popData(char  * aArea, bool &aIsData, ifstream &ifsFile) _WARNUNUSED;
+//bool popData( const char  * aArea, int    &aData, ifstream &ifsFile) _WARNUNUSED;
+//bool popData( const char  * aArea, double &aData, ifstream &ifsFile) _WARNUNUSED;
+//bool popData(char * aArea, double &aData, ifstream &ifsFile) _WARNUNUSED;
+
+/*  --- put data into filestream -- */
+//bool pushData(const int     aData, ofstream &ofsFile) _WARNUNUSED;
+//bool pushData(const double  aData, ofstream &ofsFile) _WARNUNUSED;
+bool pushColo(const char  * aArea, const int    aData, ofstream &ofsFile) _WARNUNUSED;
+bool pushData(const char  * aData, ofstream &ofsFile) _WARNUNUSED;
+bool pushData(const char  * aArea, const int    aData, ofstream &ofsFile) _WARNUNUSED;
+//bool pushName(const char  * aData, ofstream &ofsFile) _WARNUNUSED; // Special function for name saving
+bool pushData(const char  * aArea, const double aData, ofstream &ofsFile) _WARNUNUSED;
+
+/*  --- seek specific data within filestream -- */
+//bool seekData(const int     aData, ifstream &ifsFile) _WARNUNUSED;
+//bool seekData(const char  * aData, ifstream &ifsFile) _WARNUNUSED;
+
+// handle changes to global settings
+int Change_Settings(double old_mouse, double old_sound, double new_mouse, double new_sound, void *mouse_image);
+
+int *Sort_Scores(GLOBALDATA *global);
+int Game_Client(GLOBALDATA *global, ENVIRONMENT *env, int socket_number);
+
+#include "externs.h"
+
+#endif
+
diff --git a/src/menu.h b/src/menu.h
new file mode 100644
index 0000000..2f5bf24
--- /dev/null
+++ b/src/menu.h
@@ -0,0 +1,69 @@
+#ifndef	MENU_HEADER
+#define	MENU_HEADER
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+#include "globaldata.h"
+
+
+#define PLAY_GAME 1
+#define LOAD_GAME 2
+#define ESC_MENU 3
+
+#define TEXT_BOX_LENGTH 14
+
+
+enum	menuEntryType
+{
+  OPTION_MENUTYPE, OPTION_DOUBLETYPE, OPTION_TOGGLETYPE, OPTION_SPECIALTYPE, OPTION_ACTIONTYPE, OPTION_TEXTTYPE, OPTION_COLORTYPE
+};
+typedef struct
+  {
+    const char	*name;
+    int	(*displayFunc) (ENVIRONMENT*, int, int, void*);
+    int	color;
+    double	*value;
+    void	*data;
+    const char	*format;
+    double	min, max;
+    double	increment;
+    double	defaultv;
+    char	**specialOpts;
+    char	type;
+    int	viewonly;
+    int	x;
+    int	y;
+  } MENUENTRY;
+
+typedef struct
+  {
+    const char *title;
+    int numEntries;
+    MENUENTRY *entries;
+    int quitButton;
+    int okayButton;
+  } MENUDESC;
+
+
+// Set the menus to appear in English or Portugese
+void Select_Menu_Language(GLOBALDATA *global);
+
+int options (GLOBALDATA *global, ENVIRONMENT *env, MENUDESC *menu);
+
+#endif
diff --git a/src/menucontent.h b/src/menucontent.h
new file mode 100644
index 0000000..f3e93cf
--- /dev/null
+++ b/src/menucontent.h
@@ -0,0 +1,852 @@
+#ifndef MENUCONTENT_HEADER_
+#define MENUCONTENT_HEADER_
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+char *onOffText[2] = { "Off", "On"};
+char *onOffRandomText[3] = { "Off", "On", "Random"};
+char *landSlideText[5] = { "None", "Tank Only", "Instant", "Gravity", "Cartoon"};
+char *wallTypeText[5] = { "Rubber", "Steel", "Spring", "Wrap", "Random"};
+char *mouseText[2] = { "Custom", "Default"};
+char *meteorText[4] = { "Off", "Light", "Heavy", "Lethal"};
+char *lightningText[4] = { "Off", "Weak", "Energetic", "Violent"};
+char *laserSatelliteText[4] = { "Off", "Weak", "Strong", "Super"};
+char *languageText[8] = { "English", "Português", "Français", "Deutsch", "Slovak", "Russian", "Spanish", "Italian"};
+char *colourText[2] = { "Regular", "Crispy"};
+char *landTypeText[8] = { "Random", "Canyons", "Mountains", "Valleys", "Hills", "Foothills", "Plains", "None" };
+char *turnTypeText[4] = { "High+", "Low+", "Random", "Simul" };
+char *skipTypeText[2] = { "Off", "Humans Dead"};
+char *soundDriver[6] = { "Auto Detect", "OSS", "ESD", "ARTS", "ALSA", "JACK" };
+
+// portuege version
+char *onOffText_ptbr[2] = { "Desligado", "Ligado"};
+/*translate*/
+char *onOffRandomText_ptbr[3] = { "Desligado", "Ligado", "Aleatório"};
+char *landSlideText_ptbr[5] = { "Nenhum", "Tanque Somente", "Instantâneo", "Gravidade", "Cartoon"};
+char *wallTypeText_ptbr[5] = { "Elástico", "Aço", "Mola", "Envoltório", "Aleatório"};
+char *mouseText_ptbr[2] = { "Personalizado", "Padrão"};
+char *meteorText_ptbr[4] = { "Desligado", "Fraco", "Forte", "Letal"};
+char *lightningText_ptbr[4] = { "Desligado", "Fraco", "Energético", "Violento"};
+char *laserSatelliteText_ptbr[4] = { "Desligado", "Fraco", "Forte", "Super"};
+char *languageText_ptbr[8] = { "English", "Português", "Français", "Deutsch", "Slovak", "Russian", "Spanish", "Italian"};
+char *colourText_ptbr[2] = { "Regular", "Crispy"};
+char *landTypeText_ptbr[8] = { "Aleatório", "Canyons", "Montanhas", "Vales", "Colinas", "Morros", "Planos", "Nenhum" };
+char *turnTypeText_ptbr[4] = { "Melhores+", "Piores+", "Aleatório", "Simular" };
+char *skipTypeText_ptbr[2] = { "Sim", "Não" };
+
+
+// french version
+char *onOffText_fr[2] = { "Non", "Oui"};
+/*translate*/
+char *onOffRandomText_fr[3] = { "Non", "Oui", "Hasard"};
+char *landSlideText_fr[5] = { "Aucun", "Réservoir Seulement", "Instantané", "Gravité", "Dessin animé"};
+char *wallTypeText_fr[5] = { "Elastique", "Acier", "Mou", "Enveloppe", "Aléatoire"};
+char *mouseText_fr[2] = { "Pesonnel", "Défaut"};
+char *meteorText_fr[4] = { "Off", "Light", "Heavy", "Lethal"};
+char *lightningText_fr[4] = { "Aucun", "Faible", "Energique", "Violent"};
+char *laserSatelliteText_fr[4] = { "Aucun", "Faible", "Fort", "Super"};
+char *languageText_fr[8] = { "English", "Português", "Français", "Deutsch", "Slovak", "Russian", "Spanish", "Italian"};
+char *colourText_fr[2] = { "Régulier", "Croustillant"};
+char *landTypeText_fr[8] = { "Aléatoire", "Canyons", "Montagnes", "Vallées", "Collines", "Contreforts", "Plaines", "Aucun" };
+char *turnTypeText_fr[4] = { "Haut", "Bas", "Aléatoire", "Similaire" };
+char *skipTypeText_fr[2] = { "Oui", "Non"};
+
+
+// german version
+char *onOffText_de[2] = { "Aus", "An"};
+char *onOffRandomText_de[3] = { "Aus", "An", "Zufällig"};
+char *landSlideText_de[5] = { "Keine", "Nur Panzer", "Sofort", "Schwerkraft", "Cartoon"};
+char *wallTypeText_de[5] = { "Gummi", "Stahl", "Federnd", "Verbunden", "Zufällig"};
+char *mouseText_de[2] = { "Angepasst", "Standard"};
+char *meteorText_de[4] = { "Aus", "Leicht", "Schwer", "Tödlich"};
+char *lightningText_de[4] = { "Aus", "Schwach", "Stark", "Brutal"};
+char *laserSatelliteText_de[4] = { "Aus", "Schwach", "Stark", "Super"};
+char *languageText_de[8] = { "English", "Português", "Français", "Deutsch", "Slovak", "Russian", "Spanish", "Italian"};
+char *colourText_de[2] = { "Normal", "Kontrastreich"};
+char *landTypeText_de[8] = { "Zufällig", "Canyons", "Berge", "Täler", "Hügel", "Flache Hügel", "Ebene", "Nichts" };
+char *turnTypeText_de[4] = { "Hoch+", "Niedrig+", "Zufällig", "Simul" };
+char *skipTypeText_de[2] = { "Aus", "An"};
+
+// slovak version
+char *onOffText_sk[2] = { "Vypnuté", "Zapnuté"};
+char *onOffRandomText_sk[3] = { "Vypnutý", "Zapnutý", "Náhodný"};
+char *landSlideText_sk[5] = { "Žiaden", "Iba tank", "Okamžitý", "Gravitácia", "Kresl.film"};
+char *wallTypeText_sk[5] = { "Guma", "Oceľ", "Pružina", "Prikrývka", "Náhodný"};
+char *mouseText_sk[2] = { "Vlastné", "Východzie"};
+char *meteorText_sk[4] = { "Vypnuté", "Ľahké", "Ťažké", "Smrteľné"};
+char *lightningText_sk[4] = { "Vypnuté", "Slabé", "Energetické", "Kruté"};
+char *laserSatelliteText_sk[4] = { "Vypnutý", "Slabý", "Silný", "Super"};
+char *languageText_sk[8] = { "Anglicky", "Portugalsky", "Francúzsky", "Nemecky", "Slovensky", "Rusky", "Spanish", "Italian"};
+char *colourText_sk[2] = { "Normálna", "Svieža"};
+char *landTypeText_sk[8] = { "Náhodná", "Kaňony", "Hory", "Údolia", "Kopce", "Úpätia", "Nížiny", "Žiadna" };
+char *turnTypeText_sk[4] = { "Vysoký+", "Nízky+", "Náhodný", "Simul" };
+char *skipTypeText_sk[2] = { "Vypnuté", "Smrť ľudí"};
+
+// Russian version
+char *onOffText_ru[2] = { "Выкл.", "Вкл."};
+char *onOffRandomText_ru[3] = { "Выкл.", "Вкл.", "Случайно"};
+char *landSlideText_ru[5] = { "Выкл.", "Только танки", "Сразу же", "По умолчанию", "Как в мультиках"};
+char *wallTypeText_ru[5] = { "Резиновые", "Непробиваемые", "Пружинящие", "Бесконечность", "Случайные"};
+char *mouseText_ru[2] = { "Собственный", "По умолчанию"};
+char *meteorText_ru[4] = { "Нет", "Слабый", "Сильный", "Смертельный"};
+char *lightningText_ru[4] = { "Нет", "Слабые", "Сильные", "Мощные"};
+char *laserSatelliteText_ru[4] = { "Нет", "Слабые", "Сильные", "Супер!!"};
+char *languageText_ru[8] = { "English", "Português", "Français", "Deutsch", "Slovak", "Русский", "Spanish", "Italian"};
+char *colourText_ru[2] = { "Обычная", "Четкая"};
+char *landTypeText_ru[8] = { "Случайный", "Каньоны", "Горы", "Возвышенность", "Холмы", "Предгорья", "Равнины", "Выкл." };
+char *turnTypeText_ru[4] = { "Сильные +", "Слабые +", "Случайно", "Все сразу" };
+char *skipTypeText_ru[2] = { "Выкл.", "Вкл."};
+
+
+
+
+// declare variables
+MENUDESC mainMenu;
+
+if ( (global->language == LANGUAGE_ENGLISH) || (global->language == LANGUAGE_SPANISH) || (global->language == LANGUAGE_ITALIAN) )
+  {
+    MENUENTRY physicsOpts[8] =
+    {
+      { "Gravity", NULL, WHITE, &env->gravity, NULL, "%2.3f", .025, .325, 0.025, .075, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 80},
+      { "Viscosity", NULL, WHITE, &env->viscosity, NULL, "%2.2f", .25, 2.0, 0.25, 1.0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 60},
+      { "Land Slide", NULL, WHITE, &env->landSlideType, NULL, "%s", 0, 4, 1, 3, landSlideText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 40},
+      { "Land Slide Delay", NULL, WHITE, &env->landSlideDelay, NULL, "%4.0f", 1, 5, 1, 3, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 20},
+      { "Wall Type", NULL, WHITE, &env->wallType, NULL, "%s", 0, 4, 1, 1, wallTypeText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight},
+      { "Boxed Mode", NULL, WHITE, &env->dBoxedMode, NULL, "%s", 0, 2, 1, 0, onOffRandomText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 20},
+      { "Violent Death", NULL, WHITE, &global->violent_death, NULL, "%s", 0, 3, 1, 0, lightningText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 40},
+      { "Timed Shots", NULL, WHITE, &global->max_fire_time, NULL, "%3.0f", 0, 180, 5, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 60}
+    };
+    MENUDESC physicsMenu = { "Physics", 8, physicsOpts, TRUE, FALSE};
+
+    MENUENTRY weatherOpts[7] =
+    {
+      { "Meteor Showers", NULL, WHITE, &env->meteors, NULL, "%s", 0, 3, 1, 0, meteorText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Lightning", NULL, WHITE, &env->lightning, NULL, "%s", 0, 3, 1, 0, lightningText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Falling Dirt", NULL, WHITE, &env->falling_dirt_balls, NULL, "%s", 0, 3, 1, 0, meteorText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Laser Satellite", NULL, WHITE, &env->satellite, NULL, "%s", 0, 3, 1, 0, laserSatelliteText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Fog", NULL, WHITE, &env->fog, NULL, "%s", 0, 1, 1, 0, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Max Wind Strength", NULL, WHITE, (double*)&env->windstrength, NULL, "%2.0f", 0, 100, 5, 40, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Wind Variation", NULL, WHITE, (double*)&env->windvariation, NULL, "%2.1f", 0, 100, 3, 10, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+    };
+    MENUDESC weatherMenu = { "Weather", 7, weatherOpts, TRUE, FALSE};
+
+
+    MENUENTRY soundOpts[3] =
+    {
+      { "All Sound", NULL, WHITE, &global->sound, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Sound Driver", NULL, WHITE, &global->sound_driver, NULL, "%s", 0, 5, 1, 0, soundDriver, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Music", NULL, WHITE, &global->play_music, NULL, "%s", 0, 1, 1, 0, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28}
+    };
+   MENUDESC soundMenu = { "Sound", 3, soundOpts, TRUE, FALSE};
+
+
+    MENUENTRY graphicsOpts[12] =
+    {
+      { "Full Screen", NULL, WHITE, &global->full_screen, NULL, "%s", 0, 1, 1, 0, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 108},
+      { "Dithering", NULL, WHITE, &global->ditherGradients, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 88},
+      { "Detailed Land", NULL, WHITE, &global->detailedLandscape, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Detailed Sky", NULL, WHITE, &global->detailedSky, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Fading Text", NULL, WHITE, &env->dFadingText, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Shadowed Text", NULL, WHITE, &env->dShadowedText, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Colour Theme", NULL, WHITE, &global->colour_theme, NULL, "%s", 0, 1, 1, 1, colourText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Screen Width", NULL, WHITE, &global->temp_screenWidth, NULL, "%4.0f", 800, 1600, 200, 800, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Screen Height", NULL, WHITE, &global->temp_screenHeight, NULL, "%4.0f", 600, 1200, 200, 600, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Mouse Pointer", NULL, WHITE, &global->os_mouse, NULL, "%s", 0, 1, 1, 1, mouseText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 1, global->halfHeight + 72},
+      { "Game Speed", NULL, WHITE, &global->frames_per_second, NULL, "%3.0f", 30, 120, 5, 60, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "Custom Background", NULL, WHITE, &env->custom_background, NULL, "%s", 0, 1, 1, 0, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+    };
+    MENUDESC graphicsMenu = { "Graphics", 12, graphicsOpts, TRUE, FALSE};
+
+    MENUENTRY financeOpts[9] =
+    {
+      { "Starting Money", NULL, WHITE, (double*)&global->startmoney, NULL, "%2.0f", 0, 200000, 5000, 20000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Interest Rate", NULL, WHITE, (double*)&global->interest, NULL, "%2.2f", 1.0, 1.5, 0.05, 1.25, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Round Win Bonus", NULL, WHITE, (double*)&global->scoreRoundWinBonus, NULL, "%2.0f", 0, 50000, 5000, 10000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Damage Bounty", NULL, WHITE, (double*)&global->scoreHitUnit, NULL, "%2.0f", 0, 500, 25, 75, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Self-Damage Penalty", NULL, WHITE, (double*)&global->scoreSelfHit, NULL, "%2.0f", 0, 10000, 1000, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Tank Destruction Bonus", NULL, WHITE, (double*)&global->scoreUnitDestroyBonus, NULL, "%2.0f", 0, 20000, 2500, 5000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Tank Self-Destruction Penalty", NULL, WHITE, (double*)&global->scoreUnitSelfDestroy, NULL, "%2.0f", 0, 20000, 2500, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 72},
+      { "Item Sell Multiplier", NULL, WHITE, (double*)&global->sellpercent, NULL, "%1.2f", 0.0, 1.0, 0.10, 0.80, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth -3, global->halfHeight + 92},
+      { "Teams Share", NULL, WHITE, (double *) &global->divide_money, NULL, "%s", 0.0, 1.0, 1.0, 0.0, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+    };
+    MENUDESC financeMenu = { "Money", 9, financeOpts, TRUE, FALSE};
+
+    MENUENTRY networkOpts[5] =
+    {
+       {  "Check Updates", NULL, WHITE, (double*) &global->check_for_updates, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+       {  "Networking", NULL, WHITE, (double*) &global->enable_network, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+       {  "Listen Port", NULL, WHITE, (double*) &global->listen_port, NULL, "%5.0f", 10645, 64645, 1000, 25645, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+       {  "Server address", NULL, WHITE, (double *) &(global->server_name), NULL, "%s", 0, 0, 0, 0, NULL, OPTION_TEXTTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12 },
+       { "Server port", NULL, WHITE, (double *) &(global->server_port), NULL, "%s", 0, 0, 0, 0, NULL, OPTION_TEXTTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32}
+    };
+    MENUDESC networkMenu = { "Network", 5, networkOpts, TRUE, FALSE};
+
+    void *pPhysicsMenu  =       &physicsMenu;
+    void *pWeatherMenu  =       &weatherMenu;
+    void *pGraphicsMenu =       &graphicsMenu;
+    void *pFinanceMenu  =       &financeMenu;
+    void *pnetworkMenu =        &networkMenu;
+    void *pSoundMenu   =        &soundMenu;
+
+    MENUENTRY mainOpts[12] =
+    {
+      { "Physics", NULL, WHITE, (double*)pPhysicsMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 88},
+      { "Weather", NULL, WHITE, (double*)pWeatherMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Graphics", NULL, WHITE, (double*)pGraphicsMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Money", NULL, WHITE, (double*)pFinanceMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Network", NULL, WHITE, (double*)pnetworkMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Sound", NULL, WHITE, (double*) pSoundMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Weapon Tech Level", NULL, WHITE, (double*)&env->weapontechLevel, NULL, "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Item Tech Level", NULL, WHITE, (double *) &env->itemtechLevel, NULL, "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Landscape", NULL, WHITE, (double*)&env->landType, NULL, "%s", 0, 7, 1, LANDTYPE_HILLS, landTypeText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 72},
+      { "Turn Order", NULL, WHITE, (double*)&global->turntype, NULL, "%s", 0, 3, 1, TURN_RANDOM, turnTypeText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "Skip AI-only play", NULL, WHITE, &global->skipComputerPlay, NULL, "%s", 0, 1, 1, 1, skipTypeText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112},
+      { "Language", NULL, WHITE, &global->language, NULL, "%s", 0, 7, 1, 0, languageText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 132}
+    };
+// mainMenu = { "Main Menu", 10, mainOpts, TRUE, FALSE};
+    mainMenu.title = "Main Menu";
+    mainMenu.numEntries = 12;
+    mainMenu.entries = mainOpts;
+    mainMenu.quitButton = TRUE;
+    mainMenu.okayButton = FALSE;
+
+  }  // end of English
+
+if (global->language == LANGUAGE_PORTUGUESE)  // Portuguese
+  {
+    MENUENTRY physicsOpts[8] =
+    {
+      { "Gravidade", NULL, WHITE, &env->gravity, NULL, "%2.3f", .025, .325, 0.025, .075, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 80},
+      { "Viscosidade", NULL, WHITE, &env->viscosity, NULL, "%2.2f", .25, 2.0, 0.25, 1.0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 60},
+      { "Deslizamento de Terra", NULL, WHITE, &env->landSlideType, NULL, "%s", 0, 4, 1, 3, landSlideText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 40},
+      { "Corrediça da terra atrasa", NULL, WHITE, &env->landSlideDelay, NULL, "%4.0f", 1, 5, 1, 3, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 20},
+      { "Tipo de Parede", NULL, WHITE, &env->wallType, NULL, "%s", 0, 4, 1, 1, wallTypeText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight},
+      { "Modalidade encaixotada", NULL, WHITE, &env->dBoxedMode, NULL, "%s", 0, 2, 1, 0, onOffRandomText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 20},
+      { "Morte violenta", NULL, WHITE, &global->violent_death, NULL, "%s", 0, 3, 1, 0, lightningText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 40},
+      { "Tiro programado", NULL, WHITE, &global->max_fire_time, NULL, "%3.0f", 0, 180, 5, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 60}
+
+    };
+    MENUDESC physicsMenu = { "Física", 7, physicsOpts, TRUE, FALSE};
+
+    MENUENTRY weatherOpts[7] =
+    {
+      { "Chuvas de Meteoro", NULL, WHITE, &env->meteors, NULL, "%s", 0, 3, 1,
+        0, meteorText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3,
+        global->halfHeight - 68},
+      { "Relâmpagos", NULL, WHITE, &env->lightning, NULL, "%s", 0, 3, 1, 0,
+        lightningText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3,
+        global->halfHeight - 48},
+      { "Sujeira de queda", NULL, WHITE, &env->falling_dirt_balls, NULL, "%s", 0, 3, 1, 0, meteorText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Satélite do Laser", NULL, WHITE, &env->satellite, NULL, "%s", 0, 3, 1, 0,
+        laserSatelliteText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3,
+        global->halfHeight - 8},
+      { "Neblina", NULL, WHITE, &env->fog, NULL, "%s", 0, 1, 1,
+        0, onOffText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3,
+        global->halfHeight + 12},
+      { "Velocidade Max do Vento", NULL, WHITE, (double*)&env->windstrength,
+        NULL, "%2.0f", 0, 100, 5, 40, NULL, OPTION_DOUBLETYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight + 32 },
+      { "Variação do Vento", NULL, WHITE, (double*)&env->windvariation,
+        NULL, "%2.1f", 0, 100, 3, 10, NULL, OPTION_DOUBLETYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight + 52},
+    };
+    MENUDESC weatherMenu = { "Condições Meteorológicas", 7, weatherOpts,
+                             TRUE, FALSE
+                           };
+
+    MENUENTRY soundOpts[3] =
+    {
+      { "Efeitos de Som", NULL, WHITE, &global->sound, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Sistema de Som", NULL, WHITE, &global->sound_driver, NULL, "%s", 0, 5, 1, 0, soundDriver, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Música", NULL, WHITE, &global->play_music, NULL, "%s", 0, 1, 1, 0, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28}
+    };
+   MENUDESC soundMenu = { "Som", 3, soundOpts, TRUE, FALSE};
+
+
+    MENUENTRY graphicsOpts[12] =
+    {
+      { "Tela Cheia", NULL, WHITE, &global->full_screen, NULL, "%s", 0, 1, 1, 0, onOffText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 108},
+      { "Pontilhamento", NULL, WHITE, &global->ditherGradients, NULL, "%s",
+        0, 1, 1, 1, onOffText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3,
+        global->halfHeight - 88},
+      { "Detalhes do Terreno", NULL, WHITE, &global->detailedLandscape, NULL,
+        "%s", 0, 1, 1, 1, onOffText_ptbr, OPTION_SPECIALTYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight - 68},
+      { "Detalhes do Céu", NULL, WHITE, &global->detailedSky, NULL, "%s", 0,
+        1, 1, 1, onOffText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3,
+        global->halfHeight - 48},
+      { "texto sombreado", NULL, WHITE, &env->dFadingText, NULL, "%s", 0, 1, 1, 1, onOffText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "texto de desvanecimento", NULL, WHITE, &env->dShadowedText, NULL, "%s", 0, 1, 1, 1, onOffText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "tema da cor", NULL, WHITE, &global->colour_theme, NULL, "%s", 0, 1, 1, 1, colourText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+
+      { "Largura da Tela", NULL, WHITE, &global->temp_screenWidth,
+        NULL, "%4.0f", 800, 1600, 200, 800, NULL, OPTION_DOUBLETYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight + 32 },
+      { "Altura da Tela", NULL, WHITE, &global->temp_screenHeight,
+        NULL, "%4.0f", 600, 1200, 200, 600, NULL, OPTION_DOUBLETYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight + 52},
+      { "Ponteiro do Rato", NULL, WHITE, &global->os_mouse, NULL,
+        "%s", 0, 1, 1, 1, mouseText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth
+        - 1, global->halfHeight + 72},
+      { "Velocidade do jogo", NULL, WHITE, &global->frames_per_second, NULL, "%3.0f", 30, 120, 5, 60, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "Fundo personalizado", NULL, WHITE, &env->custom_background, NULL, "%s", 0, 1, 1, 0, onOffText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+
+    };
+    MENUDESC graphicsMenu = { "Gráficos", 12, graphicsOpts, TRUE, FALSE};
+
+    MENUENTRY financeOpts[9] =
+    {
+      { "Dinheiro inicial", NULL, WHITE, (double*)&global->startmoney, NULL,
+        "%2.0f", 0, 200000, 5000, 20000, NULL, OPTION_DOUBLETYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight - 68},
+      { "Taxa de Juros", NULL, WHITE, (double*)&global->interest, NULL,
+        "%2.2f", 1.0, 1.5, 0.05, 1.25, NULL, OPTION_DOUBLETYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight - 48},
+      { "Bônus por Vitória", NULL, WHITE,
+        (double*)&global->scoreRoundWinBonus, NULL, "%2.0f", 0, 50000, 5000, 10000, NULL, OPTION_DOUBLETYPE,
+        FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Bônus por Estrago", NULL, WHITE, (double*)&global->scoreHitUnit,
+        NULL, "%2.0f", 0, 500, 25, 75, NULL, OPTION_DOUBLETYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight + 12},
+      { "Penalidade por Auto-Estrago", NULL, WHITE,
+        (double*)&global->scoreSelfHit, NULL, "%2.0f", 0, 10000, 1000, 0, NULL, OPTION_DOUBLETYPE,
+        FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Bônus por Tanque Destruído", NULL, WHITE,
+        (double*)&global->scoreUnitDestroyBonus, NULL, "%2.0f", 0, 20000, 2500, 5000, NULL,
+        OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Penalidade por Auto-Destruição", NULL, WHITE,
+        (double*)&global->scoreUnitSelfDestroy, NULL, "%2.0f", 0, 20000, 2500, 0, NULL,
+        OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 72},
+      { "Multiplicador de Item Vendido", NULL, WHITE,
+        (double*)&global->sellpercent, NULL, "%1.2f", 0.0, 1.0, 0.10, 0.80, NULL, OPTION_DOUBLETYPE,
+        FALSE, global->halfWidth -3, global->halfHeight + 92},
+      { "Parte das equipes", NULL, WHITE, (double *) &global->divide_money, NULL, "%s", 0.0, 1.0, 1.0, 0.0, onOffText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+
+    };
+    MENUDESC financeMenu = { "Dinheiro", 9, financeOpts, TRUE, FALSE};
+
+    MENUENTRY networkOpts[3] =
+    {
+       {  "Procurar actualizações", NULL, WHITE, (double*) &global->check_for_updates, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+       {  "Activar Rede", NULL, WHITE, (double*) &global->enable_network, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+       {  "Número de Porta", NULL, WHITE, (double*) &global->listen_port, NULL, "%5.0f", 10645, 64645, 1000, 25645, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8}
+    };
+    MENUDESC networkMenu = { "Network", 3, networkOpts, TRUE, FALSE};
+
+
+    void *pPhysicsMenu  =       &physicsMenu;
+    void *pWeatherMenu  =       &weatherMenu;
+    void *pGraphicsMenu =       &graphicsMenu;
+    void *pFinanceMenu  =       &financeMenu;
+    void *pnetworkMenu  =       &networkMenu;
+    void *pSoundMenu    =       &soundMenu;
+
+    MENUENTRY mainOpts[12] =
+    {
+      { "Física", NULL, WHITE, (double*)pPhysicsMenu, NULL, NULL, 0, 0, 0,
+        0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3,
+        global->halfHeight - 88},
+      { "Condições Meteorológicas", NULL, WHITE, (double*)pWeatherMenu,
+        NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth -
+        3, global->halfHeight - 68},
+      { "Gráficos", NULL, WHITE, (double*)pGraphicsMenu, NULL, NULL, 0, 0,
+        0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3,
+        global->halfHeight - 48},
+      { "Finanças", NULL, WHITE, (double*)pFinanceMenu, NULL, NULL, 0, 0, 0,
+        0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3,
+        global->halfHeight - 28},
+       { "Rede", NULL, WHITE, (double*)pnetworkMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Som", NULL, WHITE, (double*) pSoundMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Arma Nível Tecnológico", NULL, WHITE, (double*)&env->weapontechLevel, NULL,
+        "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth -
+        3, global->halfHeight + 32},
+      { "Artigo Nível Tecnológico", NULL, WHITE, (double*) &env->itemtechLevel, NULL,
+        "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Cenário", NULL, WHITE, (double*)&env->landType, NULL, "%s", 0, 7,
+        1, LANDTYPE_HILLS, landTypeText_ptbr, OPTION_SPECIALTYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight + 72},
+      { "Ordem de Jogadas", NULL, WHITE, (double*)&global->turntype, NULL,
+        "%s", 0, 3, 1, TURN_RANDOM, turnTypeText_ptbr, OPTION_SPECIALTYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight + 92},
+      { "Continuar o Jogo Só com Robôs", NULL, WHITE, &global->skipComputerPlay,
+        NULL, "%s", 0, 2, 1, 1, skipTypeText_ptbr, OPTION_SPECIALTYPE, FALSE,
+        global->halfWidth - 3, global->halfHeight + 112},
+      { "Língua", NULL, WHITE, &global->language, NULL, "%s", 0, 7, 1, 0, languageText_ptbr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 132}
+
+    };
+// mainMenu = { "Menu Principal", 10, mainOpts, TRUE, FALSE};
+    mainMenu.title = "Menu Principal";
+    mainMenu.numEntries = 12;
+    mainMenu.entries = mainOpts;
+    mainMenu.quitButton = TRUE;
+    mainMenu.okayButton = FALSE;
+
+  }   // end of Portuguese
+
+
+// french
+if (global->language == LANGUAGE_FRENCH)
+  {
+    MENUENTRY physicsOpts[8] =
+    {
+      { "Gravité", NULL, WHITE, &env->gravity, NULL, "%2.3f", .025, .325, 0.025, .075, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 80},
+      { "Viscosité", NULL, WHITE, &env->viscosity, NULL, "%2.2f", .25, 2.0, 0.25, 1.0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 40},
+      { "Glissements de terrain", NULL, WHITE, &env->landSlideType, NULL, "%s", 0, 4, 1, 3, landSlideText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 40},
+      { "Délai glissements de terrain", NULL, WHITE, &env->landSlideDelay, NULL, "%4.0f", 1, 5, 1, 3, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 20},
+      { "Murs", NULL, WHITE, &env->wallType, NULL, "%s", 0, 4, 1, 1, wallTypeText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight},
+      { "Enfermé dans boîte", NULL, WHITE, &env->dBoxedMode, NULL, "%s", 0, 2, 1, 0, onOffRandomText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 20},
+      { "Mort violente", NULL, WHITE, &global->violent_death, NULL, "%s", 0, 3, 1, 0, lightningText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 40},
+      { "Projectile synchronisé", NULL, WHITE, &global->max_fire_time, NULL, "%3.0f", 0, 180, 5, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 60}
+
+    };
+    MENUDESC physicsMenu = { "Physique", 7, physicsOpts, TRUE, FALSE};
+
+    MENUENTRY weatherOpts[7] =
+    {
+      { "Orages de météorites", NULL, WHITE, &env->meteors, NULL, "%s", 0, 3, 1, 0, meteorText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Éclairs", NULL, WHITE, &env->lightning, NULL, "%s", 0, 3, 1, 0, lightningText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Saleté en chute", NULL, WHITE, &env->falling_dirt_balls, NULL, "%s", 0, 3, 1, 0, meteorText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Satellites Laser", NULL, WHITE, &env->satellite, NULL, "%s", 0, 3, 1, 0, laserSatelliteText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Brouillard", NULL, WHITE, &env->fog, NULL, "%s", 0, 1, 1, 0, onOffText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Force maxi du vent", NULL, WHITE, (double*)&env->windstrength, NULL, "%2.0f", 0, 100, 5, 40, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Variation du vent", NULL, WHITE, (double*)&env->windvariation, NULL, "%2.1f", 0, 100, 3, 10, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+    };
+    MENUDESC weatherMenu = { "Météo", 7, weatherOpts, TRUE, FALSE};
+
+    MENUENTRY soundOpts[3] =
+    {
+      { "Effets Sonores", NULL, WHITE, &global->sound, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Système de Son", NULL, WHITE, &global->sound_driver, NULL, "%s", 0, 5, 1, 0, soundDriver, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Musique", NULL, WHITE, &global->play_music, NULL, "%s", 0, 1, 1, 0, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28}
+    };
+   MENUDESC soundMenu = { "Sound", 3, soundOpts, TRUE, FALSE};
+
+
+    MENUENTRY graphicsOpts[12] =
+    {
+      { "Full Screen", NULL, WHITE, &global->full_screen, NULL, "%s", 0, 1, 1, 0, onOffText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 108},
+      { "Tramage", NULL, WHITE, &global->ditherGradients, NULL, "%s", 0, 1, 1, 1, onOffText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 88},
+      { "Détails du terrain", NULL, WHITE, &global->detailedLandscape, NULL, "%s", 0, 1, 1, 1, onOffText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Ciel détaillé", NULL, WHITE, &global->detailedSky, NULL, "%s", 0, 1, 1, 1, onOffText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "texte ombragé", NULL, WHITE, &env->dFadingText, NULL, "%s", 0, 1, 1, 1, onOffText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "texte de effacement", NULL, WHITE, &env->dShadowedText, NULL, "%s", 0, 1, 1, 1, onOffText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Thème de couleurs", NULL, WHITE, &global->colour_theme, NULL, "%s", 0, 1, 1, 1, colourText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Largeur d'écran", NULL, WHITE, &global->temp_screenWidth, NULL, "%4.0f", 800, 1600, 200, 800, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Hauteur d'écran", NULL, WHITE, &global->temp_screenHeight, NULL, "%4.0f", 600, 1200, 200, 600, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Curseur de souris", NULL, WHITE, &global->os_mouse, NULL, "%s", 0, 1, 1, 1, mouseText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 1, global->halfHeight + 72},
+      { "Vitesse du jeu", NULL, WHITE, &global->frames_per_second, NULL, "%3.0f", 30, 120, 5, 60, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "Fond fait sur commande", NULL, WHITE, &env->custom_background, NULL, "%s", 0, 1, 1, 0, onOffText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+    };
+    MENUDESC graphicsMenu = { "Graphismes", 12, graphicsOpts, TRUE, FALSE};
+
+    MENUENTRY financeOpts[9] =
+    {
+      { "Somme de départ", NULL, WHITE, (double*)&global->startmoney, NULL, "%2.0f", 0, 200000, 5000, 20000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Taux d'intérêt", NULL, WHITE, (double*)&global->interest, NULL, "%2.2f", 1.0, 1.5, 0.05, 1.25, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Gains par victoire", NULL, WHITE, (double*)&global->scoreRoundWinBonus, NULL, "%2.0f", 0, 50000, 5000, 10000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Bonus dommages", NULL, WHITE, (double*)&global->scoreHitUnit, NULL, "%2.0f", 0, 500, 25, 75, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Pénalité auto-dommages", NULL, WHITE, (double*)&global->scoreSelfHit, NULL, "%2.0f", 0, 10000, 1000, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Bonus destruction tank", NULL, WHITE, (double*)&global->scoreUnitDestroyBonus, NULL, "%2.0f", 0, 20000, 2500, 5000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Pénalité autodestruction tank", NULL, WHITE, (double*)&global->scoreUnitSelfDestroy, NULL, "%2.0f", 0, 20000, 2500, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 72},
+      { "Coeff. vente item", NULL, WHITE, (double*)&global->sellpercent, NULL, "%1.2f", 0.0, 1.0, 0.10, 0.80, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth -3, global->halfHeight + 92},
+      { "Part d'equipes", NULL, WHITE, (double *) &global->divide_money, NULL, "%s", 0.0, 1.0, 1.0, 0.0, onOffText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+
+    };
+    MENUDESC financeMenu = { "Finances", 9, financeOpts, TRUE, FALSE};
+
+    MENUENTRY networkOpts[3] =
+    {
+       {  "Check Updates", NULL, WHITE, (double*) &global->check_for_updates, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+       {  "Networking", NULL, WHITE, (double*) &global->enable_network, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+       {  "Listen Port", NULL, WHITE, (double*) &global->listen_port, NULL, "%5.0f", 10645, 64645, 1000, 25645, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8}
+    };
+    MENUDESC networkMenu = { "Network", 3, networkOpts, TRUE, FALSE};
+
+
+
+    void *pPhysicsMenu  =       &physicsMenu;
+    void *pWeatherMenu  =       &weatherMenu;
+    void *pGraphicsMenu =       &graphicsMenu;
+    void *pFinanceMenu  =       &financeMenu;
+    void *pnetworkMenu  =       &networkMenu;
+    void *pSoundMenu    =       &soundMenu;
+
+    MENUENTRY mainOpts[12] =
+    {
+      { "Physique", NULL, WHITE, (double*)pPhysicsMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 88},
+      { "Météo", NULL, WHITE, (double*)pWeatherMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Graphismes", NULL, WHITE, (double*)pGraphicsMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Finances", NULL, WHITE, (double*)pFinanceMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Réseau", NULL, WHITE, (double*)pnetworkMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Sound", NULL, WHITE, (double*) pSoundMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Niveau technique armes", NULL, WHITE, (double*)&env->weapontechLevel, NULL, "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Niveau technique équipement", NULL, WHITE, (double *) &env->itemtechLevel, NULL, "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Paysage", NULL, WHITE, (double*)&env->landType, NULL, "%s", 0, 7, 1, LANDTYPE_HILLS, landTypeText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 72},
+      { "Ordre de passage", NULL, WHITE, (double*)&global->turntype, NULL, "%s", 0, 3, 1, TURN_RANDOM, turnTypeText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "Continuer le Jeu Robots seuls", NULL, WHITE, &global->skipComputerPlay, NULL, "%s", 0, 1, 1, 1, skipTypeText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112},
+      { "Langue", NULL, WHITE, &global->language, NULL, "%s", 0, 7, 1, 0, languageText_fr, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 132}
+    };
+// mainMenu = { "Menu principal", 10, mainOpts, TRUE, FALSE};
+    mainMenu.title = "Menu principal";
+    mainMenu.numEntries = 12;
+    mainMenu.entries = mainOpts;
+    mainMenu.quitButton = TRUE;
+    mainMenu.okayButton = FALSE;
+
+
+  }       // end of french
+
+if (global->language == LANGUAGE_GERMAN)
+  {
+    MENUENTRY physicsOpts[8] =
+    {
+      { "Gravitation", NULL, WHITE, &env->gravity, NULL, "%2.3f", .025, .325, 0.025, .075, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 80},
+      { "Reibung", NULL, WHITE, &env->viscosity, NULL, "%2.2f", .25, 2.0, 0.25, 1.0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 60},
+      { "Erdrutsch", NULL, WHITE, &env->landSlideType, NULL, "%s", 0, 4, 1, 3, landSlideText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 40},
+      { "Erdrutsch Verzögerung", NULL, WHITE, &env->landSlideDelay, NULL, "%4.0f", 1, 5, 1,3, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 20},
+      { "Wand Art", NULL, WHITE, &env->wallType, NULL, "%s", 0, 4, 1, 1, wallTypeText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight},
+      { "Höhlenmodus", NULL, WHITE, &env->dBoxedMode, NULL, "%s", 0, 2, 1, 0, onOffRandomText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 20},
+      { "Gewalttätiger Tod", NULL, WHITE, &global->violent_death, NULL, "%s", 0, 3, 1, 0, lightningText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 40},
+      { "Zeitlimit", NULL, WHITE, &global->max_fire_time, NULL, "%3.0f", 0, 180, 5, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 60}
+    };
+    MENUDESC physicsMenu = { "Physik", 8, physicsOpts, TRUE, FALSE};
+
+    MENUENTRY weatherOpts[7] =
+    {
+      { "Meteoritenregen", NULL, WHITE, &env->meteors, NULL, "%s", 0, 3, 1, 0, meteorText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Gewitter", NULL, WHITE, &env->lightning, NULL, "%s", 0, 3, 1, 0, lightningText_de,OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Schmutzregen", NULL, WHITE, &env->falling_dirt_balls, NULL, "%s", 0, 3, 1, 0, meteorText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Lasersatellit", NULL, WHITE, &env->satellite, NULL, "%s", 0, 3, 1, 0, laserSatelliteText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Nebel", NULL, WHITE, &env->fog, NULL, "%s", 0, 1, 1, 0, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Max Windstärke", NULL, WHITE, (double*)&env->windstrength, NULL, "%2.0f", 0, 100, 5, 40, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Windveränderung", NULL, WHITE, (double*)&env->windvariation, NULL, "%2.1f", 0, 100, 3, 10, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+    };
+    MENUDESC weatherMenu = { "Wetter", 7, weatherOpts, TRUE, FALSE};
+
+    MENUENTRY soundOpts[3] =
+    {
+      { "Alle Sounds", NULL, WHITE, &global->sound, NULL, "%s", 0, 1, 1, 1, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Sound Treiber", NULL, WHITE, &global->sound_driver, NULL, "%s", 0, 5, 1, 0, soundDriver, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Musik", NULL, WHITE, &global->play_music, NULL, "%s", 0, 1, 1, 0, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28}
+    };
+   MENUDESC soundMenu = { "Sounds", 3, soundOpts, TRUE, FALSE};
+
+
+
+    MENUENTRY graphicsOpts[12] =
+    {
+      { "Full Screen", NULL, WHITE, &global->full_screen, NULL, "%s", 0, 1, 1, 0, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 108},
+      { "Dithering", NULL, WHITE, &global->ditherGradients, NULL, "%s", 0, 1, 1, 1, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 88},
+      { "Landdetails", NULL, WHITE, &global->detailedLandscape, NULL, "%s", 0, 1, 1, 1, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Himmeldetails", NULL, WHITE, &global->detailedSky, NULL, "%s", 0, 1, 1, 1, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Ausblendender Text", NULL, WHITE, &env->dFadingText, NULL, "%s", 0, 1, 1, 1, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Schattierter Text", NULL, WHITE, &env->dShadowedText, NULL, "%s", 0, 1, 1, 1, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Farbschema", NULL, WHITE, &global->colour_theme, NULL, "%s", 0, 1, 1, 1, colourText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Bildschirmbreite", NULL, WHITE, &global->temp_screenWidth, NULL, "%4.0f", 800, 1600, 200, 800, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Bildschirmhöhe", NULL, WHITE, &global->temp_screenHeight, NULL, "%4.0f", 600, 1200, 200, 600, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Mauszeiger", NULL, WHITE, &global->os_mouse, NULL, "%s", 0, 1, 1, 1, mouseText_de,OPTION_SPECIALTYPE, FALSE, global->halfWidth - 1, global->halfHeight + 72},
+      { "Spielgeschwindigket", NULL, WHITE, &global->frames_per_second, NULL, "%3.0f", 30, 120, 5, 60, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "kundenspezifischer Hintergrund", NULL, WHITE, &env->custom_background, NULL, "%s", 0, 1, 1, 0, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+    };
+    MENUDESC graphicsMenu = { "Grafik", 12, graphicsOpts, TRUE, FALSE};
+
+
+    MENUENTRY financeOpts[9] =
+    {
+      { "Startgeld", NULL, WHITE, (double*)&global->startmoney, NULL, "%2.0f", 0, 200000, 5000, 20000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Zinssatz", NULL, WHITE, (double*)&global->interest, NULL, "%2.2f", 1.0, 1.5, 0.05,1.25, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Rundenbonus", NULL, WHITE, (double*)&global->scoreRoundWinBonus, NULL, "%2.0f", 0,50000, 5000, 10000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Schadensbonus", NULL, WHITE, (double*)&global->scoreHitUnit, NULL, "%2.0f", 0, 500, 25, 75, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Strafe für Selbstschaden", NULL, WHITE, (double*)&global->scoreSelfHit, NULL, "%2.0f", 0, 10000, 1000, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Zerstörungsbonus", NULL, WHITE, (double*)&global->scoreUnitDestroyBonus, NULL, "%2.0f", 0, 20000, 2500, 5000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Selbstzerstörungsstrafe", NULL, WHITE, (double*)&global->scoreUnitSelfDestroy, NULL, "%2.0f", 0, 20000, 2500, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 72},
+      { "Verkaufsmultiplikator", NULL, WHITE, (double*)&global->sellpercent, NULL, "%1.2f",0.0, 1.0, 0.10, 0.80, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth -3, global->halfHeight + 92},
+      { "Mannschaftanteil", NULL, WHITE, (double *) &global->divide_money, NULL, "%s", 0.0, 1.0, 1.0, 0.0, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+
+    };
+    MENUDESC financeMenu = { "Geld", 9, financeOpts, TRUE, FALSE};
+
+    MENUENTRY networkOpts[3] =
+    {
+       {  "Auf Aktualisierungen prüfen", NULL, WHITE, (double*) &global->check_for_updates, NULL, "%s", 0, 1, 1, 1, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+       {  "Netzwerk", NULL, WHITE, (double*) &global->enable_network, NULL, "%s", 0, 1, 1, 1, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+       {  "offener Port", NULL, WHITE, (double*) &global->listen_port, NULL, "%5.0f", 10645, 64645, 1000, 25645, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8}
+    };
+    MENUDESC networkMenu = { "Netzwerk", 3, networkOpts, TRUE, FALSE};
+
+
+    void *pPhysicsMenu  =       &physicsMenu;
+    void *pWeatherMenu  =       &weatherMenu;
+    void *pGraphicsMenu =       &graphicsMenu;
+    void *pFinanceMenu  =       &financeMenu;
+    void *pnetworkMenu  =       &networkMenu;
+    void *pSoundMenu    =       &soundMenu;
+
+    MENUENTRY mainOpts[12] =
+    {
+      { "Physik", NULL, WHITE, (double*)pPhysicsMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 88},
+      { "Wetter", NULL, WHITE, (double*)pWeatherMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Grafik", NULL, WHITE, (double*)pGraphicsMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Geld", NULL, WHITE, (double*)pFinanceMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Netzwerk", NULL, WHITE, (double*)pnetworkMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Sounds", NULL, WHITE, (double*) pSoundMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Technologiestufe Waffen", NULL, WHITE, (double*)&env->weapontechLevel, NULL, "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Technologiestufe Gegenstände", NULL, WHITE, (double *) &env->itemtechLevel, NULL, "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Landschaft", NULL, WHITE, (double*)&env->landType, NULL, "%s", 0, 7, 1, LANDTYPE_HILLS, landTypeText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight+ 72},
+      { "Reihenfolge", NULL, WHITE, (double*)&global->turntype, NULL, "%s", 0, 3, 1, TURN_RANDOM, turnTypeText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "Überspringe Nur-KI", NULL, WHITE, &global->skipComputerPlay, NULL, "%s", 0, 1, 1, 1, skipTypeText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112},
+      { "Sprache", NULL, WHITE, &global->language, NULL, "%s", 0, 7, 1, 0, languageText_de,OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 132}
+    };
+// mainMenu = { "Hauptmenü", 10, mainOpts, TRUE, FALSE};
+    mainMenu.title = "Hauptmenü";
+    mainMenu.numEntries = 12;
+    mainMenu.entries = mainOpts;
+    mainMenu.quitButton = TRUE;
+    mainMenu.okayButton = FALSE;
+
+  }  // end of German
+
+
+if (global->language == LANGUAGE_SLOVAK)
+  {
+    MENUENTRY physicsOpts[8] =
+    {
+      { "Gravitácia", NULL, WHITE, &env->gravity, NULL, "%2.3f", .025, .325, 0.025, .075, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 80},
+      { "Viskozita", NULL, WHITE, &env->viscosity, NULL, "%2.2f", .25, 2.0, 0.25, 1.0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 60},
+      { "Zosun zeme", NULL, WHITE, &env->landSlideType, NULL, "%s", 0, 4, 1, 3, landSlideText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 40},
+      { "Zdržanie zosunu zeme", NULL, WHITE, &env->landSlideDelay, NULL, "%4.0f", 1, 5, 1, 3, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 20},
+      { "Typ steny", NULL, WHITE, &env->wallType, NULL, "%s", 0, 4, 1, 1, wallTypeText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight},
+      { "Režim krabíc", NULL, WHITE, &env->dBoxedMode, NULL, "%s", 0, 2, 1, 0, onOffRandomText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 20},
+      { "Krutá smrť", NULL, WHITE, &global->violent_death, NULL, "%s", 0, 3, 1, 0, lightningText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 40},
+      { "Časované strely", NULL, WHITE, &global->max_fire_time, NULL, "%3.0f", 0, 180, 5, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 60}
+    };
+    MENUDESC physicsMenu = { "Fyzika", 7, physicsOpts, TRUE, FALSE};
+
+    MENUENTRY weatherOpts[7] =
+    {
+      { "Dážď meteorov", NULL, WHITE, &env->meteors, NULL, "%s", 0, 3, 1, 0, meteorText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Blesky", NULL, WHITE, &env->lightning, NULL, "%s", 0, 3, 1, 0, lightningText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Padajúca zem", NULL, WHITE, &env->falling_dirt_balls, NULL, "%s", 0, 3, 1, 0, meteorText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Laserový satelit", NULL, WHITE, &env->satellite, NULL, "%s", 0, 3, 1, 0, laserSatelliteText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Hmla", NULL, WHITE, &env->fog, NULL, "%s", 0, 1, 1, 0, onOffText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Maximálna sila vetra", NULL, WHITE, (double*)&env->windstrength, NULL, "%2.0f", 0, 100, 5, 40, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Zmena vetra", NULL, WHITE, (double*)&env->windvariation, NULL, "%2.1f", 0, 100, 3, 10, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+    };
+    MENUDESC weatherMenu = { "Počasie", 7, weatherOpts, TRUE, FALSE};
+
+    MENUENTRY soundOpts[3] =
+    {
+      { "Všetky zvuky", NULL, WHITE, &global->sound, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Ovládač zvuku", NULL, WHITE, &global->sound_driver, NULL, "%s", 0, 5, 1, 0, soundDriver, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Hudba", NULL, WHITE, &global->play_music, NULL, "%s", 0, 1, 1, 0, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28}
+    };
+   MENUDESC soundMenu = { "Zvuk", 3, soundOpts, TRUE, FALSE};
+
+
+
+    MENUENTRY graphicsOpts[12] =
+    {
+      { "Na celú obrazovku", NULL, WHITE, &global->full_screen, NULL, "%s", 0, 1, 1, 0, onOffText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 108},
+      { "Rozptyl", NULL, WHITE, &global->ditherGradients, NULL, "%s", 0, 1, 1, 1, onOffText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 88},
+      { "Detaily krajiny", NULL, WHITE, &global->detailedLandscape, NULL, "%s", 0, 1, 1, 1, onOffText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Detaily oblohy", NULL, WHITE, &global->detailedSky, NULL, "%s", 0, 1, 1, 1, onOffText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Slabnúci text", NULL, WHITE, &env->dFadingText, NULL, "%s", 0, 1, 1, 1, onOffText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Text s tieňom", NULL, WHITE, &env->dShadowedText, NULL, "%s", 0, 1, 1, 1, onOffText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Farebná téma", NULL, WHITE, &global->colour_theme, NULL, "%s", 0, 1, 1, 1, colourText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Šírka obrazovky", NULL, WHITE, &global->temp_screenWidth, NULL, "%4.0f", 800, 1600, 200, 800, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Výška obrazovky", NULL, WHITE, &global->temp_screenHeight, NULL, "%4.0f", 600, 1200, 200, 600, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Ukazovateľ myši", NULL, WHITE, &global->os_mouse, NULL, "%s", 0, 1, 1, 1, mouseText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 1, global->halfHeight + 72},
+      { "Rýchlosť hry", NULL, WHITE, &global->frames_per_second, NULL, "%3.0f", 30, 120, 5, 60, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "Vlastné pozadie", NULL, WHITE, &env->custom_background, NULL, "%s", 0, 1, 1, 0, onOffText_de, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+    };
+    MENUDESC graphicsMenu = { "Grafika", 12, graphicsOpts, TRUE, FALSE};
+
+    MENUENTRY financeOpts[9] =
+    {
+      { "Peniaze na začiatku", NULL, WHITE, (double*)&global->startmoney, NULL, "%2.0f", 0, 200000, 5000, 20000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Úroková miera", NULL, WHITE, (double*)&global->interest, NULL, "%2.2f", 1.0, 1.5, 0.05, 1.25, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Bonus pri skončení kola", NULL, WHITE, (double*)&global->scoreRoundWinBonus, NULL, "%2.0f", 0, 50000, 5000, 10000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Odmena za poškodenie", NULL, WHITE, (double*)&global->scoreHitUnit, NULL, "%2.0f", 0, 500, 25, 75, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Pokuta za vlastné poškodenie", NULL, WHITE, (double*)&global->scoreSelfHit, NULL, "%2.0f", 0, 10000, 1000, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Bonus za zničenie tanku", NULL, WHITE, (double*)&global->scoreUnitDestroyBonus, NULL, "%2.0f", 0, 20000, 2500, 5000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Pokuta za vlastné zničenie tanku", NULL, WHITE, (double*)&global->scoreUnitSelfDestroy, NULL, "%2.0f", 0, 20000, 2500, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 72},
+      { "Násobiteľ pri predaji položiek", NULL, WHITE, (double*)&global->sellpercent, NULL, "%1.2f", 0.0, 1.0, 0.10, 0.80, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth -3, global->halfHeight + 92},
+      { "Teamy zdieľajú peniaze", NULL, WHITE, (double *) &global->divide_money, NULL, "%s", 0.0, 1.0, 1.0, 0.0, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+
+    };
+    MENUDESC financeMenu = { "Peniaze", 9, financeOpts, TRUE, FALSE};
+
+
+    MENUENTRY networkOpts[3] =
+    {
+       {  "Kontrola aktualizácii", NULL, WHITE, (double*) &global->check_for_updates, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+       {  "Sieťová hra", NULL, WHITE, (double*) &global->enable_network, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+       {  "Port pre načúvanie", NULL, WHITE, (double*) &global->listen_port, NULL, "%5.0f", 10645, 64645, 1000, 25645, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8}
+    };
+    MENUDESC networkMenu = { "Sieť", 3, networkOpts, TRUE, FALSE};
+
+
+    void *pPhysicsMenu  =       &physicsMenu;
+    void *pWeatherMenu  =       &weatherMenu;
+    void *pGraphicsMenu =       &graphicsMenu;
+    void *pFinanceMenu  =       &financeMenu;
+    void *pnetworkMenu  =       &networkMenu;
+    void *pSoundMenu    =       &soundMenu;
+
+
+    MENUENTRY mainOpts[12] =
+    {
+      { "Fyzika", NULL, WHITE, (double*)pPhysicsMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 88},
+      { "Počasie", NULL, WHITE, (double*)pWeatherMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Grafika", NULL, WHITE, (double*)pGraphicsMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Peniaze", NULL, WHITE, (double*)pFinanceMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Sieť", NULL, WHITE, (double*)pnetworkMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Zvuk", NULL, WHITE, (double*) pSoundMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Tech úroveň zbraní", NULL, WHITE, (double*)&env->weapontechLevel, NULL, "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Tech úroveň vecí", NULL, WHITE, (double *) &env->itemtechLevel, NULL, "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Krajina", NULL, WHITE, (double*)&env->landType, NULL, "%s", 0, 7, 1, LANDTYPE_HILLS, landTypeText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 72},
+      { "Poradie", NULL, WHITE, (double*)&global->turntype, NULL, "%s", 0, 3, 1, TURN_RANDOM, turnTypeText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "Preskočiť hru samotného PC", NULL, WHITE, &global->skipComputerPlay, NULL, "%s", 0, 1, 1, 1, skipTypeText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112},
+      { "Jazyk", NULL, WHITE, &global->language, NULL, "%s", 0, 7, 1, 0, languageText_sk, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 132}
+    };
+    mainMenu.title = "Hlavné menu";
+    mainMenu.numEntries = 12;
+    mainMenu.entries = mainOpts;
+    mainMenu.quitButton = TRUE;
+    mainMenu.okayButton = FALSE;
+
+  }  // end of Slovak
+
+
+if (global->language == LANGUAGE_RUSSIAN)
+{
+    MENUENTRY physicsOpts[8] =
+    {
+      { "Гравитация", NULL, WHITE, &env->gravity, NULL, "%2.3f", .025, .325, 0.025, .075, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 80},
+      { "Сила трения", NULL, WHITE, &env->viscosity, NULL, "%2.2f", .25, 2.0, 0.25, 1.0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 60},
+      { "Падение земли", NULL, WHITE, &env->landSlideType, NULL, "%s", 0, 4, 1, 3, landSlideText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 40},
+      { "Задержка падения земли", NULL, WHITE, &env->landSlideDelay, NULL, "%4.0f", 1, 5, 1, 3, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 20},
+      { "Тип стен", NULL, WHITE, &env->wallType, NULL, "%s", 0, 4, 1, 1, wallTypeText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight},
+      { "Потолок", NULL, WHITE, &env->dBoxedMode, NULL, "%s", 0, 2, 1, 0, onOffRandomText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 20},
+      { "Мощные взрывы танков", NULL, WHITE, &global->violent_death, NULL, "%s", 0, 3, 1, 0, lightningText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 40},
+      { "Задержка выстрела", NULL, WHITE, &global->max_fire_time, NULL, "%3.0f", 0, 180, 5, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 60}
+    };
+    MENUDESC physicsMenu = { "Физика", 7, physicsOpts, TRUE, FALSE};
+
+
+    MENUENTRY weatherOpts[7] =
+    {
+      { "Метеоритный дождь", NULL, WHITE, &env->meteors, NULL, "%s", 0, 3, 1, 0, meteorText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Молнии", NULL, WHITE, &env->lightning, NULL, "%s", 0, 3, 1, 0, lightningText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Падающая грязь", NULL, WHITE, &env->falling_dirt_balls, NULL, "%s", 0, 3, 1, 0, meteorText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Удары со спутника", NULL, WHITE, &env->satellite, NULL, "%s", 0, 3, 1, 0, laserSatelliteText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Туман", NULL, WHITE, &env->fog, NULL, "%s", 0, 1, 1, 0, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Макс. сила ветра", NULL, WHITE, (double*)&env->windstrength, NULL, "%2.0f", 0, 100, 5, 40, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Изменения силы ветра", NULL, WHITE, (double*)&env->windvariation, NULL, "%2.1f", 0, 100, 3, 10, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+    };
+    MENUDESC weatherMenu = { "Погода", 7, weatherOpts, TRUE, FALSE};
+
+
+    MENUENTRY soundOpts[3] =
+    {
+      { "All Sound", NULL, WHITE, &global->sound, NULL, "%s", 0, 1, 1, 1, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Sound Driver", NULL, WHITE, &global->sound_driver, NULL, "%s", 0, 5, 1, 0, soundDriver, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Music", NULL, WHITE, &global->play_music, NULL, "%s", 0, 1, 1, 0, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28}
+    };
+   MENUDESC soundMenu = { "Sound", 3, soundOpts, TRUE, FALSE};
+
+
+    MENUENTRY graphicsOpts[12] =
+    {
+      { "Full Screen", NULL, WHITE, &global->full_screen, NULL, "%s", 0, 1, 1, 0, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 108},
+      { "Сглаживание", NULL, WHITE, &global->ditherGradients, NULL, "%s", 0, 1, 1, 1, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 88},
+      { "Детализированный ландшафт", NULL, WHITE, &global->detailedLandscape, NULL, "%s", 0, 1, 1, 1, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Детализированное небо", NULL, WHITE, &global->detailedSky, NULL, "%s", 0, 1, 1, 1, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Исчезающий текст", NULL, WHITE, &env->dFadingText, NULL, "%s", 0, 1, 1, 1, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Оттененный текст", NULL, WHITE, &env->dShadowedText, NULL, "%s", 0, 1, 1, 1, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Цветовая тема", NULL, WHITE, &global->colour_theme, NULL, "%s", 0, 1, 1, 1, colourText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Ширина окна игры", NULL, WHITE, &global->temp_screenWidth, NULL, "%4.0f", 800, 1600, 200, 800, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Высота окна игры", NULL, WHITE, &global->temp_screenHeight, NULL, "%4.0f", 600, 1200, 200, 600, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Курсор в игре", NULL, WHITE, &global->os_mouse, NULL, "%s", 0, 1, 1, 1, mouseText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 1, global->halfHeight + 72},
+      { "Скорость игры", NULL, WHITE, &global->frames_per_second, NULL, "%3.0f", 30, 120, 5, 60, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "Собственный фон", NULL, WHITE, &env->custom_background, NULL, "%s", 0, 1, 1, 0, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+    };
+    MENUDESC graphicsMenu = { "Графика", 12, graphicsOpts, TRUE, FALSE};
+
+
+    MENUENTRY financeOpts[9] =
+    {
+      { "Начальные деньги", NULL, WHITE, (double*)&global->startmoney, NULL, "%2.0f", 0, 200000, 5000, 20000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Банковский процент", NULL, WHITE, (double*)&global->interest, NULL, "%2.2f", 1.0, 1.5, 0.05, 1.25, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Бонус за победу", NULL, WHITE, (double*)&global->scoreRoundWinBonus, NULL, "%2.0f", 0, 50000, 5000, 10000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Бонус за попадание", NULL, WHITE, (double*)&global->scoreHitUnit, NULL, "%2.0f", 0, 500, 25, 75, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Штраф за попадание в себя", NULL, WHITE, (double*)&global->scoreSelfHit, NULL, "%2.0f", 0, 10000, 1000, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Бонус за уничтожение", NULL, WHITE, (double*)&global->scoreUnitDestroyBonus, NULL, "%2.0f", 0, 20000, 2500, 5000, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Штраф за самоуничтожение", NULL, WHITE, (double*)&global->scoreUnitSelfDestroy, NULL, "%2.0f", 0, 20000, 2500, 0, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 72},
+      { "Коэфф. продажи снаряжения", NULL, WHITE, (double*)&global->sellpercent, NULL, "%1.2f", 0.0, 1.0, 0.10, 0.80, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth -3, global->halfHeight + 92},
+      { "Командные боеприпасы", NULL, WHITE, (double *) &global->divide_money, NULL, "%s", 0.0, 1.0, 1.0, 0.0, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112}
+    };
+    MENUDESC financeMenu = { "Экономика", 9, financeOpts, TRUE, FALSE};
+
+
+    MENUENTRY networkOpts[3] =
+    {
+       {  "Проверять обновления", NULL, WHITE, (double*) &global->check_for_updates, NULL, "%s", 0, 1, 1, 1, onOffText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+       {  "Networking", NULL, WHITE, (double*) &global->enable_network, NULL, "%s", 0, 1, 1, 1, onOffText, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+       {  "Listen Port", NULL, WHITE, (double*) &global->listen_port, NULL, "%5.0f", 10645, 64645, 1000, 25645, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8}
+    };
+    MENUDESC networkMenu = { "Настройки сети", 3, networkOpts, TRUE, FALSE};
+
+    void *pPhysicsMenu  =       &physicsMenu;
+    void *pWeatherMenu  =       &weatherMenu;
+    void *pGraphicsMenu =       &graphicsMenu;
+    void *pFinanceMenu  =       &financeMenu;
+    void *pnetworkMenu  =       &networkMenu;
+    void *pSoundMenu    =       &soundMenu;
+
+
+    MENUENTRY mainOpts[12] =
+    {
+      { "Физика", NULL, WHITE, (double*)pPhysicsMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 88},
+      { "Погода", NULL, WHITE, (double*)pWeatherMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 68},
+      { "Графика", NULL, WHITE, (double*)pGraphicsMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 48},
+      { "Экономика", NULL, WHITE, (double*)pFinanceMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 28},
+      { "Настройки сети", NULL, WHITE, (double*)pnetworkMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight - 8},
+      { "Звук", NULL, WHITE, (double*)pSoundMenu, NULL, NULL, 0, 0, 0, 0, NULL, OPTION_MENUTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 12},
+      { "Уровень оружия", NULL, WHITE, (double*)&env->weapontechLevel, NULL, "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 32},
+      { "Уровень снаряжения", NULL, WHITE, (double *) &env->itemtechLevel, NULL, "%2.0f", 0, 5, 1, 5, NULL, OPTION_DOUBLETYPE, FALSE, global->halfWidth - 3, global->halfHeight + 52},
+      { "Тип ландшафта", NULL, WHITE, (double*)&env->landType, NULL, "%s", 0, 7, 1, LANDTYPE_HILLS, landTypeText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 72},
+      { "Порядок хода", NULL, WHITE, (double*)&global->turntype, NULL, "%s", 0, 3, 1, TURN_RANDOM, turnTypeText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 92},
+      { "Пропускать игру компьютеров", NULL, WHITE, &global->skipComputerPlay, NULL, "%s", 0, 1, 1, 1, skipTypeText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 112},
+      { "Язык (Language)", NULL, WHITE, &global->language, NULL, "%s", 0, 7, 1, 0, languageText_ru, OPTION_SPECIALTYPE, FALSE, global->halfWidth - 3, global->halfHeight + 132}
+    };
+// mainMenu = { "Main Menu", 10, mainOpts, TRUE, FALSE};
+     mainMenu.title = "Главное меню";
+     mainMenu.numEntries = 12;
+     mainMenu.entries = mainOpts;
+     mainMenu.quitButton = TRUE;
+     mainMenu.okayButton = FALSE;
+
+}   // end of Russian
+
+
+
+#endif
+
diff --git a/src/missile.cpp b/src/missile.cpp
new file mode 100644
index 0000000..a3833d0
--- /dev/null
+++ b/src/missile.cpp
@@ -0,0 +1,798 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "environment.h"
+#include "globaldata.h"
+#include "explosion.h"
+#include "missile.h"
+#include "decor.h"
+#include "tank.h"
+
+
+MISSILE::~MISSILE ()
+{
+  _env->removeObject (this);
+  _global = NULL;
+  _env    = NULL;
+  weap    = NULL;
+}
+
+MISSILE::MISSILE (GLOBALDATA *global, ENVIRONMENT *env, double xpos, double ypos, 
+                  double xvel, double yvel,
+                  int weaponType):PHYSICAL_OBJECT(),weap(NULL)
+{
+  setEnvironment (env);
+  player = NULL;
+  _align = LEFT;
+  _global = global;
+  #ifdef NETWORK
+  char buffer[256];
+  sprintf(buffer, "MISSILE %d %d %lf %lf %d", (int)xpos, (int)ypos,
+                  xvel, yvel, weaponType);
+  global->Send_To_Clients(buffer);
+  #endif
+  x = xpos;
+  y = ypos;
+  xv = xvel;
+  yv = yvel;
+  type = weaponType;
+  if (type < WEAPONS)
+    weap = &weapon[type];
+  else
+    weap = &naturals[type - WEAPONS];
+  mass = weap->mass;
+  drag = weap->drag;
+  sound = weap->sound;
+  expSize = weap->radius;
+  etime = weap->etime;
+  damage = weap->damage;
+  eframes = weap->eframes;
+  picpoint = weap->picpoint;
+  noimpact = weap->noimpact;
+  countdown = -1;
+  _bitmap = (BITMAP *)_global->missile[picpoint];
+  physics = 0;
+  age = 0;
+  destroy = FALSE;
+  if (type >= SML_METEOR && type <= LRG_METEOR)
+    {
+      angle = rand () % 360;
+      spin = rand () % 20 - 10;
+    }
+  else
+    {
+      angle = 0;
+      spin = 0;
+    }
+
+  // Napalm grows, others do not:
+  if (type == NAPALM_JELLY)
+    {
+     bIsGrowing = true;
+     iGrowRadius= 1;
+    }
+  else
+    {
+     bIsGrowing = false;
+     iGrowRadius= expSize;
+    }
+  if ( (type == FUNKY_BOMBLET) || (type == FUNKY_DEATHLET) )
+  {
+      int temp_number = rand() % 5;
+      switch (temp_number)
+      {
+         case 0: funky_colour = makecol(200, 0, 0); break;
+         case 1: funky_colour = makecol(0, 200, 0); break;
+         case 2: funky_colour = makecol(0, 0, 200); break;
+         case 3: funky_colour = makecol(200, 200, 0); break;
+         case 4: funky_colour = makecol(200, 0, 200); break;
+      }
+  }
+}
+
+void MISSILE::initialise ()
+{
+  PHYSICAL_OBJECT::initialise ();
+  physics = 0;
+  age = 0;
+  if (type >= SML_METEOR && type <= LRG_METEOR)
+    {
+      angle = rand () % 360;
+      spin = rand () % 20 - 10;
+    }
+  else
+    {
+      angle = 0;
+      spin = 0;
+    }
+}
+
+
+
+int MISSILE::triggerTest ()
+{
+  int quell = 1;
+  TANK *tank;
+  double old_delta_x = xv;
+
+  // Has it hit a tank?
+  for (int objCount = 0; (tank = (TANK*)_env->getNextOfClass (TANK_CLASS, &objCount)) && tank; objCount++)
+    {
+      if (x > tank->x - TANKWIDTH && x < tank->x + TANKWIDTH && y > tank->y && y < tank->y + TANKHEIGHT && tank->l > 0)
+        {
+          hitSomething = 1;
+          tank->requireUpdate ();
+        }
+    }
+  if (noimpact)
+    {
+      quell = 1;
+    }
+  else if ((y > 0) && (hitSomething || (y >= _global->screenHeight) || (getpixel (_env->terrain, (int)x, (int)y) != PINK)))
+    // else if ( (y > 0) && (hitSomething || (y >= _global->screenHeight) || (_env->surface[(int)x] <= y) ) )
+    {
+      quell = 0;
+      if (type >= SML_ROLLER && type <= DTH_ROLLER && !physics)
+        {
+          /* rollerupdate */
+          if (age > 1)
+            {
+
+              quell = 1;
+              physics = 1;
+              y -= 5;
+              if (x < 1)
+                x = 1;
+              if (x > (_global->screenWidth - 2))
+                x = (_global->screenWidth - 2);
+
+              if ( (y >= _env->surface[(int)x])       // y is surface or below
+                   && (y <= _env->surface[(int)x] + 2) )  // but not burried more than 2 px
+                y = _env->surface[(int)x] - 1;
+
+              yv = 0.0;
+              // if (xv > 0.0) yv = 1.0;
+              // if (xv < 0.0) yv =-1.0;
+
+              xv = 0.0;
+              if (x == 1)
+                  xv++;
+              else if (x == (_global->screenWidth - 2) )
+                  xv--;
+              else
+              {
+                  int can_go_left = FALSE, can_go_right = FALSE;
+                  if (getpixel (_env->terrain, (int)x + 1, (int)y + 1) == PINK)
+                     can_go_right = TRUE;
+                  if (getpixel (_env->terrain, (int)x - 1, (int)y + 1) == PINK)
+                     can_go_left = TRUE;
+
+                  if ( (can_go_left) && (!can_go_right) )
+                  {
+                     xv--;
+                  }
+                  else if ( (! can_go_left) && (can_go_right) )
+                  {
+                     xv++;
+                  }
+                  else if ( (can_go_left) && (can_go_right) )
+                  {
+                     xv = old_delta_x;      // if both are open, continue on old course
+                  }
+              }
+              if (xv == 0.0)     // nothing worked, try something!
+              {
+                xv = yv;
+              }
+              yv = 0.0;
+              hitSomething = 0;
+            }
+          else
+            {
+              physics = 4;
+            }
+        }
+      else if (type == BURROWER || type == PENETRATOR)
+        {
+          if (physics == 1)
+            {
+              if (!hitSomething)
+                quell = 1;
+            }
+          if (!physics)
+            {
+              physics = 1;
+              xv *= 0.1;
+              yv *= 0.1;
+              quell = 1;
+            }
+
+        }
+      // our weapon has sub weapons
+      else if (weap->submunition >= 0)
+        {
+          WEAPON *submunition = &weapon[weap->submunition];
+
+          quell = 1;
+          if (weap->numSubmunitions > 0)
+            {
+              double divergenceStep = weap->divergence / (weap->numSubmunitions - 1);
+              int startPoint;
+              int randStart = rand () % 1000000;
+              int submunitionPhys = 0;
+              double inheritedXV = weap->impartVelocity * xv;
+              double inheritedYV = weap->impartVelocity * yv;
+
+              if (type == FUNKY_BOMB || type == FUNKY_DEATH)
+                submunitionPhys = 1;
+
+              if (divergenceStep < 0)
+                {
+                  startPoint = 0;
+                }
+              else
+                {
+                  startPoint = 180;
+                }
+              for (int spreadCount = 0; spreadCount < weap->numSubmunitions; spreadCount++)
+                {
+                  MISSILE *newmis;
+                  double launchSpeed;
+                  int newmisCount;
+                  int dAngle;
+
+                  dAngle = (int) (startPoint - (weap->divergence / 2) + (divergenceStep * spreadCount));
+                  if (weap->spreadVariation > 0)
+                    {
+                      double variation = Noise (randStart + 1054 + spreadCount) * weap->spreadVariation;
+                      dAngle += (int)(weap->divergence * variation);
+                    }
+                  while (dAngle < 0)
+                    dAngle += 360;
+                  while (dAngle >= 360)
+                    dAngle -= 360;
+
+                  newmisCount = submunition->countdown;
+                  if (submunition->countVariation > 0)
+                    {
+                      double variation = Noise (randStart + 78689 + spreadCount) * submunition->countVariation;
+                      newmisCount += (int)(submunition->countdown * variation);
+                      if (newmisCount <= 0)
+                        newmisCount = 1;
+                    }
+
+                  launchSpeed = weap->launchSpeed;
+                  if (weap->speedVariation > 0)
+                    {
+                      double variation = Noise (randStart + 124786 + spreadCount) * weap->speedVariation;
+                      launchSpeed += weap->launchSpeed * variation;
+                    }
+
+                  newmis = new MISSILE (_global, _env, x, y - 20, _global->slope[dAngle][0] * launchSpeed * (100.0 / _global->frames_per_second) + inheritedXV, _global->slope[dAngle][1] * launchSpeed * (100.0 / _global->frames_per_second) + inheritedYV, weap->submunition);
+
+                  if (newmis)
+                  {
+
+                      newmis->physics = submunitionPhys;
+                      newmis->player = player;
+                      newmis->countdown = newmisCount;
+                      newmis->noimpact = weapon[weap->submunition].noimpact;
+                      newmis->setUpdateArea
+                       ((int) newmis->x - 20,
+                       (int) newmis->y - 20, 40, 40);
+                  }
+                  else
+                      perror ( "missile.cc: Failed allocating memory for newmis in MISSILE::triggerTest (CLUSTER)");
+                }
+            }
+          destroy = TRUE;
+        }
+    }
+
+  if (countdown >= 0 && age >= countdown)
+    {
+      quell = 0;
+    }
+  if (type >= RIOT_CHARGE && type <= RIOT_BLAST)
+    {
+      quell = 0;
+      destroy = TRUE;
+    }
+  if (!quell)
+    {
+      _env->realm--;
+      trigger ();
+    }
+
+
+  return (!quell);
+}
+
+int MISSILE::applyPhysics ()
+{
+  TANK *ltank;
+  int detonate = FALSE;
+  int max_age;
+  int above_ground;
+
+  age++;
+
+  // meteors live less time than regular missles
+  if ( (type >= SML_METEOR) && (type <= LRG_METEOR) )
+    max_age = MAX_METEOR_AGE;
+  else
+    max_age = MAX_MISSLE_AGE;
+
+  // Napalm grows first:
+  if (bIsGrowing)
+    {
+      if (age < max_age)
+        {
+          iGrowRadius = (int)round((double)expSize * ((double)age / (double)max_age));
+          if (iGrowRadius < 2)
+            iGrowRadius = 2;
+        }
+      else
+        bIsGrowing = false; // Finished growing!
+    }
+
+  if ( (age > max_age * _global->frames_per_second) || (y < -65535) )
+    detonate = 1;
+  if (!physics)
+    {
+      if (type >= SML_METEOR && type <= LRG_METEOR)
+        {
+          angle += spin;
+          angle = angle % 360;
+        }
+      else
+        {
+          angle = (int) (atan (yv / xv) * (180 / PI) * ACHANGE) - 64 + ((xv < 0) ? 128 : 0);
+        }
+      for (int objCount = 0; (ltank = (TANK*)_env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
+        {
+          if (ltank->player != player)
+            {
+              double xaccel = 0, yaccel = 0;
+              ltank->repulse (x + xv, y + yv, &xaccel, &yaccel, type);
+              xv += xaccel;
+              yv += yaccel;
+            }
+        }
+      if ( PHYSICAL_OBJECT::applyPhysics () )
+      {
+        detonate = 1;
+      }
+      if (! detonate)
+        detonate = checkPixelsBetweenPrevAndNow ();
+
+      // mirvs trigger above ground
+      if ( (! detonate) && ( (type == SMALL_MIRV) || (type == CLUSTER_MIRV) ) )
+        {
+          above_ground = Height_Above_Ground();
+          if ( (above_ground > 0) && (above_ground < TIGGER_HEIGHT) &&
+               (yv > 0) )
+            detonate = 1;
+        }
+
+      // if (! detonate &&
+      if ( (type == BURROWER || type == PENETRATOR) )
+        {
+          hitSomething = 0;
+          if ( ( y >= _global->screenHeight) &&
+               ( (_env->current_wallType == WALL_STEEL) || (_env->current_wallType == WALL_WRAP) ) )
+            {
+              detonate = TRUE;
+              hitSomething = 1;
+              y = _global->screenHeight;
+              yv = 0;
+            }
+        }
+      if (rand () % 5 == 0)
+        {
+          DECOR *decor;
+          decor = new DECOR (_global, _env, x, y, xv, yv, expSize / 20, DECOR_SMOKE);
+          if (!decor)
+            {
+              perror ( "missile.cc: Failed allocating memory for decor in MISSILE::applyPhysics (METEOR)");
+              // exit (1);
+            }
+        }
+    }
+  else
+    {
+      if (type >= SML_ROLLER && type <= DTH_ROLLER)
+        {
+          /* rollerupdate */
+          // check whether we have hit anything
+          if (	 (x < 1)
+                ||(x > (_global->screenWidth - 2))
+                ||(y > (_global->screenHeight - 2))
+                ||(getpixel(_env->terrain, (int)x, (int)y) != PINK))
+            detonate = 1;
+          else
+            {
+              // roll roller
+              float fSurfY = (float)_env->surface[(int)x] - 1;
+              if ((fSurfY > y) && (y < (_global->screenHeight - 5)))
+                {
+                  if (fSurfY < (y + 5))
+                    y = fSurfY;
+                  else
+                    y+=5;
+                  if (xv > 0.0) 		angle += 3;
+                  if (xv < 0.0) 		angle -= 3;
+                  if (angle < 0)		angle += 256;
+                  if (angle > 255)	angle -= 256;
+                }
+              else
+                {
+                  if (xv > 0.0)
+                    {
+                      angle += 3;
+                      x++;
+                    }
+                  else
+                    {
+                      angle -= 3;
+                      x--;
+                    }
+                  if (angle < 0)
+                    angle += 256;
+                  if (angle > 255)
+                    angle -= 256;
+                  if	(y >= MENUHEIGHT)
+                    {
+                      if (fSurfY > y)
+                        y++;
+                      else if (fSurfY >= (y - 2))
+                        y = fSurfY - 1;
+                    }
+                }
+              if (y > (_global->screenHeight - 5) && !detonate)
+                y = (_global->screenHeight - 5);
+            }
+        }
+      else if (type == FUNKY_BOMBLET || type == FUNKY_DEATHLET)
+        {
+          //double accel = (_env->wind - xv) / mass * drag;
+          if (x + xv < 1 || x + xv > (_global->screenWidth-1))
+            {
+              xv = -xv;	//bounce on the border
+            }
+          else
+            {
+              x += xv;
+            }
+
+          // hit screen bottom then change the y velocity direction
+          if (y + yv >= _global->screenHeight)
+            {
+              // only bounce if the wall is rubber
+              if ( _env->current_wallType == WALL_RUBBER )
+                {
+                  yv = -yv * 0.5;
+                  xv *= 0.95;
+                }
+              // bounce back with more force
+              else if ( _env->current_wallType == WALL_SPRING )
+                {
+                  yv = -yv * SPRING_CHANGE;
+                  xv *= 1.05;
+                }
+              // steel or wrap floor, detonate
+              else
+                {
+                  y = _global->screenHeight;
+                  yv = 0;
+                  detonate = TRUE;
+                }
+            }
+          else if (y+yv < 0) //hit screen top
+            {
+              yv = -yv * 0.5;
+              xv *= 0.95;
+            }
+          y += yv;
+        }
+      else if (type == BURROWER || type == PENETRATOR)
+        {
+          angle = (int) (atan (yv / xv) * (180 / PI) * ACHANGE) - 64 + ((xv < 0) ? 128 : 0);
+          for (int objCount = 0; (ltank = (TANK*)_env->getNextOfClass (TANK_CLASS, &objCount)) && ltank; objCount++)
+            {
+              if (ltank->player != player)
+                {
+                  double xaccel = 0, yaccel = 0;
+                  ltank->repulse (x + xv, y + yv, &xaccel, &yaccel, type);
+                  xv += xaccel * 0.1;
+                  yv += yaccel * 0.1;
+                }
+            }
+          if (x + xv < 1 || x + xv > (_global->screenWidth-1))
+            {
+              // if the wall is rubber, then bouce
+              if ( _env->current_wallType == WALL_RUBBER )
+                xv = -xv;	//bounce on the border
+              // bounce with more force
+              else if ( _env->current_wallType == WALL_SPRING )
+                xv = -xv * SPRING_CHANGE;
+              // wall is steel, detonate
+              else if ( _env->current_wallType == WALL_STEEL )
+                detonate = TRUE;
+              // wrap around to other side of the screen
+              else if ( _env->current_wallType == WALL_WRAP )
+                {
+                  if (xv < 0)
+                    x = _global->screenWidth - 1;
+                  else
+                    x = 1;
+                }
+            }
+          if (y + yv >= _global->screenHeight)
+            {
+              yv = -yv * 0.5;
+              xv *= 0.95;
+            }
+          else if (y+yv < 0)   //hit screen top
+            {
+              yv = -yv *0.5;
+              xv *= 0.95;
+            }
+          y += yv;
+          x += xv;
+          yv -= _env->gravity * 0.05 * (100.0 / _global->frames_per_second);
+          if (getpixel (_env->terrain, (int)x, (int)y) == PINK)
+            {
+              detonate = TRUE;
+            }
+        }
+    }
+
+  if (detonate)
+    {
+      hitSomething = 1;
+      if (y <= MENUHEIGHT)
+        y = MENUHEIGHT + 1;
+    }
+  else if ((y <= MENUHEIGHT) && _global->bIsBoxed)
+    {
+      detonate = 1;
+      hitSomething = 1; // Sorry, no more ceiling-drops for rollers!
+    }
+
+  return (detonate);
+}
+
+
+void MISSILE::trigger ()
+{
+  EXPLOSION *explosion;
+
+  if (type >= TREMOR && type <= TECTONIC)
+    explosion = new EXPLOSION (_global, _env, x, y, xv, yv, type);
+  else if (type >= RIOT_CHARGE && type <= RIOT_BLAST) 
+    explosion = new EXPLOSION (_global, _env, x, y, xv, yv, type);
+  else
+    explosion = new EXPLOSION (_global, _env, x, y, type);
+
+  if (!explosion)
+    {
+      perror ( "missile.cc: Failed allocating memory for explosion in MISSILE::trigger");
+      // exit (1);
+    }
+  else
+     explosion->player = player;
+
+
+
+  if ((_env->current_wallType == WALL_WRAP) && (type < WEAPONS))
+    {
+      EXPLOSION *cSecondExplo = NULL;
+      if (x < weapon[type].radius)
+        {
+          if   (   (type >= TREMOR && type <= TECTONIC)
+                   ||(type >= RIOT_CHARGE && type <= RIOT_BLAST)   )
+            cSecondExplo = new EXPLOSION (_global, _env, _global->screenWidth + x, y, xv, yv, type);
+          else
+            cSecondExplo = new EXPLOSION (_global, _env, _global->screenWidth + x, y, type);
+          if (!cSecondExplo)
+            {
+              perror ( "missile.cc: Failed allocating memory for cSecondExplo in MISSILE::trigger");
+              // exit (1);
+            }
+        }
+      if (x > (_global->screenWidth - weapon[type].radius))
+        {
+          if   (   (type >= TREMOR && type <= TECTONIC)
+                   ||(type >= RIOT_CHARGE && type <= RIOT_BLAST)   )
+            cSecondExplo = new EXPLOSION (_global, _env, x - _global->screenWidth, y, xv, yv, type);
+          else
+            cSecondExplo = new EXPLOSION (_global, _env, x - _global->screenWidth, y, type);
+          if (!cSecondExplo)
+            {
+              perror ( "missile.cc: Failed allocating memory for cSecondExplo in MISSILE::trigger");
+              // exit (1);
+            }
+        }
+      if (cSecondExplo)
+        cSecondExplo->player = player;
+    }
+
+
+
+  destroy = TRUE;
+
+  if ((type >= DIRT_BALL && type <= SMALL_DIRT_SPREAD) || (type >= RIOT_CHARGE && type <= RIOT_BLAST))
+    {
+      play_sample ((SAMPLE *) _global->sounds[9], 128 + (expSize / 2), 128, 1000 - (expSize * 2), 0);
+    }
+  else if (type == NAPALM_JELLY)
+    {
+      //play_sample ((SAMPLE *) _global->SOUND[9].dat, 128 + (expSize / 2), 128, 1000 - (expSize * 2), 0);
+    }
+  else
+    {
+      play_sample ((SAMPLE *) _global->sounds[WEAPONSOUNDS + sound], 255, 128, 1000, 0);
+    }
+}
+
+void MISSILE::draw (BITMAP *dest)
+{
+  if (!destroy)
+    {
+      // draw missile if it is above the screen
+      if (y < MENUHEIGHT)
+        {
+          BITMAP *bbitmap = _bitmap;
+          double by = y;
+          int bangle = angle;
+
+          _bitmap = (BITMAP*)_global->misc[3];
+          y = (double)MENUHEIGHT + (_bitmap->h / 2);
+          angle = 0;
+
+          VIRTUAL_OBJECT::draw (dest);
+          _bitmap = bbitmap;
+          y = by;
+          angle = bangle;
+        }
+
+      // draw missile on the screen
+      else
+        {
+
+          if (type == NAPALM_JELLY)
+            {
+              if (bIsGrowing)
+                {
+                  circlefill (_env->db, (int)x, (int)y, iGrowRadius - 2, makecol (255, 0, 0));
+                  circle(_env->db, (int)x, (int)y, iGrowRadius - 1, makecol(255, 150, 0));
+                  circle(_env->db, (int)x, (int)y, iGrowRadius, makecol(255, 150, 0));
+                  setUpdateArea ( (int)x - (iGrowRadius + 1),
+                                  (int)y - (iGrowRadius + 1),
+                                  (iGrowRadius + 1) * 2,
+                                  (iGrowRadius + 1) * 2);
+                }
+              else
+                {
+                  circlefill (_env->db, (int)x, (int)y, expSize - 2, makecol (255, 0, 0));
+                  circle(_env->db, (int)x, (int)y, expSize - 1, makecol(255, 150, 0));
+                  circle(_env->db, (int)x, (int)y, expSize, makecol(255, 150, 0));
+                  setUpdateArea ((int)x - (expSize + 1), (int)y - (expSize + 1), (expSize + 1) * 2, (expSize + 1) * 2);
+                }
+              requireUpdate ();
+            }   // end of napalm
+
+          // try drawing a funky bomblet
+          else if ( ( type == FUNKY_BOMBLET) || (type == FUNKY_DEATHLET) )
+          {
+              circlefill(_env->db, (int) x, (int) y, 4, funky_colour );
+              circle(_env->db, (int) x, (int) y, 5, makecol(0, 0, 0) );
+              setUpdateArea( (int) x - 10, (int) y - 10, 20, 20);
+              requireUpdate();
+          } 
+          // draw anything else, besides napalm
+          else
+            {
+              VIRTUAL_OBJECT::draw (dest);
+            }
+        }
+    }
+}
+
+
+void MISSILE::setEnvironment(ENVIRONMENT *env)
+    {
+      if (!_env || (_env != env))
+        {
+          _env = env;
+          _index = _env->addObject (this);
+        }
+    }
+
+
+
+int MISSILE::isSubClass (int classNum)
+{
+  if (classNum == MISSILE_CLASS)
+    return (TRUE);
+  else
+    return (FALSE);
+  //return (PHYSICAL_OBJECT::isSubClass (classNum));
+}
+
+
+// This function returns the distance above ground of
+// the missile.
+int MISSILE::Height_Above_Ground()
+{
+  int height = (int)y + 1;
+
+  if (y < 0)
+    return height;
+
+  height = _env->surface[(int) x] - y;
+  return height;
+}
+
+
+
+// Check to see if any tanks have SDI defense. If they
+// do, then see if this missile should be shot down.
+// Returns the shooting tank if a shot is to be fired
+// or NULL if no tank will shoot.
+TANK *MISSILE::Check_SDI(GLOBALDATA *global)
+{
+    TANK *my_tank;
+    int index;
+    double distance;
+    int chance;
+
+    if (type == NAPALM_JELLY)     // can't shoot jelly
+       return NULL;
+
+    for (index = 0; index < global->numPlayers; index++)
+    {
+        if ( ( global->players[index] ) && ( global->players[index]->tank) )
+        {
+            my_tank = global->players[index]->tank;
+            if ( (my_tank->player->ni[ITEM_SDI]) && (my_tank->player != this->player) )
+            {
+                 distance = pow(x - my_tank->x, 2);
+                 distance += pow(y - my_tank->y, 2);
+                 distance = sqrt(distance);
+                 // only fire if within range and above the tank
+                 if ( ( distance < SDI_DISTANCE ) && (my_tank->y > y) )
+                 {
+                      chance = rand() % 5;
+                      if (! chance)
+                      {
+                         return my_tank;
+                      }
+                 }        // within range
+            }      // we have SDI
+        }       // end of we have a valid player/tank
+       
+    }           // finished going through all players
+    
+    return NULL;
+}
+
+
diff --git a/src/missile.h b/src/missile.h
new file mode 100644
index 0000000..db78512
--- /dev/null
+++ b/src/missile.h
@@ -0,0 +1,74 @@
+#ifndef MISSILE_DEFINE
+#define MISSILE_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "main.h"
+#include "physobj.h"
+
+#define MAX_MISSLE_AGE 20
+#define MAX_METEOR_AGE 5
+
+#define TIGGER_HEIGHT 300
+
+#define SDI_DISTANCE 100
+
+class MISSILE: public PHYSICAL_OBJECT
+  {
+  private:
+    // New values for growing napalm jelly:
+    int iGrowRadius;
+    int bIsGrowing;
+
+  public:
+    int	countdown;
+    int	expSize;
+    int	etime;
+    int	damage;
+    int	eframes;
+    int	picpoint;
+    int	type;
+    int	sound;
+    int funky_colour;
+    WEAPON	*weap;
+
+    virtual ~MISSILE ();
+    MISSILE (GLOBALDATA *global, ENVIRONMENT *env, double xpos, double ypos, double xvel, double yvel, int weaponType);
+    void	draw (BITMAP *dest);
+    int	triggerTest ();
+    void	trigger ();
+    // void	explode ();
+    int	applyPhysics ();
+    void	initialise ();
+    int	isSubClass (int classNum);
+    void setEnvironment(ENVIRONMENT *env);
+
+    inline virtual int	getClass ()
+    {
+      return (MISSILE_CLASS);
+    }
+
+    int     Height_Above_Ground ();
+    TANK *Check_SDI(GLOBALDATA *global);       // see if missile should be shot down
+  };
+
+#endif
+
diff --git a/src/network.cpp b/src/network.cpp
new file mode 100644
index 0000000..e712f42
--- /dev/null
+++ b/src/network.cpp
@@ -0,0 +1,509 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NETWORK
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <netdb.h>
+#include <errno.h>
+#include <unistd.h>
+#include <pthread.h>
+#endif
+
+#include "network.h"
+#include "player.h"
+#include "globaldata.h"
+
+
+// init the object
+MESSAGE_QUEUE::MESSAGE_QUEUE()
+{
+   first_message = last_message = NULL;
+}
+
+
+
+// do clean up on all messages
+MESSAGE_QUEUE::~MESSAGE_QUEUE()
+{
+   Erase_All();
+}
+
+
+
+// add a new message to the queue
+// Returns true on success and false is an error occures
+bool MESSAGE_QUEUE::Add(char *some_text, int to)
+{
+    MESSAGE *new_message;
+
+    if (! some_text)
+      return false;
+
+    new_message = (MESSAGE *) calloc(1, sizeof(MESSAGE));
+    if (! new_message)
+        return false;
+    new_message->text = (char *) calloc( strlen(some_text), sizeof(char) );
+    if (! new_message->text)
+    {
+       free(new_message);
+       return false;
+    }
+
+    // fill the message structure
+    strcpy(new_message->text, some_text);
+    new_message->to = to;
+    // next is already cleared by calloc
+
+    // empty line, create new line
+    if (! first_message)
+    {
+       first_message = new_message;
+       last_message = new_message;
+    }
+
+    else // we have a line, add it to the end
+    {
+       last_message->next = new_message;
+       last_message = new_message;
+    }
+    return true;
+}
+
+
+
+// retreive a message and erase it from the queue
+// returns a message on success and NULL on failure
+MESSAGE *MESSAGE_QUEUE::Read()
+{
+   MESSAGE *my_message;
+
+   my_message = Peek();       // grab next message
+   if (my_message)
+      Erase();            // clear it from the queue
+
+   return my_message;
+}
+
+
+
+// returns a message from the queue without removing it from the line
+// Returns a message on success or a NULL on failure
+MESSAGE *MESSAGE_QUEUE::Peek()
+{
+   MESSAGE *my_message;
+
+   // see if there is a message to get
+   if ( (! first_message) || (! first_message->text) )
+      return NULL;
+
+   // we want to make a copy of the message, not just pass back a pointer
+   my_message = (MESSAGE *) calloc( 1, sizeof(MESSAGE) );
+   if (! my_message)
+      return NULL;
+   my_message->text = (char *) calloc( strlen(first_message->text), sizeof(char) );
+   if (! my_message->text)
+   {
+      free(my_message);
+      return NULL;
+   }
+
+   // we have an empty message. Now fill it
+   strcpy(my_message->text, first_message->text);
+   my_message->to = first_message->to;
+   
+   return my_message;
+}
+
+
+
+// Finds the next message destined "to" a given player
+// This function returns the first message it finds and
+// erases it. The message is returned on success or a
+// NULL is returned if no message is found.
+MESSAGE *MESSAGE_QUEUE::Read_To(int my_to)
+{
+    MESSAGE *current, *previous = NULL, *my_message = NULL;
+    bool found = false;
+
+    // search for matching to field
+    current = first_message;
+    while ( (current) && (! found) )
+    {
+       if ( current->to == my_to )
+          found = true;
+       else
+       {
+          previous = current;
+          current = (MESSAGE *) current->next;
+       }
+    }
+
+    if (! found)
+        return NULL;
+
+    // found match, create a copy and erase the original
+    my_message = (MESSAGE *) calloc( 1, sizeof(MESSAGE));
+    if (! my_message)
+        return NULL;
+
+    my_message->text = (char *) calloc( strlen(current->text), sizeof(char));
+    if (! my_message->text)
+    {
+        free(my_message);
+        return NULL;
+    }
+
+    my_message->to = current->to;
+    strcpy(my_message->text, current->text);
+    if (previous)
+       previous->next = current->next;
+    else
+       first_message = (MESSAGE *) current->next;
+
+    if (last_message == current)
+        last_message = previous;
+
+    free(current->text);
+    free(current);
+    return my_message;
+}
+
+
+// Erases the next message in the line without returning anything
+void MESSAGE_QUEUE::Erase()
+{
+   MESSAGE *next_in_line;
+
+   if (first_message)
+   {
+      next_in_line = (MESSAGE *) first_message->next;
+      // clean up
+      if (first_message->text)
+      {
+         free(first_message->text);
+         first_message->text = NULL;
+      }
+      free(first_message);
+
+      // see if we are at the end of the list
+      if (last_message == first_message)
+        last_message = next_in_line;
+
+      first_message = next_in_line;
+   }
+
+}
+
+
+
+// This function erases all messages in the queue.
+void MESSAGE_QUEUE::Erase_All()
+{
+   MESSAGE *current, *coming_up;
+
+   current = first_message;
+   while (current)
+   {
+       coming_up = (MESSAGE *) current->next;
+       if (current->text)
+          free(current->text);
+       free(current);
+       current = coming_up;
+   }
+
+   first_message = last_message = NULL;
+}
+
+
+
+
+
+//
+// Past this point we have socket functions.
+//
+//
+#ifdef NETWORK
+
+
+// Create a socket for listening. Returns a listening socket
+// on success or -1 on failure.
+int Setup_Server_Socket(int port)
+{
+   int listensocket;
+   struct sockaddr_in myaddr;
+   
+   listensocket = socket(AF_INET, SOCK_STREAM, 0);
+   myaddr.sin_port = htons(port);
+   myaddr.sin_addr.s_addr = INADDR_ANY;
+   if (bind(listensocket, (struct sockaddr *) &myaddr, sizeof(myaddr)) < 0) 
+   {
+       printf("Bind failed: %s\n", strerror(errno));
+       return -1;
+   }
+   if (listen(listensocket, 5)) 
+   {
+       printf("Listen failed: %s\n", strerror(errno));
+       return -1;
+   }
+
+   return listensocket;
+}
+
+
+
+
+// Connect to a remote server. Returns -1 on failure or
+// a socket (int) on success.
+int Setup_Client_Socket(char *server_name, char *port)
+{
+   int socket_num, port_number;
+   struct sockaddr_in server_address;
+   struct hostent *server;
+
+   sscanf(port, "%d", &port_number);
+   socket_num = socket(AF_INET, SOCK_STREAM, 0);
+   if (socket_num < 0)
+      return -1;
+   server = gethostbyname(server_name);
+   if (! server)
+      return -1;
+   bzero((char *) &server_address, sizeof(server_address));
+   server_address.sin_family = AF_INET;
+   bcopy((char *) server->h_addr,
+         (char *) &server_address.sin_addr.s_addr,
+         server->h_length);
+   server_address.sin_port = htons(port_number);
+
+   // try to connect
+   if ( connect(socket_num, (sockaddr *)&server_address, sizeof(server_address)) < 0)
+       return -1;
+
+   return socket_num;
+}
+
+
+
+// Accepts an incoming connection request. Returns the
+// new socket connection on success or -1 on failure.
+int Accept_Incoming_Connection(int my_socket)
+{
+   int new_connection;
+   socklen_t my_length;
+   struct sockaddr new_address;
+
+   my_length = sizeof(new_address);
+   new_connection = accept(my_socket, (struct sockaddr *) &new_address, &my_length);
+   return new_connection;
+}
+
+
+
+// Take whatever is in the message and send it
+// to a socket.
+// Returns a negative number on failure. Zero and
+// positive numbers indicate success.
+int Send_Message(MESSAGE *mess, int to_socket)
+{
+    int status;
+    char buffer[MAX_MESSAGE_LENGTH];
+
+    strncpy(buffer, mess->text, MAX_MESSAGE_LENGTH);
+    buffer[MAX_MESSAGE_LENGTH - 1] = '\0';
+    status = write(to_socket, buffer, strlen(buffer) );
+    return status;
+}
+
+
+
+// Read data from a socket and put it in a message
+// Returns the message on success and NULL on failure.
+// Note: the "to" field of the message is not set.
+MESSAGE *Receive_Message(int from_socket)
+{
+  MESSAGE *my_message;
+  int bytes_read;
+  char buffer[MAX_MESSAGE_LENGTH];
+
+  my_message = (MESSAGE *) calloc( 1, sizeof(MESSAGE) );
+  if (! my_message)
+     return NULL;
+
+  memset(buffer, '\0', MAX_MESSAGE_LENGTH);
+  bytes_read = read(from_socket, buffer, MAX_MESSAGE_LENGTH);
+  if (bytes_read > 0)
+  {
+     buffer[MAX_MESSAGE_LENGTH - 1] = '\0';
+     my_message->text = (char *) calloc( strlen(buffer), sizeof(char) );
+     if (! my_message->text)
+     {
+         free(my_message);
+         return NULL;
+     }
+     strcpy(my_message->text, buffer);
+     return my_message;
+  }
+  else   // error while reading
+  {
+      free(my_message);
+      return NULL;
+  }
+
+}
+
+
+
+void Clean_Up_Server_Socket(int my_socket)
+{
+   close(my_socket);
+}
+
+
+void Clean_Up_Client_Socket(int my_socket)
+{
+   close(my_socket);
+}
+
+
+
+// This function checks the socket to see if there is data ready to
+// be read. If there is data ready, then the function returns TRUE. If
+// an error occures, the function returns -1. If there is no data
+// and no error, the function returns FALSE.
+int Check_For_Incoming_Data(int socket_number)
+{
+   fd_set rfds;
+   struct timeval tv;
+   int retval;
+
+   FD_ZERO(&rfds);
+   FD_SET(socket_number, &rfds);
+
+   tv.tv_sec = 0;
+   tv.tv_usec = 0;
+
+   retval = select(socket_number + 1, &rfds, NULL, NULL, &tv);
+
+   if (retval == -1)
+       return -1;
+
+   else if (retval)
+       return TRUE;
+
+   else
+       return FALSE;
+
+    return TRUE;
+}
+
+
+
+
+// This function checks the passed socket for errors. If the socket
+// is error-free, the function returns FALSE. If an exception
+// has occured, the function returns TRUE.
+int Check_For_Errors(int socket_number)
+{
+    fd_set exds;
+    struct timeval tv;
+    int expval;
+
+    FD_ZERO(&exds);
+    FD_SET(socket_number, &exds);
+    tv.tv_sec = 0;
+    tv.tv_usec = 0;
+
+    expval = select(socket_number + 1, NULL, NULL, &exds, &tv);
+
+    if (expval == -1)
+       return TRUE;
+    else if (expval)
+       return TRUE;
+    else
+       return FALSE;
+}
+
+
+
+
+// This function will probably be called as a separate thread at the
+// start of the game. It will set up a listening port, accept
+// incoming connections and manage them. That is, they will be
+// passed on to AI players. 
+void *Send_And_Receive(void *all_the_data)
+{
+   SEND_RECEIVE_TYPE *send_receive_data = (SEND_RECEIVE_TYPE *) all_the_data;
+   int server_socket, new_socket;
+   int status, counter;
+   GLOBALDATA *global = (GLOBALDATA *) send_receive_data->global;
+   bool found;
+
+   // set up listening socket
+   server_socket = Setup_Server_Socket(send_receive_data->listening_port);
+   if (server_socket == -1)
+   {
+      printf("Error creating listening socket.\n");
+      pthread_exit(NULL);
+   }
+
+   while (! send_receive_data->shut_down)
+   {
+      // check for incoming connections
+      status = Check_For_Incoming_Data(server_socket);
+      if (status)
+      {
+         new_socket = Accept_Incoming_Connection(server_socket);
+         printf("Accepted connection.\n");
+         // give connection to AI player
+         found = false;
+         while ( (! found) && (counter < global->numPlayers) )
+         {
+              if ( ( global->players[counter]->type >= USELESS_PLAYER) &&
+                   ( global->players[counter]->type <= DEADLY_PLAYER) )
+              {
+                  found = true;
+                  global->players[counter]->server_socket = new_socket;
+                  global->players[counter]->previous_type = global->players[counter]->type;
+                  global->players[counter]->type = NETWORK_CLIENT;
+                  printf("Assigned connection to %s\n", global->players[counter]->getName() );
+              }
+              else
+                 counter++;
+         }
+         // in case we did not find a match
+         if (! found)
+         {
+            printf("Unable to assign new connection to player.\n");
+            write(new_socket, "NOROOM", strlen("NOROOM") );
+            close(new_socket);
+         }
+      }
+     
+      // consider resting for a moment?
+      usleep(10000);
+   }
+
+   // clean up everything
+   printf("Cleaning up networking\n");
+   Clean_Up_Server_Socket(server_socket);
+   counter = 0;
+   while (counter < global->numPlayers)
+   {
+      if (global->players[counter]->type == NETWORK_CLIENT)
+      {
+          write(global->players[counter]->server_socket, "CLOSE", strlen("CLOSE") );
+          close(global->players[counter]->server_socket);
+      }
+      counter++;
+   }
+
+   pthread_exit(NULL);
+}
+
+
+#endif
+
+
+
diff --git a/src/network.h b/src/network.h
new file mode 100644
index 0000000..3fbdb38
--- /dev/null
+++ b/src/network.h
@@ -0,0 +1,98 @@
+#ifndef NETWORK_HEADER_FILE__
+#define NETWORK_HEADER_FILE__
+
+/*
+This file will contain two sets of headers and data. One for dealing with queued message
+and the other for handling server sockets. This queue will be in standard, platform-neutral
+C++. However, the sockets will use Linux/UNIX/BSD specific code, which will have to be
+updated to run on other operating systems.
+-- Jesse
+*/
+
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define MAX_MESSAGE_LENGTH 256
+
+typedef struct message_struct
+{
+  char *text;
+  int to;   // which client does the message go to? May not be used as most will go to everyone
+  void *next;
+} MESSAGE;
+
+ 
+
+class MESSAGE_QUEUE
+{
+public:
+   MESSAGE *first_message, *last_message;
+
+   MESSAGE_QUEUE();
+   ~MESSAGE_QUEUE();
+
+   // add a message to the queue
+   bool Add(char *some_text, int to);
+
+   // pull the first message from the queue and erase it from the queue
+   MESSAGE *Read();
+
+   // read the next message in the queue without erasing it
+   MESSAGE *Peek();
+
+   MESSAGE *Read_To(int to);
+
+   // erases the next message in the queue without reading it
+   void Erase();
+
+   // erase all messages in the queue
+   void Erase_All();
+   
+};
+
+
+
+typedef struct send_receive_struct
+{
+    int listening_port;
+    int shut_down;
+    void *global;
+} SEND_RECEIVE_TYPE;
+
+
+#ifdef NETWORK
+
+#define MAX_CLIENTS 10
+#define DEFAULT_LISTEN_PORT 25645
+
+int Setup_Server_Socket(int port);
+
+int Setup_Client_Socket(char *server, char *port);
+
+int Accept_Incoming_Connection(int my_socket);
+
+int Send_Message(MESSAGE *mess, int to_socket);
+
+MESSAGE *Receive_Message(int from_socket);
+
+void Clean_Up_Server_Socket(int my_socket);
+
+void Clean_Up_Client_Socket(int my_socket);
+
+int Check_For_Incoming_Data(int socket_number);
+
+int Check_For_Errors(int socket_number);
+
+void *Send_And_Receive(void *data_we_need);
+
+#endif
+
+
+
+#endif
+
diff --git a/src/perlin.cpp b/src/perlin.cpp
new file mode 100644
index 0000000..ed08e9b
--- /dev/null
+++ b/src/perlin.cpp
@@ -0,0 +1,158 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+perlin.cc
+
+Provides noise and interpolation functionality, as prototyped in main.h
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+#include "main.h"
+
+
+
+/*****************************************************************************
+Noise, Noise2D
+
+A floating point pseudorandom number generator.  Given a seed input value,
+returns a randomized double in the range [-1.0,+1.0] .  Maintains no state.
+
+Noise2D requires and uses two integer parameters.
+*****************************************************************************/
+double Noise (int x)
+{
+  x = (x<<13) ^ x;
+  return ( 1.0 - ((x * (x * x * 15731 + 789221) + 1376312589) & 0x7fffffff)
+           / 1073741824.0);
+}
+
+double Noise2D (int x, int y)
+{
+  int n;
+
+  n = x + y * 57;
+  n = (n << 13) ^ n;
+  return ( 1.0 - ( (n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff)
+           / 1073741824.0);
+}
+
+
+
+/*****************************************************************************
+interpolate
+
+Performs a cosine interpolation between two points.  Given two y values
+and a distance between them, return the interpolated y.  x1 and x2 are the y
+values (sorry, it's the best I could explain it).  i is the distance,
+expressed as a percentage of the wave length, ie 0<=i<1 .
+*****************************************************************************/
+/*
+double interpolate (double x1, double x2, double i)
+{
+	double ft = i * M_PI;
+	double f = (1 - cos(ft)) * 0.5;
+
+	return (x1 * (1 - f) + (x2 * f));
+}
+*/
+
+
+double interpolate (double x1, double x2, double i)
+{
+  double ft = i * M_PI;
+  double f = (1 - cos(ft)) * 0.5;
+  double result = (x1 * (1 - f) + (x2 * f));
+
+  if (isnan(x1)||isnan(x2))
+    return 0.0;
+  if (isnan(result))
+    return (x1+x2)/2.0; /* fall back to linear interpolation */
+  return result;
+}
+
+
+
+
+/*
+*
+* For a really good explanation of perlin noise (and where most of this
+*   perlin code was adapted from) see:
+*
+* http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
+*
+* It must be good because I understood it <:-)
+*
+* - Tom Hudson
+*
+*/
+double perlin2DPoint (double amplitude, double scale, double xo, double yo,
+                      double lambda, int octaves)
+{
+  double	maxH = 0;
+  double	h = 0;
+  for (int iteration = 1; iteration <= octaves; iteration++)
+    {
+      double	zoom = scale / (iteration * iteration);
+      double	fractX = xo / zoom;
+      double	fractY = yo / zoom;
+      double	h1 = Noise2D ((int)fractX, (int)fractY);
+      double	h2 = Noise2D ((int)fractX + 1, (int)fractY);
+      double	h3 = Noise2D ((int)fractX, (int)fractY + 1);
+      double	h4 = Noise2D ((int)fractX + 1, (int)fractY + 1);
+
+      double	xi = fractX - (int)fractX;
+      double	yi = fractY - (int)fractY;
+
+      double	i1 = interpolate (h1, h2, xi);
+      double	i2 = interpolate (h3, h4, xi);
+      double	i3 = interpolate (i1, i2, yi);
+
+      h += amplitude * i3;
+      maxH += amplitude;
+
+      amplitude *= lambda;
+    }
+
+  // Normalised
+  return (h / maxH);
+}
+
+double perlin1DPoint (double amplitude, double scale, double xo,
+                      double lambda, int octaves)
+{
+  double	maxH = 0;
+  double	h = 0;
+  for (int iteration = 1; iteration <= octaves; iteration++)
+    {
+      double	zoom = scale / (iteration * iteration);
+      double	fractX = xo / zoom;
+      double	h1 = Noise ((int)fractX);
+      double	h2 = Noise ((int)fractX + 1);
+      double	i = fractX - (int)fractX;
+
+      h += amplitude * interpolate (h1, h2, i);
+      maxH += amplitude;
+
+      amplitude *= lambda;
+    }
+
+  // Normalised
+  return (h / maxH);
+}
+
diff --git a/src/physobj.cpp b/src/physobj.cpp
new file mode 100644
index 0000000..695b95e
--- /dev/null
+++ b/src/physobj.cpp
@@ -0,0 +1,250 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "physobj.h"
+#include "environment.h"
+
+
+void PHYSICAL_OBJECT::initialise ()
+    {
+      VIRTUAL_OBJECT::initialise ();
+      hitSomething = 0;
+    }
+
+
+void PHYSICAL_OBJECT::draw (BITMAP *dest)
+    {
+      VIRTUAL_OBJECT::draw (dest);
+    }
+
+
+
+int  PHYSICAL_OBJECT::checkPixelsBetweenPrevAndNow ()
+    {
+      double startX = x - xv;
+      double startY = y - yv;
+
+      if (checkPixelsBetweenTwoPoints (_global, _env, &startX, &startY, x, y))
+        {
+          x = startX;
+          y = startY;
+          return (1);
+        }
+
+      return (0);
+    }
+
+
+
+/** @brief applyPhysics
+  *
+  * Moves the object according to momentum and wind, boundec off of walls/ceiling/floor, and checks
+  * whether something is hit.
+  */
+int PHYSICAL_OBJECT::applyPhysics()
+{
+  // Normal physics
+
+  double dPrevX = x;
+  double dPrevY = y;
+  if (((x + xv) <= 1) || ((x + xv) >= (_global->screenWidth - 1)))
+    {
+      if	(	(((x + xv) < 1) && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, 1, y))
+           ||(	((x + xv) > (_global->screenWidth - 2))
+               && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, (_global->screenWidth - 2), y))	)
+        {
+          x = dPrevX;
+          y = dPrevY;
+          hitSomething = true;
+        }
+      else
+        {
+          //motion - wind affected
+          switch (_env->current_wallType)
+            {
+            case WALL_RUBBER:
+              xv = -xv;	//bounce on the border
+              break;
+            case WALL_SPRING:
+              xv = -xv * SPRING_CHANGE;
+              break;
+            case WALL_WRAP:
+              if (xv < 0)
+                x = _global->screenWidth - 2; // -1 is the wall itself
+              else
+                x = 1;
+              break;
+            case WALL_STEEL:
+              x += xv;
+              if (x < 1)
+                x = 1;
+              if (x > (_global->screenWidth - 2))
+                x = _global->screenWidth - 2;
+              xv = 0; // already applied!
+              hitSomething = 1; // blow up on steel
+              break;
+            }
+        }
+    }
+  if (!hitSomething)
+    xv += (double)(_env->wind - xv) / mass * drag * _env->viscosity;
+
+  // hit floor or boxed top
+  if ((y + yv >= (_global->screenHeight - 1))
+      ||((y + yv <= MENUHEIGHT) && (_global->bIsBoxed)))
+    {
+      if	(	(	_global->bIsBoxed && ((y + yv) <= MENUHEIGHT)
+             && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, x, MENUHEIGHT + 1))
+           ||(	((y + yv) > (_global->screenHeight - 2))
+               && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, x, (_global->screenHeight - 2)))	)
+        {
+          x = dPrevX;
+          y = dPrevY;
+          hitSomething = true;
+        }
+      else
+        {
+          switch (_env->current_wallType)
+            {
+            case WALL_RUBBER:
+              yv = -yv * 0.5;
+              xv *= 0.95;
+              break;
+            case WALL_SPRING:
+              yv = -yv * SPRING_CHANGE;
+              xv *= 1.05;
+              break;
+            default:
+              // steel or wrap floor (ceiling)
+              y += yv;
+              if (y >= (_global->screenHeight - 1))
+                y = _global->screenHeight - 2; // -1 would be the floor itself!
+              else
+                y = MENUHEIGHT + 1; // +1 or it would be the wall itself
+              yv = 0; // already applied!
+              hitSomething = 1;
+            }
+          if (fabs(xv) + fabs(yv) < 0.8)
+            hitSomething = 1;
+        }
+    }
+
+  // velocity check:
+  /** the old calculation was wrong, but the new one, taking FPS into account, eventually works! **/
+  double dActVelocity = ABSDISTANCE((long double)xv, (long double)yv, 0, 0); // a²+b²=c² ... says Pythagoras :)
+  double dMaxVelocity = _global->dMaxVelocity * (1.20 + ((double)mass / ((double)MAX_POWER / 10.0)));
+  // apply mass, as more mass allows more max velocity:
+
+  // The default means, that a small missile can be accelerated by 25% over MAX_POWER,
+  // while a large Napalm Bomb can go up to 220%.
+
+  if (dActVelocity > dMaxVelocity)
+    {
+#ifdef DEBUG
+      cout << "** Missile too fast!" << endl;
+      cout << "mass: " << mass << " - Max Velocity: " << dMaxVelocity << " (FPS: " << _global->frames_per_second << ")" << endl;
+      cout << "xv: " << xv << " - yv: " << yv << " - Act Velocity: " << dActVelocity << endl;
+#endif // DEBUG
+      // apply *some* velocity, as the thing is killed on its way
+      y += yv / (1.0 + ((double)(rand() % 40) / 10.0)); // This produces somthing
+      x += xv / (1.0 + ((double)(rand() % 40) / 10.0)); // between 1.0 and 5.0
+      xv = 0.0;
+      yv = 0.0;
+      if (y <= MENUHEIGHT)
+        y = MENUHEIGHT + 1;
+      if (y > (_global->screenHeight - 2))
+        y = _global->screenHeight - 2;
+      if ((x < 1) && (_env->current_wallType != WALL_WRAP))
+        x = 1; // Wrapped Explosion takes care for explosions off the screen
+      if ((x > (_global->screenWidth - 2)) && (_env->current_wallType != WALL_WRAP))
+        x = _global->screenWidth - 2; // Wrapped Explosion takes care for explosions off the screen
+      hitSomething = 1;
+    }
+  if (!hitSomething)
+    {
+      x += xv;
+      y += yv;
+      yv += _env->gravity * (100.0 / _global->frames_per_second);
+      // Barrier test:
+      if ( (yv <= -1.0) && (y <= (_global->screenHeight * -25.0)))
+        yv *= -1.0;
+    }
+  else
+    {
+      // if something *is* hit, ensure that that damn thing is on screen! (only y matters here!)
+      if ((y < (MENUHEIGHT + 1)) && _global->bIsBoxed)	y = MENUHEIGHT + 1;
+      if ((y < MENUHEIGHT) && !_global->bIsBoxed)				y = MENUHEIGHT;
+    }
+  return (hitSomething);
+}
+
+/* --- global method --- */
+int checkPixelsBetweenTwoPoints (GLOBALDATA *global, ENVIRONMENT *env, double *startX, double *startY, double endX, double endY)
+{
+  int landFound = 0;
+
+  // only check if on screen
+  double xDist = endX - *startX;
+  double yDist = endY - *startY;
+  double length;
+  double xInc;
+  double yInc;
+
+  if ((fabs(xDist) < 2) && (fabs(yDist) < 2))
+    {
+      if	(	(endX > 0) 													// 0 is the wall!
+           &&(endX < (global->screenWidth - 1))	// -1 is the wall!
+           &&(endY < (global->screenHeight - 1))	// -1 is the floor!
+           &&(endY > (MENUHEIGHT + 1))						// or it would always fail for high shots!
+           &&(getpixel (env->terrain, (int)endX, (int)endY) != PINK)	)
+        return (1);
+      else
+        return (0);
+    }
+
+  length = FABSDISTANCE(xDist, yDist, 0, 0);
+  yInc = yDist / length;
+  xInc = xDist / length;
+
+  // sanity check
+  if (length > (global->screenWidth + global->screenHeight))
+    length = global->screenWidth + global->screenHeight;
+
+  //check all pixels along line for land
+  for (int lengthPos = 0; lengthPos < length; lengthPos++)
+    {
+      //found land
+      if	(	(*startX > 0) 													// 0 is the wall!
+           &&(*startX < (global->screenWidth - 1))		// -1 is the wall!
+           &&(*startY < (global->screenHeight - 1))	// -1 is the floor!
+           &&(*startY > (MENUHEIGHT + 1))						// or it would always fail for high shots!
+           &&(getpixel(env->terrain, (int)*startX, (int)*startY) != PINK)	)
+        {
+          // Leaves startX and Y at current point if within range!
+          landFound = 1;
+          break;
+        }
+      *startX += xInc;
+      *startY += yInc;
+    }
+
+  return (landFound);
+}
+
diff --git a/src/physobj.h b/src/physobj.h
new file mode 100644
index 0000000..32cfd72
--- /dev/null
+++ b/src/physobj.h
@@ -0,0 +1,59 @@
+#ifndef	PHYSOBJ_DEFINE
+#define	PHYSOBJ_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "main.h"
+#include "virtobj.h"
+#include "globaldata.h"
+//#include "environment.h"
+
+class PHYSICAL_OBJECT: public VIRTUAL_OBJECT
+  {
+  public:
+    int	noimpact;
+    int	hitSomething;
+    double	mass;
+    double	drag;
+    int	spin;
+
+    /* --- constructor --- */
+    PHYSICAL_OBJECT ():VIRTUAL_OBJECT(),hitSomething(0) { }
+
+    /* --- pure virtual methods --- */
+    virtual int	isSubClass (int classNum)_PURE;
+    virtual int	getClass ()_PURE;
+
+    /* --- non-virtual methods --- */
+
+    /* --- inline methods --- */
+    int	applyPhysics ();
+
+
+    int	checkPixelsBetweenPrevAndNow ();
+
+    void	initialise ();
+
+    void	draw (BITMAP *dest);
+  };
+
+#endif
+
diff --git a/src/player.cpp b/src/player.cpp
new file mode 100644
index 0000000..64a2171
--- /dev/null
+++ b/src/player.cpp
@@ -0,0 +1,4828 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "environment.h"
+#include "globaldata.h"
+#include "player.h"
+#include "tank.h"
+#include "menu.h"
+#include "files.h"
+#include "floattext.h"
+#include "network.h"
+
+// When defined draws AI 'planning'
+//#define AI_PLANNING_DEBUG	1
+
+PLAYER::PLAYER (GLOBALDATA *global, ENVIRONMENT *env):_global(global),_env(env),_turnStage(0),_target(NULL),
+    _oldTarget(NULL),iTargettingRound(0),revenge(NULL),tank(NULL),pColor(NULL),menuopts(NULL),menudesc(NULL)
+{
+  int my_colour;
+
+  money = 15000;
+  score = 0;
+  played = 0;
+  won = 0;
+  tank = NULL;
+  team = TEAM_NEUTRAL;
+
+  iBoostItemsBought = -1;
+
+  selected = FALSE;
+  changed_weapon = false;
+
+
+  tank_bitmap = 0.0;
+
+  nm[0] = 99;
+  for (int count = 1; count < WEAPONS; count++)
+    nm[count] = 0;
+
+  for (int count = 0; count < ITEMS; count++)
+    ni[count] = 0;
+
+  strncpy (_name, "New", NAME_LENGTH);
+  type = HUMAN_PLAYER;
+
+  // 25% of time set to perplay weapon preferences
+  preftype = (rand () % 4)?ALWAYS_PREF:PERPLAY_PREF;
+//  generatePreferences (); <-- not here!
+
+  defensive = (double)((rand () % 10000) - 5000) / 5000.0;
+  vengeful = rand () % 100;
+  vengeanceThreshold = (double)(rand () % 1000) / 1000.0;
+  revenge = NULL;
+  /** @TODO: These two values are nowhere used.
+    * We should think about a usage, because bot characteristics could become
+    * alot more wide spread with their help. **/
+  selfPreservation = (double)(rand () % 3000) / 1000;
+  painSensitivity = (double)(rand () % 3000) / 1000;
+
+  // color = rand () % WHITE;
+  my_colour = rand() % 4;
+  switch (my_colour)
+    {
+    case 0:
+      color = makecol(200 + (rand() % 56), rand() % 25, rand() % 25);
+      break;
+    case 1:
+      color = makecol( rand() % 25, 200 + (rand() % 56), rand() % 25);
+      break;
+    case 2:
+      color = makecol( rand() % 25, rand() % 25, 200 + (rand() % 56) );
+      break;
+    case 3:
+      color = makecol( 200 + (rand() % 56), rand() % 25, 200 + (rand() % 56));
+      break;
+    }
+  typeText[0] = global->ingame->complete_text[54];
+  typeText[1] = global->ingame->complete_text[55];
+  typeText[2] = global->ingame->complete_text[56];
+  typeText[3] = global->ingame->complete_text[57];
+  typeText[4] = global->ingame->complete_text[58];
+  typeText[5] = global->ingame->complete_text[59];
+  preftypeText[0] = global->ingame->complete_text[60];
+  preftypeText[1] = global->ingame->complete_text[61];
+  tank_type[0] = global->ingame->complete_text[62];
+  tank_type[1] = global->ingame->complete_text[63];
+  tank_type[2] = global->ingame->complete_text[64];
+  tank_type[3] = global->ingame->complete_text[65];
+  tank_type[4] = global->ingame->complete_text[73];
+  tank_type[5] = global->ingame->complete_text[74];
+  tank_type[6] = global->ingame->complete_text[75];
+  tank_type[7] = global->ingame->complete_text[76];
+  teamText[0] = global->ingame->complete_text[66];
+  teamText[1] = global->ingame->complete_text[67];
+  teamText[2] = global->ingame->complete_text[68];
+
+  // Weapon Preferences need to be initalized!
+  for (int weapCount = 0; weapCount < THINGS; weapCount++)
+    _weaponPreference[weapCount] = 0;
+
+  menudesc = NULL;
+  menuopts = NULL;
+  initMenuDesc ();
+  skip_me = false;
+  #ifdef NETWORK
+  server_socket = 0;
+  #endif
+}
+
+/*
+PLAYER::PLAYER (GLOBALDATA *global, ENVIRONMENT *env, ifstream &ifsFile, bool file):_global(global),_env(env),
+    _target(NULL),revenge(NULL),tank(NULL),pColor(NULL),menuopts(NULL),menudesc(NULL)
+{
+  money = 15000;
+  score = 0;
+  _turnStage = 0;
+  selected = FALSE;
+
+  tank_bitmap = 0.0;
+  team = TEAM_NEUTRAL;
+
+  iBoostItemsBought = -1;
+
+  nm[0] = 99;
+  for (int count = 1; count < WEAPONS; count++)
+    nm[count] = 0;
+
+  for (int count = 0; count < ITEMS; count++)
+    ni[count] = 0;
+
+  if (file)
+    loadFromFile(ifsFile);
+
+  type = (int)type;
+
+  typeText[0] = "Human";
+  typeText[1] = "Useless";
+  typeText[2] = "Guesser";
+  typeText[3] = "Ranger";
+  typeText[4] = "Targetter";
+  typeText[5] = "Deadly";
+  preftypeText[0] = "Per Game";
+  preftypeText[1] = "Only Once";
+  tank_type[0] = "Normal";
+  tank_type[1] = "Classic";
+  tank_type[2] = "Big Grey";
+  tank_type[3] = "T34";
+  teamText[0] = "Sith";
+  teamText[1] = "Neutral";
+  teamText[2] = "Jedi";
+  initMenuDesc ();
+  skip_me = false;
+  #ifdef NETWORK
+  net_command[0] = '\0';
+  #endif
+}
+*/
+
+
+int PLAYER::getBoostValue()
+{
+      return ((int)(ni[ITEM_ARMOUR] * ((double) item[ITEM_ARMOUR].vals[0] / (double) item[ITEM_PLASTEEL].vals[0])) + ni[ITEM_PLASTEEL] +
+              (int)(ni[ITEM_INTENSITY_AMP] * ((double) item[ITEM_INTENSITY_AMP].vals[0] / (double) item[ITEM_VIOLENT_FORCE].vals[0])) +
+              ni[ITEM_VIOLENT_FORCE]);
+}
+
+
+
+void PLAYER::setComputerValues (int aOffset)
+{
+  int iType = (int) type + aOffset;
+  if (iType > (int) DEADLY_PLAYER)
+    iType	=	(int) DEADLY_PLAYER;
+  rangeFindAttempts	=	(int)(pow(iType + 1, 2) + 1);				// Useless: 5  , Deadly: 37
+  retargetAttempts  = (int)(pow(iType, 2) + 1);						// Useless: 2  , Deadly: 26
+  focusRate         = ( (double) iType * 2.0) / 10.0;     // Useless: 0.2, Deadly:  1.0
+  errorMultiplier	=	(double)(DEADLY_PLAYER + 1 - iType) / (double)rangeFindAttempts;
+  if (errorMultiplier > 2.0) errorMultiplier	= 2.0;
+}
+
+int displayPlayerName (GLOBALDATA *global, ENVIRONMENT *env, int x, int y, void *data);
+void PLAYER::initMenuDesc ()
+{
+ GLOBALDATA *global = _global;
+  int destroyPlayer (GLOBALDATA *global, ENVIRONMENT *env, void *data);
+  int i = 0;
+  int height = -68;
+
+  // before we get started, eraw any old version of the menu
+  if (menuopts)
+     free(menuopts);
+  if (menudesc)
+     free(menudesc);
+
+  // menudesc = new MENUDESC;
+  menudesc = (MENUDESC *) calloc(1, sizeof(MENUDESC));
+  if (!menudesc)
+    {
+      perror ( "player.cc: Failed allocating memory for menudesc in PLAYER::initMenuDesc");
+      return;
+      // exit (1);
+    }
+  menudesc->title = _name;
+
+  // Name,Color
+  menudesc->numEntries = 10;
+  menudesc->okayButton = TRUE;
+  menudesc->quitButton = FALSE;
+
+  // menuopts = new MENUENTRY[menudesc->numEntries];
+  menuopts = (MENUENTRY *) calloc(menudesc->numEntries, sizeof(MENUENTRY));
+  if (!menuopts)
+    {
+      perror ( "player.cc: Failed allocating memory for menuopts in PLAYER::initMenuDesc");
+      return;
+      // exit (1);
+    }
+
+  //init memory
+  // memset(menuopts, 0, menudesc->numEntries * sizeof(MENUENTRY));
+
+  // Player name
+  menuopts[i].name = global->ingame->complete_text[29];
+  menuopts[i].displayFunc = NULL;
+  menuopts[i].color = color;
+  menuopts[i].value = (double*)_name;
+  menuopts[i].specialOpts = NULL;
+  menuopts[i].type = OPTION_TEXTTYPE;
+  menuopts[i].viewonly = FALSE;
+  menuopts[i].x = _global->halfWidth - 3;
+  menuopts[i].y = _global->halfHeight + height;
+  i++;
+  height += 20;
+
+  // Player colour
+  menuopts[i].name = global->ingame->complete_text[30];
+  menuopts[i].displayFunc = NULL;
+  menuopts[i].color = WHITE;
+  pColor = &color;
+  menuopts[i].value = (double*) pColor;
+  menuopts[i].specialOpts = NULL;
+  menuopts[i].type = OPTION_COLORTYPE;
+  menuopts[i].viewonly = FALSE;
+  menuopts[i].x = _global->halfWidth - 3;
+  menuopts[i].y = _global->halfHeight + height;
+  i++;
+  height += 20;
+
+  // Player type (human, computer)
+  menuopts[i].name = global->ingame->complete_text[31];
+  menuopts[i].displayFunc = NULL;
+  menuopts[i].color = WHITE;
+  menuopts[i].value = (double*)&type;
+  menuopts[i].min = 0;
+  menuopts[i].max = LAST_PLAYER_TYPE - 1;
+  menuopts[i].increment = 1;
+  menuopts[i].defaultv = 0;
+  menuopts[i].format = "%s";
+  menuopts[i].specialOpts = typeText;
+  menuopts[i].type = OPTION_SPECIALTYPE;
+  menuopts[i].viewonly = FALSE;
+  menuopts[i].x = _global->halfWidth - 3;
+  menuopts[i].y = _global->halfHeight + height;
+  i++;
+  height += 20;
+
+  menuopts[i].name = global->ingame->complete_text[20];
+  menuopts[i].displayFunc = NULL;
+  menuopts[i].color = WHITE;
+  menuopts[i].value = (double *)&team;
+  menuopts[i].min = 0;
+  menuopts[i].max = TEAM_JEDI;
+  menuopts[i].increment = 1;
+  menuopts[i].defaultv = TEAM_NEUTRAL;
+  menuopts[i].format = "%s";
+  menuopts[i].specialOpts = teamText;
+  menuopts[i].type = OPTION_SPECIALTYPE;
+  menuopts[i].viewonly = FALSE;
+  menuopts[i].x = _global->halfWidth - 3;
+  menuopts[i].y = _global->halfHeight + height;
+  i++;
+  height += 20;
+
+  // Player preftype (human, computer)
+  menuopts[i].name = global->ingame->complete_text[32];
+  menuopts[i].displayFunc = NULL;
+  menuopts[i].color = WHITE;
+  menuopts[i].value = (double*)&preftype;
+  menuopts[i].min = 0;
+  menuopts[i].max = ALWAYS_PREF;
+  menuopts[i].increment = 1;
+  menuopts[i].defaultv = 0;
+  menuopts[i].format = "%s";
+  menuopts[i].specialOpts = preftypeText;
+  menuopts[i].type = OPTION_SPECIALTYPE;
+  menuopts[i].viewonly = FALSE;
+  menuopts[i].x = _global->halfWidth - 3;
+  menuopts[i].y = _global->halfHeight + height;
+  i++;
+  height += 20;
+
+  menuopts[i].name = global->ingame->complete_text[33];
+  menuopts[i].displayFunc = NULL;
+  menuopts[i].color = WHITE;
+  menuopts[i].value = (double*)&played;
+  menuopts[i].format = "%.0f";
+  menuopts[i].specialOpts = NULL;
+  menuopts[i].type = OPTION_DOUBLETYPE;
+  menuopts[i].viewonly = TRUE;
+  menuopts[i].x = _global->halfWidth - 3;
+  menuopts[i].y = _global->halfHeight + height;
+  i++;
+  height += 20;
+
+  menuopts[i].name = global->ingame->complete_text[34];
+  menuopts[i].displayFunc = NULL;
+  menuopts[i].color = WHITE;
+  menuopts[i].value = (double*)&won;
+  menuopts[i].format = "%.0f";
+  menuopts[i].specialOpts = NULL;
+  menuopts[i].type = OPTION_DOUBLETYPE;
+  menuopts[i].viewonly = TRUE;
+  menuopts[i].x = _global->halfWidth - 3;
+  menuopts[i].y = _global->halfHeight + height;
+  i++;
+  height += 20;
+
+  menuopts[i].name = global->ingame->complete_text[35];
+  menuopts[i].displayFunc = Display_Tank_Bitmap;
+  menuopts[i].color = WHITE;
+  menuopts[i].value = &tank_bitmap;
+  menuopts[i].min = 0;
+  menuopts[i].max = TANK_TYPES;
+  menuopts[i].increment = 1;
+  menuopts[i].defaultv = 0;
+  menuopts[i].format = "%1.0f";
+  menuopts[i].specialOpts = tank_type;
+  menuopts[i].type = OPTION_SPECIALTYPE;
+  menuopts[i].viewonly = FALSE;
+  menuopts[i].x = _global->halfWidth - 3;
+  menuopts[i].y = _global->halfHeight + height;
+  i++;
+  height += 20;
+
+  menuopts[i].name = global->ingame->complete_text[36];
+  menuopts[i].displayFunc = NULL;
+  menuopts[i].color = WHITE;
+  menuopts[i].value = (double*)destroyPlayer;
+  menuopts[i].data = (void*)this;
+  menuopts[i].type = OPTION_ACTIONTYPE;
+  menuopts[i].viewonly = FALSE;
+  menuopts[i].x = _global->halfWidth - 3;
+  menuopts[i].y = _global->halfHeight + height;
+  i++;
+  height += 20;
+
+  menudesc->entries = menuopts;
+}
+
+PLAYER::~PLAYER ()
+{
+  if (tank)
+    delete(tank);
+
+  if (menuopts)
+     free(menuopts);
+    // delete(menuopts);
+  if (menudesc)
+    free(menudesc);
+    // delete(menudesc);
+
+  _global = NULL;
+  _env    = NULL;
+  _target = NULL;
+  revenge = NULL;
+
+  pColor = NULL;
+}
+
+
+
+
+/*
+Save the player settings in text form. Fields are
+formateed as
+[name]=[value]\n
+
+Function returns true on success and false on failure.
+*/
+int PLAYER::saveToFile_Text (FILE *file)
+{
+  int count;
+
+  if (! file) return FALSE;
+  // start section with (char *)"*PLAYER*"
+  fprintf (file, "*PLAYER*\n");
+  fprintf (file, "NAME=%s\n", _name);
+  fprintf (file, "VENGEFUL=%d\n", vengeful);
+  fprintf (file, "VENGEANCETHRESHOLD=%lf\n", vengeanceThreshold);
+  fprintf (file, "TYPE=%lf\n", type);
+  fprintf (file, "TYPESAVED=%lf\n", type_saved);
+  fprintf (file, "COLOR=%d\n", color);
+  fprintf (file, "COLOR2=%d\n", color2);
+  for (count = 0; count < THINGS; count++)
+    fprintf (file, "WEAPONPREFERENCES=%d %d\n", count, _weaponPreference[count]);
+
+  fprintf (file, "PLAYED=%lf\n", played);
+  fprintf (file, "WON=%lf\n", won);
+  fprintf (file, "PREFTYPE=%lf\n", preftype);
+  fprintf (file, "SELFPRESERVATION=%lf\n", selfPreservation);
+  fprintf (file, "PAINSENSITIVITY=%lf\n", painSensitivity);
+  fprintf (file, "DEFENSIVE=%lf\n", defensive);
+  fprintf (file, "TANK_BITMAP=%lf\n", tank_bitmap);
+  fprintf (file, "TEAM=%lf\n", team);
+  fprintf (file, "***\n");
+  return TRUE;
+}
+
+
+/*
+This function tries to load player data from a text file.
+Each line is parsed for (char *)"field=value", except WEAPONPREFERENCES
+which is parsed (char *)"field=index value".
+If all goes well TRUE is returned, on error the function returns FALSE.
+-- Jesse
+*/
+
+int PLAYER::loadFromFile_Text (FILE *file)
+{
+  char line[MAX_CONFIG_LINE];
+  int equal_position, line_length;
+  int index, wp_value;
+  char field[MAX_CONFIG_LINE], value[MAX_CONFIG_LINE];
+  char *result = NULL;
+  bool done = false;
+
+  if (! file) return FALSE;
+
+  // read until we hit line (char *)"*PLAYER*" or "***" or EOF
+  do
+    {
+      result = fgets(line, MAX_CONFIG_LINE, file);
+      if (! result)     // eof
+        return FALSE;
+       if (! strncmp(line, "***", 3) )     // end of record
+         return FALSE;
+    }
+  while ( strncmp(line, "*PLAYER*", 8) );     // read until we hit new record
+
+  while ( (result) && (!done) )
+    {
+      // read a line
+      memset(line, '\0', MAX_CONFIG_LINE);
+      result = fgets(line, MAX_CONFIG_LINE, file);
+      if (result)
+        {
+          // if we hit end of the record, stop
+          if (! strncmp(line, "***", 3) ) return TRUE;
+          // find equal sign
+         line_length = strlen(line);
+          // strip newline character
+          if ( line[line_length - 1] == '\n')
+            {
+              line[line_length - 1] = '\0';
+              line_length--;
+            }
+          equal_position = 1;
+          while ( ( equal_position < line_length) && (line[equal_position] != '=') )
+           equal_position++;
+          // make sure we have valid equal sign
+          if (equal_position <= line_length)
+            {
+              // seperate field from value
+              memset(field, '\0', MAX_CONFIG_LINE);
+              memset(value, '\0', MAX_CONFIG_LINE);
+              strncpy(field, line, equal_position);
+              strcpy(value, & (line[equal_position + 1]));
+              // check which field we have and process value
+              if (! strcasecmp(field, "name") )
+                strncpy(_name, value, NAME_LENGTH);
+              else if (! strcasecmp(field, "vengeful") )
+                sscanf(value, "%d", &vengeful);
+              else if (! strcasecmp(field, "vengeancethreshold") )
+                sscanf(value, "%lf", &vengeanceThreshold);
+              else if (! strcasecmp(field, "type") )
+                sscanf(value, "%lf", &type);
+              else if (! strcasecmp(field, "typesaved") )
+                {
+                  sscanf(value, "%lf", &type_saved);
+                  if (type_saved > HUMAN_PLAYER)
+                    type = type_saved;
+                }
+              else if (! strcasecmp(field, "color") )
+                sscanf(value, "%d", &color);
+              else if (! strcasecmp(field, "color2") )
+                sscanf(value, "%d", &color2);
+              else if (! strcasecmp(field, "played") )
+                sscanf(value, "%lf", &played);
+              else if (! strcasecmp(field, "won") )
+                sscanf(value, "%lf", &won);
+              else if (! strcasecmp(field, "preftype") )
+                sscanf(value, "%lf", &preftype);
+              else if (! strcasecmp(field, "selfpreservation") )
+                sscanf(value, "%lf", &selfPreservation);
+              else if (! strcasecmp(field, "painsensititveity") )
+                sscanf(value, "%lf", &painSensitivity);
+              else if (! strcasecmp(field, "defensive") )
+                sscanf(value, "%lf", &defensive);
+              else if (! strcasecmp(field, "tank_bitmap") )
+                sscanf(value, "%lf", &tank_bitmap);
+              else if (! strcasecmp(field, "team") )
+                sscanf(value, "%lf", &team);
+              else if (! strcasecmp(field, "weaponpreferences") )
+                {
+                  sscanf(value, "%d %d", &index, &wp_value);
+                  if ( (index < THINGS) && (index >= 0) )
+                    _weaponPreference[index] = wp_value;
+                }
+
+            }    // end of valid data line
+        }      // end of if we read a line properly
+    }   // end of while not done
+
+  // make sure previous human players are restored as humans
+  if (type == PART_TIME_BOT)
+    type = HUMAN_PLAYER;
+
+  return TRUE;
+}
+
+
+
+
+void PLAYER::exitShop ()
+{
+  double tmpDM = 0;
+
+  damageMultiplier = 1.0;
+  tmpDM += ni[ITEM_INTENSITY_AMP] * item[ITEM_INTENSITY_AMP].vals[0];
+  tmpDM += ni[ITEM_VIOLENT_FORCE] * item[ITEM_VIOLENT_FORCE].vals[0];
+  if (tmpDM > 0)
+    damageMultiplier += pow (tmpDM, 0.6);
+}
+
+
+// run this at the begining of each turn
+void PLAYER::newRound ()
+{
+  // if the player is under computer control, give it back to the player
+  if ( type == PART_TIME_BOT )
+    type = HUMAN_PLAYER;
+
+  setComputerValues ();
+
+  if (!tank)
+    {
+      tank = new TANK(_global, _env);
+      if (tank)
+      {
+        tank->player = this;
+        tank->initialise();
+      }
+      else
+          perror ( "player.cc: Failed allocating memory for tank in PLAYER::newRound");
+    }
+  // newRound() doesn't need to be called, because ENVIRONMENT::newRound() has already done that!
+
+  changed_weapon = false;
+  // if we are playing in a campaign, raise the AI level
+  if (_global->campaign_mode)
+    {
+      if ( (type > HUMAN_PLAYER) && (type < DEADLY_PLAYER) )
+        type += 1.0;
+    }
+
+  // forget revenge under certain circumstances
+  if (revenge)
+    {
+      if ((team != TEAM_NEUTRAL) && (team == revenge->team))
+        revenge = NULL; // No more round breaking revenge on team mates!
+      else if (  (team == TEAM_NEUTRAL)
+                 ||((team != TEAM_NEUTRAL) && (revenge->team == TEAM_NEUTRAL)))
+        {
+          // neutral to !neutral and vice versa might forget...
+          if (  (!(rand() % (int)labs((type + 3) / 2)))
+                ||((rand() % 100) > vengeful) )
+            revenge = NULL;
+          /* This gives:
+           * USELESS: (1 + 3) / 2) = 2 => 50%
+           * GUESSER: (2 + 3) / 2) = 2 => 50%
+           * RANGEFI: (3 + 3) / 2) = 3 => 34%
+           * TARGETT: (4 + 3) / 2) = 3 => 34%
+           * DEADLY : (5 + 3) / 2) = 4 => 25%
+           * chance to "forgive". Should be okay...
+           * The check against "vengeful" makes "peacefull" bots to forget more easily
+           */
+        }
+    }
+
+  if (!revenge && (rand() % ((int)type + 1)))
+    {
+      // If there is no revengee there is a small chance the player will seek the leader!
+      int iMaxScore = score;
+      int iCurScore = 0;
+      for (int i = 0; i < _global->numPlayers; i++)
+        {
+          if (_global->players[i])
+            {
+              iCurScore = _global->players[i]->score;
+              if (  (iCurScore > iMaxScore)
+                    &&( (team == TEAM_NEUTRAL)
+                        ||(team != _global->players[i]->team)) )
+                {
+                  // Higher score found, record as possible revengee
+                  iMaxScore = iCurScore;
+                  if (abs(iMaxScore - score) > (int)type)
+                    revenge = _global->players[i];
+                }
+            }
+        }
+    }
+
+  time_left_to_fire = (int) _global->max_fire_time;
+  skip_me = false;
+  iTargettingRound = 0;
+  _target = NULL;
+  _oldTarget = NULL;
+  last_shield_used = 0;
+}
+
+
+void PLAYER::initialise ()
+{
+  long int totalPrefs;
+  int rouletteCount;
+
+  nm[0] = 99;
+  for (int count = 1; count < WEAPONS; count++)
+    nm[count] = 0;
+
+  for (int count = 0; count < ITEMS; count++)
+    ni[count] = 0;
+
+  totalPrefs = 0;
+  for (int weapCount = 0; weapCount < THINGS; weapCount++)
+    totalPrefs += _weaponPreference[weapCount];
+
+  rouletteCount = 0;
+  for (int weapCount = 0; weapCount < THINGS; weapCount++)
+    {
+      int weapRSpace = (int)((double)_weaponPreference[weapCount] / totalPrefs * NUM_ROULETTE_SLOTS);
+      int weapRCount = 0;
+
+      if (weapRSpace < 1)
+        weapRSpace = 1;
+      while (weapRCount < weapRSpace && rouletteCount + weapRCount < NUM_ROULETTE_SLOTS)
+        {
+          _rouletteWheel[rouletteCount + weapRCount] = weapCount;
+          weapRCount++;
+        }
+      rouletteCount += weapRSpace;
+    }
+  while (rouletteCount < NUM_ROULETTE_SLOTS)
+    _rouletteWheel[rouletteCount++] = rand () % THINGS;
+
+  kills       = 0;
+  killed       = 0;
+  tank        = NULL;
+  _target     = NULL;
+  _oldTarget  = NULL;
+}
+
+void PLAYER::generatePreferences ()
+{
+  double dBaseProb	=	(double) MAX_WEAP_PROBABILITY / 2.0;
+  int currItem	=	0;
+  double dWorth;
+  int iValue;
+  bool	bIsWarhead	= false;
+  int iMaxWeapPref = 0;
+  int iMaxItemPref = 0;
+
+  defensive	=	(2.0 * ( (double) rand () / (double) RAND_MAX)) - 1.0;
+  double dDefenseMod = (defensive * -1.0) + 2.0;
+  // DefenseMod will be between 1.0 (defensive) and 3.0 (offensive)
+  // and is used to modifiy vengeful, vengeanceThreshold, selfPreservation and painSensitivity
+  vengeful *= 1.0 + (dDefenseMod / 5.0); // +0% - +60% (defensive - offensive)
+  if (vengeful > 100) vengeful = 100;
+  vengeanceThreshold *= 1.0 - (dDefenseMod / 5.0); // -0% - -60%
+  selfPreservation /= dDefenseMod;
+  painSensitivity  /= dDefenseMod;
+
+  // Now defensive can be modified by team:
+  if (team == TEAM_JEDI)
+    {
+      defensive += (double)((double)(rand() % 1000)) / 1000.0;
+      if (defensive > 1.25)
+        defensive = 1.25; // + 1.25 is SuperDefensive
+    }
+  if (team == TEAM_SITH)
+    {
+      defensive -= (double)((double)(rand() % 1000)) / 1000.0;
+      if (defensive < -1.25)
+        defensive = -1.25; // - 1.25 is SuperAggressive
+    }
+#ifdef DEBUG
+  cout << "Generating Preferences for \"" << getName() << "\" (" << defensive << ")" << endl;
+  cout << "----------------------------------------------------" << endl;
+#endif // DEBUG
+  _weaponPreference[0] = 0; // small missiles are always zero!
+  for (int weapCount = 1; weapCount < THINGS; weapCount++)
+    {
+      dWorth			=	-1.0 * ( (double) MAX_WEAP_PROBABILITY / 4.0);
+      bIsWarhead	=	false;
+      if (weapCount < WEAPONS)
+        {
+          // Talking about weapons
+          currItem	=	weapCount;
+          if (weapon[currItem].warhead || ( (currItem >= SML_METEOR) && (currItem <= LRG_LIGHTNING)))
+            bIsWarhead	=	true; // Bots don't think about warheads or environment!
+          else
+            {
+              // 1. Damage:
+              int iWarheads = weapon[currItem].spread; // For non-spread this is always 1
+              if (weapon[currItem].numSubmunitions > 0)
+                {
+                  iWarheads	=	weapon[currItem].numSubmunitions;	// It's a cluster
+
+                  dWorth		= weapon[weapon[currItem].submunition].damage * iWarheads; // total damage for clusters
+
+                  if	( ( (currItem >= SML_NAPALM) && (currItem <= LRG_NAPALM))
+                       || ( (currItem >= FUNKY_BOMB) && (currItem <= FUNKY_DEATH)))
+                    dWorth /= defensive + 1.0 + ( (double) type / 2.0);
+                  // These weapons are too unpredictable to be counted full
+                  // But a true offensive useless bot devides only by 1.0 (not all all, doesn't mind)
+                  // And a true defensive deadly bot devides by 5.0
+                  if (dWorth > dBaseProb) dWorth = dBaseProb; // Or Large Napalm will always be everybodys favorite
+                }
+              else
+                dWorth			=	weapon[currItem].damage * (iWarheads * 2.0);	// total damage for (non-)spreads
+              // Note: iWarheads is counted twice, because otherwise spread weapons get far too low score!
+              dWorth = dWorth * (dBaseProb * 0.0005); // 1 Damage is worth 0.5%o of dBaseProb
+
+              // 2. Defensiveness multiplier
+              // As said above, defensive players avoid spread/cluster weapons. Thus they rate non-spreads higher:
+              if (iWarheads == 1)
+                dWorth *= (defensive + 1.5) * ( (double) type / 2.0);
+              else
+                dWorth -= (defensive * ( (double) type / 2.0)) * dWorth;
+
+              // 3. Dirtballs do no damage and have to be rated by defensiveness
+              if ( (currItem >= DIRT_BALL) && (currItem <= SUP_DIRT_BALL))
+                dWorth = (double) (currItem - (double) DIRT_BALL + 1.0) * 150.0 * ( (double) type / 2.0) * (defensive + 2.0);
+
+              // 4.: Shaped charges, wide boys and cutters are deadly but limited:
+              if ( (currItem	>= SHAPED_CHARGE) && (currItem <= CUTTER))
+                dWorth *= 1.0 - ( ( (double) type + (defensive * 5.0)) / 20.0);
+              // useless, full offensive: * 1.20
+              // deadly, full defensive : * 0.50
+
+              // 5.: rollers and penetrators are modified by type, as they *are* usefull
+              if	(	((currItem >= SML_ROLLER) && (currItem <= DTH_ROLLER))
+                   ||((currItem >= BURROWER) && (currItem <= PENETRATOR)))
+                dWorth *= 1.0 + ((double)type / 10.0) + (defensive  / 2);
+
+              // 6.: Tectonis need to be raised!
+              if ((currItem >= TREMOR) && (currItem <= TECTONIC))
+                dWorth *= 2.0 + ((double)type / 10.0) + (defensive  / 2);
+
+              // finally dWorth must not be greater than the 3/4 of MAX_WEAPON_PROBABILITY
+              if (dWorth > (MAX_WEAP_PROBABILITY * 0.75))
+                dWorth	=	MAX_WEAP_PROBABILITY * 0.75;
+            }
+        }
+      else
+        {
+          // Talking about items
+          currItem	=	weapCount - WEAPONS;
+          // unfortunately we can only switch here...
+          /* Theory:
+          		As for armour/amps/shields, offensive bots go for amps and reflector
+          		shields, defensive bots go for armour and hard shields.	*/
+          switch (currItem)
+            {
+            case ITEM_TELEPORT:
+              dWorth = -1.0 * ((defensive - 1.5) * ((double)MAX_WEAP_PROBABILITY / 10.0));
+              break;
+            case ITEM_SWAPPER:
+              dWorth = -1.0 * ((defensive - 1.5) * ((double)MAX_WEAP_PROBABILITY / 7.5));
+              break;
+            case ITEM_FAN:
+              dWorth = 0.0; // useless things!
+              break;
+            case ITEM_VENGEANCE:
+            case ITEM_DYING_WRATH:
+            case ITEM_FATAL_FURY:
+              dWorth = (defensive + 1.5) * ((double)weapon[(int)item[currItem].vals[0]].damage * (double)item[currItem].vals[1]);
+              break;
+            case ITEM_ARMOUR:
+            case ITEM_PLASTEEL:
+              dWorth	=	dBaseProb * ( (double) item[currItem].vals[0] / (double) item[ITEM_PLASTEEL].vals[0]);
+              dWorth	*=	defensive;
+              break;
+            case ITEM_LGT_SHIELD:
+            case ITEM_MED_SHIELD:
+            case ITEM_HVY_SHIELD:
+              dWorth	=	dBaseProb * ( (double) item[currItem].vals[0] / (double) item[ITEM_HVY_SHIELD].vals[0]);
+              dWorth	*=	defensive;
+              break;
+            case ITEM_INTENSITY_AMP:
+            case ITEM_VIOLENT_FORCE:
+              dWorth	=	dBaseProb * ( (double) item[currItem].vals[0] / (double) item[ITEM_VIOLENT_FORCE].vals[0]);
+              dWorth	*=	(-1.0 * defensive);
+              break;
+            case ITEM_LGT_REPULSOR_SHIELD:
+            case ITEM_MED_REPULSOR_SHIELD:
+            case ITEM_HVY_REPULSOR_SHIELD:
+              dWorth	=	dBaseProb * ( (double) item[currItem].vals[0] / (double) item[ITEM_HVY_REPULSOR_SHIELD].vals[0]);
+              dWorth	*=	(-1.0 * defensive);
+              break;
+            case ITEM_REPAIRKIT:
+              dWorth	=	dBaseProb * ( (defensive + 1.0) / 2.0);
+              break;
+            case ITEM_PARACHUTE:
+              dWorth	=	dBaseProb * ( (defensive + 1.0) / 1.5);	// Parachutes *are* popular! :)
+              break;
+            case ITEM_SLICKP:
+              dWorth	=	(int) type * 250;
+              break;
+            case ITEM_DIMPLEP:
+              dWorth	=	(int) type * 500;
+              break;
+            case ITEM_FUEL:
+              dWorth	=	-5000;	// Bots don't need  fuel
+              bIsWarhead	=	true;	// Yes, it's a lie. ;-)
+            }
+          // dWorth must not be greater than the half of MAX_WEAPON_PROBABILITY
+          if (dWorth > (MAX_WEAP_PROBABILITY / 2))
+            dWorth	=	MAX_WEAP_PROBABILITY / 2;
+        }
+      iValue	=	fabs (dWorth);
+      if (iValue < (MAX_WEAP_PROBABILITY / 10)) iValue = MAX_WEAP_PROBABILITY / 10;
+      dWorth += (double) (rand() % iValue); // allow to double (more or less)
+
+      if (dWorth	>	MAX_WEAP_PROBABILITY)
+        dWorth	=	MAX_WEAP_PROBABILITY;
+      if (dWorth	<	(MAX_WEAP_PROBABILITY / 100.0))
+        dWorth	=	MAX_WEAP_PROBABILITY / 100.0; // Which is very very little...
+
+      if (bIsWarhead)
+        _weaponPreference[weapCount] = 0;	// It will not get any slot!
+      else
+        _weaponPreference[weapCount] = (int) dWorth;
+
+      if ((weapCount  < WEAPONS) && (_weaponPreference[weapCount] > iMaxWeapPref))
+        iMaxWeapPref = _weaponPreference[weapCount];
+      if ((weapCount >= WEAPONS) && (_weaponPreference[weapCount] > iMaxItemPref))
+        iMaxItemPref = _weaponPreference[weapCount];
+
+#ifdef DEBUG
+      if (weapCount < WEAPONS)
+        printf( "%23s (weapon): % 5d", weapon[weapCount].name, _weaponPreference[weapCount]);
+      else
+        printf( "%23s ( item ): % 5d", item[weapCount-WEAPONS].name, _weaponPreference[weapCount]);
+      cout << endl;
+#endif // DEBUG
+    }
+
+  // Before we are finished, we need to amplify the preferences (well, maybe...)
+  if (iMaxWeapPref < MAX_WEAP_PROBABILITY)
+    {
+      // Yes, amplification for the weapons needed!
+      dWorth = (double)MAX_WEAP_PROBABILITY / (double)iMaxWeapPref;
+      for (int weapCount = 1; weapCount < WEAPONS; weapCount++)
+        {
+          if (_weaponPreference[weapCount] > (MAX_WEAP_PROBABILITY / 100.0))
+            {
+              _weaponPreference[weapCount] = (int)((double)_weaponPreference[weapCount] * dWorth);
+#ifdef DEBUG
+              printf( "%23s (weapon) amplified to: % 5d", weapon[weapCount].name, _weaponPreference[weapCount]);
+              cout << endl;
+#endif // DEBUG
+            }
+        }
+    }
+  if (iMaxItemPref < MAX_WEAP_PROBABILITY)
+    {
+      // Yes, amplification for the items needed!
+      dWorth = (double)MAX_WEAP_PROBABILITY / (double)iMaxItemPref;
+      for (int weapCount = WEAPONS; weapCount < THINGS; weapCount++)
+        {
+          if (_weaponPreference[weapCount] > (MAX_WEAP_PROBABILITY / 100.0))
+            {
+              _weaponPreference[weapCount] = (int)((double)_weaponPreference[weapCount] * dWorth);
+#ifdef DEBUG
+              printf( "%23s ( item ) amplified to: % 5d", item[weapCount-WEAPONS].name, _weaponPreference[weapCount]);
+              cout << endl;
+#endif // DEBUG
+            }
+        }
+    }
+
+#ifdef DEBUG
+  cout << "===================================================" << endl << endl;
+#endif // DEBUG
+}
+
+int PLAYER::selectRandomItem ()
+{
+  // return (_rouletteWheel[rand () % NUM_ROULETTE_SLOTS]);
+  return rand() % THINGS;
+}
+
+void PLAYER::setName (char *name)
+{
+  // initalize name
+  memset(_name, '\0', NAME_LENGTH);
+  strncpy (_name, name, NAME_LENGTH - 1);
+}
+
+int PLAYER::controlTank ()
+{
+  if (key[KEY_F1])
+    save_bmp ( "scrnshot.bmp", _env->db, NULL);
+
+  if (key_shifts & KB_CTRL_FLAG && ctrlUsedUp)
+    {
+      if (key[KEY_LEFT] || key[KEY_RIGHT] ||
+          key[KEY_UP] || key[KEY_DOWN] ||
+          key[KEY_PGUP] || key[KEY_PGDN] ||
+          key[KEY_A] || key[KEY_D] ||         //additional control
+          key[KEY_W] || key[KEY_S] ||
+          key[KEY_R] || key[KEY_F])
+        ctrlUsedUp = TRUE;
+      else
+        ctrlUsedUp = FALSE;
+    }
+  else
+    {
+      ctrlUsedUp = FALSE;
+    }
+
+  if (_global->computerPlayersOnly &&
+      ((int)_global->skipComputerPlay >= SKIP_HUMANS_DEAD))
+    {
+      if (_env->stage == STAGE_ENDGAME)
+        return (-1);
+    }
+
+  k = 0;
+  #ifdef NEW_GAMELOOP
+  if ( keypressed() )
+  #else
+  if (keypressed () && !fi)
+  #endif
+    {
+      k = readkey ();
+
+      if ((_env->stage == STAGE_ENDGAME) &&
+          (k >> 8 == KEY_ENTER ||
+           k >> 8 == KEY_ESC ||
+           k >> 8 == KEY_SPACE))
+        return (-1);
+      if ( (k >> 8 == KEY_ESC) || (k >> 8 == KEY_P) )
+        {
+          void clockadd ();
+          install_int_ex (clockadd, SECS_TO_TIMER(6000));
+          int mm = _env->ingamemenu ();
+          install_int_ex(clockadd, BPS_TO_TIMER(_global->frames_per_second));
+          _env->make_update (0, 0, _global->screenWidth, _global->screenHeight);
+          _env->make_bgupdate (0, 0, _global->screenWidth, _global->screenHeight);
+
+          //Main Menu
+          if (mm == 1)
+          {
+              _global->wr_lock_command();
+              _global->command = GLOBAL_COMMAND_MENU;
+              _global->unlock_command();
+              return (-1);
+          }
+          else if (mm == 2)  //Quit game
+          {
+              _global->wr_lock_command();
+              _global->command = GLOBAL_COMMAND_QUIT;
+              _global->unlock_command();
+              return (-1);
+          }
+          else if (mm == 3)   // skip AI
+          {
+              return (-2);
+          }
+        }
+      // check for number key being pressed
+      if ( (k >> 8 >= KEY_0) && (k >> 8 <= KEY_9) )
+        {
+          int value = (k >> 8) - KEY_0;
+
+          // make sure the value is within range
+          if (value < _global->numPlayers)
+            {
+              if ( _global->players[value] )
+                {
+                  TANK *my_tank = _global->players[value]->tank;
+                  if (my_tank)
+                    {
+                      sprintf(_global->tank_status, "%s: %d + %d -- Team: %s", _global->players[value]->_name, my_tank->l, my_tank->sh, _global->players[value]->Get_Team_Name() );
+                      /* We do this in atanks.cpp, to kill this wretched "No Format Error"
+                      strcat(_global->tank_status, _global->players[value]->Get_Team_Name()); */
+                      _global->tank_status_colour = _global->players[value]->color;
+                      _global->updateMenu = 1;
+                    }
+                  else
+                    _global->tank_status[0] = 0;
+                }
+            }
+
+        }    // end of check status keys
+    }
+
+  if ((int)type == HUMAN_PLAYER || !tank)
+  {
+      return (humanControls ());
+  }
+  #ifdef NETWORK
+  else if ((int) type == NETWORK_CLIENT)
+      return (Execute_Network_Command(TRUE));
+  #endif
+  else if (_env->stage == STAGE_AIM)
+  {
+      return (computerControls ());
+  }
+  return (0);
+}
+
+int PLAYER::computerSelectPreBuyItem (int aMaxBoostValue)
+{
+  double dMood = 1.0 + defensive + (double) ( (double) (rand() / ( (double) RAND_MAX / 2.0)));
+  // dMood is 0.0 <= x <= 4.0
+  int currItem = 0;
+  /*	Prior buying anything else, a 5 step system takes place:
+  		1.: Parachutes (if gravity is on)
+  		2.: Minimum weapon probability (aka 5 medium and 3 large missiles
+  		3.: Armor/Amps
+  		4.: "Tools" to free themselves like Riot Blasts
+  		5.: Shields, if enough money is there
+  		6.: if all is set, look for dimpled/slick projectiles! */
+
+  // Step 1:
+
+  if	( (type >= RANGEFINDER_PLAYER)
+       && (_env->landSlideType > LANDSLIDE_NONE)
+       && (ni[ITEM_PARACHUTE] < 10))
+    currItem = WEAPONS + ITEM_PARACHUTE;
+
+  // Step 3:
+  // Even here bots might forget
+  if	(!currItem && (rand() % ( (int) type + 1)))
+    {
+      int iLimit = aMaxBoostValue - getBoostValue(); // > 0 means: Someone has more than we have!
+#ifdef DEBUG
+      printf( "%10s: Boost: %4d, Max: %4d, Limit: %4d\n", getName(), getBoostValue(), aMaxBoostValue, iLimit);
+#endif // DEBUG
+      if ( ((dMood >= 2.75) && (iLimit > 0)) || ((dMood >= 2.0) && (iLimit > getBoostValue())) )
+        {
+          // The player is in a defensive mood
+          // If we have 25% more money than the plasteel cost, buy it, else the armour will do
+          if (money >= (item[ITEM_PLASTEEL].cost * 1.25))
+            currItem = WEAPONS + ITEM_PLASTEEL;
+          else
+            if	( (money >= (item[ITEM_ARMOUR].cost * 2.0))
+                 && ( (ni[ITEM_ARMOUR] < ni[ITEM_PLASTEEL])
+                      || (dMood >= 3.5)))
+              currItem = WEAPONS + ITEM_ARMOUR;
+        }
+
+      // Now iBoostItemsBought must be checked:
+      if (currItem && (iBoostItemsBought >= (int)type))
+        currItem = 0; // Sorry, bought enough this round!
+      if (currItem && (iBoostItemsBought < (int)type))
+        iBoostItemsBought++; // Okay, take it!
+    }
+
+  // 5.: Shields
+  if (!currItem && (rand() % ( (int) type + 1)) && ( (int) type >= RANGEFINDER_PLAYER))
+    {
+      if (dMood <= 1.5)
+        {
+          // offensive type, go through reflectors
+          if ( (ni[ITEM_LGT_REPULSOR_SHIELD] <= (item[ITEM_LGT_REPULSOR_SHIELD].amt * (int) type))
+               && (money >= (item[ITEM_LGT_REPULSOR_SHIELD].cost * 2.0)))
+            currItem	=	WEAPONS + ITEM_LGT_REPULSOR_SHIELD;
+
+          if ( (ni[ITEM_MED_REPULSOR_SHIELD] <= (item[ITEM_MED_REPULSOR_SHIELD].amt * (int) type))
+               && (money >= (item[ITEM_MED_REPULSOR_SHIELD].cost * 1.75)))
+            currItem	=	WEAPONS + ITEM_MED_REPULSOR_SHIELD;
+
+          if ( (ni[ITEM_HVY_REPULSOR_SHIELD] <= (item[ITEM_HVY_REPULSOR_SHIELD].amt * (int) type))
+               && (money >= (item[ITEM_HVY_REPULSOR_SHIELD].cost * 1.5)))
+            currItem	=	WEAPONS + ITEM_HVY_REPULSOR_SHIELD;
+        }
+
+      if (dMood >= 2.5)
+        {
+          // defensive type, go through hard shields
+          if ( (ni[ITEM_LGT_SHIELD] <= (item[ITEM_LGT_SHIELD].amt * (int) type))
+               && (money >= (item[ITEM_LGT_SHIELD].cost * 2.0)))
+            currItem	=	WEAPONS + ITEM_LGT_SHIELD;
+
+          if ( (ni[ITEM_MED_SHIELD] <= (item[ITEM_MED_SHIELD].amt * (int) type))
+               && (money >= (item[ITEM_MED_SHIELD].cost * 1.75)))
+            currItem	=	WEAPONS + ITEM_MED_SHIELD;
+
+          if ( (ni[ITEM_HVY_SHIELD] <= (item[ITEM_HVY_SHIELD].amt * (int) type))
+               && (money >= (item[ITEM_HVY_SHIELD].cost * 1.5)))
+            currItem	=	WEAPONS + ITEM_HVY_SHIELD;
+        }
+    }
+
+  return (currItem);
+}
+
+int PLAYER::chooseItemToBuy (int aMaxBoostValue)
+{
+  int currItem = computerSelectPreBuyItem (aMaxBoostValue);
+  int oldItem = 0;
+  int itemNum = 0;
+  int cumulative;
+  int nextMod, curramt, newamt;
+  int iTRIES = THINGS; // pow((int)type + 1, 2);
+  int iDesiredItems[iTRIES]; // Deadly bots have large shopping carts. ;)
+  bool bIsSorted = false; // Whether the cart is sorted or not
+  bool bIsPreSelected = currItem?true:false;	// Whether or not the PreBuy steps found something
+  int i = 0;
+
+  if (currItem)
+  {
+       if ( Buy_Something(currItem) )
+         return currItem;
+  }
+
+  // init desired items
+  for (i = 0; i < iTRIES; i++)
+     iDesiredItems[i] = 0;
+ 
+  // 1.: Fill cart
+  i = 0;
+  while (i < iTRIES)
+    {
+      // while (currItem == oldItem)
+      currItem = (int) fabs (selectRandomItem());
+      oldItem = currItem;
+      if (currItem >= THINGS)
+        currItem	%=	THINGS;	// Put in range
+      // now currItem is 0<= currItem < THINGS
+      if ( (_env->isItemAvailable (currItem)) && (currItem != 0))
+        {
+          iDesiredItems[i]	=	currItem;
+        }
+        i++;
+    }
+
+  // 2.: sort these items by preferences
+  while (!bIsSorted)
+    {
+      if (bIsPreSelected)
+        i = 2; // The first item shall not be sorted somewhere else!
+      else
+        i = 1;
+      bIsSorted	=	true;
+      while (i < iTRIES)
+        {
+          if (_weaponPreference[iDesiredItems[i-1]] < _weaponPreference[iDesiredItems[i]])
+            {
+              bIsSorted	=	false;
+              currItem	=	iDesiredItems[i];
+              iDesiredItems[i]	=	iDesiredItems[i-1];
+              iDesiredItems[i-1] =	currItem;
+            }
+          i++;
+        }
+    }
+
+  // 3.: loop through all weapon preferences
+  for (int i = 0; i < iTRIES; i++)
+    {
+      currItem	=	iDesiredItems[i];
+      itemNum = currItem - WEAPONS;
+      //determine the likelyhood of purchasing this selection
+      //less likely the more of the item is owned
+      //if have zero of item, it is a fifty/fifty chance of purchase
+      if (currItem < WEAPONS)
+        {
+          curramt = nm[currItem];
+          newamt = weapon[currItem].amt;
+          cumulative = FALSE;
+        }
+      else
+        {
+          curramt = ni[itemNum];
+          newamt = item[itemNum].amt;
+          if ( (itemNum >= ITEM_INTENSITY_AMP &&
+                itemNum <= ITEM_VIOLENT_FORCE) ||
+               (itemNum == ITEM_REPAIRKIT) ||
+               (itemNum >= ITEM_ARMOUR &&
+                itemNum <= ITEM_PLASTEEL))
+            cumulative = TRUE;
+          else
+            cumulative = FALSE;
+        }
+      nextMod = 1;
+      if (!cumulative)
+        nextMod = curramt / newamt;
+      if (nextMod <= 0)
+        nextMod = 1;
+      if (rand () % nextMod)
+        continue;
+
+      //weapon
+      if (currItem < WEAPONS)
+        {
+          //don't buy if already maxed out
+          if (nm[currItem] >= 99)
+            continue;
+
+          //purchase the item
+          if (money >= weapon[currItem].cost)
+            {
+              money -= weapon[currItem].cost;
+              nm[currItem] += weapon[currItem].amt;
+              //don't allow more than 99
+              if (nm[currItem] > 99)
+                nm[currItem] = 99;
+              return currItem;
+            }
+        }
+      else   //item
+        {
+          //don't buy if already maxed out
+          if (ni[itemNum] >= 99)
+            continue;
+          //purchase the item
+          if (money >= item[itemNum].cost)
+            {
+              // Check against iBoostItemsBought
+              if ( (itemNum >= ITEM_INTENSITY_AMP &&
+                    itemNum <= ITEM_VIOLENT_FORCE) ||
+                   (itemNum >= ITEM_ARMOUR &&
+                    itemNum <= ITEM_PLASTEEL))
+                {
+                  if ((iBoostItemsBought >= (int)type)
+                      ||(getBoostValue() > aMaxBoostValue))
+                    continue; // no chance pal!
+                  else
+                    iBoostItemsBought++; // Okay, take it!
+                }
+              money -= item[itemNum].cost;
+              ni[itemNum] += item[itemNum].amt;
+              //don't allow more than 999
+              if (ni[itemNum] > 99)
+                ni[itemNum] = 99;
+              return (currItem);
+            }
+        }
+    }
+  return (-1);
+}
+
+
+
+// An item has been selected, this function merely buys it. It
+// first does checks to make sure the item can be bought.
+// The function returns TRUE if we successfuly bought the item or
+// FALSE if we could not get it for some reason.
+int PLAYER::Buy_Something(int currItem)
+{
+   int itemNum = currItem - WEAPONS;
+   int bought = FALSE;
+
+    if (currItem < WEAPONS)
+    {
+        if ( (money >= weapon[currItem].cost) && (nm[currItem] < 99) )
+        {
+             money -= weapon[currItem].cost;
+             nm[currItem] += weapon[currItem].amt;
+             //don't allow more than 99
+             if (nm[currItem] > 99)
+                nm[currItem] = 99;
+             bought = TRUE;
+        }
+        // check tech level
+        if (weapon[currItem].techLevel <= _env->weapontechLevel)
+           bought = TRUE;
+        else
+           bought = FALSE;
+       
+    }    // end of weapons
+
+    else   // item
+    { 
+      if ( (money > item[itemNum].cost) && (ni[itemNum] < 99) )
+      {
+         money -= item[itemNum].cost;
+         ni[itemNum] += item[itemNum].amt;
+         // don't allow more than 99
+         if (ni[itemNum] > 99)
+            ni[itemNum] = 99;
+         bought = TRUE;
+      }
+      // check technology level
+      if (item[itemNum].techLevel <= _env->itemtechLevel)
+          bought = TRUE;
+      else
+          bought = FALSE;
+    }    
+   return bought;
+}
+
+
+
+char *PLAYER::selectRevengePhrase ()
+{
+  char *line;
+
+  line = _global->revenge->Get_Random_Line();
+  return line;
+}
+
+char *PLAYER::selectGloatPhrase ()
+{
+  char *line;
+  line = _global->gloat->Get_Random_Line();
+  return line;
+}
+
+char *PLAYER::selectSuicidePhrase ()
+{
+  char *line;
+  line = _global->suicide->Get_Random_Line();
+  return line;
+}
+
+
+char *PLAYER::selectKamikazePhrase ()
+{
+  char *line;
+  line = _global->kamikaze->Get_Random_Line();
+  return line;
+}
+
+char *PLAYER::selectRetaliationPhrase ()
+{
+  char *line;
+  char *pText;
+
+  if (! revenge)
+     return NULL;
+
+  line = _global->retaliation->Get_Random_Line();
+  pText = (char *) calloc (strlen (revenge->getName()) + 32 + strlen(line), sizeof (char));
+  if (! pText)
+    return NULL;
+
+  strcpy(pText, line);
+  strcat(pText, revenge->getName());
+  strcat(pText, " !!!");
+
+  return(pText);
+}
+
+int PLAYER::traceShellTrajectory (double aStartX, double aStartY, double aVelocityX, double aVelocityY, double &aReachedX, double &aReachedY)
+{
+  TANK *tankPool[10];						// For repulsion
+  bool bHasHit				= false;	// will be set to true if something is hit
+  bool bIsWallHit			= false;	// For steel walls and wrap floor/ceiling
+  bool bIsWrapped			=	false;	// For special handling in distance calcualtion when a shot goes through the wall
+  int iWallBounce 		= 0; 			// For wrap, rubber and spring walls
+  int iMaxBounce			=	pow((int)type, 2); // Useless can calculate 1, deadly bots 25 bounces
+  int iTargetDistance	=	ABSDISTANCE(_targetX, _targetY, aStartX, aStartY);
+  int iDistance				=	MAX_OVERSHOOT;
+  int iDirection			=	0;	// records the current direction of the shot
+  int iPriStageTicks	=	0;	// There is no unlimited tracking!
+  int iMaxPriStTicks	=	MAX_POWER * focusRate * 2.5;
+  int iSecStageTicks	=	0;	// rollers and burrowers can't be followed forever!
+  int iMaxSecStTicks	=	MAX_POWER * focusRate * 1.5;
+  double dDrag				=	weapon[tank->cw].drag;
+  double dMass				=	weapon[tank->cw].mass;
+  double dPosX				=	aStartX;
+  double dPosY				=	aStartY;
+  double dVelX				=	aVelocityX;
+  double dVelY				=	aVelocityY;
+  double dMaxVelocity = 0;
+  double dPrevX, dPrevY;	// to check pixels between two points
+  bool bIsSecondStage	=	false;	// Applies to burrowers and rollers
+
+  dMaxVelocity = _global->dMaxVelocity * (1.20 + (dMass / ((double)MAX_POWER / 10.0)));
+
+  // Set drag do the correct value:
+  if 			(ni[ITEM_DIMPLEP])
+    {
+      dDrag *= item[ITEM_DIMPLEP].vals[0];
+    }
+  else if (ni[ITEM_SLICKP])
+    {
+      dDrag *= item[ITEM_SLICKP].vals[0];
+    }
+
+  // Fill tankPool
+  for (int i = 0; i < _global->numPlayers; i++)
+    {
+      if ( (_global->players[i]) && (_global->players[i]->tank) )
+        tankPool[i] = _global->players[i]->tank;
+      else
+        tankPool[i] = NULL;
+    }
+
+  // Initial direction:
+  if (dVelX > 0.0) iDirection = 1;
+  if (dVelX < 0.0) iDirection = -1;
+
+  // On y va!
+  while (!bHasHit && !bIsWallHit && (iWallBounce < iMaxBounce)
+         && (iPriStageTicks < iMaxPriStTicks) && (iSecStageTicks < iMaxSecStTicks))
+    {
+      /*	---	First Stage - Applies to all weapons	---	*/
+      if (!bIsSecondStage)
+        {
+          // Apply Repulsor effects
+          for (int i = 0; i < _global->numPlayers; i++)
+            {
+              if (tankPool[i] && (tankPool[i] != tank))
+                {
+                  double xAccel = 0.0, yAccel = 0.0;
+                  tankPool[i]->repulse (dPosX + dVelX, dPosY + dVelY, &xAccel, &yAccel, tank->cw);
+                  if (tankPool[i] == _target)
+                    {
+                      // Without this, the shield would be nearly useless!
+                      xAccel *= focusRate;
+                      yAccel *= focusRate;
+                      // But the lesser bots wouldn't hit anything anymore if more than _target would be handled like that!
+                    }
+                  dVelX += xAccel;
+                  dVelY += yAccel;
+                }
+            }
+
+          dPrevX = dPosX;
+          dPrevY = dPosY;
+          //motion - wind affected
+          if (((dPosX + dVelX) < 1) || ((dPosX + dVelX) > (_global->screenWidth - 2)))
+            {
+              if	(	(((dPosX + dVelX) < 1) && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, 1, dPosY))
+                   ||(	((dPosX + dVelX) > (_global->screenWidth - 2))
+                       && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, (_global->screenWidth - 2), dPosY))	)
+                {
+                  dPosX = dPrevX;
+                  dPosY = dPrevY;
+                  bHasHit = true;
+                }
+              else
+                {
+                  switch (_env->current_wallType)
+                    {
+                    case WALL_RUBBER:
+                      dVelX = -dVelX;	//bounce on the border
+                      iWallBounce++;
+                      break;
+                    case WALL_SPRING:
+                      dVelX = -dVelX * SPRING_CHANGE;
+                      iWallBounce++;
+                      break;
+                    case WALL_WRAP:
+                      if (dVelX < 0)
+                        dPosX = _global->screenWidth - 2; // -1 is the wall itself
+                      else
+                        dPosX = 1;
+                      iWallBounce++;
+                      bIsWrapped = true;
+                      break;
+                    default:
+                      dPosX += dVelX;
+                      if (dPosX < 1)
+                        dPosX = 1;
+                      if (dPosX > (_global->screenWidth - 2))
+                        dPosX= _global->screenWidth - 2;
+                      dVelX = 0; // already applied!
+                      bIsWallHit = true;
+                    }
+                }
+            }
+
+          // hit floor or boxed top
+          if (	(	 (dPosY + dVelY) >= (_global->screenHeight - 1))
+               ||(((dPosY + dVelY) <= MENUHEIGHT) && _global->bIsBoxed))
+            {
+              if	(	(	_global->bIsBoxed && ((dPosY + dVelY) <= MENUHEIGHT)
+                     && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, dPosX, MENUHEIGHT + 1))
+                   ||(	((dPosY + dVelY) > (_global->screenHeight - 2))
+                       && checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, dPosX, (_global->screenHeight - 2)))	)
+                {
+                  dPosX = dPrevX;
+                  dPosY = dPrevY;
+                  bHasHit = true;
+                }
+              else
+                {
+                  switch (_env->current_wallType)
+                    {
+                    case WALL_RUBBER:
+                      dVelY = -dVelY * 0.5;
+                      dVelX *= 0.95;
+                      iWallBounce++;
+                      break;
+                    case WALL_SPRING:
+                      dVelY = -dVelY * SPRING_CHANGE;
+                      dVelX *= 1.05;
+                      iWallBounce++;
+                      break;
+                    default:
+                      // steel or wrap floor (ceiling)
+                      dPosY += dVelY;
+                      if (dPosY >= (_global->screenHeight - 1))
+                        dPosY = _global->screenHeight - 2; // -1 would be the floor itself!
+                      else
+                        dPosY= MENUHEIGHT + 1; // +1 or it would be the wall itself
+                      dVelY = 0; // already applied!
+                      bIsWallHit = true;
+                    }
+                  if (!bIsWallHit &&((fabs(dVelX) + fabs(dVelY)) < 0.8))
+                    bHasHit = true;
+                }
+            }
+
+          // velocity check:
+          double dActVelocity = ABSDISTANCE(dVelX, dVelY, 0, 0); // a²+b²=c² ... says Pythagoras :)
+          if ((dActVelocity > dMaxVelocity) && !bHasHit && !bIsWallHit)
+            {
+              // Velocity is applied first and modified by errorMultiplier
+              dPosY += dVelY * errorMultiplier;
+              dPosX += dVelX * errorMultiplier;
+              dVelX = 0.0;
+              dVelY = 0.0;
+              if ((dPosY <= MENUHEIGHT) && _global->bIsBoxed)
+                dPosY = MENUHEIGHT + 1;
+              if (dPosY > (_global->screenHeight - 2))
+                dPosY = _global->screenHeight - 2;
+              if (dPosX < 1)
+                {
+                  if (_env->current_wallType == WALL_WRAP)
+                    dPosX += _global->screenWidth - 2;
+                  else
+                    dPosX = 1;
+                }
+              if (dPosX > (_global->screenWidth - 2))
+                {
+                  if (_env->current_wallType == WALL_WRAP)
+                    dPosX -= _global->screenWidth - 2;
+                  else
+                    dPosX = _global->screenWidth - 2;
+                }
+              bHasHit = true;
+            }
+
+          // Now check for hits
+          if (!bHasHit && !bIsWallHit)
+            {
+              // Save Positions:
+              dPrevX = dPosX;
+              dPrevY = dPosY;
+              // Apply movement:
+              dPosX += dVelX;
+              dPosY += dVelY;
+              dVelX += (double)(_env->wind - dVelX) / dMass * dDrag * _env->viscosity;
+              dVelY += _env->gravity * (100.0 / _global->frames_per_second);
+              // Barrier test:
+              if ( (dVelY <= -1.0) && (dPosY <= (_global->screenHeight * -25.0)))
+                dVelY *= -1.0;
+
+              // See, if we have hit something
+              //	---	Environment-Test -- flight?
+              if (checkPixelsBetweenTwoPoints (_global, _env, &dPrevX, &dPrevY, dPosX, dPosY))
+                {
+                  dPosX = dPrevX;
+                  dPosY = dPrevY;
+                  bHasHit = true;
+                }
+            }
+          // Now that all modifications are applied, record direction:
+          if (dVelX > 0.0) iDirection = 1;
+          if (dVelX < 0.0) iDirection = -1;
+        }
+
+      /*	---	Second Stage - Applies to burrowers and rollers	---	*/
+      if (bIsSecondStage)
+        {
+          iSecStageTicks++;
+          // The weapon is on the ground and rolling or penetrating the ground:
+          if ((tank->cw >= SML_ROLLER) && (tank->cw <= DTH_ROLLER))
+            {
+              // check whether we have hit anything
+              if (	(dPosX < 1)
+                   ||(dPosX > (_global->screenWidth - 2))
+                   ||(dPosY > (_global->screenHeight - 2))
+                   ||(getpixel(_env->terrain, (int)dPosX, (int)dPosY) != PINK))
+                bHasHit = true;
+              else
+                {
+                  // roll roller
+                  float fSurfY = (float)_env->surface[(int)dPosX] - 1;
+                  if ((fSurfY > dPosY) && (dPosY < (_global->screenHeight - 5)))
+                    {
+                      if (fSurfY < (dPosY + 5))
+                        dPosY = fSurfY;
+                      else
+                        dPosY+=5;
+                    }
+                  else
+                    {
+                      if (dVelX > 0.0)
+                        dPosX++;
+                      else
+                        dPosX--;
+                      if	(dPosY >= MENUHEIGHT)
+                        {
+                          if (fSurfY > dPosY)
+                            dPosY++;
+                          else if (fSurfY >= (dPosY - 2))
+                            dPosY = fSurfY - 1;
+                        }
+                    }
+                  if (dPosY > (_global->screenHeight - 5) && !bHasHit)
+                    dPosY = (_global->screenHeight - 5);
+                }
+            }
+
+          if ((tank->cw >= BURROWER) && (tank->cw <= PENETRATOR))
+            {
+              // Apply Repulsor effects, but not fully, as it is a burrower!
+              for (int i = 0; i < _global->numPlayers; i++)
+                {
+                  if (tankPool[i] && (tankPool[i] != tank))
+                    {
+                      double xAccel = 0.0, yAccel = 0.0;
+                      tankPool[i]->repulse (dPosX + dVelX, dPosY + dVelY, &xAccel, &yAccel, tank->cw);
+                      if (tankPool[i] == _target)
+                        {
+                          // Without this, the shield would be nearly useless!
+                          xAccel *= focusRate;
+                          yAccel *= focusRate;
+                          // But the lesser bots wouldn't hit anything anymore if more than _target would be handled like that!
+                        }
+                      dVelX += xAccel * 0.1;
+                      dVelY += yAccel * 0.1;
+                    }
+                }
+              if (((dPosX + dVelX) < 1) || ((dPosX + dVelX) > (_global->screenWidth-1)))
+                {
+                  // if the wall is rubber, then bouce
+                  if ( _env->current_wallType == WALL_RUBBER )
+                    dVelX = -dVelX;	//bounce on the border
+                  // bounce with more force
+                  else if ( _env->current_wallType == WALL_SPRING )
+                    dVelX = -dVelX * SPRING_CHANGE;
+                  // wall is steel, detonate
+                  else if ( _env->current_wallType == WALL_STEEL )
+                    bHasHit = true;
+                  // wrap around to other side of the screen
+                  else if ( _env->current_wallType == WALL_WRAP )
+                    {
+                      if (dVelX < 1)
+                        dPosX = _global->screenWidth - 2;
+                      else
+                        dPosX = 1;
+                    }
+                }
+              if ((dPosY + dVelY) >= (_global->screenHeight - 1))
+                {
+                  dVelY = -dVelY * 0.5;
+                  dVelX *= 0.95;
+                }
+              else if ((dPosY + dVelY) < MENUHEIGHT)   //hit screen top
+                {
+                  dVelY = -dVelY *0.5;
+                  dVelX *= 0.95;
+                }
+              dPosY += dVelY;
+              dPosX += dVelX;
+              dVelY -= _env->gravity * 0.05 * (100.0 / _global->frames_per_second);
+              if (getpixel (_env->terrain, (int)dPosX, (int)dPosY) == PINK)
+                bHasHit = true;
+            }
+        }
+      else
+        iPriStageTicks++;
+
+#ifdef DEBUG_AIM_SHOW
+      if (_global->bASD)
+        {
+          // Plot trajectories for debugging purposes
+          circlefill (screen, (int)dPosX, (int)dPosY, 2, color);
+        }
+#endif
+
+      /*	---	Third Stage - Applies to burrowers and rollers	---	*/
+      if	(	(!bIsSecondStage && (bHasHit || bIsWallHit))
+           &&(	((tank->cw >= SML_ROLLER) && (tank->cw <= DTH_ROLLER))
+               ||((tank->cw >= BURROWER) && (tank->cw <= PENETRATOR))))
+        {
+          // Only Rollers and Penetrators can enter the second stage!
+          bIsSecondStage = true;
+          bHasHit = false;
+          bIsWallHit = false;
+          if ((tank->cw >= SML_ROLLER) && (tank->cw <= DTH_ROLLER))
+            {
+              dPosY -= 5;
+              if (dPosX < 1)
+                dPosX = 1;
+              if (dPosX > (_global->screenWidth - 2))
+                dPosX = (_global->screenWidth - 2);
+
+              if	(	(dPosY >= _env->surface[(int)dPosX])				// y is surface or below
+                   &&(dPosY <= _env->surface[(int)dPosX] + 2) )  // but not burried more than 2 px
+                dPosY = _env->surface[(int)dPosX] - 1;
+
+
+              dVelX = 0.0;
+              if (getpixel (_env->terrain, (int)dPosX + 1, (int)dPosY + 1) == PINK)
+                dVelX = 1.0;
+              if (getpixel (_env->terrain, (int)dPosX - 1, (int)dPosY + 1) == PINK)
+                dVelX = -1.0;
+              if (dVelX == 0.0)
+                // if both sides are free (should be impossible, but might be a 1-pixel-peak) the shooting direction decides
+                dVelX = (double)iDirection;
+              dVelY = 0.0;
+            }
+          if ((tank->cw == BURROWER) || (tank->cw == PENETRATOR))
+            {
+              dVelX *= 0.1;
+              dVelY *= 0.1;
+            }
+          if ((dPosY <= MENUHEIGHT) && !_global->bIsBoxed)
+            dPosY = MENUHEIGHT + 1;
+          if ((dPosY <= MENUHEIGHT) && _global->bIsBoxed)
+            bIsWallHit = true; // Sorry, no more ceiling-drop!
+        }
+
+      /*	---	Fourth Stage - Tank hit test	---	*/
+      if (!bIsWallHit)
+        {
+          for (int i = 0; i < _global->numPlayers; i++)
+            {
+              if (tankPool[i])
+                {
+                  if	(	 (dPosX > (tankPool[i]->x - TANKWIDTH))
+                        &&(dPosX < (tankPool[i]->x + TANKWIDTH))
+                        &&(dPosY > (tankPool[i]->y))
+                        &&(dPosY < (tankPool[i]->y + TANKHEIGHT))
+                        &&(tankPool[i]->l > 0))
+                    bHasHit = true;
+                }
+            }
+        }
+
+      // if something is hit, be sure the values are in range and movement stopped!
+      if (bHasHit || bIsWallHit)
+        {
+          dVelX = 0.0;
+          dVelY = 0.0;
+          if (dPosY <= MENUHEIGHT)
+            dPosY = MENUHEIGHT + 1;
+          if (dPosY > (_global->screenHeight - 2))
+            dPosY = _global->screenHeight - 2;
+          if (dPosX < 1)
+            dPosX = 1;
+          if (dPosX > (_global->screenWidth - 2))
+            dPosX = _global->screenWidth - 2;
+        }
+    }
+
+#ifdef DEBUG_AIM_SHOW
+  if (_global->bASD)
+    {
+      // Targetting circle for debugging purposes
+      circlefill (screen, (int)dPosX, (int)dPosY, 10, BLACK);
+      circlefill (screen, (int)_targetX, (int)_targetY, 20, color);
+      LINUX_REST;
+    }
+#endif
+#ifdef DEBUG_AIM
+  if (bIsWallHit)
+    cout << "WALL ";
+  if (bHasHit)
+    cout << "HIT ";
+  if (iWallBounce >= iMaxBounce)
+    cout << "BOUNCE (" << iMaxBounce << ") ";
+  if (iPriStageTicks >= iMaxPriStTicks)
+    cout << "TICKS1 (" << iPriStageTicks << ") ";
+  if (iSecStageTicks >= iMaxSecStTicks)
+    cout << "TICKS2 (" << iSecStageTicks << ") ";
+#endif // DEBUG_AIM
+
+  // Now see where we are and calculate the distance difference between (char *)"hit" and "has to be hit"
+  if (!bIsWallHit && (iWallBounce < iMaxBounce))
+    {
+      iDistance = ABSDISTANCE(_targetX, _targetY, dPosX, dPosY);
+
+#ifdef DEBUG_AIM
+      cout << "(" << iDistance << " <- " << (int)dPosX << " x " << (int)dPosY << ") ";
+#endif // DEBUG_AIM
+
+      // Special handling for wrapped shots:
+      if (bIsWrapped)
+        {
+          int iHalfX = _global->halfWidth;
+
+          // Only shots where dPosX and _targetX are on opposite sides are relevant
+          if	(	(((int)dPosX < iHalfX) && (_targetX >=iHalfX))
+               ||(((int)dPosX >=iHalfX) && (_targetX < iHalfX))	)
+            {
+              if (((int)dPosX < iHalfX) && (_targetX >=iHalfX))
+                iDistance = ABSDISTANCE(dPosX + iHalfX, dPosY, _targetX, _targetY);
+              else
+                iDistance = ABSDISTANCE(_targetX + iHalfX, _targetY, dPosX, dPosY);
+            }
+          else
+            bIsWrapped = false; // not relevant
+        }
+
+      bool bIsWrongDir = false;
+      if	(!bIsWrapped
+          &&(	((dPosX < aStartX) && (_targetX > aStartX))
+              ||((dPosX > aStartX) && (_targetX < aStartX))	)	)
+        bIsWrongDir = true; // wrong side!
+
+      if (!iDirection)
+        {
+          // If we have no direction (very unlikely!) we can only guess by comparing x-coordinates:
+          if	(	(iTargetDistance > ABSDISTANCE(aStartX, aStartY, dPosX, dPosY))
+               ||(bIsWrongDir && (_env->current_wallType != WALL_STEEL))	)
+            // Too short or wrong direction, negate iDistance!
+            iDistance *= -1;
+        }
+      else
+        {
+          // with the help of the direction, we can exactly see, whether the shot is too short or too far
+          if	(!bIsWrapped	// This doesn't apply for wrapped shots!
+              &&(	(	(iDirection < 0.0) 		// shoot to the left...
+                    &&(dPosX > _targetX))		// ...and the shot hits right of target
+                  ||(	(iDirection > 0.0) 		// shoot to the right...
+                      &&(dPosX < _targetX))	)// ...and the shot hits left of target
+             )	iDistance *= -1; // too short!
+        }
+
+      if (bIsWrongDir && (_env->current_wallType == WALL_STEEL))
+        iDistance = MAX_OVERSHOOT; // wrong side and target unreachable!
+    }
+  else
+    iDistance = MAX_OVERSHOOT;
+
+  // Give the X- and Y-position back:
+  aReachedX = dPosX;
+  aReachedY	=	dPosY;
+
+  return(iDistance);
+}
+
+int PLAYER::rangeFind (int &aAngle, int &aPower)
+{
+#ifdef DEBUG_AIM
+printf("This is range find function\n");
+#endif
+  int iOvershoot			=	MAX_OVERSHOOT;
+  int iActOvershoot		= MAX_OVERSHOOT;
+  int iSpreadOvershoot= MAX_OVERSHOOT;
+  int iBestOvershoot	=	MAX_OVERSHOOT + 1; // So there will be at least one recorded!
+  int iLastOvershoot	=	MAX_OVERSHOOT;
+  int iAngle					=	aAngle;
+  int iAngleMod				=	0;
+  double dAngleMul		=	0.0;
+  double dPowerMul		=	0.0;
+  int iCalcAngle			= aAngle;
+  int iLastAngle 			= aAngle;
+  int iBestAngle			= aAngle;
+  int iAngleBarrier		=	aAngle;	// This will be the flattest angle possible, thus normalized aAngle + savety
+  int iIdealAngle			=	135;	// 135 translates to 45°, but will be raised if the barrier is higher
+  bool bIsRaisingMode = false;
+  int iPower					= aPower;
+  int iPowerMod				=	0;
+  int iPowerModFixed	=	0;
+  int iLastPower			= aPower;
+  int iBestPower			=	aPower;
+  int iAttempts				=	0;
+  int iSelfHitMult		=	0;
+  int iSpread					=	weapon[tank->cw].spread;
+  int iSpreadCount		=	0;
+  int iSpreadOdd[]		= {0,-1 * SPREAD, SPREAD, -2 * SPREAD, 2 * SPREAD};
+  int iSpreadEven[]		=	{-0.5 * SPREAD, 0.5 * SPREAD, -1.5 * SPREAD, 1,5 * SPREAD};
+  int iMaxSpread			=	(int)type; // more intelligent bots can calculate more shots bearing spreads!
+  double dStartX, dStartY, dVelocityX, dVelocityY;	// No initialization needed, they are calculated anyway.
+  double dHitX, dHitY;
+
+#ifdef DEBUG_AIM
+printf("Starting RangeFind\n");
+#endif
+
+  // We need to be sure that iSpread is at least 1:
+  if (iSpread < 1)	iSpread	=	1;
+
+  // iMaxSpread needs to be adapted:
+  switch ((int)type)
+    {
+    case USELESS_PLAYER:
+    case GUESSER_PLAYER:
+      if (iSpread % 2)	iMaxSpread	=	1;
+      else							iMaxSpread	=	2;
+      break;
+    case RANGEFINDER_PLAYER:
+      if (iSpread % 2)	iMaxSpread	=	3;
+      else							iMaxSpread	=	4;
+      break;
+    case TARGETTER_PLAYER:
+      if (iSpread % 2)	iMaxSpread	=	5;
+      else							iMaxSpread	=	4;
+      break;
+    default:
+      if (iSpread % 2)	iMaxSpread	=	9; // I know there is nothing like that...
+      else							iMaxSpread	=	8; // ... but maybe in the future?
+      break;
+    }
+  if (iSpread > iMaxSpread)	iSpread = iMaxSpread;	// Now iSpread is limited to iMaxSpread...
+  // ...adapted to a test like (iSpreadCount < iSpread) but not larger then weapon[x].spread
+
+  /* Outline:
+   * RangeFind tries to adapt the given angle and power to minimize overshoot.
+   * to do so we have some facts to keep in mind:
+   * - ideal angle is 45° in both directions, giving most distance.
+   * - This angle translates into 135° for a shoot to the left, and 225° to the right
+   * - aAngle is considered to be the flattest shot possible, as it has been manipulated
+   *   by calculateAttackValues(), meaning that lowering it will lead to an obstacle
+   *   hit.
+   * - as a safety measure, when lowering an angle, a savety range of (int)type above
+   *   aAngle is applied
+   *
+   * The calculation is done in four steps:
+   * 1.: Calculate the real angle, as it is, at least for spreads, different with every shot shell
+   * 2.: Calculate the overshoot for each shot (or the one if no spread is given)
+   * 3.: Record angle, power and overshoot if the overshoot is smaller than the best recorderd so far
+   * 4.: Alter angle, or power if the angle can't be manipulated anymore, and start over, if the best
+   *     overshoot is != 0;
+   *
+   * This fourth step is divided into the following parts:
+   * a) short shots (overshoot < 0) - raise power
+   *    i.: angle lowering mode     - adjust the angle towards 45° until it (or aAngle) is reached
+   *    ii.:power raising mode      - after the first positive overshoot is reached, the angle won't be changed any more
+   * b) long shots (overshoot > 0)  - lower power
+   *    i.: angle raising mode      - adjust the angle towards 89° until it is reached
+   *    ii.:power lowering mode     - once the angle can't be changed any more, only power is changed
+   * angle raising/lowering modes are entered, and not left until iLastAngle == iAngle
+   *
+   * Note: Before you think all those step 4 calculations are wrong, they aren't, I am using a math trick to reduce
+   *       the amount of calculations:
+   *       180 + (180 - Angle) flips an angle between left and right. So the angle will be normalized to the right,
+   *       (aka 90° - 180°) and all calculations done there. If it was flipped, it will be flipped back for
+   *       traceShellTrajectory. This saves alot of (char *)"if(angle > 180)" lines!
+   */
+
+  // Preperations:
+  if (aAngle > 180)	iAngleBarrier = 180 + (180 - iAngleBarrier); // flip
+
+  // if we have some (char *)"space", add a savety distance:
+  if (iAngleBarrier < 170)	iAngleBarrier += (int)type - 1;
+
+  // We need some savety distance for spreads:
+  if (weapon[tank->cw].spread > 1)
+    {
+      // normal spread size:
+      iAngleBarrier += SPREAD * ((int)weapon[tank->cw].spread / 2);
+      if (!(weapon[tank->cw].spread % 2))
+        // Even spreads have half of SPREAD more than neccessary, so adapt:
+        iAngleBarrier -= SPREAD / 2;
+      // but be sure the barrier isn't too large:
+      if (iAngleBarrier > 179) iAngleBarrier = 179;
+    }
+
+  // Adapt the ideal angle if we are facing an obstacel:
+  if (iAngleBarrier > 135)	iIdealAngle = iAngleBarrier;
+
+#ifdef DEBUG_AIM
+  printf("New Target Try using....\n");
+  if (tank->cw < WEAPONS)
+    printf("%s\n", weapon[tank->cw].name);
+  else
+    printf("%s\n", item[tank->cw - WEAPONS].name);
+#endif // DEBUG_AIM
+
+  // Okay, here we go:
+  #ifdef DEBUG_AIM
+  printf("Best: %d .. Attempts %d  ..  RFattempts %d\n", iBestOvershoot, iAttempts, rangeFindAttempts);
+  #endif
+  while (iBestOvershoot && (iAttempts < rangeFindAttempts))
+    {
+      iAttempts++;
+
+#ifdef DEBUG_AIM
+      printf("--> %d. rangeFind:\n", iAttempts);
+      printf( (char *)" Angle: %3d Power: %4d\n", (iAngle - 90), iPower);
+#endif // DEBUG_AIM
+
+      /* --- Step 1: Calculate angle for spreads: --- */
+      iSpreadCount	= 0;
+      iOvershoot		=	MAX_OVERSHOOT;
+      iSpreadOvershoot	=	0;
+      iSelfHitMult	=	0;
+      iLastOvershoot= iOvershoot;
+
+      while (iSpreadCount < iSpread)
+        {
+          #ifdef DEBUG_AIM
+          printf("Inside the wee while loop.\n");
+          #endif
+          iCalcAngle		= iAngle;
+
+          // Two cases: Even and odd spreads.
+          if (iSpread > 1)
+            {
+              // odd spreads:
+              if (weapon[tank->cw].spread % 2)
+                iCalcAngle += iSpreadOdd[iSpreadCount];
+              // even spreads:
+              else
+                iCalcAngle += iSpreadEven[iSpreadCount];
+            }
+          dVelocityX = _global->slope[iCalcAngle][0] * (double)iPower * (100.0 / _global->frames_per_second) / 100.0;
+          dVelocityY = _global->slope[iCalcAngle][1] * (double)iPower * (100.0 / _global->frames_per_second) / 100.0;
+
+          dStartX = tank->x + (_global->slope[iCalcAngle][0] * GUNLENGTH);
+          dStartY	= tank->y + (_global->slope[iCalcAngle][1] * GUNLENGTH);
+
+          /* --- Step 2: Calculate overshoots: --- */
+          #ifdef DEBUG_AIM
+          printf("Trace the shell\n");
+          #endif
+          iActOvershoot = traceShellTrajectory(dStartX, dStartY, dVelocityX, dVelocityY, dHitX, dHitY);
+          #ifdef DEBUG_AIM
+          printf("Back from shell tracing.\n");
+          #endif
+          if (abs(iActOvershoot) < _global->screenWidth)
+            iSelfHitMult += adjustOvershoot(iActOvershoot, dHitX, dHitY);
+          // Otherwise it's a wall hit and not relevant!
+
+          #ifdef DEBUG_AIM
+          printf("Passed hit multi\n");
+          #endif
+          // With this method only the best hit of spreads is counted.
+          if (abs(iActOvershoot) < abs(iOvershoot))
+            iOvershoot = iActOvershoot;
+          
+          #ifdef DEBUG_AIM
+          printf("Passed overshoot. Spread: %d\n", iSpread);
+          #endif
+          // iSpreadOvershoot calculates the average absolute Overshoot
+          if (iActOvershoot)
+            iSpreadOvershoot += (int)(fabs((double)iActOvershoot) / (double)iSpread);
+
+          iSpreadCount++;
+
+#ifdef DEBUG_AIM
+          if (iSpreadCount > 1)
+            {
+              if (iSpreadCount == 2)
+                printf( (char *)" (%3d ", iCalcAngle - 90);
+              else
+                printf( (char *)",%3d ", iCalcAngle - 90);
+              if (iSpread == iSpreadCount)
+                printf( (char *)"\b)");
+            }
+#endif // DEBUG_AIM
+        }
+
+     #ifdef DEBUG_AIM
+     printf("Moving right along\n");
+     #endif
+
+      if (iOvershoot < 0)
+        iSpreadOvershoot *= -1;
+
+      if (iSelfHitMult > 0)
+        {
+          // We hit ourselves, so the larger Overshoot will be multiplied and taken!
+          if (abs(iSpreadOvershoot) > abs(iOvershoot))
+            iOvershoot = iSpreadOvershoot;
+          if (abs(iOvershoot) < _global->screenWidth)
+            iOvershoot = _global->screenWidth;
+          if (abs(iOvershoot) < MAX_OVERSHOOT)
+            iOvershoot*= iSelfHitMult;
+        }
+      else
+        {
+          // everything okay, just take the smaller one!
+          if (abs(iSpreadOvershoot) < abs(iOvershoot))
+            iOvershoot = (int)(((double)iSpreadOvershoot + ((double)iOvershoot * focusRate)) / 2);
+          else
+            iOvershoot = (int)(((double)iOvershoot + ((double)iSpreadOvershoot * focusRate)) / 2);
+        }
+
+      /* --- Step 3.: Record angle, power and overshoot if the overshoot is smaller than the best recorderd so far: --- */
+      if (abs(iOvershoot) < abs(iBestOvershoot))
+        {
+          iBestOvershoot	= iOvershoot;
+          iBestAngle			=	iAngle;
+          iBestPower			=	iPower;
+        }
+
+#ifdef DEBUG_AIM
+      printf( (char *)" Overshoot: %6d (%4d x %4d) SH: %1d\n", iOvershoot, (int)dHitX, (int)dHitY, iSelfHitMult);
+#endif // DEBUG_AIM
+
+      /* --- Step 4.: Alter angle, or power if the angle can't be manipulated anymore, and start over: --- */
+      if (iOvershoot)
+        {
+          // Preperation: flip iAngle if neccessary
+          if (iAngle > 180) iAngle = 180 + (180 - iAngle); // flip
+
+          // Preperation: Decide over angle and power modification depending on overshoot
+          if (abs(iOvershoot) < _global->screenWidth)
+            {
+              dAngleMul = 1.0 + fabs((double)iOvershoot / (double)_global->screenWidth); // between 1.0 and 2.0
+              iAngleMod = (int)(fabs((double)iOvershoot) / 10.0);
+              if (iAngleMod > 15)
+                iAngleMod = 15; // need a barrier here, too
+
+              // Power modification is calculated depending on overshoot
+              // To raise or lower by 100 pixels, we need aproximately 100 power (at 45°)
+              dPowerMul				=	pow(1.0 + (fabs((double)iAngle - 135.0) / 50.0), 2.0); 		// between 1.0 and 3,61
+              iPowerModFixed	=	5 + (int)(				(double)type	*	(fabs(iOvershoot) / 10.0)); // useless 10%, deadly 50% fix
+              iPowerMod				=	5 + (int)((10.0	-	(double)type)	*	(fabs(iOvershoot) / 10.0)); // useless 90%, deadly 50% variable
+              iPowerMod = (rand() % iPowerMod) + iPowerModFixed;
+            }
+          else
+            {
+              // As the overshoot is too high, probably a wall hit, Modification is done in a more limited way:
+              dAngleMul = 1.0 + ((double)type / 10.0);
+              dPowerMul = 1.0 + ((double)type / 10.0);
+              iAngleMod = (rand() % 11) + 5;
+              iPowerMod	=	(MAX_POWER / 8) + (rand() % (MAX_POWER / 8));
+              if ((iOvershoot < 0) || (iAngle >= 170))
+                // we need to raise distance urgently, so cancel bIsRaisingMod
+                bIsRaisingMode = false;
+              else
+                // we need to lower distance urgently, so enter bIsRaisingMod
+                bIsRaisingMode = true;
+            }
+
+          // before entering the step 4 modification parts, we could try a trick:
+          if	(	(abs(iLastOvershoot) < abs(iOvershoot))
+               &&(	((iLastOvershoot < 0) && (iOvershoot > 0))		// be sure that the overshoots switches
+                   ||((iLastOvershoot > 0) && (iOvershoot < 0))	) // between signed and unsigned
+               &&(	(abs(iLastAngle - iAngle) >= 2)								// There has to be something to do or
+                   ||(abs(iLastPower - iPower) >=10)	)						// we might waste all remaining attempts
+               &&(abs(iLastOvershoot) < _global->screenWidth)			// don't try it on wallhits, selfhits
+               &&(abs(iOvershoot) < _global->screenWidth)	)
+            {
+              // the current modification made the shot worse,
+              // but switched between too short and too long,
+              // so revert to half the modification:
+              iAngleMod		= (iLastAngle + iAngle) / 2; // We use the mod to save declaring
+              iPowerMod		= (iLastPower + iPower) / 2; // two new vars!
+              iLastAngle	= iAngle;
+              iLastPower	= iPower;
+              iAngle			= iAngleMod;
+              iPower			= iPowerMod;
+              // Note: This trick won't work when both are too short or too long,
+              // because then bots would never get over too high obstacles!
+            }
+          else
+            {
+              // No trick needed, we are getting nearer!
+              iLastAngle	=	iAngle;
+              iLastPower	=	iPower;
+              iAngleMod		=	(int)((double)iAngleMod * focusRate * dAngleMul);
+              iPowerMod		=	(int)((double)iPowerMod * focusRate * dPowerMul);
+              //	 * a) short shots (overshoot < 0) - raise power
+              if (iOvershoot < 0)
+                {
+                  // If we are too short and have (char *)"overbend" in raising mode, it has to be cancelled!
+                  if (bIsRaisingMode && (iAngle > 180))
+                    bIsRaisingMode = false;
+
+                  if (!bIsRaisingMode)
+                    {
+                      //	 *    i.: angle lowering mode     - adjust the angle towards 45° until it (or aAngle) is reached
+                      if (iAngle > iIdealAngle)
+                        {
+                          iAngle -= iAngleMod;
+                          if (iAngle < iIdealAngle)	iAngle = iIdealAngle;
+                        }
+                      if (iAngle < iIdealAngle)
+                        {
+                          iAngle += iAngleMod;
+                          if (iAngle > iIdealAngle) iAngle = iIdealAngle;
+                        }
+
+                      // Apply as much power as is neccessary:
+                      iPower += iPowerMod - (abs(iLastAngle - iAngle) * 10);
+
+                      // check to see whether Raising mode should be entered:
+                      if ((iAngle == iIdealAngle) && (iAngle == iLastAngle))
+                        bIsRaisingMode = true;
+                    }
+                  else
+                    //	 *    ii.:power raising mode      - after the first positive overshoot is reached, the angle won't be changed any more
+                    iPower += (int)((double)iPowerMod * dAngleMul);
+                }
+              //	 * b) long shots (overshoot > 0)  - lower power
+              if (iOvershoot > 0)
+                {
+                  if (bIsRaisingMode)
+                    {
+                      //   *    i.: angle raising mode      - adjust the angle towards 89° until it is reached
+                      if (iAngle > 178)
+                        iAngleMod = 1;  // for small (char *)"overbends"
+                      iAngle += iAngleMod;
+
+                      // Apply as much power as is neccessary:
+                      iPower -= iPowerMod - (abs(iLastAngle - iAngle) * 10);
+                    }
+                  else
+                    //   *    ii.:power lowering mode     - once the angle can't be changed any more, only power is changed
+                    iPower -= (int)((double)iPowerMod * dAngleMul);
+                }
+            }
+
+          // last step: check iPower and iAngle:
+          while	(	(iPower >= MAX_POWER)
+                  ||(iPower <= (MAX_POWER / 20)))
+            iPower = ((MAX_POWER / 2) + iPower) / 2;
+          iPower -= iPower % 5;
+
+          // check the angle, it must not be flatter than iAngleBarrirer!
+          if (iAngle < iAngleBarrier)
+            iAngle = iAngleBarrier;
+
+          // Now flip the angle back if neccessary:
+          if (aAngle > 180)
+            iAngle = 180 + (180 - iAngle); // flip back!
+
+#ifdef DEBUG_AIM
+          printf( (char *)" --> AngleMod: %3d PowerMod: %4d\n", (iAngle - iLastAngle), (iPower - iLastPower));
+#endif // DEBUG_AIM
+        } // end of if(iOvershoot)
+    }
+
+#ifdef DEBUG_AIM
+  printf("looks like the end of the while loop in aiming\n");
+#endif
+  // Record the best found values in tank if possible
+  if (abs(iBestOvershoot) < tank->smallestOvershoot)
+    {
+#ifdef DEBUG_AIM
+      printf( (char *)" New best Overshoot: %5d\n", iBestOvershoot);
+#endif // DEBUG_AIM
+      tank->smallestOvershoot = abs(iBestOvershoot);
+      tank->bestAngle					=	iBestAngle;
+      tank->bestPower					=	iBestPower;
+      // Give the best ones back if possible
+      if (iBestAngle != aAngle)	aAngle = iBestAngle;
+      if (iBestPower != aPower)	aPower = iBestPower;
+    }
+#ifdef DEBUG_AIM
+  else
+    cout << " No new best Overshoot..." << endl;
+#endif // DEBUG_AIM
+  return(iBestOvershoot);
+}
+
+int PLAYER::adjustOvershoot(int &aOvershoot, double aReachedX, double aReachedY)
+{
+  TANK *pTankHit			=	NULL;				//	For hitting quality analysis
+  long int iOvershoot	=	aOvershoot;	// To calculate with locally
+  bool bIsDirectHit		=	true;				//	false for shaped charges and napalm is chosen
+  bool bIsShaped			=	false;			//	true for shaped charges (special radius calculation needed!)
+  int iDamage					=	weapon[tank->cw].damage;
+  int iRadius					=	weapon[tank->cw].radius;
+  int iSelfHits				=	0;					// Will be raised for every self- and team-hit and then returned
+
+  if (iRadius < 10)	iRadius = 10;	// several things wouldn't function otherwise
+  if (iDamage < 10)	iDamage = 10; // if we didn't set minimum values
+
+  if ((tank->cw >= SHAPED_CHARGE) && (tank->cw <= CUTTER))
+    bIsShaped = true;
+  if (bIsShaped || ((tank->cw >= SML_NAPALM) && (tank->cw <= LRG_NAPALM)))
+    bIsDirectHit = false;
+
+  /* --- Step 1: See whether a tank is hit: */
+  for (int i = 0; i < 10; i++)
+    {
+      if (_global->players[i] && _global->players[i]->tank)
+        {
+          if	(	(aReachedX > (_global->players[i]->tank->x - TANKWIDTH))
+               &&(aReachedX < (_global->players[i]->tank->x + TANKWIDTH))
+               &&(aReachedY > (_global->players[i]->tank->y))
+               &&(aReachedY < (_global->players[i]->tank->y + TANKHEIGHT))
+               &&(_global->players[i]->tank->l > 0))
+            pTankHit = _global->players[i]->tank;
+        }
+    }
+
+  /* --- Step 2: See whether the target tank is hit or in weapon radius: --- */
+  // check these values in case of segfault
+  if ( (_target) && (pTankHit) &&
+       (pTankHit == _target) && bIsDirectHit && (pTankHit->player != this))
+    // A Direct hit with a direct weapon is what we want, so give 0 back
+    {
+      iOvershoot = 0;
+#ifdef DEBUG_AIM
+      cout << "ON TARGET! ";
+#endif // DEBUG_AIM
+    }
+  else
+    {
+      if (!iOvershoot)
+        {
+          if	(	(	((tank->x < _targetX) && (_targetX > aReachedX))
+                 ||((tank->x > _targetX) && (_targetX < aReachedX)) )
+               &&(iOvershoot > 0)
+               &&(iOvershoot < MAX_OVERSHOOT)	)
+            iOvershoot *= -1; // the shot is too short
+          else
+            iOvershoot = 1;
+        }
+      if (pTankHit)
+        {
+          // We *have* hit a tank, let's see to that it isn't us or a friend:
+          if ((pTankHit == tank) || (pTankHit->player == this))
+            {
+              // Ourselves, not good!
+              iOvershoot *= iRadius * iDamage;
+              iSelfHits++;
+            }
+          else if (pTankHit->player->team == team)
+            {
+              // We hit someone of the same team, but only Jedi and SitH care, of course:
+              if (team == TEAM_JEDI)
+                iOvershoot *= iRadius * (defensive + 2) * focusRate;
+              if (team == TEAM_SITH)
+                iOvershoot *= iRadius * (-1 * (defensive - 2)) * focusRate;
+              if (team != TEAM_NEUTRAL)
+                iSelfHits++;
+            }
+        }
+
+      /* --- Step 3: See, whether we, or a team member, is in blast radius and manipulate Overshoot accordingly --- */
+      for (int i = 0; i < 10; i++)
+        {
+          if (_global->players[i] && _global->players[i]->tank && (_global->players[i]->tank != _target))
+            {
+              // _target is skipped, so we don't get wrong values when revenging on a team mate!
+              int iX					= _global->players[i]->tank->x;
+              int iY 					= _global->players[i]->tank->y;
+              int iRadiusDist;
+              int iBlastDist	= ABSDISTANCE(aReachedX, aReachedY, iX, iY);
+
+              iRadiusDist = iRadius - iBlastDist;
+              if (!iRadiusDist)	iRadiusDist = 1;
+
+              if (iBlastDist < iRadius)
+                {
+                  // Is in Blast range. (maybe)
+                  if (	!bIsShaped
+                       ||(bIsShaped && (abs(iY - (int)aReachedY) <= (iRadius / 20))))
+                    {
+                      // Either no shaped charge or in radius
+                      if (_global->players[i]->tank == tank)
+                        {
+                          // Ourselves, not good!
+                          iOvershoot *= iRadiusDist * iDamage;
+                          iSelfHits++;
+                        }
+                      else if (_global->players[i]->team == team)
+                        {
+                          // We hit someone of the same team, but only Jedi and SitH care, of course:
+                          if (team == TEAM_JEDI)
+                            iOvershoot *= iRadiusDist * (defensive + 2) * focusRate;
+                          if (team == TEAM_SITH)
+                            iOvershoot *= iRadiusDist * (-1 * (defensive - 2)) * focusRate;
+                          if (team != TEAM_NEUTRAL)
+                            iSelfHits++;
+                        }
+                    }
+                }
+            }
+        }
+
+      // Be sure to not give a ridiculously high overshoot back:
+      while (abs(iOvershoot) >= MAX_OVERSHOOT)
+        iOvershoot /= 2;
+    }
+  aOvershoot = (int)iOvershoot;
+
+  return(iSelfHits);
+}
+
+// If Napalm or a shaped weapon is chosen, the target has to be modified!
+int PLAYER::getAdjustedTargetX(TANK * aTarget)
+{
+  int iTargetX, iTargetY;
+  int iMinOffset	=	0;
+  int iMaxOffset	= 1;
+
+  if (aTarget)
+    {
+      iTargetX  = aTarget->x;
+      iTargetY  = aTarget->y;
+    }
+  else if (_target)
+    {
+      iTargetX  = _target->x;
+      iTargetY  = _target->y;
+    }
+  else   // avoid segfault
+    return ( rand() % _global->screenWidth ) ;
+
+
+  // tank is dead, bail out to avoid segfault
+  if (! tank)
+      return iTargetX;
+
+  if ( (tank->cw >= SHAPED_CHARGE) && (tank->cw <= CUTTER))
+    {
+      int iBestLeftOffset	=	0;
+      int iBestRightOffset	=	0;
+      int iLeftY = 0;
+      int iBestLeftY = 0;
+      int iRightY = 0;
+      int iBestRightY = 0;
+      iMinOffset	=	(int)((TANKWIDTH / 2) + ((double)TANKWIDTH * focusRate));
+      iMaxOffset	= iMinOffset + (TANKWIDTH * (((int)type + 1) / 2));
+
+      for (int i = iMinOffset; i < iMaxOffset; i++)
+        {
+          // Get Y-Data:
+          if ((iTargetX - i) > 1)
+            iLeftY = _env->surface[iTargetX - i];
+          if ((iTargetX + i) < (_global->screenWidth - 1))
+            iRightY= _env->surface[iTargetX + i];
+          // Check whether new Y-Data is better than what we have:
+          if (abs(iLeftY - iTargetY) < abs(iBestLeftY - iTargetY))
+            {
+              iBestLeftOffset = i;
+              iBestLeftY 			= iLeftY;
+            }
+          if (abs(iRightY - iTargetY) < abs(iBestRightY - iTargetY))
+            {
+              iBestRightOffset	= i;
+              iBestRightY				=	iRightY;
+            }
+        }
+      // Now see whether we go left or right:
+      if (abs(iBestLeftY - iTargetY) < abs(iBestRightY - iTargetY))
+        // use left:
+        iTargetX -= iBestLeftOffset;
+      else
+        // use right:
+        iTargetX += iBestRightOffset;
+    }
+
+  if ( (tank->cw >= SML_NAPALM) && (tank->cw <= LRG_NAPALM))
+    {
+      // here we only check one side, the one to the wind:
+      iMaxOffset			= abs((int)((double)iMaxOffset * _env->wind * focusRate));
+      iMinOffset			=	abs((int)(_env->wind * (double)TANKWIDTH * focusRate));
+      int iSurfY			=	0;
+      int iBestY			=	0;
+      int iOffset			=	0;
+      int iBestOffset	=	0;
+      int iDirection	=	0;
+
+      if (_env->wind < 0)	iDirection = 1;		// for some reason I do not know, wind is
+      if (_env->wind > 0)	iDirection = -1;	// used (char *)"the wrong way". (???)
+
+      // Don't stretch the offset onto ourselves:
+      if	(	((tank->x < iTargetX) && ((iTargetX - tank->x - (iDirection * iMaxOffset)) < (TANKWIDTH * 2)))
+           ||((tank->x > iTargetX) && ((tank->x - iTargetX - (iDirection * iMaxOffset)) < (TANKWIDTH * 2)))	)
+        iMaxOffset = abs(iTargetX - (int)tank->x) - (TANKWIDTH * 2);
+
+      // And don't allow a negative offset either (would be useless due to wind!)
+      if (iMaxOffset < TANKWIDTH)
+        iMaxOffset = TANKWIDTH;
+
+      // But be sure iMinOffset is smaller than iMaxOffset:
+      if (iMinOffset >= iMaxOffset)
+        iMinOffset = iMaxOffset - (int)type;
+
+      if (iDirection)
+        {
+          // Without wind there is nothing to do!
+          for (int i = iMinOffset; i < iMaxOffset; i++)
+            {
+              iOffset = i * iDirection;
+              // Get Y-Data:
+              if (((iTargetX + iOffset) > 1) && (((iTargetX + iOffset) < (_global->screenWidth - 1))))
+                iSurfY = _env->surface[iTargetX + iOffset];
+
+              // Check whether new Y-Data is better than what we have:
+              if	(	((iTargetY - iSurfY) < (iTargetY - iBestY))
+                   ||(!iBestY)	)
+                {
+                  iBestOffset = iOffset;
+                  iBestY 			= iSurfY;
+                }
+            }
+          iTargetX += iBestOffset;
+        }
+    }
+
+  return (iTargetX);
+}
+
+int PLAYER::calculateAttack(TANK *aTarget)
+{
+  /* There are two general possibilities:
+   * - aTarget provided:
+   *   This function was called from computerSelectTarget() and will only check if it is possible
+   *   to reach a target, aka try only once and give the overshoot back.
+   * - default (aTarget is automatically NULL)
+   *   This function was called from computerControl() and will go forth and try to hit _target
+   *
+   * Outline:
+   * --------
+   * There are the following possibilities:
+   * a) An Item or a laser is chosen
+   *    -> a direct angle will do!
+   * b) We are burried
+   *    -> fire unburying tool at +/-60° to the middle of the screen
+   * c) Kamikaze
+   *    -> indicated by targetX/Y being tank.x/y
+   *    -> if shaped weapon is chosen, fire 45° and power 100 to the side where y is nearest to tank.y
+   *    -> if napalm is chosen, fire 90° and power 0
+   *    -> otherwise fire 90° and power 250
+   * d) Fire in non-boxed mode
+   *    -> normal calculation
+   * e) Fire in non-boxed mode
+   *    -> extended power-control after normal calculation
+   *    -> if the target can't be reached while staying below the ceiling,
+   *       check for an obstacle than can be removed and do so if found.
+   * --> boxed mode is included in non-boxed mode now. I hope it works as I intent!
+   *
+   * Update for dynamization: The previous target is recorded, aiming starts at the old values,
+   *                          if the target didn't change. */
+
+  int iXdistance, iYdistance;
+  if (aTarget)
+    {
+      iXdistance = aTarget->x - tank->x;
+      iYdistance = aTarget->y - tank->y;
+    }
+  else
+    {
+      iXdistance = _targetX - tank->x;
+      iYdistance = _targetY - tank->y;
+    }
+
+#ifdef DEBUG_AIM
+  if (!aTarget && !iTargettingRound)
+    {
+      printf("\n-----------------------------------------------\n");
+      if (_target)
+         printf("%s is starting to aim at %s\n", getName(), _target->player->getName() );
+      else
+         printf("%s is aiming without a target!\n", getName());
+    }
+#endif // DEBUG_AIM
+
+  /* --- case a) An Item is chosen --- */
+  if	( (!aTarget) && ( (tank->cw >= WEAPONS) ||
+          ((tank->cw >= SML_LAZER) && (tank->cw <= LRG_LAZER))))
+    {
+#ifdef DEBUG_AIM
+      printf("About to calc direct angle.\n");
+#endif
+      _targetAngle = calculateDirectAngle (iXdistance, iYdistance);
+      _targetPower = MAX_POWER / 2;
+
+#ifdef DEBUG_AIM
+      cout << "Direct " << _targetAngle - 90 << " for ";
+      printf("Direct %d for %s\n", _targetAngle -90, (tank->cw < WEAPONS) ? weapon[tank->cw].name : item[tank->cw - WEAPONS].name);
+#endif // DEBUG_AIM
+
+      iTargettingRound = retargetAttempts; // So it is done!
+
+      return(0);
+    }
+
+
+  /* --- case b) We are burried --- */
+  if (!aTarget &&(tank->howBuried () > BURIED_LEVEL))
+    {
+      // Angle is 60° to the middle of the screen:
+      int iAngleVariation = rand() % (20 - ((int)type * 3));
+      iAngleVariation -= (int)((double)type / 1.5);
+      if (tank->x <= _global->halfWidth)
+        _targetAngle = 150 + iAngleVariation;
+      else
+        _targetAngle = 210 - iAngleVariation;
+#ifdef DEBUG_AIM
+      printf("Freeing self with Angle %d and Power %d\n", _targetAngle, _targetPower);
+#endif // DEBUG_AIM
+
+      iTargettingRound = retargetAttempts;
+
+      return(0);
+    }
+
+  /* --- case c) Kamikaze --- */
+  if (!aTarget && (_targetX == tank->x) && (_targetY == tank->y))
+    {
+#ifdef DEBUG_AIM
+      cout << "Going bye bye with ";
+      if (tank->cw < WEAPONS)
+        cout << weapon[tank->cw].name;
+      else
+        cout << item[tank->cw - WEAPONS].name;
+      cout << " !!!" << endl;
+      cout << "GERONNNNNIIIIIMOOOOOOOOOO !!!" << endl;
+#endif // DEBUG_AIM
+
+      iTargettingRound = retargetAttempts;
+
+      // For a nice bye bye we set angle/power directly
+      if ((tank->cw >= SHAPED_CHARGE) && (tank->cw <= CUTTER))
+        {
+          // shaped weapons are a bit special:
+          int iHLeft, iHRight;
+          int iCount = 0;
+          for (int i = TANKWIDTH; i <= (TANKWIDTH * 2); i++)
+            {
+              iCount++;
+              iHLeft = _env->surface[(int)(tank->x - i)];
+              iHRight= _env->surface[(int)(tank->x + i)];
+            }
+          iHRight /= iCount;
+          iHLeft  /= iCount;
+          if (fabs(iHRight - tank->y) < fabs(iHLeft - tank->y))
+            _targetAngle = 135;
+          else
+            _targetAngle = 225;
+          _targetPower = MAX_POWER / 20;
+          return(0);
+        }
+      // The other possibilities are easier:
+      if ((tank->cw >= SML_NAPALM) && (tank->cw <= LRG_NAPALM))
+        _targetPower = 0;
+      else
+        _targetPower = MAX_POWER / 8;
+      _targetAngle = 180;
+
+      return(0);
+    }
+
+  /* --- case d) Fire in non-boxed mode --- */
+  int iRawAngle, iAdjAngle, iPower, iLastPower, iSavetyPower;
+  int iOvershoot = MAX_OVERSHOOT;
+  int iLastOvershoot = MAX_OVERSHOOT;
+  int iBestOvershoot = MAX_OVERSHOOT;
+
+  _targetX = getAdjustedTargetX(aTarget);
+  calculateAttackValues(iXdistance, iYdistance, iRawAngle, iAdjAngle, iPower, false);
+
+  if (!iTargettingRound)
+    {
+      // Initializiation, if this is the first try:
+
+      if (!aTarget && (_oldTarget == _target) )
+        {
+          // Target didn't change, use last rounds values:
+          tank->bestAngle = tank->a;
+          tank->bestPower = tank->p;
+          iRawAngle = tank->a;
+          iAdjAngle = tank->a;
+          iPower    = tank->p;
+        }
+      else
+        {
+          // new target, new values:
+          tank->bestAngle = 180;
+          tank->bestPower = MAX_POWER;
+          if (!aTarget)
+            _oldTarget = _target;
+        }
+
+      tank->smallestOvershoot = MAX_OVERSHOOT + 1; // So there will be at least one recorded
+
+    }
+  else
+    {
+      // This is a follow-up round, get the last values back:
+      iAdjAngle = _targetAngle;
+      iPower    = _targetPower;
+      iBestOvershoot = tank->smallestOvershoot;
+    }
+
+  iLastPower=	iPower;
+
+  if (aTarget)
+  {
+    #ifdef DEBUG_AIM
+    printf("Returning a range find.\n");
+    #endif
+    return(rangeFind(iAdjAngle, iPower));
+  }
+
+  // Now that we are here, normal handling is needed:
+#ifdef DEBUG_AIM
+  if (!iTargettingRound)
+    {
+      printf("Intitial try:\n");
+      printf("About to range find.\n");
+    }
+#endif // DEBUG_AIM
+
+  iOvershoot			= rangeFind(iAdjAngle, iPower);
+  iLastOvershoot	=	iBestOvershoot;
+  if (abs(iOvershoot) < abs(iBestOvershoot))
+    iBestOvershoot = iOvershoot;
+
+#ifdef DEBUG_AIM
+  cout << "Overshoot: " << iOvershoot << " (best so far: " << iBestOvershoot << ")" << endl << endl;
+  cout << iTargettingRound + 1 << ". re-try:";
+#endif // DEBUG_AIM
+
+  // There is still an Overshoot, so see what we can do:
+  if (abs(iLastOvershoot - iOvershoot) <= 1)
+    {
+      // rangeFind can't get a better version, so start completely different!
+      int iAngleRange = 180;
+      if (_env->current_wallType == WALL_STEEL)
+        iAngleRange /= 2;
+      if (_targetX > tank->x)
+        // shoot basically to the right:
+        iRawAngle = 90 + (rand() % iAngleRange);
+      else
+        // shoot basically to the left:
+        iRawAngle = 270 - (rand() % iAngleRange);
+      iAdjAngle = (iAdjAngle + iRawAngle) / 2;
+      iPower		=	(iPower + (rand() % (MAX_POWER / 2))) / 2;
+#ifdef DEBUG_AIM
+      cout << " Starting over! " << endl;
+#endif
+    }
+  else
+    {
+      // Just calculate anew:
+      calculateAttackValues(iXdistance, iYdistance, iRawAngle, iAdjAngle, iPower, true);
+#ifdef DEBUG_AIM
+      cout << " recalculating! " << endl;
+#endif
+    }
+
+  /* SavetyPower is as follows:
+   * abs(iAdjAngle -180) changes the value to be between:
+   * ->  0 : Straight upwards       (originally 180)
+   * -> 90 : Straight Left or right (originally 270/90)
+   * 91 - abs(...) gives a value between 1 and 91 which is multiplied with the radius */
+  iSavetyPower = ((91 - abs(iAdjAngle - 180)) * (weapon[tank->cw].radius * focusRate)) / focusRate;
+  if (iSavetyPower > (MAX_POWER / 4))	iSavetyPower	= MAX_POWER / 4;
+  if (iPower < iSavetyPower)					iPower 				= iSavetyPower;
+
+  iLastOvershoot = iOvershoot;
+  iOvershoot = rangeFind(iAdjAngle, iPower);
+
+  if (abs(iOvershoot) < abs(iBestOvershoot))
+    iBestOvershoot = iOvershoot;
+
+  iTargettingRound++;
+
+  // Do not count this attempt if the currently best overshoot is too high:
+  if ((iBestOvershoot > _global->screenWidth) && (rand() % ((int)type * 2)))
+    iTargettingRound--; // if ibestOvershoot is negative it will alwys be counted!
+
+  if (tank->smallestOvershoot < (weapon[tank->cw].radius / (int)type))
+    iTargettingRound = retargetAttempts;
+
+  // Now the best Version has to be tested:
+  iOvershoot	= tank->smallestOvershoot; // Always a positive number!
+  _targetAngle = tank->bestAngle; // Record for foolow-up rounds
+  _targetPower = tank->bestPower; // Record for follow-up rounds
+
+  if (iTargettingRound == retargetAttempts)
+    {
+#ifdef DEBUG_AIM
+      cout << "  ---  ---" << endl;
+      cout << "Final Decision:" << endl;
+      cout << "Angle    : " << _targetAngle - 90 << endl;
+      cout << "Power    : " << _targetPower << endl;
+      cout << "Overshoot: " << iBestOvershoot << endl;
+#endif // DEBUG_AIM
+
+      if (iOvershoot > weapon[tank->cw].radius)
+        {
+          if (_targetAngle > 180)
+            iRawAngle = _targetAngle + 10 + (rand() % ((int)type * 4));
+          else
+            iRawAngle = _targetAngle - (10 + (rand() % ((int)type * 4)));
+
+          // There are three possibilities:
+          if	(	(iBestOvershoot < 0)
+               &&(abs(_targetAngle - 180) <= (10 + ((iXdistance / _global->screenWidth) * 10)))
+               &&(!tank->shootClearance(iRawAngle, weapon[tank->cw].radius * 1.5)))
+            {
+              // a) there is an obstacle in our way!
+              tank->cw = getUnburyingTool();
+              if (tank->cw < WEAPONS)
+                {
+                  _targetAngle = iRawAngle;
+#ifdef DEBUG_AIM
+                  cout << "Revised Angle for unburying: " << _targetAngle - 90 << endl;
+#endif // DEBUG_AIM
+                }
+            }
+          else
+            {
+              // b) the way is clear, so either try to switch weapon or fire away!
+              if (iBestOvershoot < 0)
+                {
+                  // As we are too short, see whether another weapon might be good
+                  if (nm[TREMOR])	tank->cw = TREMOR;
+                  if (nm[SHOCKWAVE])	tank->cw = SHOCKWAVE;
+                  if ((_targetY < (_global->screenHeight - iOvershoot)) && nm[BURROWER])
+                    tank->cw = BURROWER;
+                  if (nm[TECTONIC])	tank->cw = TECTONIC;
+                  if ((_targetY < (_global->screenHeight - iOvershoot)) && nm[PENETRATOR])
+                    tank->cw = PENETRATOR;
+
+                  // if it is boxed, it is better to teleport out!
+                  if ((_global->bIsBoxed) && (iOvershoot > (weapon[tank->cw].radius * 2)))
+                    {
+                      // no way, teleport out!
+                      if (ni[ITEM_TELEPORT])	tank->cw = ITEM_TELEPORT + WEAPONS;
+                      if (ni[ITEM_SWAPPER])		tank->cw = ITEM_SWAPPER + WEAPONS;
+                    }
+                }
+              else
+                {
+                  // look for tectonis and their range
+                  if (nm[TREMOR]		&& (weapon[TREMOR].radius >= iOvershoot))			tank->cw = TREMOR;
+                  if (nm[SHOCKWAVE] && (weapon[SHOCKWAVE].radius >= iOvershoot))	tank->cw = SHOCKWAVE;
+                  if (nm[TECTONIC]	&& (weapon[TECTONIC].radius >= iOvershoot))		tank->cw = TECTONIC;
+                }
+
+              // c) we have no chance to reach anything!
+              if (iOvershoot > _global->screenWidth)
+                {
+                  // no way, teleport out!
+                  if (ni[ITEM_TELEPORT])	tank->cw = ITEM_TELEPORT + WEAPONS;
+                  if (ni[ITEM_SWAPPER])		tank->cw = ITEM_SWAPPER + WEAPONS;
+                }
+
+            }
+        }
+      else
+        {
+          // If we *are* hitting ok, Angle and Power need to be manipulated by errorMultiplier
+          int iAngleMod, iPowerMod;
+          int iAngleModLimit = (42 - (10 * ((int)type - 1))); 	// =  42,  32,  22, 12,  2 for useless -> deadly
+          int iPowerModLimit = (210 - (50 * ((int)type - 1)));	// = 210, 160, 110, 60, 10 for useless -> deadly
+
+          iAngleMod = (rand() % 51) * errorMultiplier;	//	useless: 0 -  100, deadly: 0 - 2 (with 2 being very unlikely)
+          if (iAngleMod > iAngleModLimit)
+            iAngleMod = iAngleModLimit;
+
+          iPowerMod	=	(rand() % 251) * errorMultiplier;	//	useless: 0 - 500, deadly: 0 - 10 (with 10 being *very* unlikely)
+          if (iPowerMod > iPowerModLimit)
+            iPowerMod = iPowerModLimit;
+
+          // In boxed mode, errors have quite more impact and are therefore cut down to be only two thirds
+          if (_global->bIsBoxed)
+            {
+              iAngleMod = (int)((double)iAngleMod / 3.0 * 2.0);
+              iPowerMod = (int)((double)iPowerMod / 3.0 * 2.0);
+            }
+
+          // 25 % to get a flattening anglemod (aka nearing to the ground)
+          if ((!(rand() % 4)) && (_targetAngle < 180))
+            iAngleMod *= -1; // right side angle
+          if ((rand() % 4) && (_targetAngle > 180))
+            iAngleMod *= -1; // right side angle (other way round, because here a positive mod is flattening!
+
+          // 25 % to get a lessening powermod. (it is more likely to overshoot than be too short!)
+          if (!(rand() % 4)) 		// (and it leads to too many stupid self
+            iPowerMod	*=	-1;	// hits to allow negative PoerMod too often
+
+          // The modification must not lead to a too stupid angle
+          while (	iAngleMod
+                  &&(	(	(_targetAngle < 180)
+                        &&(	((iAngleMod + _targetAngle) < 95)
+                            ||((iAngleMod	+	_targetAngle) > 175) ) )
+                      ||(	(_targetAngle >=180)
+                          &&(	((iAngleMod + _targetAngle) > 265)
+                              ||((iAngleMod	+	_targetAngle) < 185) ) )
+                    ) ) iAngleMod /= 2;
+          _targetAngle += iAngleMod;
+
+          // Same applies for Power:
+          while	(	iPowerMod
+                  &&(	((iPowerMod + _targetPower) > MAX_POWER)
+                      ||((iPowerMod + _targetPower) < (MAX_POWER * 0.1)) ) )
+            iPowerMod /= 2;
+
+          // iPowerMod needs to be a multiplier of 5:
+          iPowerMod -= iPowerMod % 5;
+
+          _targetPower += iPowerMod;
+
+#ifdef DEBUG_AIM
+          printf( "Error-Adjusting: Angle %3d Power %4d\n", iAngleMod, iPowerMod);
+#endif // DEBUG_AIM
+        }
+
+#ifdef DEBUG_AIM
+      cout << "HITTING " << _target->player->getName() << " ???" << endl << endl;
+#endif // DEBUG_AIM
+
+      // Last one: if we are revenging, tell em!
+      // Added _target check to avoid segfault
+      if  ( (tank->cw < WEAPONS) && (_target)                      // Wepaon selected?
+            && (weapon[tank->cw].damage > 1)                       // One that delivers damage?
+            && (revenge == _target->player)                        // And the target is our revengee?
+            && ((rand() % ((int)DEADLY_PLAYER + 2 - (int)type)))	) // And we do really want to taunt?
+        {
+          FLOATTEXT *DIEText;
+          char *my_text;
+          my_text = selectRetaliationPhrase();
+          DIEText = new FLOATTEXT (_global, _env, my_text, (int) tank->x, (int) tank->y - 30, color, CENTRE);
+          if (my_text) free(my_text);
+          if ( DIEText)
+          {
+              //DIEText->xv = 0;
+              //DIEText->yv = -0.4;
+              DIEText->set_speed(0.0, -0.4);
+              DIEText->maxAge = 150;
+          }
+          else
+              perror ( "player.cc: Failed allocating memory for DieText in calculateAttack().");
+        }
+      // As we might finish here because of a good overshoot, iTargettingRounds need to be maxed!
+      iTargettingRound = retargetAttempts;
+    }
+  return(0);
+}
+
+void PLAYER::calculateAttackValues(int &aDistanceX, int aDistanceY, int &aRawAngle, int &aAdjAngle, int &aPower, bool aAllowFlip)
+{
+  double dAirTime, dxTime;
+  double dSlopeX, dSlopeY;
+  double dAngleVariation, dPowerVariation;
+  bool bIsWrapped = false; // Special handling for wrapped walls
+
+  aDistanceX = _targetX - tank->x;
+
+  /* --- Step 1: find the raw angle, aka the obstacle-free optimal angle --- */
+
+  aRawAngle = (int)(atan2((double)aDistanceX, (double)(aDistanceY - abs (aDistanceX))) / PI * 180.0);
+
+  // Bring in Range:
+  if (aRawAngle < 0)		aRawAngle = aRawAngle + 360;
+  if (aRawAngle < 90)		aRawAngle = 135;
+  if (aRawAngle > 270)	aRawAngle = 225;
+
+  if ((_env->current_wallType == WALL_WRAP) && ((rand() % ((int)type + 1)) || !aAllowFlip))
+    {
+      // Note: We always wrap when possible and flipping not allowed, to have the shorter distance for sure!
+      int iWrapDistance = 0;
+
+      // if the distance through the wall is shorter, take it!
+      if (tank->x < _targetX)
+        iWrapDistance = -1 * (tank->x -1 + _global->screenWidth - 2 - _targetX);
+      else
+        iWrapDistance = tank->x -1 + _global->screenWidth - 2 - _targetX;
+
+      if (abs(iWrapDistance) < abs(aDistanceX))
+        {
+          bIsWrapped = true;
+          aDistanceX = iWrapDistance;
+          aRawAngle = 180 + (180 - aRawAngle); // flip!
+        }
+    }
+
+  // Angle variation for more flavour:
+  dAngleVariation = (rand() % 21) * focusRate; // useless: 0-4, deadly: 0-20
+  if (rand() % 2) dAngleVariation *= -1.0;
+  while	(	(dAngleVariation > 0.0)
+          &&(	((aRawAngle > 180) && (	((aRawAngle + dAngleVariation) < 190)
+                                      ||((aRawAngle + dAngleVariation) > 260)))
+              ||((aRawAngle < 180) && (	((aRawAngle + dAngleVariation) > 170)
+                                        ||((aRawAngle + dAngleVariation) < 100))) )	)
+    dAngleVariation /= 2.0;
+  aRawAngle += (int)dAngleVariation;
+
+  // Maybe we could switch sides?
+  if ((_env->current_wallType != WALL_STEEL) && (rand() % 2) && (rand() % (int)type) && aAllowFlip)
+    {
+      // Yes, we can! ( (char *)"Change is coming!" ;-) (b.h.o) )
+      aRawAngle = 180 + (180 - aRawAngle); // This switches sides, yes. :-D
+
+      if (tank->x < _targetX)
+        {
+          // We switch angle from right to left: (original distance is positive)
+          switch (_env->current_wallType)
+            {
+            case WALL_RUBBER:
+              // Add Distances to the wall to bounce from:
+              aDistanceX += 2 * (tank->x - 1);
+              break;
+            case WALL_SPRING:
+              // Spring walls add velocity, so adapt a bit
+              aDistanceX += tank->x - 1 + ((tank->x - 1) * 0.75);
+              break;
+            case WALL_WRAP:
+              // Distance is new: only distances from the wall:
+              if (bIsWrapped)
+                aDistanceX = tank->x -1 + _global->screenWidth - 2 - _targetX;
+              else
+                aDistanceX = -1 * (tank->x -1 + _global->screenWidth - 2 - _targetX);
+              break;
+            }
+        }
+      else
+        {
+          // We switch angle from left to right: (original distance is negative)
+          switch (_env->current_wallType)
+            {
+            case WALL_RUBBER:
+              // Add Distances to the wall to bounce from:
+              aDistanceX += 2 * (_global->screenWidth - tank->x - 2);
+              break;
+            case WALL_SPRING:
+              // Spring walls add velocity, so adapt a bit
+              aDistanceX += _global->screenWidth - tank->x - 2 + ((_global->screenWidth - tank->x - 2) * 0.75);
+              break;
+            case WALL_WRAP:
+              // Distance is new: only distances from the wall:
+              if (bIsWrapped)
+                aDistanceX = -1 * (tank->x -1 + _global->screenWidth - 2 - _targetX);
+              else
+                aDistanceX = tank->x -1 + _global->screenWidth - 2 - _targetX;
+              break;
+            }
+        }
+    }
+
+  /* --- Step 2: Adjust the Angle given clearance --- */
+
+  aAdjAngle = aRawAngle;
+  while ((aAdjAngle < 180) && !(tank->shootClearance(aAdjAngle)))
+    aAdjAngle++;
+  while ((aAdjAngle > 180) && !(tank->shootClearance(aAdjAngle)))
+    aAdjAngle--;
+
+  /* --- Step 3: Find neccessary Power --- */
+  dSlopeX = _global->slope[aAdjAngle][0];
+  dSlopeY = _global->slope[aAdjAngle][1];
+
+  if (dSlopeX != 0.0)
+    dxTime = ((double)aDistanceX / fabs(dSlopeX));
+  else
+    // entirely down to the elements now
+    dxTime = ((double)aDistanceX / 0.000001);
+
+  // Low target, less power
+  // xdistance proportional to sqrt(dy)
+  dAirTime = fabs(dxTime) + (((double)aDistanceY * dSlopeY) * _env->gravity * (100.0 / _global->frames_per_second)) * 2.0;
+
+  // Less airTime doesn't necessarily mean less power
+  // Horizontal firing means more power needed even though
+  //   airTime is minimised
+
+  aPower = (int)(sqrt (dAirTime * _env->gravity * (100.0 / _global->frames_per_second))) * 100;
+
+  // Power variation for more flavour:
+  dPowerVariation = (rand() % 51) * focusRate; // useless: 0-10, deadly: 0-50
+  dPowerVariation -= (int)dPowerVariation % 5;
+  if (rand() % 2) dPowerVariation *= -1.0;
+  aPower += dPowerVariation;
+
+  if (aPower > MAX_POWER)					aPower = MAX_POWER;
+  if (aPower < (MAX_POWER / 20))	aPower = MAX_POWER / 20;
+
+}
+
+int PLAYER::calculateDirectAngle (int dx, int dy)
+{
+  double angle;
+
+  angle = atan2 ((double)dx, (double)dy) / PI * 180;
+  angle += (rand () % 40 - 20) * errorMultiplier;
+
+  if (angle < 0)
+    angle = angle + 360;
+  if (angle < 90)
+    angle = 90;
+  else if (angle > 270)
+    angle = 270;
+
+  return ((int)angle);
+}
+
+TANK * PLAYER::computerSelectTarget (int aPreferredWeapon, bool aRotationMode)
+{
+  int random_target;
+  int attempts = 0;
+  int max_attempts = (int)type * 3;
+  TANK *best_target = NULL;
+  int current_score = 0;
+  int best_score = -1 * MAX_OVERSHOOT; // start with a loooooow score, so that even score<0 tanks can become best target
+  TANK *current_tank = NULL;
+  TANK *tankPool[10];
+  int iMoneyNeed = getMoneyToSave() - money;	// Are we in need for money?
+  int target_count = 0;
+
+#ifdef DEBUG
+  cout << " -> I need " << iMoneyNeed << " Credits *urgently*!" << endl;
+  if (aPreferredWeapon < WEAPONS)
+    cout << " -  Searching target for " << weapon[aPreferredWeapon].name << endl;
+  else
+    cout << " -  Searching target for " << item[aPreferredWeapon - WEAPONS].name << endl;
+#endif // DEBUG
+  // find out how many tries we have to find a good target
+
+  // Fill tankPool
+  for (int i = 0; i < _global->numPlayers; i++)
+    {
+      if ( (_global->players[i]) && (_global->players[i]->tank) )
+      {
+        tankPool[i] = _global->players[i]->tank;
+        target_count++;
+      }
+      else
+        tankPool[i] = NULL;
+    }
+
+  if (target_count < 2)     // just us left or nobody
+     return NULL;
+
+  // who do we want to shoot at?
+  while (attempts < max_attempts)
+    {
+      // select random tank for target
+      if (_global->numPlayers > 0)
+          random_target = rand() % _global->numPlayers;
+      else
+          random_target = 0;
+      current_tank	=	tankPool[random_target];
+
+      if (current_tank)
+        {
+          current_score	= 0;
+          // only consider living tanks that are not us
+
+          if ( (current_tank->l > 0) && (current_tank->player != this))
+            {
+              int iDamage		= 0;
+
+              if (weapon[aPreferredWeapon].numSubmunitions > 1)
+                iDamage	=	(damageMultiplier
+                           * weapon[weapon[aPreferredWeapon].submunition].damage
+                           * (weapon[aPreferredWeapon].numSubmunitions / 3.0));
+              else
+                iDamage	=	(damageMultiplier
+                           * weapon[aPreferredWeapon].damage
+                           * weapon[aPreferredWeapon].spread);
+
+              // compare the targets strength to ours
+              int iDiffStrength =	( (tank->l + tank->sh) - (current_tank->l + current_tank->sh));
+
+              current_score = iDiffStrength;
+
+              if (iDiffStrength < 0)
+                {
+                  // The target is stronger. Are we impressed?
+                  if ( (defensive < 0.0) && ( (rand() % ( (int) type + 1))))
+                    // No we aren't, add defensive-modified Strength
+                    // (The more offensive, the less impressed we are)
+                    current_score += (int) ( ( (defensive - 3.0) / 2.0) * (double) iDiffStrength);
+                }
+              else
+                // the target is weaker, add points modified by how defensive we are
+                current_score	+=	(int) ( (double) iDiffStrength * ( (defensive + 3.0) / 2.0));
+#ifdef DEBUG
+              cout << " (str)" << current_score;
+#endif
+              // check to see if we are on the same team
+              switch ( (int) team)
+                {
+                case TEAM_JEDI:
+                  if ((current_tank->player->team == TEAM_JEDI) && !aRotationMode)
+                    current_score -= 500 * (int) type;
+                  if ((current_tank->player->team == TEAM_JEDI) && aRotationMode)
+                    current_score -= MAX_OVERSHOOT; // no team consideration in rotation mode!
+
+                  if (current_tank->player->team == TEAM_SITH)
+                    current_score	+= -200.0 * (defensive - 2.0) * ( (double) type / 2.0);
+                  break;
+
+                case TEAM_SITH:
+                  if ((current_tank->player->team == TEAM_SITH) && !aRotationMode)
+                    current_score -= 500 * (int) type;
+                  if ((current_tank->player->team == TEAM_SITH) && aRotationMode)
+                    current_score -= MAX_OVERSHOOT; // no team consideration in rotation mode!
+
+                  if (current_tank->player->team == TEAM_JEDI)
+                    current_score	+= -200.0 * (defensive - 2.0) * ( (double) type / 2.0);
+                  break;
+/*
+                default:
+                  // Neutrals go rather for sith than jedi. (but not much)
+                  if (current_tank->player->team == TEAM_JEDI)
+                    current_score += -25.0 * (defensive - 2.0) * ( (double) type / 2.0);
+
+                  if (current_tank->player->team == TEAM_SITH)
+                    current_score	+= -50.0 * (defensive - 2.0) * ( (double) type / 2.0);
+*/
+                }
+#ifdef DEBUG
+              cout << " (team)" << current_score;
+#endif // DEBUG
+              // do we have a grudge against the target
+              if (current_tank->player == revenge)
+                {
+                  /*
+                  switch ( (int) team)
+                    {
+                    case TEAM_JEDI:
+                      // Revenge is a dark force!
+                      current_score += (50 * ( (defensive - 1.5) * -1.0));
+                      break;
+                    case TEAM_SITH:
+                      // Revenge means power!
+                      current_score += (200 * ( (defensive - 1.5) * -1.0));
+                      break;
+                    default:
+                   */
+                      current_score += (100 * ( (defensive - 1.5) * -1.0));
+                 //   }
+                }
+#ifdef DEBUG
+              cout << " (rev)" << current_score;
+#endif // DEBUG
+              // prefer targets further away when violent death is on
+              if (_global->violent_death)
+                {
+                  int distance;
+                  distance = (int) fabs (tank->x - current_tank->x);
+
+                  if (distance > _global->halfWidth)
+                    current_score += 100.0 * ( (defensive + 3.0) / 2.0);
+                }
+#ifdef DEBUG
+              cout << " (dis)" << current_score;
+#endif // DEBUG
+              // Add some points if the target is more intelligent than we are (get'em DOWN!)
+              // or substract if we are the better one. (Deal with the nutter later...)
+              if ( (current_tank->player->type != HUMAN_PLAYER)
+                   && (current_tank->player->type	<	DEADLY_PLAYER))
+                current_score +=	50 *	( (int) current_tank->player->type - (int) type);
+              else
+                current_score	+=	50 *	( (int) DEADLY_PLAYER - (int) type);
+              // Players, last player type and part time bots are counted as deadly bots.
+#ifdef DEBUG
+              cout << " (typ)" << current_score;
+#endif // DEBUG
+              // Add points for score difference if they have more than us
+              // useless bot: 1 * diff * 60 --> 4 points difference would mean +240 score
+              // deadly bot : 3 * diff * 60 --> 4 points difference would mean +720 score
+              if (current_tank->player->score > score)
+                current_score	+=	( (int) type + 1) / 2 * (current_tank->player->score - score) * 60;
+
+#ifdef DEBUG
+              cout << " (scr)" << current_score;
+#endif // DEBUG
+              if (aPreferredWeapon < WEAPONS)
+                {
+                  // As we are wanting to fire a weapon, add points, if the damage is greater than the targets health
+                  // (if we are in need for money, but not on the same team)
+                  int iDamageDiff = iDamage - (current_tank->l + current_tank->sh);
+
+                  if ( (iDamageDiff > 0) && (iMoneyNeed > 0)
+                       &&( ( team == TEAM_NEUTRAL )
+                           ||((team != TEAM_NEUTRAL) && (current_tank->player->team != team))  ) )
+                    current_score += (double) iDamageDiff * (1.0 + ( (defensive + (double) type) / 10.0));
+#ifdef DEBUG
+                  cout << " (dmg)" << current_score;
+#endif // DEBUG
+                  // Check whether the target is buried, and substract points for non-burrower/-penetrator
+                  int iBurylevel = current_tank->howBuried();
+
+                  if (iBurylevel > BURIED_LEVEL)
+                    {
+                      // The target is burried!
+                      if	( ( (aPreferredWeapon < BURROWER) || (aPreferredWeapon > PENETRATOR))
+                           && ( (aPreferredWeapon < TREMOR) || (aPreferredWeapon	> TECTONIC)))
+                        {
+                          // Napalm and shaped charges are absolutely useless
+                          if	( ( (aPreferredWeapon >= SML_NAPALM) && (aPreferredWeapon <= LRG_NAPALM))
+                               || ( (aPreferredWeapon >= SHAPED_CHARGE) && (aPreferredWeapon <= CUTTER)))
+                            current_score	-=	(int) type * 500; // Even the useless bot isn't *that* stupid
+                          else
+                            {
+                              // For all other weapons we go for the radius of the blast
+                              if (iBurylevel < weapon[aPreferredWeapon].radius)
+                                current_score *= 1.0 - ( ( (double) iBurylevel / (double) weapon[aPreferredWeapon].radius) / 2.0);
+                              else
+                                current_score	-=	(double) iDamage * (double) type * ( (double) defensive + 3.0);
+                            }
+                        }
+                      else
+                        // As we *want* to fire an appropriate weapon, the target looks rather nice to us!
+                        current_score += ( (double) (iBurylevel - BURIED_LEVEL) / ( ( (double) type + 1.0) / 2.0)) * (double) iDamage;
+#ifdef DEBUG
+                      cout << " (bur)" << current_score;
+#endif // DEBUG
+                    }
+
+                  // Finally, for weapons, see, if we can do good blast damage!
+                  if (type >= RANGEFINDER_PLAYER)
+                    {
+                      int iBlastBonus = 0;
+                      iBlastBonus = (int) ( (1.0 - ( (double) type / 10.0))
+                                            * getBlastValue (current_tank, weapon[aPreferredWeapon].damage, aPreferredWeapon)
+                                            * ( (defensive - 3.0) / -2.0));
+
+                      if (iBlastBonus > 0)
+                        {
+                          current_score	+=	iBlastBonus;
+                          // if we need money, blast bonus is valued higher:
+
+                          if (iMoneyNeed > 0)
+                            current_score	+=	iBlastBonus * ( (double) type / 2.0);
+                        }
+                    }
+                }
+
+              if (aRotationMode && ((team == TEAM_NEUTRAL) || (team != current_tank->player->team)))
+                {
+                  // In rotationmode we try to actually reach the target with the preferred weapon
+                  tank->cw	= aPreferredWeapon;
+                  _target 	= current_tank;
+                  _targetX	=	current_tank->x;
+                  _targetY	=	current_tank->y;
+                  iTargettingRound = 0;
+                  int iOvershoot = abs(calculateAttack(current_tank));
+                  if (iOvershoot > _global->screenWidth)
+                    current_score = -1 * MAX_OVERSHOOT; // Wall-Hit! Target is unreachable!
+                  else
+                    current_score -=  iOvershoot;	// substract overshoot!
+#ifdef DEBUG
+                  cout << " (rot)" << current_score;
+#endif // DEBUG
+                }
+
+#ifdef DEBUG
+              cout << " => " << current_score<< " : " << current_tank->player->getName() << endl;
+#endif // DEBUG
+
+              // decide if this target is better than others
+              if ((current_score > best_score) || (!aRotationMode && !best_target))
+                {
+                  best_score = current_score;
+                  best_target = current_tank;
+                }
+              attempts++;
+            }
+        }     // end of if we have a valid tank
+    }
+
+  if (best_target)
+    {
+      _target = best_target;
+      if (_target)
+      {
+        _targetX= _target->x;
+        _targetY= _target->y;
+#ifdef DEBUG
+        cout << " -> " << best_target->player->getName() << " wins! (";
+        cout << best_target->l << " life, " << best_target->sh << " shield)" << endl;
+#endif // DEBUG
+      }
+    }
+#ifdef DEBUG
+  else
+    cout << " -> Unable to find target!!!" << endl;
+#endif // DEBUG
+
+  return (best_target);
+}
+
+int PLAYER::getUnburyingTool()
+{
+  int iTool = 0; // small missile, if nothing else fits
+  if (nm[LRG_LAZER])			iTool = LRG_LAZER;
+  if (nm[MED_LAZER])			iTool = MED_LAZER;
+  if (nm[SML_LAZER])			iTool = SML_LAZER;
+  if (ni[ITEM_TELEPORT])	iTool = WEAPONS + ITEM_TELEPORT;
+  if (ni[ITEM_SWAPPER])		iTool = WEAPONS + ITEM_SWAPPER;
+  if (nm[HVY_RIOT_BOMB])	iTool = HVY_RIOT_BOMB;
+  if (nm[RIOT_BOMB])			iTool = RIOT_BOMB;
+  if (nm[RIOT_CHARGE])		iTool = RIOT_CHARGE;
+  if (nm[RIOT_BLAST])			iTool = RIOT_BLAST;
+  return(iTool);
+}
+
+int PLAYER::computerSelectItem ()
+{
+  int current_weapon = 0; // Current Weapon (defaults to small missile)
+  int iWeaponPool[15];
+  int iPoolSize		=	(int)type * 3;
+  int count 			= 0;
+  // Initialize targetting:
+  _target = NULL;
+  _targetX= 0;
+  _targetY= 0;
+
+#ifdef DEBUG
+  cout << getName() << " : Starting target and weapon evaluation..." << endl;
+  if (defensive < -0.9) cout << "(True Offensive)" << endl;
+  if ((defensive >=-0.9) && (defensive < -0.75)) cout << "(Very Offensive)" << endl;
+  if ((defensive >=-0.75) && (defensive < -0.25)) cout << "(Offensive)" << endl;
+  if ((defensive >=-0.25) && (defensive < 0.00)) cout << "(Slightly Offensive)" << endl;
+  if (defensive == 0.0)	cout << "(Neutral)" << endl;
+  if ((defensive >0.0) && (defensive <= 0.25)) cout << "(Slightly Defensive)" << endl;
+  if ((defensive >0.25) && (defensive <= 0.75)) cout << "(Defensive)" << endl;
+  if ((defensive >0.75) && (defensive <= 0.9)) cout << "(Very Defensive)" << endl;
+  if (defensive > 0.9)	cout << "(True Defensive)" << endl;
+  cout << "----------------------------------" << endl;
+#endif // DEBUG
+  // 1.: Preselection if buried
+
+  if (tank->howBuried () > BURIED_LEVEL)
+    {
+      current_weapon = getUnburyingTool();
+#ifdef DEBUGctank
+      if (current_weapon < WEAPONS)
+        cout << "I have chosen a \"" << weapon[current_weapon].name << "\" to free myself first!" << endl;
+      else
+        cout << "I have chosen a \"" << item[current_weapon - WEAPONS].name << "\" to free myself first!" << endl;
+#endif // DEBUG
+    }
+  else
+    {
+      // 2.: Determine iPoolSize
+      if (iPoolSize > 15)
+        iPoolSize = 15; // Or part-time-bots would bust array size!
+
+      // 3.: Fill iWeaponPool
+      iWeaponPool[0] = 0;	// The Small missile is always there!
+      count					=	1;	// ...so start from second slot!
+
+      while (count < iPoolSize)
+        {
+          int i	=	0;
+          // bots get a number of tries depending on their intelligence
+          current_weapon	=	0;
+          while (!current_weapon && (i < ( (int) type * 2)))
+            {
+              current_weapon = Select_Random_Weapon();
+              if (! current_weapon)
+                current_weapon = Select_Random_Item();
+              if	( (current_weapon	>=	THINGS)	//should never occur, but make it sure!
+                   || ( (current_weapon < WEAPONS) && (!nm[current_weapon]))
+                   || ( (current_weapon >= WEAPONS) && (!ni[current_weapon - WEAPONS])))
+                current_weapon = 0;
+              i++;
+            }
+
+          if (!current_weapon && (count > 1))
+            {
+              // Slot 0 is allways the small missile, slot 1 is always the first thing the bot "things" of
+              // "Last Resort" switching takes place from slot 2 on
+              if (nm[MED_MIS])	current_weapon	=	MED_MIS;
+
+              // Only bots with 4+ slots (rangefinder and up) revert to the large missile
+              if ( (count > 2) &&	nm[LRG_MIS])	current_weapon	= LRG_MIS;
+            }
+          iWeaponPool[count]	=	current_weapon;
+          count++;
+        }
+
+      // 4a.: check if a dirtball is chosen
+      if ( (iWeaponPool[1] >= DIRT_BALL) && (iWeaponPool[1] <= SUP_DIRT_BALL))
+        current_weapon	=	iWeaponPool[1];
+      else
+        {
+          // 4b.: Sort iWeaponPool, so that the most liked weapon is first
+          //  (...if the bot doesn't "forget" to sort ...)
+          if (rand() % ( (int) type + 1))
+            {
+              bool bIsSorted = false;
+              while (!bIsSorted)
+                {
+                  bIsSorted	=	true;
+                  // The bot does only sort the first few weapons (type+1)
+                  // Stupid: first two, deadly: first 6
+                  for (int i = 1; i < ( (int) type + 1); i++)
+                    {
+                      if (_weaponPreference[iWeaponPool[i-1]] < _weaponPreference[iWeaponPool[i]])
+                        {
+                          bIsSorted	=	false;
+                          current_weapon	=	iWeaponPool[i-1];
+                          iWeaponPool[i-1] = iWeaponPool[i];
+                          iWeaponPool[i]	=	current_weapon;
+                        }
+                    }
+                }
+            }
+          current_weapon	=	iWeaponPool[0]; // Most liked weapon, or, if not sorted, the small missile
+          // Having the small missile here means, that the bot is selecting the most easy target.
+          // Obviously that means, that the more stupid a bot is, the more often it will go for the easy strike.
+        }
+#ifdef DEBUG
+      for (int i = 0; i < iPoolSize; i++)
+        {
+          cout << i << ".: ";
+          printf( "% 5d Pref - ", _weaponPreference[iWeaponPool[i]]);
+          if (iWeaponPool[i] < WEAPONS)
+            cout << "\"" << weapon[iWeaponPool[i]].name << "\"" << endl;
+          else
+            cout << "\"" << item[iWeaponPool[i] - WEAPONS].name << "\"" << endl;
+        }
+#endif // DEBUG
+      // if boxed mode is on, we have to try to find a target in rotation mode first!
+      if (	_global->bIsBoxed	&& (current_weapon < WEAPONS)
+           && ( (current_weapon <	DIRT_BALL)
+                ||(current_weapon >	SUP_DIRT_BALL)))
+        {
+          int i		=	0;
+          while ((i < iPoolSize) && !_target)
+            {
+              _target = computerSelectTarget(iWeaponPool[i], true);
+              i++;
+            }
+          if (_target)
+            current_weapon = iWeaponPool[i - 1];
+        }
+      if (!_target)               _target =	computerSelectTarget(current_weapon);
+      #ifdef OLD_GAMELOOP
+      if (!_target && _oldTarget) _target = _oldTarget;
+      #endif
+      if (!_target) return (0); // If there is no target available, we have nothing more to do.
+      _targetX				= _target->x;
+      _targetY				= _target->y;
+
+      // 5.: if a weapon is choosen, cycle through the pool
+      // to find the best fitting one
+      if ( (current_weapon < WEAPONS)
+           && ( (current_weapon <	DIRT_BALL)
+                || (current_weapon >	SUP_DIRT_BALL)))
+        {
+          int iBestWeapon		= current_weapon;
+          int iWeaponScore	= 0; 		// Score of the currently used weapon
+          int iBestWeapScr	=	-5000;// Best score calculated so far
+          double dDamageMod	=	0.0;	// modifier for how close to targets health
+          int iWeaponDamage	=	0;		// Calculate the (real) weapon damage
+          int iTargetLife   = _target->l + _target->sh;
+          int iBurylevel    = _target->howBuried();
+          for (int i = 0; i < iPoolSize; i++)
+            {
+              current_weapon	=	iWeaponPool[i];
+
+              // 1.: avoid trying to shoot below the tank's level with lasers
+              if ( (_targetY >= tank->y) &&
+                   ( (current_weapon >= SML_LAZER) && (current_weapon <= LRG_LAZER)))
+                iWeaponPool[i] = current_weapon = 0; // revert to small missile
+#ifdef DEBUG
+              if (current_weapon < WEAPONS)
+                cout << " -> \"" << weapon[current_weapon].name << "\" : ";
+              else
+                cout << " -> (ERROR!) \"" << item[current_weapon - WEAPONS].name << "\" : ";
+#endif // DEBUG
+              // 2.: The closer the weapon damage is to the target health, the:
+              //     - more points added if it kills
+              //     - less points substracted if it doesn't kill
+              
+              // avoid trying to use weapons we do not have
+              if ( ( current_weapon < 0) || (current_weapon >= WEAPONS) )
+                 current_weapon = 0;
+
+              if (weapon[current_weapon].numSubmunitions > 1)
+                iWeaponDamage	=	damageMultiplier
+                                * weapon[weapon[current_weapon].submunition].damage
+                                * (weapon[current_weapon].numSubmunitions / (defensive + 3.0)); // Clusters don't hit well (napalm?)
+              else
+                {
+                  if (weapon[current_weapon].spread > 1)
+                    iWeaponDamage	=	damageMultiplier
+                                    * weapon[current_weapon].damage
+                                    * (weapon[current_weapon].spread / (defensive + 2.0)); // Spreads *might* hit well, but do seldom
+                  else
+                    iWeaponDamage	=	damageMultiplier
+                                    * weapon[current_weapon].damage;
+                }
+
+              // The more intelligent and defensive a bot is, the more (char *)"savety bonus" is granted:
+              iWeaponDamage = (int) ( (double) iWeaponDamage / (1.0 + ( ( (double) type * (defensive + 2.0)) / 50.0)));
+
+              // Examples:
+              // Full offensive, useless: 1.0 + ((1.0 * 1.0) / 50.0) = 1.02 <== The damage is like 102% of the real damage
+              // Full defensive, deadly : 1.0 + ((5.0 * 3.0) / 50.0) = 1.30 <== The damage is like 130% of the real damage
+#ifdef DEBUG
+              cout << iWeaponDamage << " damage, ";
+#endif // DEBUG
+              if ( iTargetLife > iWeaponDamage)
+                {
+                  // The weapon is too weak, substract points. (Less if we are offensive)
+                  dDamageMod	=	(double) iWeaponDamage / (double) iTargetLife;
+                  if (defensive < 0)
+                    iWeaponScore = (10 - (int) type) * (int) ( (-10.0 * (1.1 + defensive)) / dDamageMod);
+                  else
+                    iWeaponScore = (10 - (int) type) * (int) (-10.0 / dDamageMod);
+#ifdef DEBUG
+                  cout << "weak: ";
+#endif // DEBUG
+                  /*	Example calculations:
+                  		Bot is deadly: (int)type = 5
+                  		Weapon does 25% damage of the targets health: dDamegeMod = 0.25
+                  		iWeaponScore = (10 - 5) * (-10 / 0.25) = 5 * -40   = -200
+                  		Weapon does 50% damage of the targets health: dDamegeMod = 0.5
+                  		iWeaponScore = (10 - 5) * (-10 / 0.5)  = 5 * -20   = -100
+                  		Weapon does 75% damage of the targets health: dDamegeMod = 0.75
+                  		iWeaponScore = (10 - 5) * (-10 / 0.75) = 5 * -13,3 = -66,5
+                  		Weapon does 95% damage of the targets health: dDamegeMod = 0.95
+                  		iWeaponScore = (10 - 5) * (-10 / 0.95) = 5 * -10,5 = -52,5 */
+                }
+              else
+                {
+                  // The weapon is strong enough, add points (More, if we are defensive)
+                  dDamageMod	=	(double) iTargetLife / (double) iWeaponDamage;
+                  if (defensive > 0)
+                    iWeaponScore	=	(int) type * (int) ( (100.0 * (1.0 + defensive)) * dDamageMod);
+                  else
+                    iWeaponScore	=	(int) type * (int) (100.0 * dDamageMod);
+#ifdef DEBUG
+                  cout << "strong: ";
+#endif // DEBUG
+                  /*	Example calculations:
+                  		Bot is deadly: (int)type = 5
+                  		Weapon does 105% damage of the targets health: dDamegeMod = 0.95
+                  		iWeaponScore = 5 * (100 * 0.95) = 5 * 95   = 475
+                  		Weapon does 125% damage of the targets health: dDamegeMod = 0.8
+                  		iWeaponScore = 5 * (100 * 0.8)  = 5 * 80   = 400
+                  		Weapon does 150% damage of the targets health: dDamegeMod = 0.67
+                  		iWeaponScore = 5 * (100 * 0.67) = 5 * 67   = 335
+                  		Weapon does 200% damage of the targets health: dDamegeMod = 0.5
+                  		iWeaponScore = 5 * (100 * 0.5)  = 5 * 50   = 250 */
+                }
+#ifdef DEBUG
+              cout << dDamageMod << " dMod -> ";
+#endif // DEBUG
+              // 3.: Check if the way for a laser is clear if choosen
+              if ( (current_weapon >= SML_LAZER) && (current_weapon <= LRG_LAZER))
+                {
+                  int iXlow, iXhigh, iX, iY;	// temp vars to calculate with
+                  int iRockAmount	=	0;	// How much mountain there is in between
+
+                  if (tank->x < _targetX)
+                    {
+                      iXlow	=	tank->x;
+                      iXhigh =	_targetX;
+                    }
+                  else
+                    {
+                      iXlow	=	_targetX;
+                      iXhigh =	tank->x;
+                    }
+
+                  for (iX = iXlow; iX < iXhigh; iX++)
+                    {
+                      iY = tank->y - ( (tank->y - _targetY) / (iXhigh - iX)); // y the laser will be on it's way
+                      if (_env->surface[iX] < iY)
+                        iRockAmount++;	// Rock in the way!
+                    }
+                  iWeaponScore	-=	(int) type * iRockAmount * 10.0;
+                }
+
+              // 4.: If the target is burried, add points if we are using an adequate weapon
+              if (iBurylevel > BURIED_LEVEL)
+                {
+                  // The target is burried!
+                  if	( ( (current_weapon < BURROWER) || (current_weapon > PENETRATOR))
+                       && ( (current_weapon < TREMOR) || (current_weapon	> TECTONIC)))
+                    {
+                      // Napalm and shaped charges are absolutely useless
+                      if	( ( (current_weapon >= SML_NAPALM) && (current_weapon <= LRG_NAPALM))
+                           || ( (current_weapon >= SHAPED_CHARGE) && (current_weapon <= CUTTER)))
+                        iWeaponScore	-=	(int) type * 500; // Even the useless bot isn't *that* stupid
+                      else
+                        {
+                          // For all other weapons we go for the radius of the blast
+                          if (iBurylevel < weapon[current_weapon].radius)
+                            iWeaponScore *= 1.0 - ( ( (double) iBurylevel / (double) weapon[current_weapon].radius) / 2.0);
+                          else
+                            iWeaponScore	-=	(double) iWeaponDamage * (double) type * ( (double) defensive + 3.0);
+                        }
+                    }
+                  else
+                    // As we *want* to fire an appropriate weapon, the target looks rather nice to us!
+                    iWeaponScore += ( (double) (iBurylevel - BURIED_LEVEL) / ( ( (double) type + 1.0) / 2.0)) * (double) iWeaponDamage;
+                }
+
+              // 5.: Substract points, if we are within the blast radius
+              // 6.: Check, whether other tanks are in the blast radius, and add points according
+              //     to the additional damage delivered
+              // Note: It seems to be paradox, that defensive bots add points for spread/cluster
+              //       weapons, but they a) buy onyl few of them and b) add only noticably points
+              //       if the collateral damage is enough to kill.
+              if (type >= RANGEFINDER_PLAYER)
+                iWeaponScore	+=	getBlastValue (_target, iWeaponDamage, current_weapon, dDamageMod);
+
+              // 7.: Try to hit this target with the weapon, and substract the overshoot
+              if ((type >= RANGEFINDER_PLAYER) && (current_weapon < WEAPONS))
+                {
+                  tank->cw = current_weapon;
+                  iTargettingRound = 0;
+                  iWeaponScore -= abs(calculateAttack(_target));
+                }
+
+              // 8.: Modify the Score by weapon preferences
+              if (iWeaponScore > 0)
+                iWeaponScore	=	(int) ( (double) iWeaponScore
+                                       * (1.0
+                                          + ( (double) _weaponPreference[current_weapon]
+                                              / (double) MAX_WEAP_PROBABILITY)));
+              // (it will only have a slight effect unless the prefs are really wide apart and the
+              //  original points very close to each other)
+#ifdef DEBUG
+              cout << iWeaponScore << " points!" << endl;
+#endif // DEBUG
+              // See if the choice fits better
+              if (iWeaponScore > iBestWeapScr)
+                {
+                  iBestWeapScr	=	iWeaponScore;
+                  iBestWeapon		=	current_weapon;
+                }
+            }
+          current_weapon	=	iBestWeapon;
+        }
+    }
+
+  // 6.: Kamikaze probability:
+  // The more stupid and offensive a bot is, the more chance he has
+  // to blow himself up when life is falling below a certain limit.
+  if	( ( (tank->l + tank->sh) < 30)
+       || ( ( (tank->l + tank->sh) < 50) && (tank->howBuried () > BURIED_LEVEL)))
+    {
+      // A buried bot needs to free himself first, leaving all others a free shot!
+      double dBlowMod = defensive + 2.0;	// gives 1.0 to 3.0
+      dBlowMod	*=	(double) type / 2.0;		// gives 1.0 to 9.0
+      dBlowMod	+=	1.0;									// gives 2.0 to 10.0
+      // dBlowMod is now between  2.0 <== useless full offensive bot (50% chance)
+      //                     and 10.0 <== deadly full defensive bots (10% chance)
+
+      if (! (rand() % (int) dBlowMod))
+        {
+          // okay, I'm a goner, so BANZAAAAIIII! (maybe, check for a way first)
+          int iWeaponDamage = 0;
+          current_weapon	=	0;
+          if (nm[NUKE])							current_weapon	=	NUKE;
+          if (nm[DTH_SPREAD])				current_weapon	=	DTH_SPREAD;
+          if (nm[DTH_HEAD])					current_weapon	=	DTH_HEAD;
+          if (nm[ARMAGEDDON])				current_weapon	=	ARMAGEDDON;
+          if (nm[CUTTER])						current_weapon	=	CUTTER;
+          if (ni[ITEM_VENGEANCE])		current_weapon	=	ITEM_VENGEANCE		+	WEAPONS;
+          if (ni[ITEM_DYING_WRATH])	current_weapon	=	ITEM_DYING_WRATH	+	WEAPONS;
+          if (ni[ITEM_FATAL_FURY])	current_weapon	=	ITEM_FATAL_FURY		+	WEAPONS;
+          if (current_weapon < WEAPONS)
+            iWeaponDamage = weapon[current_weapon].damage * damageMultiplier;
+          else
+            iWeaponDamage	=		weapon[ (int) item[current_weapon - WEAPONS].vals[0]].damage
+                             *	item[current_weapon - WEAPONS].vals[1]
+                             * damageMultiplier;
+
+          // Is something available, and do we take others with us?
+          if ( (current_weapon > 0) && (getBlastValue (tank, iWeaponDamage, current_weapon) > 0.0))
+            {
+              // Yieha! Here we go!
+#ifdef DEBUG
+              printf("I have chosen to go bye bye with a...\n");
+              if (current_weapon < WEAPONS)
+                printf("%s\n", weapon[current_weapon].name);
+              else
+                printf("%s\n", item[current_weapon - WEAPONS].name);
+#endif // DEBUG
+              _targetX = tank->x;
+              _targetY = tank->y;
+              FLOATTEXT *kamikazeText;
+              kamikazeText = new FLOATTEXT (_global, _env, selectKamikazePhrase(),
+                                            (int) tank->x, (int) tank->y - 30, color, CENTRE);
+              if ( kamikazeText)
+              {
+                // kamikazeText->xv = 0;
+                // kamikazeText->yv = -0.4;
+                kamikazeText->set_speed(0.0, -0.4);
+                kamikazeText->maxAge = 300;
+              }
+              else
+                  perror ( "player.cc: Failed allocating memory for kamikazeText in computerSelectItem.");
+            }
+        }
+    }
+
+#ifdef DEBUG
+  if (_target)
+    printf("Finished!\nShooting at %s\n", _target->player->getName() );
+  else
+    printf("Finished!\nI'll free myself.\n");
+  if (current_weapon < WEAPONS)
+    printf("Using weapon %s\n", weapon[current_weapon].name);
+  else
+    printf("Using item %s\n", item[current_weapon - WEAPONS].name);
+  printf("=============================================\n");
+#endif // DEBUG
+  tank->cw = current_weapon;
+  _global->updateMenu = 1;
+  return (current_weapon);
+}
+
+int PLAYER::computerControls ()
+{
+  int status = 0;
+  // At the most basic: select target, select weapon, aim and fire
+  tank->requireUpdate ();
+  if (_turnStage == SELECT_WEAPON)
+    {
+      computerSelectItem();
+      iTargettingRound = 0;
+      _turnStage = CALCULATE_ATTACK;
+      _global->updateMenu = 1;
+    }
+  else if (_turnStage == SELECT_TARGET)
+    {
+      cout << "ERROR: _turnstage became SELECT_TARGET!" << endl;
+      // Target is already chosen by computerSelectItem()
+      _turnStage = SELECT_WEAPON;
+    }
+  else if (_turnStage == CALCULATE_ATTACK)
+    {
+
+#ifdef DEBUG_AIM_SHOW
+      _global->bASD = true; // Now it is allowed to be true
+#endif
+
+      calculateAttack(NULL);
+      _turnStage = AIM_WEAPON; // If the targetting wasn't finished, it will be done later!
+
+#ifdef DEBUG_AIM_SHOW
+      _global->bASD = false; // And now it isn't!
+#endif
+    }
+  else if (_turnStage == AIM_WEAPON)
+    {
+      // First: Determine whether there are any updates to be done yet:
+      bool bDoAngleUpdate = false;
+      bool bDoPowerUpdate = false;
+      if (iTargettingRound == retargetAttempts)
+        {
+          // Do both when finished aiming
+          bDoAngleUpdate = true;
+          bDoPowerUpdate = true;
+        }
+      else if (iTargettingRound && (abs(_targetAngle - tank->a) <= 90))
+        // Only do Angle update if still aiming and difference isn't too high
+        bDoAngleUpdate = true;
+
+      if (bDoAngleUpdate && (_targetAngle > tank->a && tank->a < 270) )
+        {
+          // Left (If already aimed)
+          tank->a++;
+          _global->updateMenu = 1;
+        }
+      else if (bDoAngleUpdate && (_targetAngle < tank->a && tank->a > 90) )
+        {
+          // Right (if already aimed)
+          tank->a--;
+          _global->updateMenu = 1;
+        }
+      else if (bDoPowerUpdate && (_targetPower < (tank->p - 3) && tank->p > 0))
+        {
+          // Reduce power (if targetting is finished)
+          tank->p -= 5;
+          _global->updateMenu = 1;
+        }
+      else if (bDoPowerUpdate && (_targetPower > (tank->p + 3) && tank->p < MAX_POWER) )
+        {
+          // Increase Power (if targetting is finished)
+          tank->p += 5;
+          _global->updateMenu = 1;
+        }
+      else
+        {
+          // Targetting finished?
+          if (iTargettingRound == retargetAttempts)
+            _turnStage = FIRE_WEAPON; // Finished aiming, go ahead!
+          else
+            _turnStage = CALCULATE_ATTACK; // Not finished, do some more aiming
+        }
+    }
+  #ifdef OLD_GAMELOOP
+  else if (fi)
+    {
+      // if (fi) don't do any of the following
+    }
+  #endif
+  else if (_turnStage == FIRE_WEAPON)
+    {
+      // tank->activateCurrentSelection ();
+      _global->updateMenu = 1;
+      #ifdef DEBUG
+      printf("About to activate weapon.\n");
+      #endif
+      tank->simActivateCurrentSelection();
+      if (type == VERY_PART_TIME_BOT)
+          type = NETWORK_CLIENT;
+      #ifdef DEBUG
+      printf("Weapon was activated.\n");
+      #endif
+      gloating = false;
+      _turnStage = 0;
+      status = CONTROL_FIRE;
+    }
+  return (status);
+}
+
+int PLAYER::humanControls ()
+{
+  int moved = 0;
+  int status = 0;
+
+  if (tank)
+    {
+      if (!_env->mouseclock && mouse_b & 1 && mouse_x >= 250
+          && mouse_x < 378 && mouse_y >= 11 && mouse_y < 19)
+        {
+          _global->updateMenu = 1;
+          if (tank->fs)
+            {
+              tank->sht++;
+            }
+          tank->fs = 1;
+          if (tank->sht > SHIELDS - 1)
+            {
+              tank->sht = 0;
+            }
+        }
+      if (!_env->mouseclock && mouse_b & 1 && mouse_x >= 250
+          && mouse_x < 378 && mouse_y >= 21
+          && mouse_y < 29 && tank->player->ni[tank->sht] > 0 && (tank->fs || tank->sh > 0))
+        {
+          _global->updateMenu = 1;
+          tank->ds = tank->sht;
+          tank->player->ni[tank->sht]--;
+          tank->sh = (int)item[tank->sht].vals[SHIELD_ENERGY];
+        }
+
+      tank->requireUpdate ();
+    }
+
+  //Keyboard control
+  if ( _env->stage == STAGE_AIM)
+    {
+      if (tank)
+        {
+          if ( (key[KEY_LEFT] || key[KEY_A]) && !ctrlUsedUp && tank->a < 270)
+            {
+              tank->a++;
+              _global->updateMenu = 1;
+              if (key_shifts & KB_CTRL_FLAG)
+                ctrlUsedUp = TRUE;
+            }
+          if ( (key[KEY_RIGHT] || key[KEY_D]) && !ctrlUsedUp && tank->a > 90)
+            {
+              tank->a--;
+              _global->updateMenu = 1;
+              if (key_shifts & KB_CTRL_FLAG)
+                ctrlUsedUp = TRUE;
+            }
+          if ( (key[KEY_DOWN] || key[KEY_S]) && !ctrlUsedUp && tank->p > 0)
+            {
+              tank->p -= 5;
+              _global->updateMenu = 1;
+              if (key_shifts & KB_CTRL_FLAG)
+                ctrlUsedUp = TRUE;
+            }
+          if ( (key[KEY_UP] || key[KEY_W]) && !ctrlUsedUp && tank->p < MAX_POWER)
+            {
+              tank->p += 5;
+              _global->updateMenu = 1;
+              if (key_shifts & KB_CTRL_FLAG)
+                ctrlUsedUp = TRUE;
+            }
+          if ( (key[KEY_PGUP] || key[KEY_R]) && !ctrlUsedUp && tank->p < MAX_POWER )
+            {
+              tank->p += 100;
+              if (tank->p > MAX_POWER)
+                tank->p = MAX_POWER;
+              _global->updateMenu = 1;
+              if (key_shifts & KB_CTRL_FLAG)
+                ctrlUsedUp = TRUE;
+            }
+          if ( (key[KEY_PGDN] || key[KEY_F]) && !ctrlUsedUp && tank->p > 0)
+            {
+              tank->p -= 100;
+              if (tank->p < 0)
+                tank->p = 0;
+              _global->updateMenu = 1;
+              if (key_shifts & KB_CTRL_FLAG)
+                ctrlUsedUp = TRUE;
+            }
+        }
+    }
+
+    #ifdef OLD_GAMELOOP
+    if (k && !fi)
+    #endif
+    #ifdef NEW_GAMELOOP
+    // if ( keypressed() )
+    //    k = readkey();
+    // else
+    //   k = 0;
+    if (! k)
+    {
+       if ( keypressed() )
+         k = readkey();
+    }
+    if (k)
+    #endif
+    {
+      status = CONTROL_PRESSED;
+      if ( _env->stage == STAGE_AIM)
+        {
+          if (tank)
+            {
+              if (k >> 8 == KEY_N)
+                {
+                  tank->a = 180;
+                  _global->updateMenu = 1;
+                }
+              if ( (k >> 8 == KEY_TAB) || (k >> 8 == KEY_C) )
+                {
+                  _global->updateMenu = 1;
+                  while (1)
+                    {
+                      tank->cw++;
+                      if (tank->cw >= THINGS)
+                        tank->cw = 0;
+                      if (tank->cw < WEAPONS)
+                        {
+                          if (tank->player->nm[tank->cw])
+                            break;
+                        }
+                      else
+                        {
+                          if (item[tank->cw - WEAPONS].selectable && tank->player->ni[tank->cw - WEAPONS])
+                            break;
+
+                        }
+                    }
+                  //calcDamageMatrix (tank, tank->cw);
+                  //selectTarget ();
+                  changed_weapon = false;
+                }
+              if ( ( k >> 8 == KEY_BACKSPACE) || ( k >> 8 == KEY_Z) )
+                {
+                  _global->updateMenu = 1;
+                  while (1)
+                    {
+                      tank->cw--;
+                      if (tank->cw < 0)
+                        tank->cw = THINGS - 1;
+
+                      if (tank->cw < WEAPONS)
+                        {
+                          if (tank->player->nm[tank->cw])
+                            break;
+                        }
+                      else
+                        {
+                          if (item[tank->cw - WEAPONS].selectable && tank->player->ni[tank->cw - WEAPONS])
+                            break;
+
+                        }
+                    }
+                  changed_weapon = false;
+                }
+
+              // put the tank under computer control
+              if (k >> 8 == KEY_F10) 
+                {
+                  type = PART_TIME_BOT;
+                  setComputerValues();
+                  return (computerControls());
+                }
+
+              // move the tank
+              if (k >> 8 == KEY_COMMA) // || (key >> 8 == KEY_H) )
+                moved = tank->Move_Tank(DIR_LEFT);
+              else if (k >> 8 == KEY_H)
+                moved = tank->Move_Tank(DIR_LEFT);
+
+              if (k >> 8 == KEY_STOP) // || (key >> 8 == KEY_J) )
+                moved = tank->Move_Tank(DIR_RIGHT);
+              else if (k >> 8 == KEY_J)
+                moved = tank->Move_Tank(DIR_RIGHT);
+              if (moved)
+                _global->updateMenu = 1;
+
+              if ((k >> 8 == KEY_SPACE) &&
+                  (((tank->cw < WEAPONS) && (tank->player->nm[tank->cw] > 0)) ||
+                   ((tank->cw < THINGS) && (tank->player->ni[tank->cw - WEAPONS] > 0))))
+                {
+                  //	tank->activateCurrentSelection ();
+                  tank->simActivateCurrentSelection();
+                  gloating = false;
+                  status = CONTROL_FIRE;
+                }
+            }
+        }
+      if ((_env->stage == STAGE_ENDGAME) && (k >> 8 == KEY_ENTER || k >> 8 == KEY_ESC || k >> 8 == KEY_SPACE))
+        return (-1);
+    }
+  return (status);
+}
+
+
+
+// returns a static string to the player's team name
+char *PLAYER::Get_Team_Name()
+{
+  char *team_name = "";
+
+  switch ( (int) team)
+    {
+    case TEAM_JEDI:
+      team_name = "Jedi";
+      break;
+    case TEAM_NEUTRAL:
+      team_name = "Neutral";
+      break;
+    case TEAM_SITH:
+      team_name = "Sith";
+      break;
+    }
+
+  return team_name;
+}
+
+
+
+// Pick a weapon to fire at random.
+// The weapon number is returned. If no other
+// weapon is in inventory, then 0 - small missile is
+// used.
+int PLAYER::Select_Random_Weapon()
+{
+  int index;
+  int num_weapons = 0;
+  int random_weapon;
+
+  // count number of different weapons we have
+  for (index = 1; index < WEAPONS; index++)
+    {
+      if ( nm[index] )
+        num_weapons++;
+    }
+
+  // we have no weapons, use default
+  if ( num_weapons == 0 )
+    return 0;
+
+  // pick a random offset from the bottom of the list
+  random_weapon = (rand() % num_weapons) + 1;
+
+  index = WEAPONS - 1;
+  while ( (index) && (random_weapon) )
+    {
+      if ( nm[index] )
+        random_weapon--;
+      if (random_weapon)
+        index--;
+    }
+
+  // If the (char *)"weapon" is a dirtball, skip it 75% of the time:
+  if	( ( (index	==	DIRT_BALL) || (index	==	LRG_DIRT_BALL)) && (rand() % 4))
+    return 0;
+
+  // Skip if it is an unburying tool
+  if	( (index	==	RIOT_CHARGE)
+       || (index	==	RIOT_BOMB)
+       || (index	==	RIOT_BLAST)
+       || (index	==	HVY_RIOT_BOMB))
+    return 0;
+  return index;
+}
+
+
+
+// This function selects a random item for
+// the AI to use.
+// This item to use is returned. If no
+// item can be found, then the function
+// returns 0
+int PLAYER::Select_Random_Item()
+{
+  int index, item_num;
+  int num_items = 0;
+  int random_item;
+
+  // count the items we have
+
+  for (index = WEAPONS; index < THINGS; index++)
+    {
+      item_num = index - WEAPONS;
+
+      if ( (ni[item_num]) && (item[item_num].selectable))
+        num_items++;
+    }    // end of counting items
+
+  if (! num_items)
+    return 0;
+
+  // if we have an item, there is still a 75% chance
+  // that we may not use it
+  if (rand() % 4)
+    return 0;
+
+  // pick a random offset from the bottom of the list
+  random_item = (rand() % num_items) + 1;
+
+  index		= THINGS - 1;
+
+  item_num =	index - WEAPONS;
+
+  while (item_num && random_item)
+    {
+      if ( (ni[item_num]) && (item[item_num].selectable))
+        random_item--;
+
+      if (random_item)
+        {
+          index--;
+          item_num	=	index - WEAPONS;
+        }
+    }
+
+  if ((item_num	==	ITEM_TELEPORT) || (item_num == ITEM_SWAPPER))
+    index = 0;
+
+//  // do not use teleport without a parachute
+//  if ( (item_num == ITEM_TELEPORT) && (! ni[ITEM_PARACHUTE]))
+//    index = 0;
+
+  // do not self destruct
+  if ( (item_num	==	ITEM_VENGEANCE)
+       || (item_num	==	ITEM_DYING_WRATH)
+       || (item_num	==	ITEM_FATAL_FURY))
+    index = 0;
+
+  if (index > 0)
+    index = item_num + WEAPONS;
+  return index;
+}
+
+// This function takes one off the player's time to fire.
+// If the player runs out of time, the function returns TRUE.
+// If the player has time left, or no time clock is being used,
+// then the function returns FALSE.
+int PLAYER::Reduce_Time_Clock()
+{
+  if (! time_left_to_fire)     // not using clock
+    return FALSE;
+
+  time_left_to_fire--;
+  if (! time_left_to_fire)    // ran out of time
+    {
+      tank->shots_fired++;      // pretend we fired
+      time_left_to_fire = _global->max_fire_time;
+      return TRUE;
+    }
+  return FALSE;
+}
+
+// The damage provided is not the weapon damage, but what the bot calculated!
+int PLAYER::getBlastValue (TANK * aTarget, int aDamage, int aWeapon, double aDamageMod)
+{
+  int iHealth				= 0;	//	Health of the evaluated tank
+  int iTeam;							//	Team of the evaluated tank
+  double dDistance;				//	Distance of the target to the evaluated tank
+  double dXdist, dYdist;	//	needed to calculate dDistance
+  int iDmgValue			=	0;	//	The value of the blast
+  int iBlastDamage	= 0;	//	The damage the weapon is doing right there
+  double dTeamMod 	= 1.0;//	Teams react differently on TAs
+  int iWeapon				=	0;	//	Items (self destruc) count as CUTTERS for their blast radius!
+  TANK * cOppTank;
+
+  if (aWeapon < WEAPONS)
+    iWeapon = aWeapon;
+  else
+    iWeapon	=	CUTTER;
+
+  for (int i = 0; i < _global->numPlayers; i++)
+    {
+      cOppTank	=	_global->players[i]->tank;
+      if (cOppTank && aTarget)
+        {
+          if (this == _global->players[i])
+            // If we'd hit ourself, life is valued twice.
+            iHealth = (cOppTank->l / 2) + cOppTank->sh;
+          else
+            iHealth = cOppTank->l + cOppTank->sh;
+          iTeam		=	_global->players[i]->team;
+          // Only count living targets that are not the official target
+          if ( (iHealth > 0) && (cOppTank != aTarget))
+            {
+              dXdist	=	fabs (aTarget->x - cOppTank->x) - (TANKWIDTH / 2);
+              dYdist	=	fabs (aTarget->y - cOppTank->y) - (TANKHEIGHT / 2);
+              if (dXdist < 0) dXdist = 1.0;
+              if (dYdist < 0) dYdist = 0.0;
+              if	( (aWeapon >= SHAPED_CHARGE)
+                   && (aWeapon <= CUTTER)
+                   && ( (dYdist		>=	(weapon[iWeapon].radius / 20))
+                        || (dXdist		<=	(TANKWIDTH / 2))))
+                dDistance = 2.0 * (double) weapon[iWeapon].radius; // out of the way!
+              else
+                dDistance = ABSDISTANCE(dXdist, dYdist, 0, 0) - ( (double) type * (defensive + 2.0));
+
+              // Now see whether the tank is in weapon blast range:
+              if (dDistance <= weapon[iWeapon].radius)
+                {
+                  // Yep, it is!
+                  iBlastDamage = (int) ( (double) aDamage * (1.0 - ( (dDistance / (double) weapon[iWeapon].radius) / 2.0)));
+                  if	( ( (team != TEAM_NEUTRAL) && (team == iTeam))
+                       || (this == _global->players[i]))
+                    {
+                      // it is a fellow team mate, or ourself
+                      // teams act differently
+                      switch ( (int) team)
+                        {
+                        case TEAM_JEDI:
+                          dTeamMod	= ( (double) type	/ 2.0) + 1.5;		// 2.0 up to 4.0
+                          break;
+                        case TEAM_SITH:
+                          dTeamMod	= ( (double) type / 4.0) + 0.75;	// 1.0 up to 2.0
+                          break;
+                        default:
+                          dTeamMod	=	(double) type;	// neutrals won't like to hit themselves at all!
+                        }
+
+                      if (iBlastDamage > iHealth)
+                        // We would kill our mate, or cost us too much health!
+                        iDmgValue -= (int) (dTeamMod	* ( (double) aDamage 			/ aDamageMod)	* ( (defensive + 3.0) / 2.0));
+                      else
+                        // We don't kill, but count the blast at least
+                        iDmgValue -= (int) (dTeamMod	* ( (double) iBlastDamage / aDamageMod)	* ( (defensive + 3.0) / 2.0));
+
+                      // Note: The /=aDamageMod results in blast damage counted worse, if the aDamageMod is low
+                    }
+                  else
+                    {
+                      // Just Someone... see if we kill them
+                      if (iBlastDamage > iHealth)
+                        // Woohoo!
+                        iDmgValue	+=	(int) ( ( (1.0 + (double) type / 10))
+                                             * (double) (iBlastDamage + iHealth)
+                                             * ( (defensive + 3.0) / 2.0));
+                      else
+                        // Well, at least...
+                        iDmgValue	+=	(int) ( ( (1.0 + (double) type / 10))
+                                             * aDamageMod
+                                             * (double) (iBlastDamage)
+                                             * ( (defensive - 3.0) / -2.0));
+                    }
+                }
+            }
+        }
+    }
+#ifdef DEBUG
+  if ((iDmgValue != 0) && (aDamageMod != 1.0))
+    cout << "(blast: " << iDmgValue << ") ";
+#endif
+  return (iDmgValue);
+}
+
+int PLAYER::getMoneyToSave()
+{
+  double dMoneyToSave	= 0.0;
+  int iAvgPref			=	0;
+  int iPrefLimit    = 0;
+  int iPrefCount    = 0;
+  int iInvCount     = 0;
+  int iInvMoney     = 0;
+  int iMaxCost			=	0;
+
+  // if the preferences are exceptionally low, a div by 0 might occur, so it has to be dynamized:
+  for (int i = 0; i < WEAPONS; i++)
+    {
+      if (_weaponPreference[i] > iPrefLimit)
+        iPrefLimit = (iPrefLimit + _weaponPreference[i]) / 2;
+    }
+  // Now it is guaranteed, that iPrefCount and iAvgPref will result in values > 0!
+  for (int i = 0; i < WEAPONS; i++)
+    {
+      if (_weaponPreference[i] > iPrefLimit)
+        {
+          iPrefCount++;
+          iAvgPref += _weaponPreference[i];
+        }
+    }
+  // we are running into divide by zero here.
+  if (iPrefCount < 1) 
+      iPrefCount = 1;
+  iAvgPref /= iPrefCount; // Now the average of all relevant weapon preferences
+
+  // Now we search for everything over this average and count costs and inventory value:
+  for (int i = 0; i < WEAPONS; i++)
+    {
+      if (_weaponPreference[i] > iAvgPref)
+        {
+          // This weapon is (char *)"wanted"
+          dMoneyToSave += weapon[i].cost;
+          if (weapon[i].cost > iMaxCost)
+            iMaxCost	=	weapon[i].cost;
+          if (nm[i])
+            {
+              // We have (some) if this already!
+              iInvCount++;
+              iInvMoney += (int) ( ( (double) nm[i] / (double) weapon[i].amt) * (double) weapon[i].cost);
+            }
+        }
+    }
+
+  // The Maximum amount is (type * 2) times the most expensive weapon we like:
+  iMaxCost *= (int) type * 2;
+  // As of writing this, this means a maximum of:
+  // Armageddon: 100,000 credits
+  // Deadly Bot: (int)type == 5
+  // iMaxCost = 100,000 * 5 * 2 = 1,000,000 credits maximum!
+
+     dMoneyToSave = (double)iMaxCost * 0.25;
+#ifdef DEBUG
+  printf( (char *)"% 4d Prefs, worth % 6d\n", iPrefCount, iAvgPref);
+  printf( (char *)"% 4d Items, worth % 6d\n", iInvCount, iInvMoney);
+  printf( (char *)"MoneyToSave:      % 6d\n", (int)dMoneyToSave);
+  printf( (char *)"Money: % 6d -> MaxCost: %6d\n", (int)money, iMaxCost);
+#endif // DEBUG
+  // Whenever dMoneyToSave is less than the money owned, iBoostItemsBought is resetted
+  if (money > (int)dMoneyToSave)
+    iBoostItemsBought = 0; // Let's go!
+  return ( (int) dMoneyToSave);
+}
+
+
+
+// if we have some shield strength at the end of the round, then
+// reclaim this shield back into our inventory
+
+int PLAYER::Reclaim_Shield()
+{
+    if (! tank)
+       return FALSE; 
+    if (! last_shield_used)
+       return FALSE;
+
+    if (tank->sh > 0)
+       ni[last_shield_used] += 1;
+   
+    last_shield_used = 0;
+    return TRUE;
+}
+
+
+
+#ifdef NETWORK
+
+
+// Removes the newline character and anything after it
+// from a string.
+void PLAYER::Trim_Newline(char *line)
+{
+    int index = 0;
+
+    while ( line[index] )
+    {
+       if ( (line[index] == '\n') || (line[index] == '\r') )
+          line[index] = '\0';
+       else
+          index++;
+    }
+}
+
+
+// This function checks for incoming data from a client.
+// If data is coming in, we put the incoming data in the net_command
+// variable. If the socket connection is broken, then we will
+// close the socket and hand control over to the AI.
+int PLAYER::Get_Network_Command()
+{
+   int status;
+
+   status = Check_For_Incoming_Data(server_socket);
+   if (status)
+   {
+      // we have something coming down the pipe
+      memset(net_command, '\0', NET_COMMAND_SIZE);    // clear buffer
+      status = read(server_socket, net_command, NET_COMMAND_SIZE);
+      if (! status)   // connection is broken
+      {
+         close(server_socket);
+         type = DEADLY_PLAYER;
+         printf("%s lost network connection. Returning control to AI.\n", _name);
+         return FALSE;
+      }
+      else   // we got data
+      {
+         net_command[NET_COMMAND_SIZE - 1] = '\0';
+         Trim_Newline(net_command);
+      }
+   }
+   return TRUE;
+}
+
+
+// This function gets called during a round when a networked
+// player gets to act. The function checks to see if anything
+// is in the net_command variable. If there is, it handles
+// the request. If not, the function returns.
+//
+// We should have some time keeping in here before this goes live
+// to avoid hanging the game.
+
+int PLAYER::Execute_Network_Command(int my_turn)
+{
+   char buffer[NET_COMMAND_SIZE];
+   static int player_index = -1;
+   static int fire_delay = 0, net_delay = 0;
+
+   if (my_turn)
+   {
+       fire_delay++;
+       // if enough time has passed, we give up and turn control over to the AI
+       if (fire_delay >= NET_DELAY)
+       {
+          setComputerValues();
+          type = VERY_PART_TIME_BOT;
+          fire_delay = 0;
+          return ( computerControls() );
+       }
+   }
+
+   if (! net_command[0])
+   {
+           net_delay++;
+           /*
+           if (my_delay >= NET_DELAY)
+           {
+              my_delay = 0;
+              setComputerValues();
+              type = VERY_PART_TIME_BOT;
+              strcpy(buffer, "PING");
+              write(server_socket, buffer, strlen(buffer));
+              return (computerControls());
+           }
+           else*/ 
+           if (net_delay >= NET_DELAY_SHORT)
+           {
+               // prompt the client to respond
+               strcpy(buffer, "PING");
+               write(server_socket, buffer, strlen(buffer));
+               return 0;
+           }
+           return 0;
+   }     // we did not get a command to process
+
+   else
+     net_delay = 0;       // we got something, so reset timer
+
+   if (! strncmp(net_command, "VERSION", 7) )
+   {
+       sprintf(buffer, "SERVERVERSION %s", VERSION);
+       write(server_socket, buffer, strlen(buffer) );
+   }
+   else if (! strncmp(net_command, "CLOSE", 5) )
+   {
+       close(server_socket);
+       type = DEADLY_PLAYER;
+   }
+   else if (! strncmp(net_command, "BOXED", 5) )
+   {
+      char buffer[32];
+      if (_global->bIsBoxed)
+         strcpy(buffer, "BOXED 1");
+      else
+         strcpy(buffer, "BOXED 0");
+      write(server_socket, buffer, strlen(buffer));
+   }
+   else if (! strncmp(net_command, "GOSSIP", 6) )
+   {
+      snprintf(_global->tank_status, 128, "%s", & (net_command[7]) );
+      _global->updateMenu = TRUE;
+   }
+   else if (! strncmp(net_command, "HEALTH", 6) )
+   {
+       int tank_index;
+       char buffer[64];
+
+       sscanf( &(net_command[7]), "%d", &tank_index );
+       if ( (tank_index >= 0) && (tank_index < _global->numPlayers) )
+       {
+           if (_global->players[tank_index]->tank)
+           {
+               snprintf(buffer, 64, "HEALTH %d %d %d %d", tank_index,
+                        _global->players[tank_index]->tank->l,
+                        _global->players[tank_index]->tank->sh,
+                        _global->players[tank_index]->tank->sht);
+               write(server_socket, buffer, strlen(buffer));
+           }
+       }
+
+   }
+   else if (! strncmp(net_command, "ITEM", 4) )
+   {
+       char buffer[32];
+       int item_index;
+       sscanf( &(net_command[5]), "%d", &item_index);
+       if ( (item_index >= 0) && (item_index < ITEMS) )
+       {
+          sprintf(buffer, "ITEM %d %d", item_index, ni[item_index]);
+          write(server_socket, buffer, strlen(buffer));
+       }
+   }
+   else if (! strncmp(net_command, "MOVE", 4) )
+   {
+       if (! my_turn) return 0;
+       if (tank)
+       {
+           if (strstr(net_command, "LEFT") )
+              tank->Move_Tank(DIR_LEFT);
+           else
+              tank->Move_Tank(DIR_RIGHT);
+           _global->updateMenu = 1;
+       }
+   }
+   else if (! strncmp(net_command, "FIRE", 4) ) 
+   {
+       int angle = 180, power = 1000, item = 0;
+       if (! my_turn) return 0;
+       sscanf( & (net_command[5]), "%d %d %d", &item, &angle, &power);
+       fire_delay = 0;
+       if (tank)
+       {
+           if (item >= THINGS) item = 0;
+           tank->cw = item;
+           if (item < WEAPONS)
+           {
+              if (nm[tank->cw] < 1)
+                 tank->cw = 0;
+           }
+           else   // item
+           {
+              if ( ni[tank->cw - WEAPONS] < 1)
+                  tank->cw = 0;
+           }
+           tank->a = angle;
+           if (tank->a > 270) tank->a = 270;
+           else if (tank->a < 90) tank->a = 90;
+           tank->p = power;
+           if (tank->p > 2000) tank->p = 2000;
+           else if (tank->p < 0) tank->p = 0;
+           tank->simActivateCurrentSelection();
+           gloating = false;
+           net_command[0] = '\0';
+           return CONTROL_FIRE;
+       }
+   }
+
+   // find out which player this is
+   else if (! strncmp(net_command, "WHOAMI", 6) )
+   {
+       bool found = false;
+       char buffer[128];
+
+       while ( (player_index < _global->numPlayers) && (! found) )
+       {
+           if ( _global->players[player_index] == this )
+           {
+               found = true;
+               sprintf(buffer, "YOUARE %d", player_index);
+           }
+           else
+              player_index++;
+       }
+       // check to see if something went very wrong
+       if (! found)
+           strcpy(buffer, "YOUARE -1");
+       write(server_socket, buffer, strlen(buffer));
+   }
+   // return wind speed
+   else if (! strncmp(net_command, "WIND", 4) )
+   {
+      char buffer[64];
+      sprintf(buffer, "WIND %f", _env->wind);
+      write(server_socket, buffer, strlen(buffer));
+   }
+
+   // find out how many players we have
+   else if (! strncmp(net_command, "NUMPLAYERS", 10) )
+   {
+      char buffer[32];
+      sprintf(buffer, "NUMPLAYERS %d", _global->numPlayers);
+      write(server_socket, buffer, strlen(buffer));
+   }
+   else if (! strncmp(net_command, "PLAYERNAME", 10) )
+   {
+      int my_number;
+      char buffer[128];
+      sscanf( &(net_command[11]), "%d", &my_number);
+      if ( (my_number >= 0) && (my_number < _global->numPlayers) )
+      {
+           sprintf(buffer, "PLAYERNAME %d %s", my_number, _global->players[my_number]->getName() );
+           write(server_socket, buffer, strlen(buffer));
+      }
+   }
+
+   // how many rounds are we playing
+   else if (! strncmp(net_command, "ROUNDS", 6) )
+   {
+       char buffer[64];
+       sprintf(buffer, "ROUNDS %d %d", (int) _global->rounds, _global->currentround);
+       write(server_socket, buffer, strlen(buffer));
+   }
+   // send back the position of each tank
+   else if (! strncmp(net_command, "TANKPOSITION", 12) )
+   {
+      char buffer[64];
+      int count;
+
+      sscanf( &(net_command[13]), "%d", &count);
+      if ( (count >= 0) && (count < _global->numPlayers) )
+      { 
+          if (_global->players[count]->tank)
+          {
+             sprintf(buffer, "TANKPOSITION %d %d %d", count, (int) _global->players[count]->tank->x,
+                 (int) _global->players[count]->tank->y);
+             write(server_socket, buffer, strlen(buffer));
+          }
+      }
+   }
+  
+   // send back the surface height of the dirt
+   else if (! strncmp(net_command, "SURFACE", 7) )
+   {
+       char buffer[32];
+       int x;
+
+       sscanf( &(net_command[8]), "%d", &x);
+       if ( (x >= 0) && (x < _global->screenWidth) )
+       {
+           sprintf(buffer, "SURFACE %d %d", x, _env->surface[x]);
+           write(server_socket, buffer, strlen(buffer));
+       }
+   }
+   else if (! strncmp(net_command, "SCREEN", 6) )
+   {
+      char buffer[64];
+      sprintf(buffer, "SCREEN %d %d", _global->screenWidth, _global->screenHeight);
+      write(server_socket, buffer, strlen(buffer));
+   }
+   else if (! strncmp(net_command, "TEAMS", 5) )
+   {
+      int count;
+      char buffer[32];
+
+      sscanf( &(net_command[6]), "%d", &count);
+      if ( (count < _global->numPlayers) && (count >= 0) )
+      {
+          sprintf(buffer, "TEAM %d %d", count, (int) _global->players[count]->team);
+          write(server_socket, buffer, strlen(buffer));
+      }
+   }
+   else if (! strncmp(net_command, "WALLTYPE", 8) )
+   {
+      char buffer[32];
+      sprintf(buffer, "WALLTYPE %d", _env->current_wallType);
+      write(server_socket, buffer, strlen(buffer));
+   }
+   else if (! strncmp(net_command, "WEAPON", 6) )
+   {
+      char buffer[32];
+      int weapon_number;
+      sscanf( &(net_command[7]), "%d", &weapon_number);
+      if ( (weapon_number >= 0) && (weapon_number < WEAPONS) )
+      {
+         sprintf(buffer, "WEAPON %d %d", weapon_number, nm[weapon_number]);
+         write(server_socket, buffer, strlen(buffer));
+      }
+   }
+
+   net_command[0] = '\0';
+   return 0;
+}
+
+#endif
+
+
+
+
diff --git a/src/player.h b/src/player.h
new file mode 100644
index 0000000..0881609
--- /dev/null
+++ b/src/player.h
@@ -0,0 +1,207 @@
+#ifndef PLAYER_HEADER_
+#define PLAYER_HEADER_
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "main.h"
+#include "menu.h"
+
+
+enum playerType
+{
+  HUMAN_PLAYER,
+  USELESS_PLAYER,
+  GUESSER_PLAYER,
+  RANGEFINDER_PLAYER,
+  TARGETTER_PLAYER,
+  DEADLY_PLAYER,
+  LAST_PLAYER_TYPE,
+  PART_TIME_BOT,         // normally a human, but acting as a deadly computer
+  VERY_PART_TIME_BOT,    // just fires one shot
+  NETWORK_CLIENT
+};
+//player weapon preference type
+//ALWAYS_PREF - only choose weapon preferences once on player creation
+//PERPLAY_PREF - choose weapon preferences once per game
+enum playerPrefType
+{
+  PERPLAY_PREF,
+  ALWAYS_PREF
+};
+enum turnStages
+{
+  SELECT_WEAPON,
+  SELECT_TARGET,
+  CALCULATE_ATTACK,
+  AIM_WEAPON,
+  FIRE_WEAPON
+};
+
+#define TANK_TYPES 8
+
+#define	NUM_ROULETTE_SLOTS (THINGS * 100)
+#define	MAX_WEAP_PROBABILITY	10000
+#define BURIED_LEVEL 135
+
+#define NET_COMMAND_SIZE 64
+// if we do not get a command after this amount of seconds,
+// turn control over to the computer for a moment
+#define NET_DELAY 1000
+#define NET_DELAY_SHORT 500
+
+
+// values the control functions return ot the main game loop
+#define CONTROL_PRESSED 2   // some key pressed, but not to shoot
+#define CONTROL_FIRE 1
+#define CONTROL_QUIT -1
+#define CONTROL_SKIP -2
+
+
+class TANK;
+class PLAYER
+  {
+
+    char	_name[NAME_LENGTH];
+    int	_currTank;
+    GLOBALDATA *_global;
+    ENVIRONMENT *_env;
+    char	_turnStage;
+    TANK	*_target;
+    TANK  *_oldTarget;
+    int	_targetAngle;
+    int	_targetPower;
+    int	_overshoot;
+    int	_weaponPreference[THINGS];
+    int	_rouletteWheel[NUM_ROULETTE_SLOTS];
+    int	_targetX;
+    int	_targetY;
+    int iBoostItemsBought;
+    int iTargettingRound;
+    int computerSelectPreBuyItem (int aMaxBoostValue = 0);
+    TANK * computerSelectTarget (int aPreferredWeapon, bool aRotationMode = false);
+    char * selectKamikazePhrase();
+    char * selectRetaliationPhrase();
+    int getBlastValue (TANK * aTarget, int aDamage, int aWeapon, double aDamageMod = 1.0);
+    int getUnburyingTool();
+    int adjustOvershoot(int &aOvershoot, double aReachedX, double aReachedY);
+    int getAdjustedTargetX(TANK * aTarget = NULL);
+    int calculateAttack(TANK *aTarget = NULL);
+    void calculateAttackValues(int &aDistanceX, int aDistanceY, int &aRawAngle, int &aAdjAngle, int &aPower, bool aAllowFlip);
+    int	traceShellTrajectory (double aTargetX, double aTargetY, double aVelocityX, double aVelocityY, double &aReachedX, double &aReachedY);
+    int	rangeFind (int &aAngle, int &aPower);
+
+  public:
+    double	type, type_saved, previous_type;
+    double preftype;
+    char* preftypeText[ALWAYS_PREF + 1];
+    char *tank_type[8];
+    char *teamText[3];
+
+    PLAYER	*revenge;
+    int	vengeful;	// 0-100 chance of retaliation
+    double	vengeanceThreshold;	// Damage required to warrant revenge
+    //   (% of max armour)
+    double	defensive;	// -1.0 - 1.0, offense - defense
+    double	annoyanceFactor;
+    double	selfPreservation;	// Lengths gone to to avoid self-harm
+    double	painSensitivity;	// How sensitive to damage
+    int	rangeFindAttempts;
+    int	retargetAttempts;
+    double	focusRate;
+    double	errorMultiplier;
+    int	score;
+    double	played, won;
+    int     kills, killed;
+    double	selected;
+    int	money;
+    double	damageMultiplier;
+    TANK	*tank;
+    int	color;
+    void *pColor;
+    int	color2;
+    int 	nm[WEAPONS], ni[ITEMS];
+    MENUENTRY	*menuopts;
+    MENUDESC	*menudesc;
+    char *typeText[LAST_PLAYER_TYPE];
+    bool changed_weapon;
+    bool gloating;
+    double tank_bitmap;      // which type of tank do we have
+    double team;
+    int time_left_to_fire;
+    bool skip_me;
+    int last_shield_used;
+    #ifdef NETWORK
+    int server_socket;
+    char net_command[NET_COMMAND_SIZE];
+    #endif
+
+    PLAYER (GLOBALDATA *global, ENVIRONMENT *env);
+    // PLAYER (GLOBALDATA *global, ENVIRONMENT *env, ifstream &ifsFile, bool file); 
+    ~PLAYER	();
+    void	setName (char *name);
+    char	*getName ()
+    {
+      return (_name);
+    };
+    int	calculateDirectAngle (int dx, int dy);
+    void	exitShop ();
+    void	newRound ();
+    void	initialise ();
+    TANK	*nextTank ();
+    TANK	*currTank ();
+    int	controlTank ();
+    int	humanControls ();
+    int	computerControls ();
+    double	calcDefenseValue (TANK *ctank, TANK *ltank);
+    double	selectTarget (); // select x to aim for
+    double	selectTarget (int *targetXCoord, int *targetYCoord); // select x to aim for
+    double  Select_Target (int *target_X, int *target_Y); // select x to aim for
+    int	computerSelectItem (); // Choose weapon to fire
+    int	chooseItemToBuy (int aMaxBoostValue = 0);
+    void	generatePreferences ();
+    void	setComputerValues (int aOffset = 0);
+    int getMoneyToSave();
+    int getBoostValue();
+    int	selectRandomItem ();
+    char	*selectRevengePhrase ();
+    char	*selectGloatPhrase ();
+    char    *selectSuicidePhrase ();
+    int     saveToFile_Text (FILE *file);
+    int     saveToFile (ofstream &ofsFile);
+    int     loadFromFile_Text (FILE *file);
+    int     loadFromFile (ifstream &ifsFile);
+    void	initMenuDesc ();
+    char    *Get_Team_Name();
+    int     Select_Random_Weapon();
+    int     Select_Random_Item();
+    int    Reduce_Time_Clock();
+    int    Buy_Something(int item_index);     // purchases the selected item
+    int    Reclaim_Shield();    // restore unused shield
+
+    #ifdef NETWORK
+    void Trim_Newline(char *line);   // sanitize input
+    int Get_Network_Command();
+    int Execute_Network_Command(int my_turn);
+    #endif
+  };
+
+#endif
+
diff --git a/src/satellite.cpp b/src/satellite.cpp
new file mode 100644
index 0000000..3b998c9
--- /dev/null
+++ b/src/satellite.cpp
@@ -0,0 +1,81 @@
+#include "environment.h"
+#include "satellite.h"
+#include "beam.h"
+
+
+SATELLITE::SATELLITE(GLOBALDATA *global, ENVIRONMENT *env):_global(global),_env(env)
+{ }
+
+SATELLITE::~SATELLITE()
+{
+  _env    = NULL;
+  _global = NULL;
+}
+
+
+void SATELLITE::Init()
+{
+  x = _global->screenWidth / 2;
+  previous_x = x;
+  y = 35;
+  xv = -2;
+}
+
+
+void SATELLITE::Move()
+{
+  if (x < -5)
+    xv += 1;
+  else if (x > (_global->screenWidth - 10) )
+    xv -= 1;
+
+  previous_x = x;
+  x += xv;
+}
+
+
+
+void SATELLITE::Draw(BITMAP *dest)
+{
+  drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+  draw_sprite(dest, (BITMAP *) _global->misc[SATELLITE_IMAGE],
+              x, y);
+
+  _env->make_update(x - 20, y, 80, 60);
+  _env->make_update(previous_x, y, 80, 60);
+}
+
+
+
+void SATELLITE::Shoot()
+{
+  int chance;
+  BEAM *my_beam;
+  int angle, laser_type;
+
+  if (_env->satellite == LASER_NONE)
+    return;
+
+  if (_env->naturals_since_last_shot >= 3)
+    return;
+
+  chance = rand() % 100;
+  if (! chance)        // !% chance to fire
+    {
+      if (_env->satellite == LASER_WEAK) laser_type = SML_LAZER;
+      else if (_env->satellite == LASER_STRONG) laser_type = MED_LAZER;
+      else if (_env->satellite == LASER_SUPER) laser_type = LRG_LAZER;
+      else return;
+
+      angle = rand() % 30;
+      my_beam = new BEAM(_global, _env, (xv < 0) ? x + 10: x + 40,
+                         y + 20, angle, laser_type);
+      if (! my_beam)
+        return;
+      my_beam->player = NULL;
+      _env->naturals_since_last_shot++;
+    }
+}
+
+
+
diff --git a/src/satellite.h b/src/satellite.h
new file mode 100644
index 0000000..3c53829
--- /dev/null
+++ b/src/satellite.h
@@ -0,0 +1,31 @@
+#ifndef SATELLITE_HEADER_FILE__
+#define SATELLITE_HEADER_FILE__
+
+
+#include "environment.h"
+#include "globaldata.h"
+#include "virtobj.h"
+
+#define SATELLITE_IMAGE 16
+#define CHANCE_TO_SHOOT 100
+
+
+class SATELLITE
+  {
+  public:
+    int x, y;
+    int xv, previous_x;
+    GLOBALDATA *_global;
+    ENVIRONMENT *_env;
+
+    SATELLITE(GLOBALDATA *global, ENVIRONMENT *env);
+    ~SATELLITE();
+    void Init();
+    void Move();
+    void Draw(BITMAP *dest);
+    void Shoot();
+
+  };
+
+#endif
+
diff --git a/src/sky.cpp b/src/sky.cpp
new file mode 100644
index 0000000..00f7f23
--- /dev/null
+++ b/src/sky.cpp
@@ -0,0 +1,433 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+sky.cc
+
+Code for generating sky backgrounds, including moons.
+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
+
+/*
+TODO
+ + Improve documentation
+ + Add clouds?
+*/
+
+#include "globaldata.h"
+#include "main.h"
+#include <vector>
+#include "environment.h"
+#include "sky.h"
+#include "files.h"
+
+
+/* Here's a function that could move nicely out of atanks.cc :) */
+int gradientColorPoint (const gradient *grad, double length, double line);
+
+
+/*============================================================================
+struct moon
+
+A simple data structure to store the parameters of a moon for easy passing.
+============================================================================*/
+struct moon
+  {
+    int radius;
+    int x;
+    int y;
+    double lambda;
+    int octaves;
+    double smoothness;
+    double xoffset;
+    double yoffset;
+    int col1;
+    int col2;
+  };
+
+
+/*############################################################################
+ZBuffer
+
+Acts a a simple, 1bpp zbuffer.  For each pixel location, the ZBuffer can
+remember if something is (char *)"popping up" at that location.
+############################################################################*/
+class ZBuffer
+  {
+  private:
+    // empty ctor, copy-ctor and assign operator are private, so the compiler won't create implicit ones!
+    inline ZBuffer () { }
+    inline ZBuffer (ZBuffer &sourceZBuf _UNUSED)_UNUSED;
+    inline const ZBuffer& operator= (const ZBuffer &sourceZBuf) { return(sourceZBuf); }
+
+    std::vector< bool >	z;
+    int shiftamt;
+
+  public:
+    /*************************************************************************
+    ctor
+
+    Construct a ZBuffer object capable of storing (char *)"popup" values for a
+    w by h grid.  All cells in the ZBuffer start out lowered.
+    *************************************************************************/
+    ZBuffer( int w, int h )
+    {
+      shiftamt = 0;
+      while ( w )
+        {
+          w >>= 1;
+          ++shiftamt;
+        }
+      z.resize( h << shiftamt );
+    }
+
+    /*************************************************************************
+    test
+
+    Returns true iff the cell at location (x,y) is raised.  Behavior is
+    undefined if x does not fall in the range [0,w) or if y does not fall in
+    the range [0,h); w and h being the parameters to the ctor.
+    *************************************************************************/
+    bool test( int x, int y ) const
+      {
+        return z[ (y<<shiftamt) | x ];
+      }
+
+
+    /*************************************************************************
+    set
+
+    Causes a cell in the ZBuffer to become raised.  Follows the same
+    conditions on x and y as the test function does.
+    *************************************************************************/
+    void set( int x, int y )
+    {
+      z[ (y<<shiftamt) | x ] = true ;
+    }
+  };
+
+
+/*****************************************************************************
+central_rand
+
+Return a random double in the range [0,u] where non-extreme values
+are preferred.
+
+Basic on a simple cubic function.
+*****************************************************************************/
+static double central_rand( double u )
+{
+  const double x = ( (double)rand( ) / RAND_MAX ) - 0.5;	// [-.5,+.5]
+  return u * (0.5 - (x*x*x)*4.0) ;
+}
+
+
+/*****************************************************************************
+clamped_int
+
+Clamps an integer value, m, into a range specified by [a,z].  Returns the
+clamped value.
+*****************************************************************************/
+static int clamped_int( int m, int a, int z )
+{
+  return (m<a) ? a : ( (m>z) ? z : m );
+}
+
+
+/*****************************************************************************
+generate_moon
+
+Returns a moon structure with appropriately randomized variables.
+*****************************************************************************/
+static moon generate_moon( int scrnw, int scrnh )
+{
+  moon m;
+
+  m.smoothness = (rand () % 20) + 3;
+  m.octaves = rand () % 4 + 6;
+  m.lambda = (rand () % 60 + 30) * (1.00/100);
+
+  //m.radius = (int)((rand () % 100 / 200.0) * (rand () % 100 / 200.0) * scrnw);
+  m.radius = (int)central_rand( scrnw/8 ) ;
+  m.x = rand () % scrnw;
+  m.y = rand () % scrnh;
+
+  m.xoffset = rand ();
+  m.yoffset = rand ();
+
+  m.col1 = makecol (rand () % 255, rand () % 255, rand () % 255);
+  m.col2 = makecol (rand () % 255, rand () % 255, rand () % 255);
+
+  return m;
+}
+
+
+/*****************************************************************************
+coverage
+
+Compute the percent coverage of a pixel by a sphere given the pixel's
+distance from the center and the sphere's radius.
+*****************************************************************************/
+static double coverage( double distance, double fradius )
+{
+  if ( distance <= fradius )
+    return 1.0 ;
+  return 1 - (distance - fradius);
+}
+
+
+/*****************************************************************************
+fract_clamp - unused
+
+Clamp a fraction down to the range [0.0,1.0]
+*****************************************************************************/
+/*static double fract_clamp( double x ) {
+	return (x < 0.0) ? 0.0 : ( (x>1.0) ? 1.0 : x );
+}*/
+
+
+
+/*****************************************************************************
+paint_moonpix
+
+Paint a pixel onto the screen for a particular part of a moon.
+
+Parameters:
+* bmp, x, y
+	The bitmap on which to paint.  Paints onto the pixel at (x,y)
+* mn, xval, yval
+	The moon to paint.  The val's give the percentage along the moon.
+	Percentages must fall within [0,1].
+* blend
+	Controls how much (char *)"paint" is used.  Must be in the range [0,1].  Higher
+	values cause stronger painting.  Used for anti-aliasing.
+
+*****************************************************************************/
+static void paint_moonpix( BITMAP* bmp, int x, int y,
+                           const moon& mn, double xval, double yval,
+                           double blend )
+{
+  const double thetax = asin (xval) * 180 / PI;
+  const double thetay = acos (yval) * 180 / PI;
+
+  const double offset = (perlin2DPoint (1.0, mn.smoothness,
+                                        mn.xoffset + mn.x + thetax,
+                                        mn.yoffset + mn.y + thetay,
+                                        mn.lambda, mn.octaves) + 1) / 2;
+  const double percentVal = (perlin2DPoint (1.0, mn.smoothness,
+                             mn.xoffset + mn.x * 1000 + thetax,
+                             mn.yoffset + mn.y * 1000 + thetay,
+                             mn.lambda, mn.octaves) + 1) / 2;
+
+  set_add_blender (0, 0, 0, (int)(blend * xval * percentVal * offset * 255));
+#ifdef THREADS
+  drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
+#endif
+  putpixel (bmp, x, y, mn.col1);
+  set_add_blender (0, 0, 0, (int)(blend * xval * (1 - percentVal) * offset * 255));
+  putpixel (bmp, x, y, mn.col2);
+#ifdef THREADS
+  solid_mode();
+#endif
+}
+
+
+
+/*****************************************************************************
+draw_amoon
+
+Renders a single moon onto a bitmap.  Assumes transparent drawing is enabled.
+Abeys the given bounding box, which may be smaller than the moon itself.
+Uses the darkside parameter to decide which side of the moon should be
+dark.  Obeys and updates the z-buffer.
+
+The current implementation of this function is beggins for some
+simplifications.  And again, what about thoes [xy]offset variables?
+*****************************************************************************/
+static void draw_amoon( BITMAP* bmp,
+                        const moon& mn, int x0, int y0, int x1, int y1,
+                        bool darkside, ZBuffer& zbuffer )
+{
+  for ( int y = y0; y != y1; ++y )
+    {
+      bool hityet = false;
+
+      for ( int x = x0; x != x1; ++x )
+        {
+          /* Occupied? */
+          if ( zbuffer.test(x,y) )
+            continue ;
+
+          /* Find distance from this moon */
+          int xdist = mn.x - x;
+          int ydist = mn.y - y;
+
+          /* Compute some other nice circle values */
+          const double fradius = (double) mn.radius ;
+          double xval = (double)xdist / fradius;
+          double yval = (double)ydist / fradius;
+          double distance2 = (xdist * xdist) + (ydist * ydist);
+          double distance = sqrt (distance2);
+
+          /* A bound check -> are we in the circle? */
+          if ( distance > fradius + 1 )
+            {
+              if ( hityet )	/* If we've already been inside at this y... */
+                break;		/* then skip ahead to the next y */
+              else			/* Otherwise... */
+                continue ;	/* Stay at this y, and skip to the next x */
+            }
+
+          /* Edges use lighter blending */
+          const double edgeval = coverage( distance, fradius );
+
+          /* Now, should we paint this side of the moon? */
+          if ( xval && ((xval<0) == darkside) )
+            {
+              paint_moonpix(
+                bmp, x, y,
+                mn, fabs(xval), yval,
+                //fract_clamp( fabs(xval) ),
+                //fract_clamp( fabs(yval) ),
+                edgeval ) ;
+            }
+
+          /* Mark this pixel as occupied */
+          zbuffer.set(x,y);
+          hityet = true ;
+        }
+    }
+}
+
+
+
+/*****************************************************************************
+draw_moons
+
+Renders a set of moons over a given bitmap.  The bitmap to draw of and the
+appropriate dimensions must be given.
+*****************************************************************************/
+void draw_moons (BITMAP* bmp, int width, int height)
+{
+  const bool darkside = rand() > (RAND_MAX/2+1) ;
+  ZBuffer	zbuffer( width, height ) ;
+
+  drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
+  for ( int numMoons = (int)central_rand( 14.0 );
+        numMoons; --numMoons )
+    {
+      int x0, y0, x1, y1;
+
+      /* Make up a moon */
+      const moon mn = generate_moon( width, height );
+
+      /* Where is it? */
+      x0 = clamped_int( mn.x - mn.radius -1, 0, width ) ;
+      y0 = clamped_int( mn.y - mn.radius -1, 0, height ) ;
+      x1 = clamped_int( mn.x + mn.radius +1, 0, width ) ;
+      y1 = clamped_int( mn.y + mn.radius +1, 0, height ) ;
+
+      /* Draw it */
+      draw_amoon( bmp, mn, x0, y0, x1, y1, darkside, zbuffer );
+    }
+  solid_mode ();
+}
+
+
+
+/*****************************************************************************
+generate_sky
+
+Given some input parameters, renders a sky (with moons) onto a bitmap.
+*****************************************************************************/
+void generate_sky (GLOBALDATA *global, BITMAP* bmp, const gradient* grad, int flags )
+{
+  double messiness = (rand () % 100 / 1000.0 + 0.05);
+  const int xoffset = rand( );	/* For perlin, random starting x */
+  const int yoffset = rand( );	/* For perlin, random starting y */
+
+  for (int x = 0; x < global->screenWidth; x++)
+    {
+      for (int y = 0; y < global->screenHeight - MENUHEIGHT; y++)
+        {
+          double offset = 0;
+
+          if ( flags & GENSKY_DETAILED )
+            offset += perlin2DPoint (1.0, 200, xoffset + x, yoffset + y, 0.3, 6) * ((global->screenHeight - MENUHEIGHT) * messiness);
+
+          if ( flags & GENSKY_DITHERGRAD )
+            offset += rand () % 10 - 5;
+
+          while (y + offset < 0)
+            offset /= 2;
+          while (y + offset + 1 > (global->screenHeight - MENUHEIGHT))
+            offset /= 2;
+
+          #ifdef THREADS
+          solid_mode();
+          #endif
+          putpixel (bmp, x, y,
+                    gradientColorPoint (grad, global->screenHeight - MENUHEIGHT, y + offset));
+          #ifdef THREADS
+          drawing_mode(global->env->current_drawing_mode, NULL, 0, 0);
+          #endif
+
+        }
+    }
+  draw_moons (bmp, global->screenWidth, global->screenHeight);
+}
+
+
+
+// This function should be a seperate thread which constantly generates
+// skies in the background so as to not to hang the game after the
+// buying screen.
+void *Generate_Sky_In_Background(void *new_env)
+{
+   ENVIRONMENT *env = (ENVIRONMENT *) new_env;
+   GLOBALDATA *my_global = env->Get_Globaldata();
+   BITMAP *sky_in_progress = NULL;
+
+   // do this constantly
+   while ( my_global->get_command() != GLOBAL_COMMAND_QUIT )
+   {
+      // create a bitmap in waiting, if none exists
+      if (! env->get_waiting_sky())
+      {
+         sky_in_progress = create_bitmap( my_global->screenWidth, my_global->screenHeight - MENUHEIGHT);
+         generate_sky (my_global, sky_in_progress, env->my_sky_gradients[my_global->cursky],
+                   (my_global->ditherGradients ? GENSKY_DITHERGRAD : 0 ) |
+                   (my_global->detailedSky ? GENSKY_DETAILED : 0 )  );
+
+         env->lock(env->waiting_sky_lock);
+         env->waiting_sky = sky_in_progress;
+         env->unlock(env->waiting_sky_lock);
+         sky_in_progress = NULL;
+      }
+
+      LINUX_SLEEP;
+   }
+
+   #ifdef THREADS
+   pthread_exit(NULL);
+   return NULL;         // we never hit this, but it keeps the compiler from complaining
+   #else
+   return NULL;
+   #endif
+}
+
diff --git a/src/sky.h b/src/sky.h
new file mode 100644
index 0000000..53d0280
--- /dev/null
+++ b/src/sky.h
@@ -0,0 +1,189 @@
+#ifndef SKY_HEADER_FILE__
+#define SKY_HEADER_FILE__
+
+#ifdef THREADS
+#include <pthread.h>
+#endif
+
+
+
+
+// Sky gradients, first line is top of screen
+const gradient sky_gradient1[] =
+{
+  {{255,255,255,0}, 0.0},
+  {{100,100,100,0}, 0.1},
+  {{ 80,100,100,0}, 0.5},
+  {{0,0,0,0}, -1}
+};
+
+const gradient sky_gradient2[] =
+{
+  {{  0,  0, 40,0}, 0.0},
+  {{ 40, 40,100,0}, 0.5},
+  {{ 80,80,100,0}, 0.75},
+  {{0,0,0,0}, -1}
+};
+
+const gradient sky_gradient3[] =
+{
+  {{240,  0, 40,0}, 0.0},
+  {{140, 40,100,0}, 0.15},
+  {{ 80, 80,100,0}, 0.75},
+  {{0,0,0,0}, -1}
+};
+
+const gradient sky_gradient4[] =
+{
+  {{ 40, 40, 40,0}, 0.0},
+  {{100, 40,100,0}, 0.2},
+  {{ 80, 80,100,0}, 0.75},
+  {{0,0,0,0}, -1}
+};
+
+const gradient sky_gradient5[] =
+{
+  {{  0, 90, 40,0}, 0.0},
+  {{  0,120,100,0}, 0.2},
+  {{ 40,200,100,0}, 0.75},
+  {{0,0,0,0}, -1}
+};
+
+// Sunset
+const gradient sky_gradient6[] =
+{
+  {{ 70,240,240,0}, 0.0},
+  {{ 70,200,200,0}, 0.3},
+  {{ 70,200,160,0}, 0.35},
+  {{255,200, 70,0}, 0.6},
+  {{255,255,128,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Burning sky
+const gradient sky_gradient7[] =
+{
+  {{ 20, 20, 20,0}, 0.0},
+  {{255,200,  0,0}, 0.08},
+  {{255,255,  0,0}, 0.13},
+  {{ 20, 20, 20,0}, 0.16},
+  {{255,200,  0,0}, 0.5},
+  {{255,255,  0,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Burning landscape, black skies
+const gradient sky_gradient8[] =
+{
+  {{  0,  0,  0,0}, 0.0},
+  {{100,  0,  0,0}, 0.4},
+  {{255,255,255,0}, 0.8},
+  {{0,0,0,0}, -1}
+};
+
+// Sky gradients, first line is top of screen
+// dark blue to darker blue
+const gradient sky_gradient9[] =
+{
+  {{ 90, 90,255,0}, 0.0},
+  {{ 60, 60,200,0}, 0.3},
+  {{ 30, 30,150,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// dark blue to blue-grey
+const gradient sky_gradient10[] =
+{
+  {{110,110,255,0}, 0.0},
+  {{150,150,255,0}, 0.3},
+  {{200,200,255,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// white to grey-blue to dark blue
+const gradient sky_gradient11[] =
+{
+  {{255,255,255,0}, 0.0},
+  {{200,200,255,0}, 0.3},
+  {{ 80, 80,180,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// simple purple: dark to light
+const gradient sky_gradient12[] =
+{
+  {{133, 33,133,0}, 0.0},
+  {{220,120,220,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// night sky: black to dark purple
+const gradient sky_gradient13[] =
+{
+  {{  0,  0,  0,0}, 0.0},
+  {{ 50,  0, 50,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Sunset
+const gradient sky_gradient14[] =
+{
+  {{  0,  0,  0,0}, 0.0},
+  {{ 50,  0, 50,0}, 0.1},
+  {{ 90, 20,  0,0}, 0.3},
+  {{180, 50,  0,0}, 0.7},
+  {{255,150,150,0}, 0.9},
+  {{255,255,100,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Burning sky
+const gradient sky_gradient15[] =
+{
+  {{185, 60, 60,0}, 0.0},
+  {{240,110,110,0}, 0.5},
+  {{255,110,110,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+// Burning landscape, black skies
+const gradient sky_gradient16[] =
+{
+  {{  0,  0,  0,0}, 0.0},
+  {{170, 50, 50,0}, 0.5},
+  {{220,110,110,0}, 1.0},
+  {{0,0,0,0}, -1}
+};
+
+
+const gradient * const sky_gradients[] =
+{
+  sky_gradient1,
+  sky_gradient2,
+  sky_gradient3,
+  sky_gradient4,
+  sky_gradient5,
+  sky_gradient6,
+  sky_gradient7,
+  sky_gradient8,
+  sky_gradient9,
+  sky_gradient10,
+  sky_gradient11,
+  sky_gradient12,
+  sky_gradient13,
+  sky_gradient14,
+  sky_gradient15,
+  sky_gradient16
+};
+
+
+
+void draw_moons (BITMAP* bmp, int width, int height);
+
+void *Generate_Sky_In_Background(void *new_env);
+
+
+
+#endif
+
+
diff --git a/src/tank.cpp b/src/tank.cpp
new file mode 100644
index 0000000..e0fcb10
--- /dev/null
+++ b/src/tank.cpp
@@ -0,0 +1,1431 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "environment.h"
+#include "globaldata.h"
+#include "floattext.h"
+#include "explosion.h"
+#include "teleport.h"
+#include "missile.h"
+#include "player.h"
+#include "beam.h"
+#include "tank.h"
+
+
+/*
+The deconstructor should be split into two pieces. One function for
+destroying a tank and another strictly for cleaning up a tank's memory
+whether it was destoryed or not.
+-- Jesse
+*/
+TANK::~TANK ()
+{
+/*
+  #ifdef NETWORK
+  if (player)        // we should always have a player, but better safe than sorry
+  {
+      int player_index = 0;
+      bool found = false;
+      char buffer[64];
+      while ( (player_index < _global->numPlayers) && (!found) )
+      {
+          // get the player index
+          if ( ( _global->players[player_index]->tank ) && (_global->players[player_index]->tank == this) )
+              found = true;
+          else
+              player_index++;
+     }
+     if (found)        // we should have found a match and now we send it to all clients
+     {
+         sprintf(buffer, "REMOVETANK %d", player_index);
+         _global->Send_To_Clients(buffer);
+     }
+  }
+  #endif
+  if (_global && player)
+    {
+      int random_item;
+      if (_global->violent_death)
+        {
+          random_item = rand() % VIOLENT_CHANCE;
+          if ( ( random_item > _global->violent_death ) && (random_item <= VIOLENT_DEATH_HEAVY) )
+            random_item = (int) _global->violent_death;
+
+          switch (random_item)
+            {
+            case VIOLENT_DEATH_LIGHT:
+              player->ni[ITEM_VENGEANCE] += 1;
+              break;
+            case VIOLENT_DEATH_MEDIUM:
+              player->ni[ITEM_DYING_WRATH] += 1;
+              break;
+            case VIOLENT_DEATH_HEAVY:
+              player->ni[ITEM_FATAL_FURY] += 1;
+              break;
+            }     //end of switch
+        }
+
+      if (player->ni[ITEM_FATAL_FURY] > 0)
+        {
+          int numLaunch = (int)item[ITEM_FATAL_FURY].vals[SELFD_NUMBER];
+          cw = (int)item[ITEM_FATAL_FURY].vals[SELFD_TYPE];
+          player->ni[ITEM_FATAL_FURY]--;
+          player->nm[cw] += numLaunch;
+          for (int count = numLaunch; count > 0; count--)
+            {
+              a = rand () % 180 + 90;
+              p = rand () % (MAX_POWER / 2);
+              activateCurrentSelection ();
+            }
+        }
+      else if (player->ni[ITEM_DYING_WRATH] > 0)
+        {
+          int numLaunch = (int)item[ITEM_DYING_WRATH].vals[SELFD_NUMBER];
+          cw = (int)item[ITEM_DYING_WRATH].vals[SELFD_TYPE];
+          player->ni[ITEM_DYING_WRATH]--;
+          player->nm[cw] += numLaunch;
+          for (int count = numLaunch; count > 0; count--)
+            {
+              a = rand () % 180 + 90;
+              p = rand () % (MAX_POWER / 2);
+              activateCurrentSelection ();
+            }
+        }
+      else if (player->ni[ITEM_VENGEANCE] > 0)
+        {
+          int numLaunch = (int)item[ITEM_VENGEANCE].vals[SELFD_NUMBER];
+          cw = (int)item[ITEM_VENGEANCE].vals[SELFD_TYPE];
+          player->ni[ITEM_VENGEANCE]--;
+          player->nm[cw] += numLaunch;
+          for (int count = numLaunch; count > 0; count--)
+            {
+              a = rand () % 180 + 90;
+              p = rand () % (MAX_POWER / 2);
+              activateCurrentSelection ();
+            }
+        }
+    }
+   */
+
+  if (player)
+    {
+      player->tank = NULL;
+      player = NULL;
+    }
+  if (_global)
+    {
+      _global->numTanks--;
+      if (_global->currTank == this)
+        _global->currTank = NULL;
+    }
+
+  if (shieldText)
+    delete (shieldText);
+  if (healthText)
+    delete (healthText);
+  if (nameText)
+    delete (nameText);
+
+  if (_env)
+    _env->removeObject(this);
+
+  shieldText  = NULL;
+  healthText  = NULL;
+  nameText    = NULL;
+  _env        = NULL;
+  _global     = NULL;
+  creditTo    = NULL;
+  _target     = NULL;
+}
+
+TANK::TANK (GLOBALDATA *global, ENVIRONMENT *env):PHYSICAL_OBJECT(),_target(NULL),creditTo(NULL),
+                                                healthText(NULL),shieldText(NULL),nameText(NULL)
+{
+  setEnvironment (env);
+  _global = global;
+  // Ask for memory
+  healthText = new FLOATTEXT (global, env, NULL, 0, 0, WHITE, CENTRE);
+  if (!healthText)
+    {
+      perror ( "tank.cc: Failed allocating memory for healthText in TANK::TANK");
+      // exit (1);
+    }
+
+  shieldText = new FLOATTEXT (global, env, NULL, 0, 0, makecol (200, 200, 255), CENTRE);
+  if (!shieldText)
+    {
+      perror ( "tank.cc: Failed allocating memory for shieldText in TANK::TANK");
+      // exit (1);
+    }
+
+  if (global->name_above_tank)
+    {
+      nameText = new FLOATTEXT (global, env, NULL, 0, 0, WHITE, CENTRE);
+      if (! nameText)
+        {
+          perror ( "tank.cc: Failed allocating memory for nameText in TANK::TANK");
+          // exit(1);
+        }
+    }
+
+  // Other initial pointers:
+  _align = LEFT;
+  _global->numTanks++;
+
+  player = NULL;
+}
+
+void TANK::initialise ()
+{
+  PHYSICAL_OBJECT::initialise ();
+  drag = 0.5;
+  mass = 3000;
+  repulsion = 0;
+  shieldColor = 0;
+  shieldThickness = 0;
+  t = 0;
+  sh = 0;
+  _targetX = -1;
+  _targetY = -1;
+  newRound ();
+}
+
+void TANK::newRound ()
+{
+  char buf[10];
+
+  cw = 0;
+  damage = 0;
+  pen = 0;
+  para = 0;
+  creditTo = NULL;
+  p = MAX_POWER / 2;
+  a = (rand () % 180) + 90;
+  if (sh > 0 && sht > 0)
+    if (player)
+      player->ni[sht]++;
+  sh = 0;
+  repulsion = 0;
+  // shPhase = rand () % 360;
+  shPhase = 0;
+  delta_phase = 0.1;
+  sht = 0;
+  l = 100;
+  repair_rate = 0;
+  if (player)
+    {
+      double tmpL = 0;
+      tmpL += (int)(player->ni[ITEM_ARMOUR] * item[ITEM_ARMOUR].vals[0]);
+      tmpL += (int)(player->ni[ITEM_PLASTEEL] * item[ITEM_PLASTEEL].vals[0]);
+      repair_rate = Get_Repair_Rate();
+      if (tmpL > 0)
+        l += (int)pow (tmpL, 0.6);
+
+      if (healthText)
+        healthText->set_color( player->color );
+      if (nameText)
+        {
+          nameText->set_text ( player->getName() );
+          nameText->set_color ( player->color );
+        }
+    }
+  maxLife = l;
+  ds = 0;
+  fs = 0;
+  sprintf (buf, "%d", l);
+  healthText->set_text (buf);
+  // delay_fall = GRAVITY_DELAY;
+  delay_fall = (int) labs(_env->landSlideDelay * 100);
+  fire_another_shot = 0;
+  shots_fired = 0;
+
+}
+
+
+
+void TANK::Destroy()
+{
+  #ifdef NETWORK
+  if (player)    // we should always have a player, but better safe than sorry
+  {
+      int player_index = 0;
+      bool found = false;
+      char buffer[64];
+      while ( (player_index < _global->numPlayers) && (!found) )
+      {
+          // get the player index
+          if ( ( _global->players[player_index]->tank ) && (_global->players[player_index]->tank == this) )
+              found = true;
+          else
+              player_index++;
+     }
+     if (found)        // we should have found a match and now we send it to all clients
+     {
+         sprintf(buffer, "REMOVETANK %d", player_index);
+         _global->Send_To_Clients(buffer);
+     }
+  }
+  #endif
+
+   if (_global && player)
+    {
+      int random_item;
+      if (_global->violent_death)
+        {
+          random_item = rand() % VIOLENT_CHANCE;
+          if ( ( random_item > _global->violent_death ) && (random_item <= VIOLENT_DEATH_HEAVY) )
+            random_item = (int) _global->violent_death;
+
+          switch (random_item)
+            {
+            case VIOLENT_DEATH_LIGHT:
+              player->ni[ITEM_VENGEANCE] += 1;
+              break;
+            case VIOLENT_DEATH_MEDIUM:
+              player->ni[ITEM_DYING_WRATH] += 1;
+              break;
+            case VIOLENT_DEATH_HEAVY:
+              player->ni[ITEM_FATAL_FURY] += 1;
+              break;
+            }     //end of switch
+        }
+
+        if (player->ni[ITEM_FATAL_FURY] > 0)
+        {
+          int numLaunch = (int)item[ITEM_FATAL_FURY].vals[SELFD_NUMBER];
+          cw = (int)item[ITEM_FATAL_FURY].vals[SELFD_TYPE];
+          player->ni[ITEM_FATAL_FURY]--;
+          player->nm[cw] += numLaunch;
+          for (int count = numLaunch; count > 0; count--)
+            {
+              a = rand () % 180 + 90;
+              p = rand () % (MAX_POWER / 2);
+              activateCurrentSelection ();
+            }
+        }
+        else if (player->ni[ITEM_DYING_WRATH] > 0)
+        {
+          int numLaunch = (int)item[ITEM_DYING_WRATH].vals[SELFD_NUMBER];
+          cw = (int)item[ITEM_DYING_WRATH].vals[SELFD_TYPE];
+          player->ni[ITEM_DYING_WRATH]--;
+          player->nm[cw] += numLaunch;
+          for (int count = numLaunch; count > 0; count--)
+            {
+              a = rand () % 180 + 90;
+              p = rand () % (MAX_POWER / 2);
+              activateCurrentSelection ();
+            }
+        }
+        else if (player->ni[ITEM_VENGEANCE] > 0)
+        {
+          int numLaunch = (int)item[ITEM_VENGEANCE].vals[SELFD_NUMBER];
+          cw = (int)item[ITEM_VENGEANCE].vals[SELFD_TYPE];
+          player->ni[ITEM_VENGEANCE]--;
+          player->nm[cw] += numLaunch;
+          for (int count = numLaunch; count > 0; count--)
+            {
+              a = rand () % 180 + 90;
+              p = rand () % (MAX_POWER / 2);
+              activateCurrentSelection ();
+            }
+        }
+    }
+}
+
+
+
+void TANK::update ()
+{
+  VIRTUAL_OBJECT::update ();
+}
+
+void TANK::requireUpdate ()
+{
+  VIRTUAL_OBJECT::requireUpdate ();
+}
+
+void TANK::applyDamage ()
+{
+  char buf[10];
+  FLOATTEXT *damageText;
+  FLOATTEXT *revengeText;
+  FLOATTEXT *gloatText;
+  FLOATTEXT *suicideText;
+  char *temp_text;
+  bool killed = false;
+
+  if (damage > sh + l)
+    {
+      damage = sh + l;
+      killed = true;
+      player->killed++;
+    }
+  sh -= (int)damage;
+  if (creditTo)
+    {
+      if (player != creditTo)  	//enemy hit ++
+        {
+          if ( killed )
+            creditTo->kills++;
+          creditTo->money += (int)(damage * _global->scoreHitUnit);
+          if (creditTo->tank)
+          {
+                char the_money[64];
+                sprintf(the_money, "$%s", Add_Comma( (int) (damage * _global->scoreHitUnit) ) );
+                // show how much the shooter gets
+                FLOATTEXT *moneyText = new FLOATTEXT(_global, _env, the_money,
+                                    (int) creditTo->tank->x, (int) creditTo->tank->y - 30,
+                                    makecol(0, 255, 0), CENTRE);
+                if (moneyText)
+                {
+                      // moneyText->xv = 0;
+                      // moneyText->yv = -0.5;
+                      moneyText->set_speed(0.0, -0.5);
+                      moneyText->maxAge = 200;
+                }
+                
+          }
+          // this tank is destroyed, the attacker gloats
+          if ( (killed) && (! creditTo->gloating) )
+            {
+              // avoid trying to print victory message over a dead tank
+              if (creditTo->tank)
+                {
+                  temp_text = creditTo->selectGloatPhrase();
+                  gloatText = new FLOATTEXT (_global, _env,
+                                             // creditTo->selectGloatPhrase( (double) damage / maxLife),
+                                             temp_text,
+                                             (int) creditTo->tank->x, (int) creditTo->tank->y - 30,
+                                             creditTo->color, CENTRE);
+                  if (gloatText)
+                  {
+                    // gloatText->xv = 0;
+                    // gloatText->yv = -0.4;
+                    gloatText->set_speed(0.0, -0.4);
+                    gloatText->maxAge = 300;
+                  }
+                  else
+                      perror ( "tank.cc: Failed allocating memory for gloatText in applyDamage.");
+                  creditTo->gloating = true;
+                }
+            }
+
+          if ((int)player->type != HUMAN_PLAYER)
+            {
+              if (player->revenge == creditTo)
+                {
+                  player->annoyanceFactor += damage;
+                }
+              else
+                {
+                  player->annoyanceFactor = damage;
+                }
+              if (  (player->annoyanceFactor > (player->vengeanceThreshold * maxLife) )
+                  &&((rand() % 100) <= player->vengeful) )
+                {
+                  player->revenge = creditTo;
+                  temp_text = player->selectRevengePhrase();
+                  revengeText = new FLOATTEXT (_global, _env,
+                                               // player->selectRevengePhrase ((double)damage / maxLife),
+                                               temp_text,
+                                               (int)x, (int)y - 30,
+                                               player->color, CENTRE);
+                  if (revengeText)
+                  {
+                    // revengeText->xv = 0;
+                    // revengeText->yv = -0.4;
+                    revengeText->set_speed(0.0, -0.4);
+                    revengeText->maxAge = 300;
+                  }
+                  else
+                      perror ( "tank.cc: Failed allocating memory for revengeText in applyDamage");
+                }
+            }
+        }
+      else  	//self hit --
+        {
+          if ( (creditTo->money - (damage * _global->scoreSelfHit)) < 0)
+            creditTo->money = 0;
+          else
+            creditTo->money -= (int)(damage * _global->scoreSelfHit);
+
+          if (damage >= (l + sh) )
+            {
+              temp_text = player->selectSuicidePhrase();
+              suicideText = new FLOATTEXT (_global, _env,
+                                           player->selectSuicidePhrase(),
+                                           (int) x, (int) y - 30,
+                                           player->color, CENTRE);
+              if (suicideText)
+              {
+                 // suicideText->xv = 0;
+                 // suicideText->yv = -0.4;
+                 suicideText->set_speed(0.0, -0.4);
+                 suicideText->maxAge = 300;
+              }
+              else
+                  perror ( "tank.cc: Failed allocating memory for suicideText in applyDamage.");
+            }
+        }
+    }
+
+  if (sh < 0)
+    l += sh;
+  if (l < 0)
+    l = 0;
+  if (sh <= 0)
+    {
+      repulsion = 0;
+      shieldColor = 0;
+      shieldThickness = 0;
+      sh = 0;
+    }
+
+  if ((int)damage > 0)
+    {
+      flashdamage = 1;
+      sprintf (buf, "%d", (int)damage);
+      damageText = new FLOATTEXT (_global, _env,
+                                  NULL, (int)x, (int)y,
+                                  makecol (255, 0, 0), CENTRE);
+      if (damageText)
+      {
+         damageText->set_text(buf);
+         // damageText->xv = 0;
+         // damageText->yv = -0.2;
+         damageText->set_speed(0.0, -0.2);
+         damageText->maxAge = 300;
+         // damageText->sway = NORMAL_SWAY;
+      }
+      else
+          perror ( "tank.cc: Failed allocating memory for damageText in TANK::TANK");
+    }
+  if (sh > 0)
+    {
+      sprintf (buf, "%d", sh);
+      shieldText->set_text (buf);
+    }
+  else
+    {
+      shieldText->set_text ( "");
+    }
+  sprintf (buf, "%d", l);
+  healthText->set_text (buf);
+}
+
+void TANK::framelyAccounting ()
+{
+  /*
+  if (shPhase < 0)
+    shPhase = rand () % 360;
+  shPhase += (int)(item[sht].vals[SHIELD_ENERGY] / sh) + 10;
+  while (shPhase >= 360)
+    shPhase -= 360;
+  */
+  shPhase = shPhase + delta_phase;
+  if ( ( shPhase > 5) || (shPhase < -2) )
+     delta_phase = -delta_phase;
+}
+
+int TANK::applyPhysics (GLOBALDATA *global)
+{
+  int stable = 0;
+  int landed_on_tank;
+
+  // if we are buried, rockets shouldn't work
+  if ( howBuried() )
+  {
+    xv = 0;
+    if (yv < 0)
+       yv = 0;
+  }
+
+  // make sure the tank does not leave the screen when flying
+  if ( (yv < 0) && (y < TANKHEIGHT) )
+     yv = 0;
+
+  if (yv < 0)
+      x += xv * 4;
+
+  if (!flashdamage)
+    {
+      if (x + xv < 1 || x + xv > (_global->screenWidth-1))
+        xv = -xv;	//bounce on the border
+      int pixelCol = getpixel (_env->terrain, (int)x, (int)y + (TANKHEIGHT - TANKSAG));
+
+      // check to see if we have landed on another tank -- Jesse
+      landed_on_tank = tank_on_tank ( global );
+
+      // we are falling and have hit the bottom of the screen or fallen onto dirt or on a tank
+      if ((l > 0) && (yv > 0) && ((y >= _global->screenHeight - TANKHEIGHT) ||
+                                  (pixelCol != PINK) ||
+                                  (landed_on_tank) ))
+        {
+          //count damage and add money
+          damage = (int) (yv * 10);
+          if (damage >= 10)
+            damage -= 10;
+          else damage = 0;
+          creditTo = NULL;
+          yv = 0;
+          xv = 0;
+          // if we passed the bottom, then stop on bottom
+          if (y > _global->screenHeight - TANKHEIGHT)
+            y = _global->screenHeight - TANKHEIGHT;
+
+          // delay_fall = GRAVITY_DELAY;
+          delay_fall = (int) _env->landSlideDelay * 100;
+
+        }
+
+      // the tank is falling
+      else if ((y < _global->screenHeight - TANKHEIGHT) && (pixelCol == PINK) && (l > 0) &&
+               (! landed_on_tank) && (_env->landSlideType > LANDSLIDE_NONE) )
+        {
+          delay_fall--;
+          if ( (delay_fall > 0) && (_env->landSlideType == LANDSLIDE_CARTOON) )
+            return stable;
+
+          #ifdef OLD_GAMELOOP
+          if (para && para < 3 && !_env->pclock)
+            para++;
+          #else
+          if ( (para) && (para < 3) )
+            para++;
+          #endif
+          if (!para)
+            {
+              yv += _env->gravity * (100.0 / _global->frames_per_second);
+              y += yv;
+            }
+          else
+            {
+              double accel = (_env->wind - xv) / mass * (drag + 0.35) * _env->viscosity;
+              xv += accel;
+              yv += _env->gravity * (100.0 / _global->frames_per_second);
+              if (yv > 0.5 )
+                yv = 0.5;
+              x += xv;
+              y += yv;
+            }
+          // falling, deploy parachute
+          if (!para)
+            {
+              if ((player->ni[ITEM_PARACHUTE]) && (yv >= 1.0))
+                {
+                  _env->pclock = 1;
+                  para = 1;
+                  player->ni[ITEM_PARACHUTE]--;
+                }
+
+            }
+          requireUpdate ();
+        }
+      else
+        {
+          stable = 1;
+          if (damage && !pen)
+            {
+              applyDamage ();
+
+              pen = 1;
+            }
+          para = 0;
+        }
+    }
+  else
+    {
+      flashdamage++;
+    }
+  return (stable);
+}
+
+void TANK::explode ()
+{
+  FLOATTEXT *revengeText;
+  EXPLOSION *explosion;
+  char *temp_text;
+
+  if ((int)player->type != HUMAN_PLAYER)
+    {
+      player->revenge = creditTo;
+      temp_text = player->selectRevengePhrase();
+      revengeText = new FLOATTEXT (_global, _env,
+                                   temp_text,
+                                   (int)x, (int)y - 30,
+                                   player->color, CENTRE);
+      if (revengeText)
+      {
+          // revengeText->xv = 0;
+          // revengeText->yv = -0.4;
+          revengeText->set_speed(0.0, -0.4);
+          revengeText->maxAge = 300;
+      }
+      else
+          perror ( "tank.cc: Failed allocating memory for revengeText in TANK::explode");
+    }
+  explosion = new EXPLOSION (_global, _env, x, y, 1);
+  if (explosion)
+  {
+     explosion->player = player;
+     explosion->bIsWeaponExplosion = false;
+  }
+  else
+      perror ( "tank.cc: Failed allocating memory for explosion in TANK::explode");
+  
+
+  destroy = TRUE;
+  play_sample ((SAMPLE *)_global->sounds[WEAPONSOUNDS], 255, 128, 1000, 0);
+}
+
+void TANK::repulse (double xpos, double ypos, double *xaccel, double *yaccel, int aWeaponType)
+{
+  if (repulsion != 0)
+    {
+      double xdist = xpos - x;
+      double ydist = -1.0 * fabs(ypos - y);
+
+      if ((xdist < 0.1) && (xdist > -0.1)) xdist = 0.1;
+      if ((ydist < 0.1) && (ydist > -0.1)) ydist = -0.1; // Assume missile comes from above
+
+      if (	(aWeaponType >= BURROWER) && (aWeaponType <= PENETRATOR)
+           &&(ypos > y)	)
+        ydist *= -1.0; // they normally come from below!
+
+      double distance2 = (xdist * xdist) + (ydist * ydist);
+      double distance = sqrt (distance2);
+
+      if (distance < (60.0 + sqrt ((double)repulsion)))
+        {
+          *xaccel = repulsion * (xdist / distance) / distance2;
+          *yaccel = repulsion * (ydist / distance) / distance2;
+        }
+    }
+}
+
+void TANK::printHealth (int offset)
+{
+  int textpos = -5;
+
+  shieldText->set_pos ((int)x, (int)y - TANKHEIGHT + textpos + offset);
+  if (sh > 0)
+    textpos -= 10;
+  healthText->set_pos ((int)x, (int)y - TANKHEIGHT + textpos + offset);
+
+  // display player name
+  if (nameText)
+  {
+      textpos -= 10;
+      nameText->set_pos ((int)x, (int)y - TANKHEIGHT + textpos + offset);
+  }
+}
+
+void TANK::draw (BITMAP *dest, int healthOffset)
+{
+  int turretAngle;
+
+  // check for foggy weather
+  if ( ( _env->fog ) && ( _global->currTank != this ) )
+    {
+      addUpdateArea ((int)(x - TANKWIDTH) - 3, (int)y - 25, 35, 46);
+      requireUpdate ();
+      return;
+    }
+
+  // get bitmap for tank
+  if (player)
+  {
+      switch ( (int) player->tank_bitmap)
+        {
+        case CLASSIC_TANK:
+          use_tank_bitmap = 8;
+          use_turret_bitmap = 1;
+          turret_x = x;
+          turret_y = y + (TANKHEIGHT / 2);
+          break;
+        case BIGGREY_TANK:
+          use_tank_bitmap = 9;
+          use_turret_bitmap = 2;
+          turret_y = y;
+          turret_x = x;
+          break;
+        case T34_TANK:
+          use_tank_bitmap = 10;
+          use_turret_bitmap = 3;
+          turret_y = y;
+          turret_x = x;
+          break;
+        case HEAVY_TANK:
+          use_tank_bitmap = 11;
+          use_turret_bitmap = 4;
+          turret_y = y;
+          turret_x = x;
+          break;
+        case FUTURE_TANK:
+          use_tank_bitmap = 12;
+          use_turret_bitmap = 5;
+          turret_y = y;
+          turret_x = x;
+          break;
+        case UFO_TANK:
+          use_tank_bitmap = 13;
+          use_turret_bitmap = 6;
+          turret_y = y;
+          turret_x = x;
+          break;
+        case SPIDER_TANK:
+          use_tank_bitmap = 14;
+          use_turret_bitmap = 7;
+          turret_y = y;
+          turret_x = x;
+          break;
+         case BIGFOOT_TANK:
+          use_tank_bitmap = 15;
+          use_turret_bitmap = 8;
+          turret_y = y;
+          turret_x = x;
+          break;
+        default:
+          use_tank_bitmap = 0;
+          use_turret_bitmap = 0;
+          turret_x = x;
+          turret_y = y;
+          break;
+        }
+    }
+
+  rectfill (dest, (int) x - (TANKWIDTH - 1),
+            (int) (y + TANKHEIGHT) - 2,
+            (int) (x + TANKWIDTH) - 2,
+            (int) (y + TANKHEIGHT),
+            this->player->color);
+  // draw_sprite (dest, (BITMAP *) _global->gfxData.T[use_tank_bitmap].dat, (int) x - TANKWIDTH, (int) y);
+
+/*
+  Drawing shields this way seems to cause a crash on multi-cpu
+  systems. Taking this out and creating new shield
+  drawing routine below. -- Jesse
+
+  if (sh > 0)
+    {
+      int phaseValue = 1;
+
+      drawing_mode(DRAW_MODE_TRANS, NULL, 0, 0);
+      _env->current_drawing_mode = DRAW_MODE_TRANS;
+      set_trans_blender (0, 0, 0, (int)50);
+      // avoid sub-index
+      if ( shPhase < 0 )
+        shPhase = 0;
+      if (sht >= ITEM_LGT_SHIELD && sht <= ITEM_HVY_SHIELD)
+        {
+          phaseValue = (int)(_global->slope[(int)shPhase][0] * 3);
+        }
+      else if (sht >= ITEM_LGT_REPULSOR_SHIELD && sht <= ITEM_HVY_REPULSOR_SHIELD)
+        {
+          phaseValue = (int)(shPhase / 360 * 6);
+        }
+
+      ellipsefill (dest, (int) x, (int) y, TANKWIDTH + 6 + phaseValue, TANKHEIGHT - 1, shieldColor);
+      set_trans_blender (0, 0, 0, (int)
+                         (50 + (((float) sh / (float) (item[sht]).vals[SHIELD_ENERGY]) * (float) 150)));
+      for (int thicknessCount = 0; thicknessCount < shieldThickness; thicknessCount++)
+        {
+          ellipse (dest, (int) x - (shieldThickness / 2) + thicknessCount, (int) y,
+                   TANKWIDTH + 6 + phaseValue, TANKHEIGHT - 1, shieldColor);
+        }
+      drawing_mode(DRAW_MODE_SOLID, NULL, 0, 0);
+      _env->current_drawing_mode = DRAW_MODE_SOLID;
+    }   // end of drawing shield
+*/
+
+  if (sh > 0)
+  {
+     int thickness = 2;
+     int counter;
+     int wobble = (int) shPhase;
+
+     if ( (sht == ITEM_LGT_SHIELD) || (sht == ITEM_LGT_REPULSOR_SHIELD) )
+       thickness = 1;
+     else if ( (sht == ITEM_HVY_REPULSOR_SHIELD) || (sht == ITEM_HVY_SHIELD) )
+       thickness = 3;
+
+     if (! shieldColor)        // client may not have set colour
+     {
+         shieldColor = makecol ((int)item[sht].vals[SHIELD_RED],
+                             (int)item[sht].vals[SHIELD_GREEN],
+                             (int)item[sht].vals[SHIELD_BLUE]);
+     }
+     for (counter = 0; counter < thickness; counter++)
+         circle(dest, (int) x, (int) y, 
+                TANKHEIGHT + counter + wobble, shieldColor);
+  }
+
+  draw_sprite (dest, (BITMAP *) _global->tank[use_tank_bitmap], (int) x - TANKWIDTH, (int) y);
+  turretAngle = (int) ((float) (90 - a) * ((float) 256 / (float) 360));
+  rotate_sprite (dest, (BITMAP *) _global->tankgun[use_turret_bitmap],
+                 (int) turret_x - GUNLENGTH, (int) turret_y - (GUNLENGTH - 2), itofix (turretAngle));
+
+
+  // when using rockets, show flame
+  if (yv < 0)
+  {
+      rectfill(dest, (int) x - TANKWIDTH, (int) y + TANKHEIGHT, x + TANKWIDTH, y + TANKHEIGHT + 10, makecol(250, 150, 0) );
+  }
+
+  if (sh > 0)
+    setUpdateArea ((int)x - TANKWIDTH - 15, (int)y - TANKHEIGHT,
+                   ((TANKWIDTH + 15) * 2) + 1, (TANKHEIGHT * 2) + 20);
+  else
+    setUpdateArea ((int)x - GUNLENGTH - 1, (int)y - GUNLENGTH - 1,
+                   (GUNLENGTH * 2) + 2, TANKHEIGHT + GUNLENGTH + 20);
+  if (para)
+    {
+      draw_sprite (dest, (BITMAP *) _global->tank[para],
+                   (int) (x - TANKWIDTH) - 3, (int) y - 25);
+      addUpdateArea ((int)(x - TANKWIDTH) - 3, (int)y - 25, 35, 66);
+    }
+
+  printHealth (healthOffset);
+  requireUpdate ();
+}
+
+int TANK::get_heaviest_shield ()
+{
+  if (player->ni[ITEM_HVY_REPULSOR_SHIELD])
+    {
+      return ITEM_HVY_REPULSOR_SHIELD;
+    }
+  if (player->ni[ITEM_HVY_SHIELD])
+    {
+      return ITEM_HVY_SHIELD;
+    }
+  if (player->ni[ITEM_MED_REPULSOR_SHIELD])
+    {
+      return ITEM_MED_REPULSOR_SHIELD;
+    }
+  if (player->ni[ITEM_MED_SHIELD])
+    {
+      return ITEM_MED_SHIELD;
+    }
+  if (player->ni[ITEM_LGT_REPULSOR_SHIELD])
+    {
+      return ITEM_LGT_REPULSOR_SHIELD;
+    }
+  if (player->ni[ITEM_LGT_SHIELD])
+    {
+      return ITEM_LGT_SHIELD;
+    }
+  return ITEM_NO_SHIELD;
+}
+
+
+
+
+void TANK::simActivateCurrentSelection ()
+{
+  char buf[16];
+
+  if (_global->turntype != TURN_SIMUL)
+    {
+      activateCurrentSelection();
+      if (fire_another_shot)
+        fire_another_shot--;
+    }
+  else
+    {
+      _env->stage = 1;
+    }
+
+  // allow naturals to happen again
+  _env->naturals_since_last_shot = 0;
+
+  // apply repairs
+  l += repair_rate;
+  if (l > maxLife)
+    l = maxLife;
+  sprintf (buf, "%d", l);
+  healthText->set_text(buf);
+
+  // avoid having key presses read in next turn
+  clear_keybuf();
+}
+
+
+
+
+void TANK::activateCurrentSelection ()
+{
+  int z;
+
+  // avoid firing weapons on exit in Windows
+  if ( (_global->get_command() == GLOBAL_COMMAND_QUIT) ||
+       (_global->get_command() == GLOBAL_COMMAND_MENU) )
+    return;
+
+  // remove status from top bar at next redraw
+  if (_global->tank_status)
+      _global->tank_status[0] = 0;
+
+  _env->time_to_fall--;
+  if (_env->time_to_fall < 0)
+    // _env->time_to_fall = (rand() % MAX_GRAVITY_DELAY) + 1;
+    _env->time_to_fall = (rand() % (int)_env->landSlideDelay) + 1;
+
+  if (cw < WEAPONS)
+    {
+      player->changed_weapon = false;
+      if (cw)
+        player->nm[cw]--;
+
+      _env->stage = 1;
+      _env->am = weapon[cw].spread;
+      _env->realm = _env->am;
+
+      if (cw < BALLISTICS)
+        {
+          play_sample ((SAMPLE *) _global->sounds[weapon[cw].sound], 255, 128, 1000, 0);
+          for (z = 0; z < _env->am; z++)
+            {
+              MISSILE *newmis;
+              double mxv,myv;
+              int ca;
+
+              ca = a + ((SPREAD * z) - (SPREAD * (_env->am - 1) / 2));
+              double dPower = (double)p;
+              if ((dPower < 200.0) && ((cw == RIOT_CHARGE) || (cw == RIOT_BLAST)))
+                dPower = 200.0;
+
+              mxv = _global->slope[ca][0] * dPower * (100.0 / _global->frames_per_second) / 100.0;
+              myv = _global->slope[ca][1] * dPower * (100.0 / _global->frames_per_second) / 100.0;
+
+              newmis = new MISSILE(_global, _env,
+                                   turret_x + (_global->slope[ca][0] * GUNLENGTH) /*- mxv*/,
+                                   turret_y + (_global->slope[ca][1] * GUNLENGTH) /*- myv*/,
+                                   mxv, myv, cw);
+              if (newmis)
+              {
+                newmis->physics = 0;
+                newmis->age = 0;
+                newmis->player = player;
+              }
+              else
+                  perror ( "tank.cc: Failed allocating memory for newmis in TANK::activateCurrentSelection");
+              // set up volley
+              if (! fire_another_shot)
+                {
+                    fire_another_shot = weapon[cw].delay * VOLLY_DELAY;
+                    if ( weapon[cw].delay )
+                    {
+                      shots_fired = shots_fired - (weapon[cw].delay - 1);
+                    }
+                }
+
+              if (player->ni[ITEM_DIMPLEP])
+                {
+                  player->ni[ITEM_DIMPLEP]--;
+                  newmis->drag *= item[ITEM_DIMPLEP].vals[0];
+                }
+              else if (player->ni[ITEM_SLICKP])
+                {
+                  player->ni[ITEM_SLICKP]--;
+                  newmis->drag *= item[ITEM_SLICKP].vals[0];
+                }
+            }
+        }
+      else          // BEAM weapon
+        {
+          play_sample ((SAMPLE *) _global->sounds[weapon[cw].sound], 255, 128, 1000, 0);
+          for (z = 0; z < _env->am; z++)
+            {
+              BEAM *newbeam;
+              int ca;
+
+              ca = a + ((SPREAD * z) - (SPREAD * (_env->am - 1) / 2));
+
+              newbeam = new BEAM (_global, _env,
+                                  turret_x + (_global->slope[ca][0] * GUNLENGTH),
+                                  turret_y + (_global->slope[ca][1] * GUNLENGTH),
+                                  ca, cw);
+              if (newbeam)
+              {
+                 newbeam->physics = 0;
+                 newbeam->age = 0;
+                 newbeam->player = player;
+              }
+              else
+                  perror ( "tank.cc: Failed allocating memory for newbeam in TANK::activateCurrentSelection");
+            }
+
+        }
+    }
+  else           // activate an item
+    {
+      int itemNum = cw - WEAPONS;
+      if (itemNum < ITEM_VENGEANCE || itemNum > ITEM_FATAL_FURY)
+        player->ni[itemNum]--;
+      _env->stage = 1;
+      if (itemNum == ITEM_TELEPORT)
+        {
+          int teleXDest = (rand () % (_global->screenWidth - TANKWIDTH * 2)) + TANKWIDTH;
+          int teleYDest = (rand () % (_global->screenHeight - TANKHEIGHT * 2)) + TANKHEIGHT;
+          TELEPORT *teleport;
+          creditTo = player;
+          teleport = new TELEPORT (_global, _env, this, teleXDest, teleYDest, TANKHEIGHT * 4 + GUNLENGTH, 120);
+          if (!teleport)
+            {
+              perror ( "tank.cc: Failed allocating memory for teleport in TANK::activateCurrentSelection");
+              // exit (1);
+            }
+        }
+      else if (itemNum == ITEM_SWAPPER)
+        {
+          int random_tank_number;
+          TANK *other_tank;
+          TELEPORT *my_teleport, *other_teleport;
+
+          // pick a random tank (not us)
+          random_tank_number = rand() % _global->numTanks;
+          other_tank = _env->order[random_tank_number];
+          while ( (! other_tank) || (other_tank == this) )
+            {
+              random_tank_number++;
+              if (random_tank_number > _global->maxNumTanks)
+                random_tank_number = 0;
+              other_tank = _env->order[random_tank_number];
+            }
+          creditTo = player;
+          // create a teleport ojbect for this tank
+          my_teleport = new TELEPORT (_global, _env, this, (int) other_tank->x, (int) other_tank->y, TANKHEIGHT * 4 + GUNLENGTH, 120);
+          // create a teleport object for the other tank
+          other_teleport = new TELEPORT (_global, _env, other_tank, (int) x, (int) y, TANKHEIGHT * 4 + GUNLENGTH, 120);
+
+        }
+      else if (itemNum == ITEM_MASS_TELEPORT)
+      {
+          TELEPORT *my_teleport;
+          int count;
+          int XDest, YDest;
+          TANK *current_tank;
+          
+          for (count = 0; count < _global->numPlayers; count++)
+          {
+             current_tank = _global->players[count]->tank;
+             if (current_tank)
+             {
+                XDest = (rand () % (_global->screenWidth - TANKWIDTH * 2)) + TANKWIDTH;
+                YDest = (rand () % (_global->screenHeight - TANKHEIGHT * 2)) + TANKHEIGHT;
+                creditTo = player;
+                my_teleport = new TELEPORT(_global, _env, current_tank, XDest, YDest, TANKHEIGHT * 4 + GUNLENGTH, 120);
+             }
+          }
+             
+      }
+
+      else if ( itemNum == ITEM_ROCKET )
+      {
+         yv = -10;
+         y -= 10;
+         if (a < 180)
+         {
+               xv += 0.3;
+         }
+         else if (a > 180)
+         {
+              xv -= 0.3;
+         }
+
+         applyPhysics(_global);
+      }
+
+      else if ( itemNum == ITEM_FAN )
+        {
+          // play wind sound
+          play_sample ((SAMPLE *) _global->sounds[2], 255, 128, 1000, 0);
+          if (a < 180)   // move wind to the right
+            _env->wind += (p / 20);
+          else     // wind to the left
+            _env->wind -= (p / 20);
+
+          // make sure wind is not too strong
+          if (_env->wind < (-_env->windstrength / 2) )
+            _env->wind = -_env->windstrength / 2;
+          else if (_env->wind > (_env->windstrength / 2) )
+            _env->wind = _env->windstrength / 2;
+
+          _env->lastwind = _env->wind;
+
+        }
+      else if ((itemNum >= ITEM_VENGEANCE) &&
+               (itemNum <= ITEM_FATAL_FURY))
+        {
+          creditTo = player;
+          damage = l + sh;
+        }
+    }
+
+  // if we are out of this type of weapon
+  // then switch to another
+  if (! player->nm[cw] )
+    {
+      cw = WEAPONS - 1;
+      while ( (cw > 0) && (! player->nm[cw] ) )
+        cw--;
+      player->changed_weapon = true;
+    }
+
+  shots_fired++;
+  player->time_left_to_fire = _global->max_fire_time;
+
+  // if not performing a volly and the player is AI then randomly select next weapon
+  // else if ( ( player->type > HUMAN_PLAYER ) && (! fire_another_shot) )
+  //    cw = player->Select_Random_Weapon();
+
+}
+
+
+void TANK::boost_up_shield ()
+{
+  char buf[10];
+  int s = get_heaviest_shield ();
+
+  if ((s != ITEM_NO_SHIELD) && (player->ni[s] > 0))
+    {
+      player->ni[s]--;
+      sh = (int)item[s].vals[SHIELD_ENERGY];
+      repulsion = (int)item[s].vals[SHIELD_REPULSION];
+      shieldColor = makecol ((int)item[s].vals[SHIELD_RED],
+                             (int)item[s].vals[SHIELD_GREEN],
+                             (int)item[s].vals[SHIELD_BLUE]);
+      shieldThickness = (int)item[s].vals[SHIELD_THICKNESS];
+      sht = s;
+      ds = sht;
+      player->last_shield_used = s;
+    }
+  if (sh)
+    {
+      sprintf (buf, "%d", sh);
+      shieldText->set_text (buf);
+    }
+  else
+    {
+      shieldText->set_text ( "");
+    }
+}
+void TANK::reactivate_shield ()
+{
+  if (!sh)  		//if no shield remains, try to reload
+    {
+      boost_up_shield ();
+    }
+}
+
+int TANK::howBuried ()
+{
+  int turrAngle;
+  int buryCount = 0;
+
+  for (turrAngle = 90; turrAngle < 270; turrAngle++)
+    {
+      if (getpixel (_env->terrain, (int)(x + (_global->slope[turrAngle][0] * GUNLENGTH)), (int)(y + (_global->slope[turrAngle][1] * GUNLENGTH))) != PINK)
+        buryCount++;
+    }
+
+  return (buryCount);
+}
+
+int TANK::shootClearance (int targetAngle, int minimumClearance)
+{
+  int clearance = 2;
+  int iXpos, iYpos;
+  do
+    {
+      iXpos	=	(int)(x + (_global->slope[targetAngle][0] * (GUNLENGTH + clearance)));
+      iYpos = (int)(y + (_global->slope[targetAngle][1] * (GUNLENGTH + clearance)));
+      if ((iYpos <= MENUHEIGHT) || (iXpos <= 1) || (iXpos >= (_global->screenWidth - 2)))
+        clearance = minimumClearance; // done it! There can't be dirt any more!
+      else
+        clearance++;
+    }
+  while ((clearance < minimumClearance) && (getpixel(_env->terrain, iXpos, iYpos) == PINK));
+
+  // If we are going for a particular minimumClearance (< screenWidth), it is important whether we hit a wall
+  if (minimumClearance < _global->screenWidth)
+    {
+      int iWall = _env->current_wallType;
+      if (	_global->bIsBoxed && (iYpos <= MENUHEIGHT)
+           &&((iWall == WALL_STEEL) || (iWall == WALL_WRAP)) )
+        clearance = -1; // Wall hit on ceiling
+      if (	((iXpos <= 1) || (iXpos >= (_global->screenWidth - 2)))
+           &&(iWall == WALL_STEEL)	)
+        clearance = -1; // Wall hit on sides
+    }
+
+  return (clearance >= minimumClearance?1:0);
+}
+
+int TANK::isSubClass (int classNum)
+{
+  if (classNum == TANK_CLASS)
+    return (TRUE);
+  else
+    return (FALSE);
+  //return (PHYSICAL_OBJECT::isSubClass (classNum));
+}
+
+
+
+/*
+This function checks to see if there is a tank directly below this
+one. This is to determine if we landed on someone.
+The function returns TRUE if we landed on another tank and
+FALSE if we did not.
+-- Jesse
+*/
+int TANK::tank_on_tank( GLOBALDATA *global )
+{
+  int found_tank = FALSE;
+  int player_count = 0;
+  int delta_x, delta_y;
+
+  while ( ( player_count < global->numPlayers ) && (! found_tank) )
+    {
+      // check to make sure this player is alive
+      if ( global->players[player_count]->tank )
+        {
+          // make sure this isn't our own tank
+          if ( ( global->players[player_count]->tank->x != x ) || (global->players[player_count]->tank->y != y ) )
+            {
+              // check to see if tanks are within TANK_WIDTH of each other's x
+              delta_x = (int) (x - global->players[player_count]->tank->x);
+              delta_y = (int) (y - global->players[player_count]->tank->y);
+
+              if ( ( abs(delta_x) <= TANKWIDTH ) && ( (delta_y < 0) && (delta_y >= -TANKHEIGHT) ) )
+                found_tank = TRUE;
+
+            }    // end of this is our own tank
+        }
+      player_count++;
+    }
+
+  return found_tank;
+}
+
+
+
+/*
+This function figures out how many points a tank
+will repair itself each turn. This is based
+on the number of repair kits a player has.
+The amount is returned as an int.
+-- Jesse
+*/
+int TANK::Get_Repair_Rate()
+{
+  int num_kits;
+  int repair_units = 0;
+  int increase_amount = 5;
+
+  num_kits = player->ni[ITEM_REPAIRKIT];
+  while (num_kits > 0)
+    {
+      repair_units += increase_amount;
+      if (increase_amount > 1)
+        increase_amount--;
+      num_kits--;
+    }
+
+  return repair_units;
+}
+
+
+
+/*
+This function tries to move the tank either
+left or right one unit. The direction is passed
+in.
+The function returns TRUE if the tank is moved and
+FALSE if something is in the way or the
+tank cannot be moved for some reason.
+-- Jesse
+*/
+int TANK::Move_Tank(int direction)
+{
+  int pixel;
+  int destination_x;
+
+  // do we have fuel?
+  if ( player->ni[ITEM_FUEL] < 1 )
+    return FALSE;
+
+  // see where we want to go
+  if (direction == DIR_RIGHT)
+    destination_x = (int) (x + TANKWIDTH - 2);
+  else
+    destination_x = (int) (x - (TANKWIDTH + 1) );
+
+  if (_env->landType != LANDTYPE_NONE)
+    {
+      // check for something in the way
+      pixel = getpixel (_env->terrain, destination_x, (int) (y + (TANKHEIGHT / 2)) );
+      if (pixel != PINK)
+        return FALSE;
+    }
+
+  // move tank
+  if (direction == DIR_RIGHT)
+    x++;
+  else
+    x--;
+
+  player->ni[ITEM_FUEL]--;
+
+  return TRUE;
+}
+
+void TANK::setEnvironment(ENVIRONMENT *env)
+{
+  if (!_env || (_env != env))
+    {
+      _env = env;
+      _index = _env->addObject (this);
+    }
+}
+
+
+/*
+Give credit to the tank who killed us.
+*/
+void TANK::Give_Credit(GLOBALDATA *global)
+{
+     if (creditTo)
+     {
+        // we shot ourselves
+        if (creditTo == player)
+           creditTo->money -= (int) global->scoreUnitSelfDestroy;
+        else   // we were killed by someone else
+           creditTo->money += (int) global->scoreUnitDestroyBonus;
+
+        // avoid over-flow
+        if (creditTo->money < 0)
+            creditTo->money = 0;
+        creditTo = NULL;
+     }
+}
+
diff --git a/src/tank.h b/src/tank.h
new file mode 100644
index 0000000..4ea6ceb
--- /dev/null
+++ b/src/tank.h
@@ -0,0 +1,100 @@
+#ifndef	TANK_DEFINE
+#define	TANK_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "physobj.h"
+
+#define	TELETIME	120
+
+#define DIR_RIGHT 1
+#define DIR_LEFT 2
+
+#define VIOLENT_CHANCE 6
+
+
+class PLAYER;
+class EXPLOSION;
+class FLOATTEXT;
+class TANK: public PHYSICAL_OBJECT
+  {
+  protected:
+    int	_targetX,_targetY;
+    int	_prevTargetX,_prevTargetY;
+    TANK	*_target;
+
+  public:
+    int	bestPower, bestAngle;
+    int	smallestOvershoot;
+    int 	t, a, p, cw, l, sh, sht, fs, ds, para, pen;
+    int	maxLife;	// amount awarded at beginning of round
+    double	damage;
+    int     repair_rate;
+    int	repulsion;
+    int	shieldColor, shieldThickness;
+    int	flashdamage, hit;
+    int	timer;
+    int	teleTimer;
+    int	teleXDest, teleYDest;
+    double	shPhase, delta_phase;
+    PLAYER	*creditTo;
+    FLOATTEXT	*healthText, *shieldText;//, *damageText;
+    FLOATTEXT       *nameText;
+    int use_tank_bitmap, use_turret_bitmap;
+    double turret_x, turret_y;
+    int delay_fall;         // time the tank will hover
+    int fire_another_shot;
+    int shots_fired;
+
+    ~TANK ();
+    TANK (GLOBALDATA *global, ENVIRONMENT *env);
+    void	initialise ();
+    void Destroy();
+    int	get_heaviest_shield ();
+    void	boost_up_shield ();
+    void	reactivate_shield ();
+    void	draw (BITMAP *dest, int healthOffset);
+    void	printHealth (int offset);
+    void	update ();
+    void	requireUpdate ();
+    void	explode ();
+    void    simActivateCurrentSelection();
+    void	activateCurrentSelection ();
+    int	isSubClass (int classNum);
+    inline virtual int	getClass ()
+    {
+      return (TANK_CLASS);
+    }
+    virtual void setEnvironment(ENVIRONMENT *env);
+    void	applyDamage ();
+    int	applyPhysics (GLOBALDATA *global);
+    void	repulse (double xpos, double ypos, double *xaccel, double *yaccel, int aWeaponType);
+    int	howBuried ();
+    int	shootClearance (int targetAngle, int minimumClearance = MAX_OVERSHOOT);
+    void	newRound ();
+    void	framelyAccounting ();
+    int     tank_on_tank(GLOBALDATA *gd); //is this tank on top of another?
+    int     Get_Repair_Rate();    // how many units a tank will repair itself per round
+    int     Move_Tank(int direction);
+    void    Give_Credit(GLOBALDATA *global);  // give credit to killer
+  };
+
+#endif
diff --git a/src/team.cpp b/src/team.cpp
new file mode 100644
index 0000000..598ba62
--- /dev/null
+++ b/src/team.cpp
@@ -0,0 +1,35 @@
+#include "tank.h"
+#include "team.h"
+#include "player.h"
+
+// check to see if a team has won.
+int Team_Won(GLOBALDATA *global)
+{
+  bool all_jedi = true;
+  bool all_sith = true;
+  int current_player = 0;
+  int my_team = 1;
+  int player_count = 0;
+
+  while ((all_jedi || all_sith) && ( current_player < global->numPlayers) )
+    {
+      if ( (global->players[current_player]->tank) &&
+           (global->players[current_player]->tank->l) )
+        {
+          my_team = (int)global->players[current_player]->team;
+          if ( (my_team == TEAM_JEDI) || (my_team == TEAM_NEUTRAL) )
+            all_sith = false;
+
+          if ( (my_team == TEAM_SITH) || (my_team == TEAM_NEUTRAL) )
+            all_jedi = false;
+          player_count++;
+        }
+      current_player++;
+    }
+
+  if (! player_count) return NO_WIN;
+  if (all_jedi) return JEDI_WIN;
+  else if (all_sith) return SITH_WIN;
+  else return NO_WIN;
+}
+
diff --git a/src/team.h b/src/team.h
new file mode 100644
index 0000000..1a99671
--- /dev/null
+++ b/src/team.h
@@ -0,0 +1,26 @@
+/*
+This file contains team related functions that
+do not fit anywhere else.
+*/
+
+#ifndef TEAM_HEADER_FILE__
+#define TEAM_HEADER_FILE__
+
+#include "globaldata.h"
+
+#define NO_WIN 0
+#define JEDI_WIN 100
+#define SITH_WIN 200
+
+// This function checks to see if one
+// team (Jedi or Sith) has won. Neutral
+// is not considered a team.
+// The function return the following:
+// 0 - no team won
+// JEDI_WON - Jedi team won
+// SITH_WON - Sith team won
+
+int Team_Won(GLOBALDATA *global);
+
+#endif
+
diff --git a/src/teleport.cpp b/src/teleport.cpp
new file mode 100644
index 0000000..3746f69
--- /dev/null
+++ b/src/teleport.cpp
@@ -0,0 +1,211 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "environment.h"
+#include "globaldata.h"
+#include "teleport.h"
+
+TELEPORT::~TELEPORT ()
+{
+  requireUpdate();
+  update();
+  _env->make_bgupdate (_current.x, _current.y, _current.w, _current.h);
+  _env->make_bgupdate (_old.x, _old.y, _old.w, _old.h);
+  _env->removeObject (this);
+  _env        = NULL;
+  _global     = NULL;
+  object      = NULL;
+  remote      = NULL;
+}
+
+TELEPORT::TELEPORT (GLOBALDATA *global, ENVIRONMENT *env, VIRTUAL_OBJECT *targetObj, int destinationX, int destinationY,
+                    int objRadius, int duration):VIRTUAL_OBJECT(),clock(duration),startClock(duration),peaked(0),
+                                                                  object(NULL),remote(NULL)
+{
+  setEnvironment (env);
+  player = NULL;
+  _align = LEFT;
+  _global = global;
+  object = targetObj;
+  radius = objRadius;
+  remote = new TELEPORT (global, env, this, destinationX, destinationY);
+  if (!remote)
+    {
+      perror ( "teleport.cc: Failed allocating memory for remote in TELEPORT::TELEPORT");
+    }
+  play_sample ((SAMPLE *) _global->sounds[item[ITEM_TELEPORT].sound], 255, 128, 1000, 0);
+
+  #ifdef NETWORK
+  // this seems to be the teleport we usually use
+  char buffer[64];
+  int player_index = 0;
+  bool found = false;
+  TANK *the_tank = (TANK*) targetObj;
+  // match the player with the tank
+  while ( (player_index < global->numPlayers) && (! found) )
+  {
+      if ( ( global->players[player_index]->tank ) && (global->players[player_index]->tank == the_tank) )
+        found = true;
+     else
+        player_index++;
+  }
+  if (found)
+  {
+     sprintf(buffer, "TELEPORT %d %d %d", player_index, destinationX, destinationY);
+     global->Send_To_Clients(buffer);
+  }
+  #endif
+}
+
+
+
+
+TELEPORT::TELEPORT (GLOBALDATA *global, ENVIRONMENT *env, TELEPORT *remoteEnd, int destX, int destY):VIRTUAL_OBJECT(),
+                    clock(remoteEnd->startClock),startClock(remoteEnd->startClock),peaked(0)
+{
+  remote = remoteEnd;
+  setEnvironment (env);
+  player = NULL;
+  _align = LEFT;
+  _global = global;
+  object = NULL;
+  x = destX;
+  y = destY;
+  radius = remote->radius;
+}
+
+void TELEPORT::initialise ()
+{
+  VIRTUAL_OBJECT::initialise ();
+  peaked = 0;
+  clock = startClock;
+}
+
+int TELEPORT::applyPhysics ()
+{
+  if (object)
+    {
+      x = object->x;
+      y = object->y;
+    }
+  else
+    {
+      clock = remote->clock;
+    }
+  if (clock < 1)
+    {
+      if (clock == 0)
+        {
+          if (object)
+            {
+              object->x = remote->x;
+              object->y = remote->y;
+              remote->object = object;
+              object = NULL;
+              remote->clock--;
+            }
+        }
+      if (clock < -startClock / 2)
+        destroy = TRUE;
+    }
+  clock--;
+  return (0);
+}
+
+
+// new telport version
+void TELEPORT::draw (BITMAP *dest)
+{
+  BITMAP *tempBitmap;
+  double pClock = clock;
+  int blobSize, pRadius, maxblobs;
+
+  if (pClock < 1.0)
+    pClock = 1.0 + (1.0 - (pClock * 2.0));
+  blobSize = 8 - (int)round(8 / (startClock / pClock)) + 1;
+  pRadius  = radius - (int)round(radius / (startClock / pClock)) + 1;
+  maxblobs = 1 + (pRadius * 4);
+
+  tempBitmap = create_bitmap (radius * 2, radius * 2);
+  blit (dest, tempBitmap, remote->x - radius, remote->y - radius, 0, 0, radius * 2, radius * 2);
+
+  if (object)
+    remote->draw(dest);
+
+  drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
+  set_trans_blender (0, 0, 0, 255 - (int)((pClock / startClock) * 255));
+  for (int count = (int)round(maxblobs + pClock); count > pClock; count--)
+    {
+      int xOff = (int)(perlin2DPoint (1.0, 200, 1278 + x + count * 100, pClock, 0.25, 6) * pRadius);
+      int yOff = (int)(perlin2DPoint (1.0, 200, 9734 + y + count * 100, pClock, 0.25, 6) * pRadius);
+      circlefill (dest, x + xOff, y + yOff, blobSize, getpixel (tempBitmap, pRadius + xOff, pRadius + yOff));
+    }
+  drawing_mode (DRAW_MODE_SOLID, NULL, 0, 0);
+  setUpdateArea (x - pRadius - blobSize, y - pRadius - blobSize, (pRadius + blobSize) * 2, (pRadius + blobSize) * 2);
+  requireUpdate ();
+
+  destroy_bitmap (tempBitmap);
+}
+
+
+/*
+ * Old version
+void TELEPORT::draw (BITMAP *dest)
+{
+  BITMAP *tempBitmap;
+  int blobSize = 8;
+  int pClock = clock;
+  if (pClock < 0)
+    {
+      pClock = 0;
+      blobSize = (startClock / 2) / -clock;
+    }
+
+  tempBitmap = create_bitmap (radius * 2, radius * 2);
+  blit (_env->db, tempBitmap, (int)remote->x - radius, (int)remote->y - radius, 0, 0, radius * 2, radius * 2);
+
+  if (object)
+    remote->draw (dest);
+
+  drawing_mode (DRAW_MODE_TRANS, NULL, 0, 0);
+  set_trans_blender (0, 0, 0, 255 - (int)((pClock / startClock) * 255));
+  for (int count = (radius * radius * 4 / (8 * 8)); count > pClock; count--)
+    {
+      int xOff = (int)(perlin2DPoint (1.0, 200, 1278 + (int)x + count * 100, clock, 0.25, 6) * (radius));
+      int yOff = (int)(perlin2DPoint (1.0, 200, 9734 + (int)y + count * 100, clock, 0.25, 6) * (radius));
+      circlefill (dest, (int)x + xOff, (int)y + yOff, blobSize, getpixel (tempBitmap, radius + xOff, radius + yOff));
+    }
+  drawing_mode (DRAW_MODE_SOLID, NULL, 0, 0);
+  setUpdateArea ((int)x - radius - blobSize, (int)y - radius - blobSize, (radius + blobSize) * 2, (radius + blobSize) * 2);
+  requireUpdate ();
+
+  destroy_bitmap (tempBitmap);
+}
+*/
+
+
+int TELEPORT::isSubClass (int classNum)
+{
+  if (classNum == TELEPORT_CLASS)
+    return (TRUE);
+  else
+    return (FALSE);
+  //return (PHYSICAL_OBJECT::isSubClass (classNum));
+}
diff --git a/src/teleport.h b/src/teleport.h
new file mode 100644
index 0000000..c4b2293
--- /dev/null
+++ b/src/teleport.h
@@ -0,0 +1,59 @@
+#ifndef TELEPORT_DEFINE
+#define TELEPORT_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+
+#include "main.h"
+#include "virtobj.h"
+
+class TELEPORT: public VIRTUAL_OBJECT
+  {
+  public:
+    int	radius;
+    int	clock;
+    int	startClock;
+    int	peaked;
+    int	dispersing;
+    VIRTUAL_OBJECT *object;
+    TELEPORT *remote;
+
+    virtual ~TELEPORT ();
+    TELEPORT (GLOBALDATA *global, ENVIRONMENT *env, VIRTUAL_OBJECT *targetObj, int destinationX, int destinationY, int objRadius, int duration);
+    TELEPORT (GLOBALDATA *global, ENVIRONMENT *env, TELEPORT *remoteEnd, int destX, int destY);
+    void	initialise ();
+    void	draw (BITMAP *dest);
+    int	applyPhysics ();
+    int	isSubClass (int classNum);
+    inline virtual int	getClass ()
+    {
+      return (TELEPORT_CLASS);
+    }
+    inline virtual void setEnvironment(ENVIRONMENT *env)
+    {
+      if (!_env || (_env != env))
+        {
+          _env = env;
+          _index = _env->addObject (this);
+        }
+    }
+  };
+
+#endif
diff --git a/src/text.cpp b/src/text.cpp
new file mode 100644
index 0000000..2005792
--- /dev/null
+++ b/src/text.cpp
@@ -0,0 +1,227 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "text.h"
+
+
+// Basic constructor to kick things off
+TEXTBLOCK::TEXTBLOCK()
+{
+    complete_text = NULL;
+    total_lines = current_line = 0;
+}
+
+
+// A constructor that also loads text from a file
+TEXTBLOCK::TEXTBLOCK(char *filename)
+{
+    int status;
+
+    complete_text = NULL;
+    total_lines = current_line = 0;
+    if (filename)
+    {
+        status = Load_File(filename);
+        if (! status)
+          printf("Something went wrong loading text from file: %s\n", filename);
+    }
+}
+
+
+// clean everything
+TEXTBLOCK::~TEXTBLOCK()
+{
+   int count;
+
+   if (complete_text)
+   {
+     for (count = 0; count < total_lines; count++)
+     {
+        if ( complete_text[count] )
+           free(complete_text[count]);
+     }
+     free(complete_text);
+   }
+
+}
+
+
+
+
+void TEXTBLOCK::Trim_Newline(char *line)
+{
+    int index = 0;
+
+    while ( line[index] )
+    {
+       if ( (line[index] == '\n') || (line[index] == '\r') )
+          line[index] = '\0';
+       else
+          index++;
+    }
+}
+
+
+
+// This function does most of the work. It loads an entire text
+// file into memory. Returns TRUE on success or FALSE if
+// somethign goes wrong.
+int TEXTBLOCK::Load_File(char *filename)
+{
+    FILE *phile;
+    int lines_loaded = 0;
+    int we_have_space = 10;
+    char line[MAX_LINE_LENGTH], *status;
+
+    // open the file
+    phile = fopen(filename, "r");
+    if (! phile)
+      return FALSE;
+
+    // give us some space  
+    complete_text = (char **) calloc(we_have_space, sizeof(char *));
+    if (! complete_text)
+    {
+       fclose(phile);
+       return FALSE;
+    }
+
+    // time to load some text!
+    status = fgets(line, MAX_LINE_LENGTH, phile);
+    while ( (status) && (lines_loaded < MAX_LINES_IN_FILE) && (complete_text)  )
+    {
+        Trim_Newline(line);
+        complete_text[lines_loaded] = (char *) calloc( strlen(line) + 1, sizeof(char));
+        if ( complete_text[lines_loaded] )
+        {
+             strcpy( complete_text[lines_loaded], line );
+             lines_loaded++;
+        }
+        if (lines_loaded >= we_have_space)
+        {
+            we_have_space += 10;
+            complete_text = (char **) realloc( complete_text, we_have_space * sizeof(char *) );
+        }
+        status = fgets(line, MAX_LINE_LENGTH, phile);
+    }       // all done loading
+
+    if (complete_text)
+       complete_text = (char **) realloc( complete_text, lines_loaded * sizeof(char *) );
+    fclose(phile);
+    total_lines = lines_loaded;
+    current_line = 0;
+    return TRUE;
+}
+
+
+
+// Find a random line and return it
+char *TEXTBLOCK::Get_Random_Line()
+{
+    int my_line;
+    char *my_text;
+
+    my_line = rand() % total_lines;
+    my_text = complete_text[my_line];
+    return my_text;
+}
+
+
+// Returns the current line
+char *TEXTBLOCK::Get_Current_Line()
+{
+   char *my_text;
+
+   my_text = complete_text[current_line];
+   return my_text;
+}
+
+
+
+
+// Move the line counter ahead, if possible
+// Returns FALSE if we hit the end of lines, or
+// true if everything is OK
+int TEXTBLOCK::Next_Line()
+{
+    current_line++;
+    if (current_line >= total_lines)
+    {
+        current_line = total_lines - 1;
+        return FALSE;
+    }
+    return TRUE;
+}
+
+
+
+// Go to the previous line. The function returns
+// TRUE is everything is OK. If we were already
+// at the beginning, then FALSE is returned.
+int TEXTBLOCK::Previous_Line()
+{
+    if (current_line > 0)
+    {
+         current_line--;
+         return TRUE;
+    }
+    return FALSE;
+}
+
+
+// This function display all lines of text. Optionally, it
+// will also print line numbers before each line.
+// The number of lines printed is returned.
+int TEXTBLOCK::Display_All(int line_numbers)
+{
+    int counter = 0;
+
+    while (counter < total_lines)
+    {
+        if (line_numbers)
+           printf("%d. ", counter);
+        printf("%s\n", complete_text[counter]);
+        counter++;
+    }
+    return counter;
+}
+
+
+
+
+
+
+
+// This is a free floating function
+char *Add_Comma(int number)
+{
+    char buffer[64];
+    static char return_value[128];
+    int index, return_index;
+    int place_counter = 0;
+
+    // we won't worry about over-flow with such a big buffer
+    sprintf(buffer, "%d", number);
+    memset(return_value, '\0', 128);
+    index = strlen(buffer);      // start from the end
+    return_index = index + (index / 3);
+    return_index -= 1;
+    if (! (index % 3) )
+       return_index--;
+    index -= 1;
+    while (index >= 0)
+    {
+        return_value[return_index] = buffer[index];
+        return_index--;
+        index--;
+        place_counter++;
+        if ( (place_counter == 3) && (return_index > 0) )
+        {
+            place_counter = 0;
+            return_value[return_index] = ',';
+            return_index--;
+        }
+    }
+    return return_value;
+}
+
diff --git a/src/text.h b/src/text.h
new file mode 100644
index 0000000..97055e7
--- /dev/null
+++ b/src/text.h
@@ -0,0 +1,59 @@
+#ifndef TEXT_HEADER_FILE__
+#define TEXT_HEADER_FILE__
+
+/* This file contains functions for reading text from files and
+ * storing it in the game. The entire text file will be kept in memory.
+ * Each text object will have the ability to return a line,
+ * track its position in the text or return a random line.
+ * This should allow for better multi-language handling, faster
+ * access to tank speech and remove the need to rely on the lineseq
+ * class.
+ * -- Jesse
+*/
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define MAX_LINE_LENGTH 512
+#define MAX_LINES_IN_FILE 1024
+
+
+class TEXTBLOCK
+{
+public:
+   int total_lines, current_line;
+   char **complete_text;
+
+
+   TEXTBLOCK();
+   TEXTBLOCK(char *filename);
+   ~TEXTBLOCK();
+
+   void Trim_Newline(char *line);     // hack the newline off a string
+   int Load_File(char *filename);    // load lines from a file
+   char *Get_Random_Line();   // give us a random line
+   char *Get_Current_Line();  // return current line
+   int Next_Line();           // advance the current line counter one
+   int Previous_Line();       // move the current line counter back one
+   int Display_All(int line_numbers); // display all text
+
+};
+
+
+
+
+// Functions we can use anywhere
+
+// This function returns a string with
+// comma characters between thousands positions
+// There is no need to free the returned string.
+char *Add_Comma(int number);
+
+
+
+#endif
+
diff --git a/src/update.cpp b/src/update.cpp
new file mode 100644
index 0000000..b765ff6
--- /dev/null
+++ b/src/update.cpp
@@ -0,0 +1,105 @@
+#ifdef NETWORK
+#ifdef THREADS
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <unistd.h>
+
+#include "update.h"
+
+
+
+
+
+
+char *Check_For_Update(char *server_name, char *remote_file, char *host_name, char *current_version)
+{
+    struct update_data *my_update;
+    pthread_t update_thread;
+
+    my_update = (struct update_data *) calloc(1, sizeof(struct update_data));
+    if (!my_update)
+       return NULL;
+    my_update->server_name = server_name;
+    my_update->remote_file = remote_file;
+    my_update->host_name = host_name;
+    my_update->current_version = current_version;
+    my_update->update_string = (char *) calloc(UPDATE_STR_LENGTH, sizeof(char));
+    if (! my_update->update_string)
+       return NULL;
+
+    pthread_create( &update_thread, NULL, Get_Latest_Version, (void *) my_update);
+    return my_update->update_string;
+}
+
+
+
+void *Get_Latest_Version(void *new_data)
+{
+  struct update_data *my_data = (struct update_data *) new_data;
+   // set up socket
+   int socket_num, port_number = 80;
+   struct sockaddr_in server_address;
+   struct hostent *server;
+   char buffer[1024];
+   char *found = NULL;
+   int got_bytes;
+   double this_version, web_version;
+
+
+   socket_num = socket(AF_INET, SOCK_STREAM, 0);
+   if (socket_num < 0)
+      pthread_exit(NULL);
+   server = gethostbyname(my_data->server_name);
+   if (! server)
+      pthread_exit(NULL);
+   bzero((char *) &server_address, sizeof(server_address));
+   server_address.sin_family = AF_INET;
+   bcopy((char *) server->h_addr,
+         (char *) &server_address.sin_addr.s_addr,
+         server->h_length);
+   server_address.sin_port = htons(port_number);
+
+   // try to connect
+   if ( connect(socket_num, (sockaddr *)&server_address, sizeof(server_address)) < 0)
+      pthread_exit(NULL);
+
+
+   // get HTTP data
+   snprintf(buffer, 1024, "GET /%s HTTP/1.1\nHost: %s\n\n", my_data->remote_file, my_data->host_name);
+   write(socket_num, buffer, strlen(buffer));
+   got_bytes = read(socket_num, buffer, 1024);
+
+   // search for version number in return data
+   if (got_bytes > 1)
+      found = strstr(buffer, "Version: ");
+   while ( (got_bytes > 1) && (! found) )
+   {
+      got_bytes = read(socket_num, buffer, 1024);
+      if (got_bytes > 1)
+         found = strstr(buffer, "Version: ");
+   }
+
+   // compare version number
+   if (found)
+   {
+      found += 9;
+      found[5] = '\0';
+      sscanf(found, "%lf", &web_version);
+      sscanf(my_data->current_version, "%lf", &this_version);
+      if (web_version > this_version)
+         sprintf(my_data->update_string, "A new version, %2.1lf, is ready for download.", web_version);
+   }
+
+   close(socket_num);
+   pthread_exit(NULL);
+}
+
+#endif
+#endif
diff --git a/src/update.h b/src/update.h
new file mode 100644
index 0000000..2f5ec4b
--- /dev/null
+++ b/src/update.h
@@ -0,0 +1,43 @@
+#ifndef UPDATE_HEADER_FILE__
+#define UPDATE_HEADER_FILE__
+
+
+#ifdef NETWORK
+#ifdef THREADS
+
+
+#define UPDATE_STR_LENGTH 256
+
+
+struct update_data
+{
+   char *server_name, *host_name;
+   char *remote_file;
+   char *update_string;
+   char *current_version;
+};
+
+
+
+// this function kicks it all off
+// returns the address of a string containing
+// update notice. The string will have a notice
+// if update is ready or be 0-length with no update.
+// The function is threaded and may change the
+// string after the function returns.
+// The returning string is allocated and should
+// be freed at the end of the calling process.
+// On error, NULL is returned.
+char *Check_For_Update(char *server_name, char *remote_file, char *host_name, char *current_version);
+
+
+
+// The function/thread that checks for new updates.
+void *Get_Latest_Version(void *data);
+
+
+#endif
+#endif
+
+#endif
+
diff --git a/src/virtobj.cpp b/src/virtobj.cpp
new file mode 100644
index 0000000..239d409
--- /dev/null
+++ b/src/virtobj.cpp
@@ -0,0 +1,212 @@
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+#include "virtobj.h"
+#include "environment.h"
+
+
+
+VIRTUAL_OBJECT::VIRTUAL_OBJECT()
+    {
+      _bitmap = NULL;
+      _env = NULL;
+      _global = NULL;
+      x = 0;
+      y = 0;
+      xv = yv = 0;
+      angle = 0;
+      destroy = FALSE;
+      age = 0;
+      maxAge = -1;
+      physics = 0;
+      _current.x = 0;
+      _current.y = 0;
+      _current.w = 0;
+      _current.h = 0;
+      _old.x = 0;
+      _old.y = 0;
+      _old.w = 0;
+      _old.h = 0;
+    }
+
+
+
+
+VIRTUAL_OBJECT::~VIRTUAL_OBJECT ()
+      {
+        _bitmap = NULL;
+        // player, _env and _global must be handled by descendants!
+      }
+
+
+
+/** @brief update
+  *
+  * This method triggers an update of the canvas (aka drawing area) with the dimensions and position
+  * of this object.
+  */
+void VIRTUAL_OBJECT::update()
+{
+  if (_requireUpdate)
+    {
+      int changed;
+
+      if (_current.w)
+        {
+          if (_align == LEFT)
+            {
+              _env->make_update (_current.x, _current.y,
+                                 _current.w, _current.h);
+            }
+          else if (_align == RIGHT)
+            {
+              _env->make_update (_current.x - _current.w,
+                                 _current.y - _current.h,
+                                 _current.w, _current.h);
+            }
+          else
+            {
+              _env->make_update (_current.x - (_current.w / 2),
+                                 _current.y - (_current.h / 2),
+                                 _current.w + 2, _current.h + 2);
+            }
+        }
+
+      if ((_old.x == _current.x) &&
+          (_old.y == _current.y) &&
+          (_old.w == _current.w) &&
+          (_old.h == _current.h))
+        changed = FALSE;
+      else
+        changed = TRUE;
+
+      if (changed)
+        {
+          if (_old.w)
+            {
+              if (_align == LEFT)
+                {
+                  _env->make_update (_old.x, _old.y,
+                                     _old.w, _old.h);
+                }
+              else if (_align == RIGHT)
+                {
+                  _env->make_update (_old.x - _old.w,
+                                     _old.y - _old.h,
+                                     _old.w, _old.h);
+                }
+              else
+                {
+                  _env->make_update (_old.x - (_old.w / 2),
+                                     _old.y - (_old.h / 2),
+                                     _old.w + 2, _old.h + 2);
+                }
+            }
+          _old.x = _current.x;
+          _old.y = _current.y;
+          _old.w = _current.w;
+          _old.h = _current.h;
+        }
+      _requireUpdate = FALSE;
+    }
+}
+
+
+void VIRTUAL_OBJECT::initialise ()
+    {
+      age = 0;
+      maxAge = -1;
+      x = 0;
+      y = 0;
+      xv = 0;
+      yv = 0;
+      destroy = false;
+      _current.x = 0;
+      _current.y = 0;
+      _current.w = 0;
+      _current.h = 0;
+      _old.x = 0;
+      _old.y = 0;
+      _old.w = 0;
+      _old.h = 0;
+    }
+
+
+
+int VIRTUAL_OBJECT::applyPhysics ()
+    {
+      x += xv;
+      y += yv;
+
+      return (0);
+    }
+
+
+
+void VIRTUAL_OBJECT::draw (BITMAP *dest)
+    {
+      if (!destroy)
+        {
+          rotate_sprite (dest, _bitmap,
+                         (int)x - (_bitmap->w / 2),
+                         (int)y - (_bitmap->h / 2),
+                         itofix (angle));
+          if (angle == 0)
+            {
+              setUpdateArea ((int)x - (_bitmap->w / 2 + 1),
+                             (int)y - (_bitmap->h / 2 + 1),
+                             _bitmap->w + 2, _bitmap->h + 2);
+            }
+          else
+            {
+              int length = MAX (_bitmap->w, _bitmap->h);
+              length += MIN (_bitmap->w, _bitmap->h) / 2;
+              setUpdateArea ((int)x - (length/2),
+                             (int)y - (length/2),
+                             length, length);
+            }
+          requireUpdate ();
+        }
+    }
+
+
+
+
+void VIRTUAL_OBJECT::setUpdateArea (int left, int top, int width, int height)
+    {
+      _current.x = left;
+      _current.y = top;
+      _current.w = width;
+      _current.h = height;
+    }
+
+
+
+void VIRTUAL_OBJECT::addUpdateArea (int left, int top, int width, int height)
+    {
+      if (left < _current.x)
+        _current.x = left;
+      if (top < _current.y)
+        _current.y = top;
+      if (left + width > _current.x + _current.w)
+        _current.w = width;
+      if (top + height > _current.y + _current.h)
+        _current.h = height;
+    }
+
diff --git a/src/virtobj.h b/src/virtobj.h
new file mode 100644
index 0000000..e8fc9a4
--- /dev/null
+++ b/src/virtobj.h
@@ -0,0 +1,93 @@
+#ifndef	VIRTOBJ_DEFINE
+#define	VIRTOBJ_DEFINE
+
+/*
+ * atanks - obliterate each other with oversize weapons
+ * Copyright (C) 2003  Thomas Hudson
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * */
+
+#ifndef _PURE
+#define _PURE =0
+#endif // _PURE
+
+enum    alignType { CENTRE, LEFT, RIGHT };
+
+#include "main.h"
+
+#include "player.h"
+
+class VIRTUAL_OBJECT
+  {
+  public:
+    BOX	_current, _old;
+    alignType	_align;
+    BITMAP	*_bitmap;
+    ENVIRONMENT	*_env;
+    GLOBALDATA	*_global;
+    int	_requireUpdate;
+    int	_index;
+    PLAYER *player;
+    double	x, y;
+    double	xv, yv;
+    int	angle;
+    int	destroy;
+    int	age, maxAge;
+    int	physics;	// Special physics processing?
+
+    /* --- constructor --- */
+    VIRTUAL_OBJECT();
+
+    /* --- destructor --- */
+    virtual	~VIRTUAL_OBJECT ();
+
+    /* --- non-inline methods --- */
+    void	update();
+
+    /* --- pure virtual (abstract) methods --- */
+    virtual int	  isSubClass (int classNum)_PURE;
+    virtual int	  getClass ()_PURE;
+    virtual void  setEnvironment(ENVIRONMENT *env)_PURE; // This is virtual, so objects add themselves to _env!
+
+    /* --- inline methods --- */
+    void	requireUpdate ()
+    {
+      _requireUpdate = TRUE;
+    }
+
+    virtual void	initialise ();
+
+    virtual int	applyPhysics ();
+
+    inline void	setGlobalData (GLOBALDATA *global)
+    {
+      if (!_global || (_global != global))
+        _global = global;
+    }
+
+virtual void	draw (BITMAP *dest);
+
+void	setUpdateArea (int left, int top, int width, int height);
+
+void	addUpdateArea (int left, int top, int width, int height);
+
+    inline int	getIndex ()
+    {
+      return (_index);
+    }
+  };
+
+#endif // VIRTOBJ_DEFINE
diff --git a/stock/0.bmp b/stock/0.bmp
new file mode 100644
index 0000000..be2bfe4
Binary files /dev/null and b/stock/0.bmp differ
diff --git a/stock/1.bmp b/stock/1.bmp
new file mode 100644
index 0000000..a5245ec
Binary files /dev/null and b/stock/1.bmp differ
diff --git a/stock/10.bmp b/stock/10.bmp
new file mode 100644
index 0000000..390003b
Binary files /dev/null and b/stock/10.bmp differ
diff --git a/stock/11.bmp b/stock/11.bmp
new file mode 100644
index 0000000..fd38254
Binary files /dev/null and b/stock/11.bmp differ
diff --git a/stock/12.bmp b/stock/12.bmp
new file mode 100644
index 0000000..4cb264e
Binary files /dev/null and b/stock/12.bmp differ
diff --git a/stock/13.bmp b/stock/13.bmp
new file mode 100644
index 0000000..2bba569
Binary files /dev/null and b/stock/13.bmp differ
diff --git a/stock/14.bmp b/stock/14.bmp
new file mode 100644
index 0000000..47f84ce
Binary files /dev/null and b/stock/14.bmp differ
diff --git a/stock/15.bmp b/stock/15.bmp
new file mode 100644
index 0000000..64b5a84
Binary files /dev/null and b/stock/15.bmp differ
diff --git a/stock/16.bmp b/stock/16.bmp
new file mode 100644
index 0000000..40bfdf3
Binary files /dev/null and b/stock/16.bmp differ
diff --git a/stock/17.bmp b/stock/17.bmp
new file mode 100644
index 0000000..432ab52
Binary files /dev/null and b/stock/17.bmp differ
diff --git a/stock/18.bmp b/stock/18.bmp
new file mode 100644
index 0000000..71b91c4
Binary files /dev/null and b/stock/18.bmp differ
diff --git a/stock/19.bmp b/stock/19.bmp
new file mode 100644
index 0000000..71b91c4
Binary files /dev/null and b/stock/19.bmp differ
diff --git a/stock/2.bmp b/stock/2.bmp
new file mode 100644
index 0000000..1f9184f
Binary files /dev/null and b/stock/2.bmp differ
diff --git a/stock/20.bmp b/stock/20.bmp
new file mode 100644
index 0000000..71b91c4
Binary files /dev/null and b/stock/20.bmp differ
diff --git a/stock/21.bmp b/stock/21.bmp
new file mode 100644
index 0000000..39e391d
Binary files /dev/null and b/stock/21.bmp differ
diff --git a/stock/22.bmp b/stock/22.bmp
new file mode 100644
index 0000000..574eee4
Binary files /dev/null and b/stock/22.bmp differ
diff --git a/stock/23.bmp b/stock/23.bmp
new file mode 100644
index 0000000..7febcd9
Binary files /dev/null and b/stock/23.bmp differ
diff --git a/stock/24.bmp b/stock/24.bmp
new file mode 100644
index 0000000..913f523
Binary files /dev/null and b/stock/24.bmp differ
diff --git a/stock/25.bmp b/stock/25.bmp
new file mode 100644
index 0000000..ba09aab
Binary files /dev/null and b/stock/25.bmp differ
diff --git a/stock/26.bmp b/stock/26.bmp
new file mode 100644
index 0000000..69b080e
Binary files /dev/null and b/stock/26.bmp differ
diff --git a/stock/27.bmp b/stock/27.bmp
new file mode 100644
index 0000000..9a5479b
Binary files /dev/null and b/stock/27.bmp differ
diff --git a/stock/28.bmp b/stock/28.bmp
new file mode 100644
index 0000000..9a5479b
Binary files /dev/null and b/stock/28.bmp differ
diff --git a/stock/29.bmp b/stock/29.bmp
new file mode 100644
index 0000000..9a5479b
Binary files /dev/null and b/stock/29.bmp differ
diff --git a/stock/3.bmp b/stock/3.bmp
new file mode 100644
index 0000000..59f5114
Binary files /dev/null and b/stock/3.bmp differ
diff --git a/stock/30.bmp b/stock/30.bmp
new file mode 100644
index 0000000..9a5479b
Binary files /dev/null and b/stock/30.bmp differ
diff --git a/stock/31.bmp b/stock/31.bmp
new file mode 100644
index 0000000..f61d6f9
Binary files /dev/null and b/stock/31.bmp differ
diff --git a/stock/32.bmp b/stock/32.bmp
new file mode 100644
index 0000000..bd298f4
Binary files /dev/null and b/stock/32.bmp differ
diff --git a/stock/33.bmp b/stock/33.bmp
new file mode 100644
index 0000000..4b5d9e6
Binary files /dev/null and b/stock/33.bmp differ
diff --git a/stock/34.bmp b/stock/34.bmp
new file mode 100644
index 0000000..6b5d46f
Binary files /dev/null and b/stock/34.bmp differ
diff --git a/stock/35.bmp b/stock/35.bmp
new file mode 100644
index 0000000..0985a44
Binary files /dev/null and b/stock/35.bmp differ
diff --git a/stock/36.bmp b/stock/36.bmp
new file mode 100644
index 0000000..fc84722
Binary files /dev/null and b/stock/36.bmp differ
diff --git a/stock/37.bmp b/stock/37.bmp
new file mode 100644
index 0000000..aa161ef
Binary files /dev/null and b/stock/37.bmp differ
diff --git a/stock/38.bmp b/stock/38.bmp
new file mode 100644
index 0000000..192bb08
Binary files /dev/null and b/stock/38.bmp differ
diff --git a/stock/39.bmp b/stock/39.bmp
new file mode 100644
index 0000000..6349f6d
Binary files /dev/null and b/stock/39.bmp differ
diff --git a/stock/4.bmp b/stock/4.bmp
new file mode 100644
index 0000000..ed45a1d
Binary files /dev/null and b/stock/4.bmp differ
diff --git a/stock/40.bmp b/stock/40.bmp
new file mode 100644
index 0000000..13d250e
Binary files /dev/null and b/stock/40.bmp differ
diff --git a/stock/41.bmp b/stock/41.bmp
new file mode 100644
index 0000000..7648253
Binary files /dev/null and b/stock/41.bmp differ
diff --git a/stock/42.bmp b/stock/42.bmp
new file mode 100644
index 0000000..696ab2e
Binary files /dev/null and b/stock/42.bmp differ
diff --git a/stock/43.bmp b/stock/43.bmp
new file mode 100644
index 0000000..39363ba
Binary files /dev/null and b/stock/43.bmp differ
diff --git a/stock/44.bmp b/stock/44.bmp
new file mode 100644
index 0000000..2832651
Binary files /dev/null and b/stock/44.bmp differ
diff --git a/stock/45.bmp b/stock/45.bmp
new file mode 100644
index 0000000..a0520fc
Binary files /dev/null and b/stock/45.bmp differ
diff --git a/stock/46.bmp b/stock/46.bmp
new file mode 100644
index 0000000..8dfc4fe
Binary files /dev/null and b/stock/46.bmp differ
diff --git a/stock/47.bmp b/stock/47.bmp
new file mode 100644
index 0000000..420f395
Binary files /dev/null and b/stock/47.bmp differ
diff --git a/stock/48.bmp b/stock/48.bmp
new file mode 100644
index 0000000..9156a2d
Binary files /dev/null and b/stock/48.bmp differ
diff --git a/stock/49.bmp b/stock/49.bmp
new file mode 100644
index 0000000..2a7d5ee
Binary files /dev/null and b/stock/49.bmp differ
diff --git a/stock/5.bmp b/stock/5.bmp
new file mode 100644
index 0000000..37e6549
Binary files /dev/null and b/stock/5.bmp differ
diff --git a/stock/50.bmp b/stock/50.bmp
new file mode 100644
index 0000000..3ac5293
Binary files /dev/null and b/stock/50.bmp differ
diff --git a/stock/51.bmp b/stock/51.bmp
new file mode 100644
index 0000000..6d2f548
Binary files /dev/null and b/stock/51.bmp differ
diff --git a/stock/52.bmp b/stock/52.bmp
new file mode 100644
index 0000000..93f838d
Binary files /dev/null and b/stock/52.bmp differ
diff --git a/stock/53.bmp b/stock/53.bmp
new file mode 100644
index 0000000..737de9a
Binary files /dev/null and b/stock/53.bmp differ
diff --git a/stock/54.bmp b/stock/54.bmp
new file mode 100644
index 0000000..da08ad6
Binary files /dev/null and b/stock/54.bmp differ
diff --git a/stock/55.bmp b/stock/55.bmp
new file mode 100644
index 0000000..2bcfb21
Binary files /dev/null and b/stock/55.bmp differ
diff --git a/stock/56.bmp b/stock/56.bmp
new file mode 100644
index 0000000..522e9ae
Binary files /dev/null and b/stock/56.bmp differ
diff --git a/stock/57.bmp b/stock/57.bmp
new file mode 100644
index 0000000..08f4f0e
Binary files /dev/null and b/stock/57.bmp differ
diff --git a/stock/58.bmp b/stock/58.bmp
new file mode 100644
index 0000000..719128a
Binary files /dev/null and b/stock/58.bmp differ
diff --git a/stock/59.bmp b/stock/59.bmp
new file mode 100644
index 0000000..0680a1d
Binary files /dev/null and b/stock/59.bmp differ
diff --git a/stock/6.bmp b/stock/6.bmp
new file mode 100644
index 0000000..c74ccc6
Binary files /dev/null and b/stock/6.bmp differ
diff --git a/stock/60.bmp b/stock/60.bmp
new file mode 100644
index 0000000..d88f781
Binary files /dev/null and b/stock/60.bmp differ
diff --git a/stock/61.bmp b/stock/61.bmp
new file mode 100644
index 0000000..62396dc
Binary files /dev/null and b/stock/61.bmp differ
diff --git a/stock/62.bmp b/stock/62.bmp
new file mode 100644
index 0000000..69588a2
Binary files /dev/null and b/stock/62.bmp differ
diff --git a/stock/63.bmp b/stock/63.bmp
new file mode 100644
index 0000000..6b4bfcf
Binary files /dev/null and b/stock/63.bmp differ
diff --git a/stock/64.bmp b/stock/64.bmp
new file mode 100644
index 0000000..89ee729
Binary files /dev/null and b/stock/64.bmp differ
diff --git a/stock/65.bmp b/stock/65.bmp
new file mode 100644
index 0000000..b3ce8b6
Binary files /dev/null and b/stock/65.bmp differ
diff --git a/stock/66.bmp b/stock/66.bmp
new file mode 100644
index 0000000..d9b65aa
Binary files /dev/null and b/stock/66.bmp differ
diff --git a/stock/67.bmp b/stock/67.bmp
new file mode 100644
index 0000000..d8cf25f
Binary files /dev/null and b/stock/67.bmp differ
diff --git a/stock/68.bmp b/stock/68.bmp
new file mode 100644
index 0000000..ae1ada9
Binary files /dev/null and b/stock/68.bmp differ
diff --git a/stock/69.bmp b/stock/69.bmp
new file mode 100644
index 0000000..744bdc6
Binary files /dev/null and b/stock/69.bmp differ
diff --git a/stock/7.bmp b/stock/7.bmp
new file mode 100644
index 0000000..b7dc01a
Binary files /dev/null and b/stock/7.bmp differ
diff --git a/stock/70.bmp b/stock/70.bmp
new file mode 100644
index 0000000..7646e83
Binary files /dev/null and b/stock/70.bmp differ
diff --git a/stock/71.bmp b/stock/71.bmp
new file mode 100644
index 0000000..66c1934
Binary files /dev/null and b/stock/71.bmp differ
diff --git a/stock/72.bmp b/stock/72.bmp
new file mode 100644
index 0000000..670ce03
Binary files /dev/null and b/stock/72.bmp differ
diff --git a/stock/73.bmp b/stock/73.bmp
new file mode 100644
index 0000000..65bbaf1
Binary files /dev/null and b/stock/73.bmp differ
diff --git a/stock/74.bmp b/stock/74.bmp
new file mode 100644
index 0000000..71d46fc
Binary files /dev/null and b/stock/74.bmp differ
diff --git a/stock/75.bmp b/stock/75.bmp
new file mode 100644
index 0000000..4394555
Binary files /dev/null and b/stock/75.bmp differ
diff --git a/stock/76.bmp b/stock/76.bmp
new file mode 100644
index 0000000..692d19b
Binary files /dev/null and b/stock/76.bmp differ
diff --git a/stock/77.bmp b/stock/77.bmp
new file mode 100644
index 0000000..d3588de
Binary files /dev/null and b/stock/77.bmp differ
diff --git a/stock/78.bmp b/stock/78.bmp
new file mode 100644
index 0000000..46c7e26
Binary files /dev/null and b/stock/78.bmp differ
diff --git a/stock/8.bmp b/stock/8.bmp
new file mode 100644
index 0000000..2216066
Binary files /dev/null and b/stock/8.bmp differ
diff --git a/stock/9.bmp b/stock/9.bmp
new file mode 100644
index 0000000..a664595
Binary files /dev/null and b/stock/9.bmp differ
diff --git a/tank/0.bmp b/tank/0.bmp
new file mode 100644
index 0000000..1556eee
Binary files /dev/null and b/tank/0.bmp differ
diff --git a/tank/1.bmp b/tank/1.bmp
new file mode 100644
index 0000000..557290b
Binary files /dev/null and b/tank/1.bmp differ
diff --git a/tank/10.bmp b/tank/10.bmp
new file mode 100644
index 0000000..f701fb0
Binary files /dev/null and b/tank/10.bmp differ
diff --git a/tank/11.bmp b/tank/11.bmp
new file mode 100644
index 0000000..be79c7a
Binary files /dev/null and b/tank/11.bmp differ
diff --git a/tank/12.bmp b/tank/12.bmp
new file mode 100644
index 0000000..8d2824d
Binary files /dev/null and b/tank/12.bmp differ
diff --git a/tank/13.bmp b/tank/13.bmp
new file mode 100644
index 0000000..b2c88ba
Binary files /dev/null and b/tank/13.bmp differ
diff --git a/tank/14.bmp b/tank/14.bmp
new file mode 100644
index 0000000..a086ccc
Binary files /dev/null and b/tank/14.bmp differ
diff --git a/tank/15.bmp b/tank/15.bmp
new file mode 100644
index 0000000..b7704a3
Binary files /dev/null and b/tank/15.bmp differ
diff --git a/tank/2.bmp b/tank/2.bmp
new file mode 100644
index 0000000..6b44915
Binary files /dev/null and b/tank/2.bmp differ
diff --git a/tank/3.bmp b/tank/3.bmp
new file mode 100644
index 0000000..ae933a3
Binary files /dev/null and b/tank/3.bmp differ
diff --git a/tank/4.bmp b/tank/4.bmp
new file mode 100644
index 0000000..5a7536d
Binary files /dev/null and b/tank/4.bmp differ
diff --git a/tank/5.bmp b/tank/5.bmp
new file mode 100644
index 0000000..b341565
Binary files /dev/null and b/tank/5.bmp differ
diff --git a/tank/6.bmp b/tank/6.bmp
new file mode 100644
index 0000000..ba0a027
Binary files /dev/null and b/tank/6.bmp differ
diff --git a/tank/7.bmp b/tank/7.bmp
new file mode 100644
index 0000000..74f7039
Binary files /dev/null and b/tank/7.bmp differ
diff --git a/tank/8.bmp b/tank/8.bmp
new file mode 100644
index 0000000..8a50018
Binary files /dev/null and b/tank/8.bmp differ
diff --git a/tank/9.bmp b/tank/9.bmp
new file mode 100644
index 0000000..3ef845d
Binary files /dev/null and b/tank/9.bmp differ
diff --git a/tankgun/0.bmp b/tankgun/0.bmp
new file mode 100644
index 0000000..40eb0bb
Binary files /dev/null and b/tankgun/0.bmp differ
diff --git a/tankgun/1.bmp b/tankgun/1.bmp
new file mode 100644
index 0000000..66c811b
Binary files /dev/null and b/tankgun/1.bmp differ
diff --git a/tankgun/2.bmp b/tankgun/2.bmp
new file mode 100644
index 0000000..c2b6829
Binary files /dev/null and b/tankgun/2.bmp differ
diff --git a/tankgun/3.bmp b/tankgun/3.bmp
new file mode 100644
index 0000000..85a202c
Binary files /dev/null and b/tankgun/3.bmp differ
diff --git a/tankgun/4.bmp b/tankgun/4.bmp
new file mode 100644
index 0000000..db4b30c
Binary files /dev/null and b/tankgun/4.bmp differ
diff --git a/tankgun/5.bmp b/tankgun/5.bmp
new file mode 100644
index 0000000..7b36a8c
Binary files /dev/null and b/tankgun/5.bmp differ
diff --git a/tankgun/6.bmp b/tankgun/6.bmp
new file mode 100644
index 0000000..26e7fc6
Binary files /dev/null and b/tankgun/6.bmp differ
diff --git a/tankgun/7.bmp b/tankgun/7.bmp
new file mode 100644
index 0000000..0162b14
Binary files /dev/null and b/tankgun/7.bmp differ
diff --git a/tankgun/8.bmp b/tankgun/8.bmp
new file mode 100644
index 0000000..6f0e9eb
Binary files /dev/null and b/tankgun/8.bmp differ
diff --git a/text/Help.pt_BR.txt b/text/Help.pt_BR.txt
new file mode 100644
index 0000000..bb7bdba
--- /dev/null
+++ b/text/Help.pt_BR.txt
@@ -0,0 +1,104 @@
+Instruções de Tanques Atômicos (Atomic Tanks)
+
+Índice:
+
+	Instruções Básicas
+		Objetivos
+		Iniciando um Jogo
+		Jogando
+
+	Configurando o Jogo
+		Alterando as Características Gerais do Jogo
+		Alterando a Física do Jogo
+		Alterando as Condições Meteorológicas do Jogo
+		Alterando a Economia do Jogo
+		Gerenciando e Configurando os Jogadores
+		Alterando os Gráficos do jogo
+
+-----------------------------
+Instruções Básicas
+
+Objetivos:
+Objetivo Primário: Destruir todos os outros tanques do cenário!
+Objetivo Secundário: Incrementar seu próprio tanque com armas e equipamentos melhores usando o dinheiro que conseguiu destruindo tanques.
+
+Iniciando um Jogo:
+1. Clique em 'Jogar' no menu principal.
+2. No menu 'Personagens', ajuste a duração do jogo em rodadas, Escolha os jogadores (máximo de 10) e clique em `Okay'.
+Jogadores humanos tem círculos púrpura, enquanto robôs tem barras de habilidade verdes; quanto mais barras, melhor o robô.
+3. No menu Armas, compre armas para seu tanque e clique `terminei' para começar o jogo.
+
+Jogando:
+1. Pressione Tab para selecionar uma arma.
+2. Use as teclas de seta esquerda/direita para apontar a arma (ângulo).
+3. Use as teclas de seta para cima/para baixo para ajustar o alcance da arma (potência).
+Você também tem que verificar a direção e força do vento no topo da tela, já que eles influem no ângulo e potência certos para atingir seus adversários. 
+DICA: Pressione CTRL enquanto estiver usando uma seta para mudar o ângulo ou a potência lentamente.
+4. Pressione Espaço para atirar.
+O menu Armas reaparece após cada rodada. Use o dinheiro ganho durannte a rodada para incrementar seu tanque, então clique em 'Terminei' para começar a próxima rodada. O vencedor do jogo é o jogador que ganhar o maior número de rodadas.
+
+Configurando o Jogo (para jogadores experientes):
+Você pode configurar Tanques Atômicos para tornar o jogo mais desafiador. Leia o que segue para aprender como configurar o jogo.
+
+Alterando as Características Gerais do Jogo:
+1. Clique em 'Opções' no menu principal para ver o menu Opções.
+2. Ajuste o nível Tecnológico para determinar as armas e equipamentos à venda na tela de armas; níveis tecnológicos mais altos oferecem maior variedade de armas e equipamentos.
+3. Ajuste o cenário para determinar o tipo de cenário no qual o as rodadas se realizarão.
+4. Ajuste a Ordem de Jogadas para determinar se a ordem dos jogadores numa rodada será pela maior pontuação (melhores+), a menor pontuação (Piores+), ou aleatoriamente.
+5. Ajuste Pular Jogo Só com Robôs para determinar se os robôs devem terminar o jogo em tempo real depois de todos os humanos terem sidos eliminados; desligue a opção Pular Jogo Só com Robôs para acelerar o jogo.
+6. Clique 'Voltar' para aplicar as alterações no próximo jogo.
+
+Alterando a Física do Jogo:
+1. Clique em 'Opções' no menu principal, então clique em Física no menu Opções.
+2. Aumente ou diminua a Gravidade para ajustar a força da gravidade; Gravidada alta reduz o alcance da maioria das armas, especialmente de projéteis como mísseis.
+3. Aumente ou diminua a Viscosidade para ajustas o fator de arrasto aplicado a armas de projéteis como mísseis; viscosidade alta reduz o alcance de todas as armas de projéteis.
+4. Ajuste o desabamento de Terra para determinar se uma arma ao atingir a terra causa um desabamento, assim como sua severidade.
+5. Clique duas vezes em 'Voltar' para aplicar as alterações no próximo jogo.
+
+Alterando as Condições Meteorológicas do Jogo:
+1. Clique em 'Opções' no menu principal, então clique em 'Condições Meteorológicas' no menu Opções.
+2. Ajuste Chuva de Meteoros para determinar a probabilidade e severidade das ocorrências de chuvas de meteoros aleatórias ao longo do jogo.
+3. Ajuste Relâmpagos para determinar a probabilidade e severidade de relâmpagos ocorrerem aleatóriamente ao longo do jogo.
+4. Ajuste Neblina para limitar a quantidade de terreno que um jogador pode ver ao seu redor.
+OBSERVAÇÃO: este recurso está atualmente em desenvolvimento.
+5. Ajuste Força Máxima do Vento para determinar quão forte o vento pode soprar durante o jogo.
+6. Ajuste a variação do vento para limitar quanto o vento muda numa rodada.
+7. Clique duas vezes em 'Voltar' para aplicar as alterações no próximo jogo.
+
+Alterando a Economia do Jogo
+OBSERVAÇÃO: Mudanças na economia do jogo pode afetar significativamente a forma de jogar.
+1. Clique em 'Opções' no menu principal, então clique em 'Dinheiro' no menu opções.
+2. Ajuste Dinheiro Inicial para determinar qual o valor que cada jogador (humano ou robô) recebe para comprar armas no começo do jogo.
+4. Ajuste Taxa de Juros para alterar a taxa de juros aplicada ao dinheiro entre uma rodada e outra.
+5. Altere Bônus por Vitória para definir quanto dinheiro um jogador ganha por vencer uma rodada.
+6. Ajuste Bônus por Estrago para determinar quanto dinheiro um jogador ganha por ponto de estrago que ele faça num adversário.
+7. Ajuste Penalidade por Auto-Estrago para determinar quanto dinheiro um jogador perde por ponto de estrago feito em si mesmo (Ser atingido por seu próprio míssil, por exemplo).
+8. Altere Bônus por Tanque Destruído para definir quanto dinheiro um jogador ganhar ao destruir um tanque.
+9. Ajuste Penalidade por Auto-Destruição para determinar quanto dinheiro um jogador perde por destruir seu próprio tanque.
+10. Clique duas vezes em 'Voltar' para aplicar as alterações no próximo jogo.
+
+Gerenciando e Configurando os Jogadores
+1. Clique em 'Jogadores' no menu principal para mostrar o menu Jogadores. 
+2. Faça uma das seguintes ações: 
+-para criar um novo jogador, clique em `Criar Novo' e então complete os passos 3 a 5.
+-para configurar um jogador, clique no seu nome e então complete qualquer um dos passos seguintes.
+-para apagar um jogador, clique em seu nome e então clique `Apagar Este Jogador' e confirme.
+OBSERVAÇÃO: Não há como recuperar um jogador apagado.
+3. Mude o Nome para renomear o jogador.
+4. Mude a cor para o jogador na paleta de cores.
+5. Ajuste o tipo para determinar se um jogador é humano ou robô; robôs podem ter os seguintes níveis de habilidade:
+-Chutador (pior nível de habilidade): se acertar algo foi por sorte
+-"Range Finder": acerta o alvo em mais ou menos metade das vezes
+-Mirador (melhor nível de habilidade): acerta quase sempre
+6. Clique em 'OK' para aplicar as alterações no próximo jogo.
+
+Alterando os Gráficos do jogo
+OBSERVAÇÃO: Alterações nos gráficos do jogo podem afetar o tempo necessário para iniciar um jogo ou uma rodada.
+1. Clique em 'Opções' no menu principal, então clique em 'Gráficos' no menu Opções.
+2. Ajuste Pontilhamento para determinar se os gráficos serão pontilhados; desligue Pontilhamento para melhores gráficos.
+3. Ajuste Detalhes do Terreno para determinar os detalhes do cenário; ligue Detalhes do Terreno para gráficos melhores.
+4. Ajuste Detalhes do Céu para determinar os detalhes do fundo; ligue Detalhes do Céu para gráficos melhores.
+5. Clique duas vezes em 'Voltar' para aplicar suas alterações no próximo jogo.
+--------------------------------------
+
+Se você não encontrou a resposta para sua pergunta aqui, nem em http://sourceforge.net/projects/atanks e nem em http://atanks.sourceforge.net, mande e-mail (em inglês) para atanks at singular.org.uk
diff --git a/text/Help.txt b/text/Help.txt
new file mode 100644
index 0000000..8990f0f
--- /dev/null
+++ b/text/Help.txt
@@ -0,0 +1,111 @@
+Instructions for Atomic Tanks
+
+Contents:
+
+	Basic Instructions
+		Objectives
+		Starting a Game
+		Playing a Game
+
+	Customising the Game
+		Changing General Game Characteristics
+		Changing Game Physics
+		Changing Game Weather
+		Changing Game Finances
+		Managing and Customizing Game Players
+		Changing Game Graphics
+
+-----------------------------
+Basic Instructions:
+
+Objectives:
+Primary Objective: Destroy all other tanks on the landscape!
+Secondary Objective: Upgrade your own tank with better weapons and equipment using money earned from tank kills.
+
+Starting a Game:
+1. Click 'Play' on the main menu.
+2. On the Players menu, set game length in rounds, choose players (10 max.) and click `Okay'.
+   Note: Human player tanks are marked with a purple circle. AI tanks are
+   indicated by green bars. The more bars, the smarter the AI.
+3. On the Weapons menu, buy weapons for your tank and click `Done' to start the game.
+
+Playing a Game:
+1. Press Tab to select a weapon.
+2. Use the left/right arrow keys to aim the weapon (called Angle).
+3. Use the up/down arrow keys to set the range of the weapon (called Power).
+You should also check the wind direction and strength at the top of the screen, as these may affect the Angle and Power required to hit your opponent. 
+TIP: Press CTRL while using an arrow key to change Angle or Power more slowly.
+4. Press Space to fire the weapon.
+The weapons menu reappears after each round. Use money earned during the round to upgrade your tank, then click 'Done' to begin the next round. The winner of the game is the player who wins the most rounds.
+
+Customizing the Game (for advanced players):
+You can customize Atomic Tanks to make the game more challenging. Read the following to learn how to customize the game.
+
+Changing General Game Characteristics:
+1. Click 'Options' on the main menu to view the Options menu.
+2. Set Tech Level to determine the weapons and equipment available for purchase on the weapons screen; higher Tech Levels offer a larger variety of weapons and equipment.
+3. Set Landscape to determine the type of landscape on which each round is played.
+4. Set Turn Order to determine if player order per round is set according to highest score (High+), the lowest score (Low+), or is chosen at random.
+5. Set Skip AI-only Play to determine if computer players complete a round in real-time after all human players are eliminated; turn on Skip AI-only Play to speed up games.
+6. Click 'Back' to apply your changes to the next game.
+
+Changing Game Physics
+1. Click 'Options' on the main menu, then click Physics on the Options menu.
+2. Increase or decrease Gravity to set the overall force of gravity; higher Gravity reduces the range of most weapons, especially projectile weapons like missiles. 
+3. Increase or decrease Viscosity to set the drag factor applied to projectile weapons like missiles; higher Viscosity reduces the range of all projectile weapons.
+4. Set Land Slide to determine if a weapon hitting the ground causes a landslide, as well as its severity.
+5. Click 'Back' twice to apply your changes to the next game.
+
+Changing Game Weather
+1. Click 'Options' on the main menu, then click 'Weather' on the Options menu.
+2. Set Meteor Showers to determine the probability and severity of meteor showers occurring at random during a game.
+3. Set Lightning to determine the probability and severity of lightning occurring at random during a game.
+4. Set Fog to limit the amount of landscape that a player can see around them.
+NOTE: This feature is currently under development.
+5. Set Max Wind Strength to determine how strong the wind can blow during a game.
+6. Set Wind Variation to limit how much the wind can change during a round.
+7. Click 'Back' twice to apply your changes to the next game.
+
+Changing Game Finances
+NOTE: Changing game finances can affect game play significantly. 
+1. Click 'Options' on the main menu, then click 'Money' on the Options menu.
+2. Set Starting Money to determine the amount each player (computer and human) gets to buy weapons at the start of a game.
+4. Set Interest Rate to change the interest rate applied to money saved between rounds.
+5. Change Round Win Bonus to set how much money a player gets per round win.
+6. Set Damage Bounty to determine how much money a player gets per point of opponent damage inflicted by the player.
+7. Set Self-Damage Penalty to determine how much money a player loses per point of self-inflicted damage (hitting yourself with a missile, for example).
+8. Change Tank Destruction Bonus to set how much a player gets per tank kill.
+9. Set Tank Self-Destruction Penalty to determine how much money a player loses for destroying their own tank.
+10. Click 'Back' twice to apply your changes to the next game.
+
+Managing and Customizing Game Players
+1. Click 'Players' on the main menu to show the Players menu. 
+2. Do one of the following: 
+-to create a new player, click `Create New' and then complete steps 3 to 5.
+-to customize a player, click their name and then complete any of the following steps.
+-to delete a player, click their name, then click `Delete This Player' and confirm the deletion.
+NOTE: You cannot restore a deleted player.
+3. Change Name to rename the player.
+4. Choose a color for the player from the color palette.
+5. Set Type to determine if a player is a human or a computer; computer players may be set to the following skill levels:
+-Useless (lowest skill level): rarely shoots anyone but itself
+-Guesser: lucky if it finds its target
+-Range Finder: finds its target about half of the time
+-Targetter: finds its target almost all of the time
+-Deadly (highest skill level): this tank shoots like Robbin Hood
+
+6. Click 'OK' to apply your changes to the next game.
+
+Changing Game Graphics
+NOTE: Changing game graphics may affect the time required to start a game or round.
+1. Click 'Options' on the main menu, then click 'Graphics' on the Options menu.
+2. Set Dithering to determine if graphics are dithered; turn on Dithering for better graphics.
+3. Set Detailed Land to determine the detail of the landscape; turn on Detailed Land for better graphics.
+4. Set Detailed Sky to determine the detail of background; turn on Detailed Sky for better graphics.
+5. Click 'Back' twice to apply your changes to the next game.
+--------------------------------------
+
+If you can't find the answer to your question here, at 
+http://atanks.sourceforge.net, email jessefrgsmith at yahoo.ca
+
+
diff --git a/text/Help_ES.txt b/text/Help_ES.txt
new file mode 100644
index 0000000..de28add
--- /dev/null
+++ b/text/Help_ES.txt
@@ -0,0 +1,112 @@
+Instrucciones para Atomic Tanks
+
+Contenidos:
+
+	Instrucciones B�sicas
+		Objetivos
+		Comenzando un juego
+		Jugando un juego
+
+	Personalizando el juego
+		Cambiando las caracter�sticas generales del juego
+		Cambiando f�sicas del juego
+		Cambiando tiempo del juego
+		Cambiando finanzas del juego
+		Dirigiendo y personalizando jugadores
+		Cambiando gr�ficos del juego
+
+-----------------------------
+Instrucciones B�sicas:
+
+Objetivos:
+Objetivo primario: Destruir los otros tanques del paisaje!
+Objetivo secundario: Actualizar tu tanque con mejores armas y equipamento usando dinero ganado por tanques destruidos.
+
+Iniciando un juego:
+1. Clic en 'Jugar' del men� principal.
+2. En Jugadores del men�, configurar las rondas, escoger jugadores (10 max.) y clic `Aceptar'.
+   Nota: Jugadores Humanos son marcados con circulo purpura. AI tanques son
+   indicados por barras verdes. Las dem�s barras, las inteligentes la AI.
+3. En armas del men�, comprar armas para tu tanque y clic `Hecho' para iniciar el juego.
+
+Jugando un juego:
+1. Presiona Tab para seleccionar un arma.
+2. Usa las teclas inzquierda/derecha para apuntar (llamado �ngulo).
+3. Usa las teclas arriba/abajo para definir el rango del arma (llamado Potencia).
+Debes chequear tambi�n la direcci�n del viento y fuerza arriba de la pantalla, como estos pueden afectar el �ngulo y potencia requerido para acertar a tu oponente. 
+Consejo: Presiona CTRL mientras usas una tecla para cambiar �ngulo o potencia m�s lento.
+4. Presiona espacio para disparar.
+El men� de armas reaparecen despu�s de cada ronda. Usa el dinero ganado durante la ronda para actualizar tu tanque, entonces haz clic en 'Hecho' para iniciar la pr�xima ronda. El ganador del juego es el jugador que gana m�s rondas.
+
+Personalizando el juego (para avanzados jugadores):
+Puedes personalizar Atomic Tanks para hacer el juego m�s estimulante. Lee lo siguiente para aprender como personalizarlo.
+
+Cambiando caracter�sticas generales del juego:
+1. Clic en 'Opciones' del men� principal para ver las opciones.
+2. Definir el Nivel para determinar las armas y equipar disponible para adquirir en la pantalla de armas; Altos niveles ofrecen una larga variedad de armas y equipamente.
+3. Definir paisaje para determinar el tipo en cada ronda jugada.
+4. Definir orden de turnos para determinar el orden por ronda de jugadores es definirda de acuerdo a la puntuaci�n m�s alta (High+), la menor puntuaci�n (Low+), o es escogida aleatoriamente.
+5. Definir saltos AI-solo Jugar para determinar si los jugadores de la computadora completan una ronda en tiempo-real despu�s de que los jugadores Humanos son eliminados; turno saltar AI-s�lo Jugar para acelerar juegos.
+6. Clic en 'Atr�s' para  aplicar cambios en el pr�ximo juego.
+
+Cambiando f�sicas del juego
+1. Clic en 'Opciones' del men� principal, entonces clic en F�sicas del menu Opciones.
+2. Aumentar o Disminuir la Gravedad para definir la fuerza total; alta gravedad reduce el rango de la mayor�a de armas, especialmente proyectiles como misiles. 
+3. Aumentar o disminuir Viscosidad para definir el factor arrastra 
+aplicado para proyectiles como misiles; alta viscosidad reduce el rango de proyectiles.
+4. Definir el desplazamiento de caida para determinar si una arma golpea las causas de corrimiento del suelo, como bien es severidad.
+5. Clic en 'Atr�s' dos veces para aplicar cambios en el pr�ximo juego.
+
+Cambiando tiempo del juego
+1. Clic en 'Opciones' del menu principal, entonces clic en 'Tiempo' de las opciones del menu.
+2. Definirt mostrador de Meteoros para determinar la probabilidad y severidad de meteoros aleatorios durante el juego.
+3. Configura Rel�mpagos para determinar la probabilidad y severidad de rel�mpagos ocurridos aleatoriamente durante el juego.
+4. Define Niebla para limitar la cantidad de paisajes que un jugador puede ver alrededor.
+NOTA: Esta caracter�stica est� actualmente bajo desarrollo.
+5. Configura Max fuerza de Viento para determinar cuan fuerte puede golpear el viento durante un juego.
+6. Configura la variaci�n del viento para limitar cu�nto el viento puede cambiar durante una ronda.
+7. Clic 'Atr�s' dos veces para aplicar los cambios en el pr�ximo juego.
+
+Cambiando Finanzas del juego
+NOTA: Cambiar las finanzas puede afectar significativamente el Juego. 
+1. Clic en 'Opciones' del menu principal, luego clic en 'Dinero' de las opciones del menu.
+2. Define Inicio de Dinero para determinar el monto de cada jugador (computador y humano) para comprar armas al comenzar un juego.
+4. Define el tipo de Interes para cambiar el tipo de interes aplicado al dinero guardado entre rondas.
+5. Cambia Bonus de ganador de Ronda para definir cuanto dinero puede conseguir por ronda un jugador ganador.
+6. Define gratificaci�n de Da�os para determinar cu�nto de dinero puede conseguir un jugador por punto de da�os a oponentes.
+7. Define Penalidad de Auto-Da�o para determinar cuanto de dinero pierde un jugador por punto de da�o Auto-Infligido (golpearte a t� mismo con un misil, por ejemplo).
+8. Cambiar Bonus de destrucci�n de Tanques para definir cu�nto consigue un jugador por tanque destruido.
+9. Define Penalidad de Auto-Destrucci�n de Tanques para determinar cuanto de dinero pierde un jugador por destruir su propio Tanque.
+10. Clic en 'Atr�s' dos veces para aplicar los cambios en el pr�ximo juego.
+
+Administrando y Personalizando Jugadores
+1. Clic en 'Jugadores' del menu principal para mostrar el menu de jugadores. 
+2. Hacer lo siguiente: 
+-para crear un nuevo jugador, clic en `Crear Nuevo' y luego completa los pasos 3 al 5.
+-para personalizar un jugador, clic en su nombre y luego completar cualquiera de los siguientes pasos.
+-para eliminar un jugadorr, clic en su nombre, luego clic en `Eliminar este Jugador' y confirma la eliminaci�n.
+NOTA: No puedes restaurar un jugador eliminado.
+3. Cambiar nombre para renombrar un jugador.
+4. Escoge un color para el jugador de la paleta de colores.
+5. Definir el Tipo para determinar si un jugador es Humano u Computador; Jugador de computadora pueden definir la habilidad de los siguientes niveles:
+-Inservible (mas bajo nivel de habilidad): raramente disparos de alguien pero aislado
+-Adivinador: suerte si encuentra el objetivo
+-Encontrador de Rango: encuentra el objetivo cerca de la mitad de tiempo
+-Apuntador: Encuentra el objetivo casi en todo el tiempo
+-Mortal (mas alta habilidad de nivel): este tanque dispara como Robbin Hood
+
+6. Clic en 'Aceptar' para aplicar los cambios en el proximo juego.
+
+Cambiando Gr�ficos del Juego
+NOTA: Cambiar los gr�ficos del juego pueden afectar el tiempo requerido para iniciar un juego o ronda.
+1. Clic en 'Opciones' del menu principal, luego clic en 'Graficos' del menu de opciones.
+2. Define vacilando para determinar si los gr�ficos son vacilados; activa Vacilando para mejores gr�ficos.
+3. Define Tierra Detallada para determinar el detalle del paisaje; activa Tierra Detallada para mejores gr�ficos.
+4. Define Cielo Detallado para determinar el detalle del fondo; activa detallado para mejores gr�ficos.
+5. Click en 'Atr�s' dos veces para aplicar los cambios al pr�ximo juego.
+--------------------------------------
+
+Si tu no puedes encontrar la respuesta aqu�, visita 
+http://atanks.sourceforge.net, email jessefrgsmith at yahoo.ca
+
+
diff --git a/text/Help_fr.txt b/text/Help_fr.txt
new file mode 100644
index 0000000..e21d534
--- /dev/null
+++ b/text/Help_fr.txt
@@ -0,0 +1,110 @@
+Atomic Tanks : instructions
+
+Sommaire :
+
+	Instructions de base
+		Objectifs
+		D�marrer un jeu
+		Comment jouer
+
+	Personnalisations du jeu
+		Modifier les caract�ristiques g�n�rales
+		Modifier les caract�ristiques physiques
+		Modifier la m�t�o du jeu
+		Modifier les finances
+		G�rer et modifier les joueurs
+		Caract�ristiques graphiques
+
+-----------------------------
+Instructions de base :
+
+Objectifs :
+Objectif basique : �liminer tous les autres tanks du paysage !
+Objectif secondaire : gagner de l'argent en d�truisant les autres tanks pour am�liorer votre tank avec de meilleures armes et �quipements.
+
+D�marrer un jeu :
+1. Cliquer 'jouer' dans le menu principal.
+2. Dans le menu 'joueurs', modifier le nombre de tours, choisir des joueurs (10 maxi.) et cliquer 'OK'.
+   Note : le joueur humain est marqu� d'un cercle violet. Les tanks g�r�s par l'ordinateur sont indiqu�s par une barre verte.    La taille de la barre refl�te l'intelligence des adversaires.
+3. Dans le menu 'armes', achetez des armes et cliquer 'termin�' pour d�marrer le jeu.
+
+Comment jouer :
+1. Appuyer sur Tabulation pour s�lectionner une arme.
+2. R�gler l'angle de tir par les touches gauche/droite.
+3. R�gler la port�e par les touches haut/bas (puissance du tir).
+Pensez � v�rifier la force et la direction du vent en haut de l'�cran, elles ont une influence sur l'angle et la puissance de tir n�cessaires � atteindre votre adversaire. 
+Astuce : la touche CTRL permet d'obtenir des r�glages plus fins lors de l'utilisation des touches de direction (angle, port�e)
+4. Pressez la touche Espace pour lancer l'arme.
+Le menu 'armes' r�appara�t � chaque tour de jeu. Utilisez l'argent gagn� pour am�liorer votre tank, puis cliquez 'Termin�' pour passer au tour suivant. Le vainqueur est le joueur qui a remport� le plus de jeux.
+
+Personnalisations du jeu (joueurs confirm�s) :
+Vous avez la possibilit� de personnaliser Atomic Tanks pour rendre le jeu plus int�ressant. Ce qui suit vous indique comment proc�der.
+
+Modification des caract�ristiques g�n�rales :
+1. Cliquer 'Options' dans le menu principal pour afficher les options du jeu.
+2. R�glez le niveau technique armes pour d�terminer les armes et �quipements disponibles dans l'�cran 'armes' ; les niveaux les plus hauts rendent disponibles une plus grande vari�t� d'armes et d'�quipements.
+3. Les options de paysage permettent de disposer d'autres types d'environnement � chaque tour.
+4. L'ordre de passage peut �tre r�gl� : le score le plus haut en premier (plus fort +), le plus bas (moins fort+), ou ordre al�atoire.
+5. La s�lection de 'Jeu IA seule' permet � l'Intelligence Artificielle (IA) de continuer � jouer en temps r�el une fois tous les joueurs humains �limin�s, alors que '�viter IA seule' acc�l�re le jeu.
+6. Le bouton 'Pr�c�dent' applique les modifications au prochain jeu.
+
+Modifier les caract�ristiques physiques :
+1. Cliquer 'Options' dans le menu principal, puis 'Physique' dans le menu 'Options'.
+2. Augmentez ou diminuez la force de gravit�. Une gravit� �lev�e r�duit la port� de la pluspart des armes, en particulier celle des projectiles de type missiles. 
+3. La viscosit� influence les frottements subis par les projectile de type missiles. Une viscosit� importante r�duit la port�e de tous les projectiles.
+4. Le facteur 'glissements de terrain' d�termine si le fait de toucher le sol cause un glissement de terrain, ainsi que l'importance de ce dernier.
+5. Le bouton 'Pr�c�dent' applique les modifications au prochain jeu.
+
+Modifier la m�t�o du jeu
+1. Cliquer 'Options' dans le menu principal, puis 'M�t�o' dans le menu 'Options'.
+2. 'Orages de m�t�orites' d�termine la probabilit� et l� s�v�rit� des orages de m�t�orites qui apparaissent al�atoirement au cours du jeu.
+3. '�clairs' fait de m�me en ce qui concerne les �clairs.
+4. 'Brouillard' permet de limiter l'environnement visible par les joueurs.
+NOTE : Cette caract�riqtique est encore � l'�tat de d�veloppement.
+5. 'Force maxi du vent' d�termine la force du vent qui pourra souffler au cours du jeu.
+6. 'Variation du vent' affecte les changements du vent au cours du jeu.
+7. Deux clics sur Le bouton 'Pr�c�dent' appliquent les modifications au prochain jeu.
+
+Modifier les finances
+NOTE: Modifier les finances peut fortement affecter le d�roulement d'une partie. 
+1. Cliquer 'Options' dans le menu principal, puis 'Finances' dans le menu 'Options'.
+2. 'Somme de d�part' sert � fixer le montant dont chaque joueur dispose en d�but de partie pour acheter ses armes.
+4. Le 'Taux d'int�r�t' est appliqu� � la somme restante entre les tours.
+5. 'Gains par victoire' d�termine le montant gagn� � chaque victoire.
+6. 'Bonus dommages' d�termine le montant gagn� � chaque point de dommages inflig� � l'adversaire.
+7. 'P�nalit� auto-dommages' d�termine le montant perdu � chaque point de dommages que vous vous infligez � vous-m�me (en vous touchant avec un de vos missiles par exemple).
+8. 'Bonus destruction tank' est le montant gagn� � chaque destruction de tank adverse.
+9. 'P�nalit� autodestruction tank' est le montant perdu � chaque destruction d'un de vos propres tanks par vous-m�me.
+10. Le bouton 'Pr�c�dent' applique les modifications au prochain jeu.
+
+G�rer et modifier les joueurs
+1. Cliquer 'Joueurs' dans le menu principal pour acc�der � ce qui suit.
+2. Vous pouvez... 
+-cr�er un nouveau joueur : cliquez 'cr�er nouveau', puis compl�ter les �tapes 3 � 5.
+-modifier un joueur : cliquez son nom, puis suivez les �tapes suivantes.
+-effacer un joueur : cliquez son nom, puis cliquez 'Effacer ce joueur' et confirmez l'effacement.
+NOTE: Vous ne pouvez pas restaurer un joueur d�truit.
+3. 'Renommer' sert � renommer un joueur (mais si !).
+4. S�lectionnez une couleur dans la palette pour l'affecter au joueur.
+5. 'Type' d�termine si le joueur est humain ou g�r� par l'IA (programme). 
+Les niveaux possibles pour les joueurs sont :
+-sous-dou� : (le plus bas !) : atteint rarement autre chose que lui-m�me
+-m�diocre : peut atteindre sa cible avec de la chance !
+-moyen : atteint sa cible la moiti� du temps
+-�lev� : atteint sa cible la pluspart du temps
+-mortel : (le plus haut) un vrai tireur d'�lite !
+6. Cliquez 'OK' pour appliquer les modifications � la prochaine partie.
+
+Caract�ristiques graphiques
+NOTE: Les modifications peuvent affecter la dur�e du d�marrage ou du changement de tour.
+1. Cliquer 'Options' dans le menu principal, puis 'Graphismes' dans le menu 'Options'.
+2. 'Tramage' : le tramage am�liore les graphismes.
+3. 'D�tails du terrain' : am�liore le sol.
+4. 'Ciel d�taill�' : am�liore les d�tails de l'arri�re-plan.
+5. Deux clics sur Le bouton 'Pr�c�dent' appliquent les modifications au prochain jeu.
+--------------------------------------
+
+Si vous ne pouvez trouver de r�ponses � vos questions, consultez le site (en Anglais)
+http://atanks.sourceforge.net, ou contactez par m�l (en Anglais) : jessefrgsmith at yahoo.ca
+
+
diff --git a/text/Help_it.txt b/text/Help_it.txt
new file mode 100644
index 0000000..1029544
--- /dev/null
+++ b/text/Help_it.txt
@@ -0,0 +1,112 @@
+Atomic Tanks : istruzioni
+
+Sommario :
+
+	Istruzioni di base
+		Obiettivi
+		Iniziare un Gioco
+		Come giocare
+
+	Personalizzazione del gioco
+		 les caract�ristiques g�n�rales
+		Modificare le caratteristiche fisiche
+		Modificare il meteo del gioco
+		Modificare le finaze
+		Gestire e Modificare i giocatori
+		Caratteristiche Grafiche
+
+-----------------------------
+Istruzioni di base :
+
+Obiettivi :
+Obiettivo Primario: Distruggere tutti i tank nel panorama!
+Obiettivo Secondario: Upgradare il vostro tank con le migliori armi ed equipaggiamenti usando il denaro preso dai tank uccisi.
+
+Partenza del Gioco:
+1. Cliccare 'Play' sul main menu.
+2. Sul menu 'Characters', settare la lunghezza dei round, scegliere i giocatori (10 max.) e cliccare `Ok'.
+   Note : I giocatori Human hanno dei cerchi viola, mentre i giocatori computer hanno delle barre verticali verdi; quante piu' barre sono indicate, tanto piu' bravi sono i giocatori.
+3. Sul menu 'Weapon', pagate le armi per il vostro tank e cliccate `Done' per iniziare a giocare.
+
+Giocare un Gioco:
+1. Premere Tab per selezionare un'arma.
+2. Usare i tasti con le frecce sinistra/destra per puntare le armi (chiamato Angolo).
+3. Usare i tasti con le frecce su/giu' per settare il range delle armi (chiamato Potenza).
+Voi potete anche controllare la direzione e la forza del vento nella parte superiore 
+dello schermo, poiche' essi possono avere effetto sull'Angolo e la Potenza di tiro. 
+TIP: Premere CTRL mentre si usa un tasto freccia per cambiare Angolo o Potenza piu' lentamente.
+4. Premere la Barra Spaziatrice per far fuoco con le armi.
+5. Se avete del Carburante, voi potete muovere il vostro tank usando i tasti < oppure >.
+Il Menu delle Armi riappare dopo ogni round.
+Usare il denaro guadagnato durante il round per upgradare il vostro tank, quindi cliccare 'Done' per iniziare il round.
+Il vincitore del gioco e' quello che vince piu' round.
+
+Personnalizzazione del gioco (Conferma giocatori) :
+Voi avete la possibilita' di personalizzare Atomic Tanks per rendere il gioco piu' interessante. Quanto segue vi indica come procedere.
+
+Modifica delle caratteristiche generali :
+1. Cliccare 'Opzions' nel menu principale per visualizzare le Opzioni del gioco.
+2. Regolare il 'Tech Level' delle armi per determinare le armi e gli equipaggiamenti disponibili nello schermo 'armi' ; i livelli piu' alti rendono disponibili una maggior variet� di armi.
+3. Le Opzioni 'Landscape' permettono di disporre d'altri tipi d'ambiente ad ogni round.
+4. Il 'Turn Order' determina se l'ordine del giocatore per round � dato dal punteggio piu' alto (High+), dal punteggio piu' basso (Low+), o in ordine aleatorio.
+5. Selezionare 'Skip AI-only Play' permette all'Intelligenza Artificiale (IA) di continuare a giocare anche quando tutti i giocatori umani sono stati eliminati; mettere ad on 'Skip AI-only Play' per accellerare il gioco.
+6. Cliccare 'Back' per applicare le modifiche al prossimo gioco.
+
+Modificare le caratteristiche fisiche :
+1. Cliccare 'Opzions' nel menu principal, poi 'Physics' nel menu 'Opzions'.
+2. Aumentate o diminuute la forza di gravita'. Una gravita' elevata riduce la portata delle armi balitiche (missili). 
+3. La viscosita' influenza lo sfregamento subito dai missili nell'aria. Una viscosita' importante riduce la portata di tutti i proietti.
+4. Settare 'Land Slide' determina se il fatto di toccare il suolo causa uno scivolamento del terreno.
+5. Cliccare 'Back' due volte per applicare le modifiche al prossimo gioco.
+
+Modificare il meteo del gioco
+1. Cliccare 'Opzions' nel menu principale, poi 'Weather' nel menu 'Opzions'.
+2. Settare 'Meteor Showers' determina la probabilita' e la potenza di pioggia di meteoriti che appariranno aleatoriamente nel corso del gioco.
+3. Settare 'Lightning' fa lo stesso per quello che concerne i fulmini.
+4. Settare 'Fog' permette di limitare la visibilita' tra giocatori.
+NOTA : Questa caratteristica e' ancora in fase di sviluppo.
+5. Settare 'Max Wind Strength' determina la forza del vento che soffia durante il gioco.
+6. Settare 'Wind Variation' permette di fissare i limiti di variazione del vento durante il gioco.
+7. Doppio clic sul tasto 'Back' per applicare le modifiche al prossimo gioco.
+
+Modificare le finanze
+NOTA: Modificare le finanze puo' fortemente variare lo svolgimento del gioco. 
+1. Cliccare 'Opzions' nel menu principale, poi 'Money' nel menu 'Opzions'.
+2. Settare 'Starting Money' serve a fissare il montante che ogni giocatore (computer o umano) dispone all'inizio del gioco per comprare le sue armi.
+4. Settare 'Interest Rate' per determinare quale rateo e' applicato al denaro salvato ad ogni round.
+5. Cambiare 'Round Win Bonus' determina il montante guadagnato ad ogni vittoria.
+6. Settare 'Damage Bounty' determina il montante guadagnato ad ogni distruzione inflitta all'avversario.
+7. Settare 'Self-Damage Penalty' determina il montante perso ad ogni distruzione che voi infliggete a voi stessi.
+8. Cambiare 'Tank Destruction Bonus' e' il montante guadagnato ad ogni distruzione di tank avversario.
+9. Settare 'Tank Self-Destruction Penalty' e' il montante perso ad ogni distruzione di uno dei vostri tank da parte di voi stessi.
+10. Cliccare 'Back' per applicare le modifiche al prossimo gioco.
+
+Gestire e Modificare i giocatori
+1. Cliccare 'Players' nel menu principal per accedere a quanto segue.
+2. Voi potete... 
+-creare un nuovo giocatore : cliccare 'Create New', poi completare i passi da 3 a 5.
+-modificare un giocatore : cliccare il suo nome, poi completare i passi seguenti.
+-cancellare un giocatore : cliccare il suo nome, poi cliccare 'Delete This Player' e confermare la cancellazione.
+NOTA: Voi non potete recuperare un giocatore cancellato.
+3. 'Change Name' serve a rinominare un giocatore (ma va' ?).
+4. Selezionare un colore nella palette per assegnarla al giocatore.
+5. Settare 'Type' per determinare se il giocatore e' umano o gestito dall'IA (programma). 
+I livelli possibili per i giocatori sono :
+-sotto-dotato (Useless) : (il piu' basso !) : raramente uccide qualcuno, a parte se stesso
+-mediocre (Guesser) : puo' colpire fortunosamente qualcuno !
+-medio (Range Finder) : colpisce il suo obiettivo per meta' delle volte
+-elevato (Targetter) : colpisce il suo obiettivo la maggior parte delle volte
+-mortale (Deadly) : (il piu' alto !) colpisce il suo obiettivo quasi sempre, come Robin Hood
+
+Caratteristiche Grafiche:
+NOTE: Le modifiche possono rallentare la partenza del gioco o del cambio di round.
+1. Cliccare 'Options' nel menu principale, poi 'Grafica' nel menu 'Options'.
+2. 'Dithering' : Dithering ON migliora la grafica.
+3. 'Detailed Land' : migliora il suolo.
+4. 'Detailed Sky' : migliora i dettagli dello sfondo.
+5. Doppio clic sul tasto 'Back' per applicare le modifiche al prossimo gioco.
+
+--------------------------------------
+
+Se non potete trovare delle risposte alle vostre domande, consultate il sito (in Inglese)
+http://atanks.sourceforge.net, o contattatemi per mail (in Inglese) : jessefrgsmith at yahoo.ca
diff --git a/text/Help_ru.txt b/text/Help_ru.txt
new file mode 100644
index 0000000..a7ca9ce
--- /dev/null
+++ b/text/Help_ru.txt
@@ -0,0 +1,127 @@
+Atomic Tanks: Описание
+
+
+Оглавление:
+
+Базовый инструктаж
+  Задачи
+  Как начать игру
+  Как играть
+
+Настройки в игре
+  Изменяем базовые характеристики
+  Изменяем физику игры
+  Изменяем настройки погоды
+  Изменяем экономику игры
+  Изменяем настройки графики
+  Редактируем игроков
+
+-----------------------------
+Базовый инструктаж
+
+Задачи:
+Первичное задание: уничтожить все вражеские танки на поле боя, уцелев самому!
+Вторичное задание: заработать на этом побольше денег и усилить свой танк, закупившись оружием и дополнительным снаряжением.
+
+Как начать игру:
+1. Щёлкнуть по кнопке "Играть" в главном меню;
+2. В меню "игроки" выставить нужное количество раундов, выбрать танки для игры (до 10 боевых единиц включительно) и щёлкнуть по кнопке "ОК".
+3. Откроется меню "Вооружение". Закупитесь оружием перед первым раундом и нажмите "Готово", чтобы начать игру!
+
+    На заметку: танк, управляемый игроком, отмечен фиолетовым кружком. Танки под управлением компьютера отмечены зелёными полосами. Чем больше зелёных полос, тем сложнее будет победить этот танк.
+
+
+Как играть:
+1. Чтобы сменить тип оружия, которым вы будете стрелять, нажмите Z или C (в русской раскладке "Я" и "С").
+2. Стрелки влево-вправо изменяют угол стрельбы. Стрелки вверх-вниз меняют силу выстрела.
+Не забывайте следить за мощностью ветра на поле боя! Указатель силы ветра находится в верху экрана (зелёная или красная полоса под надписью "Ветер"). Чем сильнее полоса вытянута влево или вправо, тем сильнее ветер будет сносить ваши ракеты в сторону!
+
+    На заметку: используйте Ctrl+(клавиши-стрелки) для тонкой настройки силы и угла удара.
+3. Клавиши "<" и ">" ("Б" и "Ю") позволяют танку передвигаться
+влево и вправо, если у вас есть достаточно топлива.
+4. Чтобы выстрелить, нажмите Пробел.
+
+
+После каждого раунда появляется меню "Вооружение". В нём вы можете потратить деньги, заработанные в бою, на оружие или снаряжение. Для этого курсором щёлкните на те товары, которые хотите купить. Правая кнопка мыши продаёт уже купленное или отменяет покупку. После того, как вы закупились оружием, нажмите "Готово", чтобы начать следующий раунд!
+
+В игре побеждает тот, кто выиграл больше всего раундов.
+
+
+Настройки в игре:
+
+Кнопка "Опции", как вы уже догадались, открывает меню настроек игры.
+
+Изменяем базовые характеристики:
+1. Пункты "Уровень оружия" и "Уровень снаряжения" определяют, насколько мощное оружие или снаряжение может приобрести игрок или компьютер перед каждым новым раундом. Полезно для тех, кто считает атомные ракеты нечестными.
+2. Настройки ландшафта определяют, на какой местности будет проводиться игра.
+3. Настройки порядка хода определяют, кто будет стрелять раньше - игроки с большим количеством очков (Сильные +), игроки с меньшим количеством очков (Слабые +), случайный танк (Случайно) или все танки одновременно (Все сразу).
+4. Настройка "Пропускать игру компьютеров" позволяет пропустить перестрелку танков компьютера, если на поле боя не осталось танков игрока. Если эта опция выключена, танки будут продолжать перестрелку как обычно в любом случае.
+5. Кнопка "Назад" сохраняет изменения и открывает главное меню.
+
+Изменяем физику игры:
+Чтобы изменить настройки физики в игре, щёлкните по кнопке "Опции" и выберите пункт "Физика".
+1. Пункт "Гравитация" изменяет силу тяжести в игре. Эта настройка влияет на все снаряды и ракеты, которыми вооружены танки.
+2. Пункт "Сила трения" определяет трение воздуха о снаряды. Чем выше этот параметр, тем труднее будут лететь в воздухе ракеты и снаряды.
+3. Пункт "Падение земли" определяет, будет ли опускаться ландшафт, если под ним образовалась воронка, и как именно он будет опускаться.
+
+Изменяем настройки погоды
+1. Опция "Метеоритный дождь" определяет, будут ли во время раунда падать на землю метеориты и другие космические объекты, и смогут ли они уничтожить треть ландшафта с пары попаданий.
+2. Опция "Молнии" определяет вероятность появления молний, которые будут бить по ландшафту, и силу ударов молнии.
+3. Опция "Туман" ограничивает пространство, на котором игрок может что-либо внятно рассмотреть.
+  ПРЕДУПРЕЖДЕНИЕ: опция "Туман" находится в разработке.
+4. Настройка "Макс. сила ветра" определяет, насколько сильно на поле боя будет дуть ветер.
+5. Настройка "Изменения силы ветра" определяет, насколько сильно ветер будет меняться каждый ход.
+
+Изменяем экономику игры
+ВНИМАНИЕ: изменение этих настроек может СИЛЬНО повлиять на ход игры.
+1. Опция "Начальные деньги" определяет, сколько денег у вас будет перед началом первого раунда игры.
+2. Опция "Банковский процент" определяет, как будет увеличиваться ваша сумма денег на счету. Помимо денег за победу и успешные попадания, вы будете получать дополнительные проценты с суммы на вашем счету каждый раунд.
+Пример: у вас на счету осталось $10000, банковский процент выставлен на значение "1.25". Даже если вы проиграли следующий раунд, сумма на вашем счету увеличится на 25% и составит $12500 (10000 * 1.25).
+3. Опция "Бонус за победу" определяет награду за победу в раунде.
+4. Опция "Бонус за попадание" определяет размер награды за каждую единицу повреждений, нанесённых любому танку оппонента.
+5. Опция "Штраф за попадание в себя" определяет сумму, которая будет списываться с вашего счёта за каждое очко повреждения, которое вы нанесли самому себе (к примеру, попав в свой танк ракетой).
+6. Опция "Бонус за уничтожение" определяет размер награды за каждый уничтоженный вражеский танк.
+7. Опция "Штраф за самоуничтожение" определяет размер штрафа за уничтожение собственного танка.
+8. Опция "Коэфф. продажи снаряжения" определяет, по какой цене можно будет продать уже купленные боеприпасы или улучшения.
+
+
+Изменяем настройки графики
+  ВНИМАНИЕ: эти настройки могут повлиять на скорость загрузки игры и смены раунда.
+Опция "Сглаживание" улучшает внешний вид игры.
+Настройки "Детализированное небо", "Детализированный ландшафт" и другие отвечают за внешний вид игры во время раунда. Настройка "Цветовая тема" определяет стиль прорисовки сражения.
+Опция "Курсор в игре" позволяет заменить традиционный курсор вашей операционной системы собственным курсором игры.
+Опция "Скорость игры" отвечает за то, как быстро будут стрелять танки, летать снаряды и т.д.
+Опция "Собственный фон" позволяет использовать в игре фон, установленный игроком.
+  Фон должен быть в формате BMP (точечный рисунок) и иметь тот же размер, что и окно игры (по умолчанию 800*600 пикселей). Картинку нужно поместить в папку, в которой находится файл "atanks-config" (по умолчанию это папка ".atanks").
+
+
+Редактируем игроков
+Нажмите на кнопку "Игроки" в главном меню, чтобы открыть соответствующее меню.
+В нём можно:
+
+- создавать новых игроков: нажмите "Создать нового";
+- редактировать игроков: щёлкните по имени нужного игрока;
+- удалять игроков: щёлкните по имени нужного игрока и выберите пункт "Удалить игрока".
+  ВНИМАНИЕ: удалённого игрока восстановить нельзя! Цените своих бойцов.
+
+
+При создании или редактировании данных об игроке открывается его личное меню.
+Чтобы переименовать игрока, щёлкните по полю с его именем, внесите нужные изменения и нажмите "Enter".
+Чтобы изменить цвет, присвоенный игроку, щёлкните по нужному оттенку в радужной полоске.
+Опция "Тип" определяет, кто управляет этим игроком (сам игрок или компьютер), а также поведение и интеллект игрока-компьютера.
+
+   Типы искусственного интеллекта:
+-Ноль: самый слабый ИИ. Вряд ли попадёт в кого-нибудь, кроме себя.
+-Слабый: ИИ начальной стадии. При достаточном везении может быстро уничтожить вражеский танк.
+-Средний: ИИ среднего уровня. С этим врагом уже стоит считаться.
+-Сильный: Улучшенный ИИ. Способен попадать во врага почти всегда.
+-Терминатор: Этот уровень ИИ был специально создан для уничтожения вышедших из-под контроля танков с ИИ. Фиг сбежишь.
+--------------------------------------
+
+Не можете найти ответа на свой вопрос?
+Посетите http://atanks.sourceforge.net (английский)
+или отправьте e-mail по адресу: jessefrgsmith at yahoo.ca (английский)
+                             или myothehedgefox at gmail.com (русский)
+
+
+
diff --git a/text/Help_sk.txt b/text/Help_sk.txt
new file mode 100644
index 0000000..b606243
--- /dev/null
+++ b/text/Help_sk.txt
@@ -0,0 +1,110 @@
+Manuál k Atomic Tanks
+
+Obsah:
+
+	Zakladné inštrukcie
+		Ciele
+		Spustenie hry
+		Priebeh hry
+
+	Úprava hry
+		Zmena všeobecných herných charakteristík
+		Zmena fyziky
+		Zmena počasia
+		Zmena financovania
+		Správa a úprava hráčov
+		Zmena grafiky v hre
+
+-----------------------------
+Základné inštrukcie:
+
+Ciele:
+Primárny cieľ: Zničiť všetky okolité tanky v krajinke!
+Sekundárny cieľ: Vylepšiť tank dokupením lepších zbraní a vybavenia s využitím peňazí získaných za zničené tanky.
+
+Spustenie hry:
+1. V hlavnom menu kliknite na tlačidlo 'Play'
+2. V menu pre výber hráčov nastavte počet kôl, vyberte hráčov (max. 10) a kliknite na `Okay'.
+   Poznámka: Hráči ovládaní človekom sú označení fialovým kruhom. Počítačoví hráči sú
+   označení zelenými paličkami. Čím viac paličiek, tým lepšiu majú umelú inteligenciu.
+3. V menu pre výber zbraní si zakúpte zbrane pre váš tank a kliknite na `Done'. Tým hru spustíte.
+
+Priebeh hry:
+1. Stlačte Tab pre výber zbrane.
+2. Použite pravé/ľavé kurzorové šípky na mierenie (uhol)
+3. Použite kurzorové šipky hore/dole na nastavenie dosahu zbrane (sila)
+Na vrchu obrazovky by ste mali kontrolovať smer a silu vetra, pretože tieto dva faktory môžu ovplyvniť uhol a silu potrebnú na zasiahnutie súpera.
+
+TIP: Stlačte CTRL počas stlačenia kurzorových kláves na jemnejšiu zmenu uhla alebo sily.
+4. Stlačte medzerník pre vypustenie zbrane.
+Menu s výberom zbraní sa objaví po každom kole. Použite peniaze získané počas kola na vylepšenie vášho tanku, potom kliknite na 'Done' a spustite ďalšie kolo. Výťazom je ten hráč, ktorý vyhrá väčšinu kôl.
+
+Úprava hry (pre pokročilých hráčov):
+Atomic Tanks môžete upraviť tak, aby bola hra náročnejšia. Nasledujúci text popisuje, ako možno hru upraviť.
+
+Zmena všeobecných herných charakteristík:
+1. V hlavnom menu kliknite na 'Options' a zobrazí sa menu s voľbami.
+2. Tech Level určuje zbrane a výbavu, ktorá sa dá zakúpiť v menu s výberom zbraní; vyššie Tech Levely ponúkajú vyššiu rozmanitosť zbraní a vybavenia.
+3. Landscape určuje typ krajinky, na ktorej sa odohráva každé kolo.
+4. Turn Order určuje, či je poradie hráčov pri začiatku každého kola určené najvyšším skóre (High+), najnižším skóre (Low+) alebo je stanovené náhodne.
+5. Skip AI-only Play určuje, či počítačoví hráči dokončia kolo v reálnom čase po tom, ako sú všetci ľudskí hráči eliminovaní; zapnite túto voľbu, ak chcete urýchliť hru.
+6. Kliknite na 'Back' pre použitie vašich zmien v ďalšej hre.
+
+Zmena fyziky
+1. V hlavnom menu kliknite na 'Options', potom kliknite na Physics.
+2. Zväčšite alebo zmenšite hodnotu Gravity a tým zmeňte celkovú silu gravitácie; väčšia gravitácia znižuje dosah väčšiny zbraní, predovšetkým zbraní s projektilom ako sú strely.
+3. Zväčšite alebo zmenšite hodnotu Viscosity a tým zmeňte faktor odporu pre zbrane s projektilom ako sú napr. strely; vyššia viskozita zmenšuje dosah všetkých zbraní s projektilom.
+4. Nastavením Land Slide určíte, či má zbraň, ktorá narazí do zeme spôsobiť zosun pôdy a jeho rozsah.
+5. Kliknite na 'Back' pre použitie vašich zmien v ďalšej hre.
+
+Zmena počasia
+1. V hlavnom menu kliknite na 'Options', potom kliknite na 'Weather'.
+2. Nastavenie Meteor Showers určuje pravdepodobnosť a škodu spôsobenú meteoritovými prehánkami, ktoré sa vyskytujú náhodne počas hry.
+3. Nastavenie Lightning určuje pravdepodobnosť a škodu spôsobenú bleskami, ktoré sa vyskytujú náhodne počas hry.
+4. Nastavenie Fog určuje množstvo krajiny, ktoré vidí hráč okolo seba.
+POZNÁMKA: Táto vlastnosť je momentálne vo vývoji.
+5. Nastavenie Max Wind Strength určuje aký silný vietor môže počas hry fúkať.
+6. Nastavenie Wind Variation stanovuje mieru, s akou sa môže vietor meniť počas kola.
+7. Kliknite na 'Back' pre použitie vašich zmien v ďalšej hre.
+
+Zmena financovania
+POZNÁMKA: Zmena financovania v hre môže významne ovplyvniť hru.
+1. V hlavnom menu kliknite na 'Options', potom kliknite na 'Money'.
+2. Starting Money určuje množstvo peňazí, ktoré každý (počítačový aj ľudský) hráč dostane na nákup zbraní na začiatku hry.
+3. Interest rate mení úrokovú mieru použitú na peniaze, ktoré hráč usporil medzi kolami.
+4. Change Round Win Bonus určuje to, koľko peňazí dostane hráč pri vyhraní kola.
+5. Nastavenie Damage Bounty určuje koľko peňazí dostane hráč za každý bod, ktorý súperovi vzal.
+6. Self-Damage Penalty určuje koľko peňazí hráč stráca pri každom stratenom bode, ak si spôsobil vlastnú škodu (napr. zásahom vlastnej strely).
+7. Tank Destruction Bonus určuje koľko dostane hráč za zničenie jednoho tanku.
+8. Tank Self-Destruction Penalty určuje koľko peňazí hráč stráca, ak si zničí vlastný tank.
+9. Kliknite na 'Back' pre použitie vašich zmien v ďalšej hre.
+
+Správa a úprava hráčov
+1. V hlavnom menu kliknite na 'Players' pre zobrazenie menu s výberom hráčov.
+2. Vyberte jednu z nasledujúcich možností:
+- pre vytvorenie nového hráča kliknite na `Create New' a potom pokračujte krokmi 3 až 5.
+- pre úpravu hráča kliknite na jeho meno a potom pokračujte ktorýmkoľvek z nasledujúcich bodov.
+- pre vymazanie hráča kliknite na jeho meno, potom kliknite na `Delete This Player' a potvrďte vymazanie.
+POZNÁMKA: Vymazaného hráča nemôžete obnoviť.
+3. Kliknutím na Change Name premenujete hráča.
+4. Kliknutím na farebnú paletu môžete zmeniť farbu hráča.
+5. Nastavením Type určíte, či má za hráča hrať človek alebo počítač; počítačom ovládaným hráčom môžete vybrať jeden z nasledujucich levelov:
+- Slepúch (najnižší level): málokedy zasiahne iného než seba
+- Tipovač: je šťastný, ak nájde cieľ
+- Junior: nájde cieľ zhruba v jednom z dvoch prípadov
+- Ostreľovač: nájde cieľ takmer vždy
+- Profík (najvyšší level): tento tank strieľa ako Robin Hood
+
+6. Kliknite na 'OK' pre použitie vašich zmien v ďalšej hre.
+
+Zmena grafiky
+POZNÁMKA: Zmena grafiky v hre môže ovplyvniť čas potrebný na spustenie hry alebo kola.
+1. V hlavnom menu kliknite na 'Options', potom kliknite na 'Graphics'.
+2. Nastavením Dithering určíte, či má grafika používať dithering; zapnite túto voľbu pre krajšiu grafiku.
+3. Nastavenie Detailed Land určuje detaily krajinky; zapnite túto voľbu pre krajšiu grafiku.
+4. Nastavenie Detailed Sky určuje detaily pozadia; zapnite túto voľbu pre krajšiu grafiku.
+5. Kliknite dvakrát na 'Back' pre použitie vašich zmien v ďalšej hre.
+--------------------------------------
+
+Ak ste nenašli odpoveď na svoju otázku tu, na
+http://atanks.sourceforge.net, pošlite e-mail na jessefrgsmith at yahoo.ca
diff --git a/text/gloat.pt_BR.txt b/text/gloat.pt_BR.txt
new file mode 100644
index 0000000..27f132c
--- /dev/null
+++ b/text/gloat.pt_BR.txt
@@ -0,0 +1,5 @@
+Ha, ha
+Ajoelhe-se perante mim
+Toma isto!
+Eu sou demais
+Uahahahaha
\ No newline at end of file
diff --git a/text/gloat.txt b/text/gloat.txt
new file mode 100644
index 0000000..a3f8726
--- /dev/null
+++ b/text/gloat.txt
@@ -0,0 +1,17 @@
+Ha, ha
+You will kneel before me
+Take that!
+I'm too sexy for this tank
+Wohahaha
+That's gotta hurt
+Sucker!
+open wide
+I pity tha foo
+w00t
+That wasn't pretty
+Hasta la vista, baby!
+Worship me
+You may address me as Your Highness
+I am master of all I survey
+Better luck next time. NOT!
+Burn baby! Burn!
diff --git a/text/gloat_ES.txt b/text/gloat_ES.txt
new file mode 100644
index 0000000..305cf58
--- /dev/null
+++ b/text/gloat_ES.txt
@@ -0,0 +1,17 @@
+Ha, ha
+Te arrodillar�s ante mi
+Toma esto!
+Soy demasiado sexy para este tanque
+Wohahaha
+Eso te doler�
+Perro!
+abierto ancho
+I pity tha foo
+w00t
+Eso no fu� lindo
+Hasta la vista, baby!
+Adorame
+Puedes dirigirte a mi como tu Superior
+Soy el maestro de todo Soy experto
+Mejor suerte la pr�xima vez. NO!
+Arde baby! ARDE!
diff --git a/text/gloat_de.txt b/text/gloat_de.txt
new file mode 100644
index 0000000..02cb3af
--- /dev/null
+++ b/text/gloat_de.txt
@@ -0,0 +1,18 @@
+Ha, ha
+Knie nieder!
+Nimm das!
+Ich bin sooo guuut!
+Wohahaha
+Das schmerzt, nicht wahr?
+Verlierer!
+Öffne dich für die Macht!
+Der Dummkopf tut mir leid!
+w00t
+Das war nicht schön...
+Hasta la vista, baby!
+Verehre mich!
+Du darfst mich mit Hoheit anreden
+Ich bin der Herr über euch!
+Mehr Glück nächstes Mal...NICHT!
+Burn baby! BURN!
+The roof, the roof, the roof is on fire...
diff --git a/text/gloat_fr.txt b/text/gloat_fr.txt
new file mode 100644
index 0000000..ab13e0c
--- /dev/null
+++ b/text/gloat_fr.txt
@@ -0,0 +1,15 @@
+Ha, ha
+A genoux devant moi !
+Prends �a !
+Je suis trop sexy pour ce tank...
+Ouahhhhhh
+�a fait mal !
+Enfoir� !
+Grand ouvert
+Je plains ce gars !
+w00t
+C'�tait pas terrible !
+Hasta la vista, baby !
+Adorez-moi !
+Appelez-moi votre hauteur !
+Je suis le ma�tre de tout ce que je vois...
diff --git a/text/gloat_it.txt b/text/gloat_it.txt
new file mode 100644
index 0000000..57c9dd4
--- /dev/null
+++ b/text/gloat_it.txt
@@ -0,0 +1,17 @@
+Ha, ha
+In ginocchio davanti a me !
+Prendi questo!
+Sono troppo sexi per questo tank
+Uuhahaha
+Questo fa male!
+Cane!
+grandi spazi
+Piango per questi ragazzi
+w00t
+Questo non e' bello
+Hasta la vista, ragazzo!
+Adoratemi !
+Rivolgetevi a me come Sua Maesta'
+Io sono il padrone di ogni cosa e persona !
+Miglior fortuna la prossima volta. NO!
+Brucia ragazzo! Brucia!
diff --git a/text/gloat_ru.txt b/text/gloat_ru.txt
new file mode 100644
index 0000000..bf90c85
--- /dev/null
+++ b/text/gloat_ru.txt
@@ -0,0 +1,17 @@
+Ха, ха, ха.
+Склонись передо мной!!!
+Вот тебе получай!
+Надо взять танк получше. Я слишком хорош для своего.
+Мухахаха!
+Должно быть, было больно.
+Салага!
+В яблочко!!
+Мне его даже жаль...
+Ы! Эт надо отметить...
+Мог бы и получше попасть, к слову...
+До следующего раунда!
+Ну и кто теперь царь горы?
+Зови меня просто: мой Генерал. Мухахаха!
+Сегодня явно мой день.
+Прикупи оружие получше. Если деньги будут...
+Зажигаем!
diff --git a/text/gloat_sk.txt b/text/gloat_sk.txt
new file mode 100644
index 0000000..635be9d
--- /dev/null
+++ b/text/gloat_sk.txt
@@ -0,0 +1,16 @@
+Ha, ha
+Poklaknes predo mnou
+Tu mas!
+Som prilis sexy na tento tank
+Buhehe
+To musi boliet
+Cucak!
+rozotriet
+Je mi luto tej potravy
+Fuuu
+To nebolo pekne
+Asta la vista, bejby!
+Uctievaj ma
+Oslovuj ma Vasa Vysost
+Som skvely vo vsetkom, na co siahnem
+Vela stastia nabuduce. April!
diff --git a/text/ingame.pt_BR.txt b/text/ingame.pt_BR.txt
new file mode 100644
index 0000000..f693193
--- /dev/null
+++ b/text/ingame.pt_BR.txt
@@ -0,0 +1,83 @@
+Select Players
+Rounds
+New Game Name
+or Load Game
+Load Game
+Campaign
+Okay
+Voltar
+You must select at least 2 players
+You can only have up to 10 players
+Player
+Money
+Round
+Score
+Press F10 to save your current game.
+Use the up and down arrows to scroll
+through the item list.
+Saved game
+Ângulo:
+Power:
+Team
+Fuel
+Wind:
+Return
+Main Menu
+Quit
+Skip AI
+Players
+Create New
+Name
+Colour
+Type
+Generate Pref
+Played
+Won
+Tank Type
+Delete This Player
+A new version
+is ready for download.
+Could not find a game by that name.
+Qty. in inventory
+Failed to save game.
+Choosing colours
+Rendering Sky
+Rendering Landscape
+Winner: Jedi
+Winner: Sith
+Winner
+Draw
+              Player Scores                   Kill:Die
+Player Scores
+Accelerated AI
+Your Name
+unnamed
+Human
+Useless
+Guesser
+Range
+Targetter
+Deadly
+Per Game
+Only Once
+Normal
+Classic
+Big Grey
+T34
+Sith
+Neutral
+Jedi
+Return
+Main Menu
+Quit
+Skip AI
+Heavy
+Future
+UFO
+Spider
+Server version did not match client version.
+Server screen size does not match ours.
+Client has become disconnected from the server.
+The server is full or the game has not started.
+The server closed our connection.
+The game is finished.
diff --git a/text/ingame.txt b/text/ingame.txt
new file mode 100644
index 0000000..20090b3
--- /dev/null
+++ b/text/ingame.txt
@@ -0,0 +1,83 @@
+Select Players
+Rounds
+New Game Name
+or Load Game
+Load Game
+Campaign
+Okay
+Back
+You must select at least 2 players
+You can only have up to 10 players
+Player
+Money
+Round
+Score
+Press F10 to save your current game.
+Use the up and down arrows to scroll
+through the item list.
+Saved game
+Angle:
+Power:
+Team
+Fuel
+Wind:
+Return
+Main Menu
+Quit
+Skip AI
+Players
+Create New
+Name
+Colour
+Type
+Generate Pref
+Played
+Won
+Tank Type
+Delete This Player
+A new version
+is ready for download.
+Could not find a game by that name.
+Qty. in inventory
+Failed to save game.
+Choosing colours
+Rendering Sky
+Rendering Landscape
+Winner: Jedi
+Winner: Sith
+Winner
+Draw
+              Player Scores                   Kill:Die
+Player Scores
+Accelerated AI
+Your Name
+unnamed
+Human
+Useless
+Guesser
+Range
+Targetter
+Deadly
+Per Game
+Only Once
+Normal
+Classic
+Big Grey
+T34
+Sith
+Neutral
+Jedi
+Return
+Main Menu
+Quit
+Skip AI
+Heavy
+Future
+UFO
+Spider
+Server version did not match client version.
+Server screen size does not match ours.
+Client has become disconnected from the server.
+The server is full or the game has not started.
+The server closed our connection.
+The game is finished.
diff --git a/text/ingame_ES.txt b/text/ingame_ES.txt
new file mode 100644
index 0000000..ebdcc40
--- /dev/null
+++ b/text/ingame_ES.txt
@@ -0,0 +1,81 @@
+Seleccionar jugadores
+Rondas
+Nuevo nombre de juego
+o cargar Juego
+Cargar Juego
+Campa�a
+Acpetar
+Atr�s
+Debes seleccionar al menos dos jugadores
+Puedes solo tener arriba de 10 jugadores
+Jugador
+Dinero
+Ronda
+Puntuaci�n
+Presiona F10 para guardar el juego actual.
+Usa las teclas de arriba y abajo para deslizarte
+a trav�s de la lista de art�culos.
+Juego guardado
+�ngulo:
+Potencia:
+Equipo
+Combustible
+Viento:
+Retornar
+Menu principal
+Salir
+Saltar AI
+Jugadores
+Crear Nuevo
+Nombre
+Color
+Tipo
+Generar Pref
+Jugado
+Ganaste
+Tipo de Tanque
+Eliminar este jugador
+Una nueva versi�n
+est� disponible para descargar.
+No se puede encontrar un juego con ese nombre.
+Qty. en inventario
+Guardar juego fallado.
+Escogiendo colores
+Mostrando Cielo
+Mostrando Paisaje
+Ganador: Jedi
+Ganador: Sith
+Ganador
+Draw
+              Puntuaci�n Jugador                  Matar:Morir
+Puntuaci�n jugador
+Acelerado AI
+Tu nombre
+sin nombre
+Humano
+Inservible
+Guesser
+Rango
+Targetter
+Mortal
+Por Juego
+Solo una vez
+Normal
+Clasico
+Big Grey
+T34
+Sith
+Neutral
+Jedi
+Retornar
+Menu Principal
+Salir
+Saltar AI
+Pesado
+Futuro
+UFO
+Ara�a
+Versi�n servidor no coincide cliente versi�n.
+Tama�o de pantalla Servidor no coincide con la nuestra.
+Cliente ha sido desconectado desde el servidor.
+
diff --git a/text/ingame_de.txt b/text/ingame_de.txt
new file mode 100644
index 0000000..b2e84c7
--- /dev/null
+++ b/text/ingame_de.txt
@@ -0,0 +1,83 @@
+Select Players
+Rounds
+New Game Name
+or Load Game
+Load Game
+Campaign
+Okay
+Back
+You must select at least 2 players
+You can only have up to 10 players
+Player
+Money
+Round
+Score
+Press F10 to save your current game.
+Use the up and down arrows to scroll
+through the item list.
+Saved game
+Angle:
+Power:
+Team
+Fuel
+Wind:
+Return
+Main Menu
+Quit
+Skip AI
+Players
+Create New
+Name
+Colour
+Type
+Generate Pref
+Played
+Won
+Tank Type
+Delete This Player
+A new version
+is ready for download.
+Could not find a game by that name.
+Qty. in inventory
+Failed to save game.
+Choosing colours
+Rendering Sky
+Rendering Landscape
+Winner: Jedi
+Winner: Sith
+Winner
+Draw
+              Player Scores                   Kill:Die
+Player Scores
+Accelerated AI
+Your Name
+unnamed
+Human
+Useless
+Guesser
+Range
+Targetter
+Deadly
+Per Game
+Only Once
+Normal
+Classic
+Big Grey
+T34
+Sith
+Neutral
+Jedi
+Zuruck
+HauptMenu
+Verlassen
+Skip AI
+Heavy
+Future
+UFO
+Spider
+Server version did not match client version.
+Server screen size does not match ours.
+Client has become disconnected from the server.
+The server is full or the game has not started.
+The server closed our connection.
+The game is finished.
diff --git a/text/ingame_fr.txt b/text/ingame_fr.txt
new file mode 100644
index 0000000..20090b3
--- /dev/null
+++ b/text/ingame_fr.txt
@@ -0,0 +1,83 @@
+Select Players
+Rounds
+New Game Name
+or Load Game
+Load Game
+Campaign
+Okay
+Back
+You must select at least 2 players
+You can only have up to 10 players
+Player
+Money
+Round
+Score
+Press F10 to save your current game.
+Use the up and down arrows to scroll
+through the item list.
+Saved game
+Angle:
+Power:
+Team
+Fuel
+Wind:
+Return
+Main Menu
+Quit
+Skip AI
+Players
+Create New
+Name
+Colour
+Type
+Generate Pref
+Played
+Won
+Tank Type
+Delete This Player
+A new version
+is ready for download.
+Could not find a game by that name.
+Qty. in inventory
+Failed to save game.
+Choosing colours
+Rendering Sky
+Rendering Landscape
+Winner: Jedi
+Winner: Sith
+Winner
+Draw
+              Player Scores                   Kill:Die
+Player Scores
+Accelerated AI
+Your Name
+unnamed
+Human
+Useless
+Guesser
+Range
+Targetter
+Deadly
+Per Game
+Only Once
+Normal
+Classic
+Big Grey
+T34
+Sith
+Neutral
+Jedi
+Return
+Main Menu
+Quit
+Skip AI
+Heavy
+Future
+UFO
+Spider
+Server version did not match client version.
+Server screen size does not match ours.
+Client has become disconnected from the server.
+The server is full or the game has not started.
+The server closed our connection.
+The game is finished.
diff --git a/text/ingame_it.txt b/text/ingame_it.txt
new file mode 100644
index 0000000..4150eb6
--- /dev/null
+++ b/text/ingame_it.txt
@@ -0,0 +1,83 @@
+Seleziona i giocatori
+Round
+Nome del Nuovo Gioco
+o Carica Gioco
+Carica Gioco
+Campagna
+Okay
+Indietro
+Devi selezionare almeno due giocatori
+Puoi avere soltanto dieci giocatori
+Giocatori
+Soldi
+Round
+Score
+Premi F10 per salvare il gioco corrente.
+Usa le frecce su e giu' per scorrere
+attraverso gli item della lista.
+Gioco Salvato
+Angolo:
+Potenza:
+Team
+Carburante
+Vento:
+Return
+Menu Pricipale
+Esci
+Salta AI
+Giocatori
+Crea Nuovo
+Nome
+Colore
+Tipo
+Genera Pref
+Giocato
+Vinto
+Tipo di Tank
+Cancella questo Giocatore
+Una nuova versione
+e' pronta per il download.
+Non trovo il Gioco con questo nome.
+Qta. in inventario
+Salvataggio gioco fallito.
+Scegli i colori
+Rendering Cielo
+Rendering Panorama
+Vincitore: Jedi
+Vincitore: Sith
+Vincitore
+Draw
+              Punteggio Giocatore                   Ucciso:Morto
+Punteggio Giocatori
+Accelerazione AI
+Tuo Nome
+senza nome
+Umano
+Sottodotato
+Mediocre
+Medio
+Elevato
+Mortale
+Per Gioco
+Only Once
+Normale
+Classico
+Big Grey
+T34
+Sith
+Neutrale
+Jedi
+Return
+Menu Pricipale
+Esci
+Salta AI
+Pesante
+Futuro
+UFO
+Spider
+Versione Server non coincide con versione client.
+Dimensioni del video Server non coincide con la nostra.
+Client disconnesso dal server.
+Il server e' completo o il gioco non e' partito.
+Il server ha chiuso la nostra connessione.
+Il gioco e' finito.
diff --git a/text/ingame_ru.txt b/text/ingame_ru.txt
new file mode 100644
index 0000000..f206eb5
--- /dev/null
+++ b/text/ingame_ru.txt
@@ -0,0 +1,83 @@
+Выберите игроков
+Кол-во раундов
+Имя для игры
+или имя прошлой игры
+Загрузить игру
+Кампания
+ОК
+Назад
+Нужно хотя бы 2 танкиста!
+В игре могут участвовать самое большее 10 танкистов одновременно!
+Танкист
+Деньги
+Раунд
+Очки
+Нажмите F10, чтобы сохранить игру.
+Чтобы просмотреть список оружия, используйте
+стрелки вверх и вниз.
+Сохранённая игра
+Угол прицела:
+Сила выстрела:
+Команда
+Топливо
+Ветер:
+Назад в игру
+В главное меню
+Выйти, надоело!
+Пропустить игру ИИ
+Танкисты
+Завербовать нового
+Имя танкиста
+Цвет
+Тип танкиста
+Сгенерировать настройки
+Провёл сражений
+Выиграл
+Тип танка
+Уволить танкиста
+Новая версия игры
+уже доступна!
+Не удалось найти сохранённую игру с таким именем.
+Кол-во зарядов
+Не удалось сохранить игру.
+Выбираем цвета...
+Смотрим на Яндекс и определяем погоду...
+Рисуем ландшафт...
+Джедаи - игры победители, сторона светлая победу празднует!
+В игре победили Ситхи! Мву-ха-ха-ха-ха-ха-а-а-а!
+Победитель
+Ничья
+               Игрок  Очки                   Убил:Погиб
+Игрок Очки
+Быстрая игра компьютеров
+Ваше имя
+Танкист
+Человек
+Ноль
+Слабый ИИ
+Средний ИИ
+Сильный ИИ
+Терминатор
+Каждую игру заново
+Только один раз
+Обычный
+В старом стиле
+Большой Серый Танк
+Т-34
+Ситх
+Нейтральный
+Джедай
+Назад в игру
+Главное меню
+Выйти, надоело!
+Пропустить игру ИИ
+Heavy
+Future
+UFO
+Spider
+Server version did not match client version.
+Server screen size does not match ours.
+Client has become disconnected from the server.
+The server is full or the game has not started.
+The server closed our connection.
+The game is finished.
diff --git a/text/ingame_sk.txt b/text/ingame_sk.txt
new file mode 100644
index 0000000..6af4cf3
--- /dev/null
+++ b/text/ingame_sk.txt
@@ -0,0 +1,83 @@
+Výber hráčov
+Kolá
+Názov novej hry
+alebo načítať hru
+Načítať hru
+Kampaň
+OK
+Späť
+Musíte vybrať aspoň 2 hráčov
+Môžete vybrať najviac 10 hráčov
+Hráč
+Peniaze
+Kolo
+Skóre
+Stlačte F10 pre uloženie aktuálnej hry.
+Použite šípky hore/dole na skrolovanie
+v zozname položiek.
+Uložená hra
+Uhol:
+Sila:
+Team
+Palivo
+Vietor:
+Návrat
+Hlavné menu
+Ukončiť
+Preskočiť AI
+Hráči
+Vytvoriť nového
+Meno
+Farba
+Typ
+Generovať pref
+Odohrané
+Vyhrané
+Typ tanku
+Vymazať tohto hráča
+Nová verzia
+je dostupná na stiahnutie.
+Nepodarilo sa nájsť hru s týmto názvom.
+Množstvo v inventári
+Nepodarilo sa uložiť hru.
+Výber farieb
+Renderujem oblohu
+Renderujem krajinku
+Víťaz: Jedi
+Víťaz: Sith
+Víťaz
+Remíza
+              Hráčske skóre                   Výhry:Prehry
+Skóre hráčov
+Zrýchlené AI
+Vaše meno
+bezmena
+Človek
+Nepoužiteľný
+Ten, čo háda
+Ten, čo hľadá správnu silu
+Ten, čo mieri
+Ten, čo prináša smrť
+Na hru
+Iba raz
+Bežný
+Klasický
+Veľký šedý
+T34
+Sith
+Neutrálny
+Jedi
+Návrat
+Hlavné menu
+Ukončiť
+Preskočiť AI
+Ťažký
+Futuristický
+UFO
+Spider
+Server version did not match client version.
+Server screen size does not match ours.
+Client has become disconnected from the server.
+The server is full or the game has not started.
+The server closed our connection.
+The game is finished.
diff --git a/text/instr.pt_BR.txt b/text/instr.pt_BR.txt
new file mode 100644
index 0000000..d72545c
--- /dev/null
+++ b/text/instr.pt_BR.txt
@@ -0,0 +1,35 @@
+Basic Instructions
+
+Objectives
+Primary Objective: Destroy all other tanks on the landscape!
+Secondary Objective: Upgrade your own tank with better weapons and
+equipment using money earned from tank kills.
+
+Starting a Game:
+1. Click 'Play' on the main menu.
+2. On the Characters menu, set game length in rounds,
+choose players (10 max.) and click `Okay'.
+Human players have purple circles, while computer players have
+green skill bars; more skill bars indicate better computer players.
+3. On the Weapons menu, buy weapons for your tank and
+click `Done' to start the game.
+
+Playing a Game:
+1. Press Tab to select a weapon.
+2. Use the left/right arrow keys to aim the weapon (called Angle).
+3. Use the up/down keys to set the range of the weapon (called Power).
+You should also check the wind direction and strength at the top of
+the screen, as these may affect the Angle and Power required to
+hit your opponent. 
+TIP: Press CTRL while using an arrow key to change Angle
+or Power more slowly.
+4. Press Space to fire the weapon.
+5. If you have bought fuel, you may move your tank using the < and > keys.
+The weapons menu reappears after each round.
+Use money earned during the round to upgrade your tank,
+then click 'Done' to begin the next round.
+The winner of the game is the player who wins the most rounds.
+
+More Information
+There are more detailed instructions about using the menu options in the
+file "Help.txt" which comes with this distribution.
diff --git a/text/instr.txt b/text/instr.txt
new file mode 100644
index 0000000..d72545c
--- /dev/null
+++ b/text/instr.txt
@@ -0,0 +1,35 @@
+Basic Instructions
+
+Objectives
+Primary Objective: Destroy all other tanks on the landscape!
+Secondary Objective: Upgrade your own tank with better weapons and
+equipment using money earned from tank kills.
+
+Starting a Game:
+1. Click 'Play' on the main menu.
+2. On the Characters menu, set game length in rounds,
+choose players (10 max.) and click `Okay'.
+Human players have purple circles, while computer players have
+green skill bars; more skill bars indicate better computer players.
+3. On the Weapons menu, buy weapons for your tank and
+click `Done' to start the game.
+
+Playing a Game:
+1. Press Tab to select a weapon.
+2. Use the left/right arrow keys to aim the weapon (called Angle).
+3. Use the up/down keys to set the range of the weapon (called Power).
+You should also check the wind direction and strength at the top of
+the screen, as these may affect the Angle and Power required to
+hit your opponent. 
+TIP: Press CTRL while using an arrow key to change Angle
+or Power more slowly.
+4. Press Space to fire the weapon.
+5. If you have bought fuel, you may move your tank using the < and > keys.
+The weapons menu reappears after each round.
+Use money earned during the round to upgrade your tank,
+then click 'Done' to begin the next round.
+The winner of the game is the player who wins the most rounds.
+
+More Information
+There are more detailed instructions about using the menu options in the
+file "Help.txt" which comes with this distribution.
diff --git a/text/instr_ES.txt b/text/instr_ES.txt
new file mode 100644
index 0000000..6ba7895
--- /dev/null
+++ b/text/instr_ES.txt
@@ -0,0 +1,33 @@
+Instrucciones B�sicas
+
+Objetivos
+Objetivo Primario: Destruir los otros Tanques del paisaje!
+Objetivo Secundario: Actualizar tu propio Tanque con mejores armas y
+equipamento usando el dinero ganado.
+
+Iniciando un Juego:
+1. Clic en 'jugar' del menu principal.
+2. En el menu de caracteres, definir la duraci�n del juego en rondas,
+escoger jugadores (10 max.) y clic en `Aceptar'.
+Jugadores Humanos tienen un circulo p�rpura, mientras que los jugadores computadora tienen
+barras verdes de destreza; mas barras indica mejor jugadores de computadora.
+3. En el menu de Armas, compra armas para tu Tanque y
+clic en `Hecho' para iniciar el juego.
+
+Jugando:
+1. Presiona Tab para seleccionar un arma.
+2. Usa las teclas izquierda/derecha para apuntar (llamado Angulo).
+3. Usa las teclas arriba/abajo para definir el rango del arma (llamado Potencia).
+Debes chequear tambi�n la direcci�n del viento y fuerza arriba de la pantalla, como estos pueden afectar el �ngulo y potencia requerido para acertar a tu oponente. 
+TIP: Consejo: Presiona CTRL mientras usas una tecla para cambiar �ngulo
+o potencia m�s lento.
+4. Presiona espacio para disparar.
+5. Si tu compraste combustible, puedes mover tu tanque usando las < y > teclas.
+El men� de armas reaparecen despu�s de cada ronda.
+Usa el dinero ganado durante la ronda para actualizar tu tanque,
+entonces haz clic en 'Hecho' para iniciar la pr�xima ronda.
+El ganador del juego es el jugador que gana m�s rondas.
+
+Mas informaci�n
+Hay instrucciones m�s detalladas acerca del uso de menu de opciones en el
+archivo "Help.txt" que viene con la distribuci�n.
diff --git a/text/instr_de.txt b/text/instr_de.txt
new file mode 100644
index 0000000..882da4a
--- /dev/null
+++ b/text/instr_de.txt
@@ -0,0 +1,35 @@
+Basisinstruktionen
+
+Ziele
+Hauptziel: Zerstöre alle anderen Panzer!
+Nebenziel: Rüste deinen panzer mit verdientem Geld auf.
+
+Ein Spiel starten:
+1. Klicke 'Play' im Hauptmenü.
+2. Im Spielermenü wählst du die Anzahl der Runden, einen
+Namen für das Spiel und die Teilnehmer (max. 10) aus.
+ Klicke dann auf 'Okay' um das Spiel zu starten.
+Menschliche Spieler haben einen violetten Kreis, Computer-
+gesteuerte Spieler habe grüne Balken, die die Schwierig-
+keitsstufe anzeigen.
+3. Im Waffenmenü kannst du Waffen und Asurüstung kaufen.
+lcike auf 'Done' um die erste Runde zu starten.
+
+Spielsteuerung:
+1. Wähle die gewünschte Waffe mit der 'Tab'-Taste aus.
+2. Mit den Pfeiltasten nach links/rechts stellst du den Winkel ein.
+3. Mit den Pfeiltasten nach oben/unten stellst du die Schussstärke ein.
+Am oberen Bildschirmrand werden Windrichtung und Stärke angezeigt,
+diese solltest du bei deinen Schusseinstellungen beachten.
+
+TIPP: Halte die STRG-Taste gedrückt, um Winkel und Schussstärke
+langsamer einzustellen!
+
+4. Drücke die Leertaste um den Schuss abzufeuern.
+
+Das Waffenmenü erscheint nach jeder Runde.
+Rüste hier deinen Panzer weiter mit dem verdienten Geld auf.
+Um die nächste Runde zu starten, klicke auf 'Done'.
+
+Das Spiel gewinnt derjenige, der die meisten Runden gewinnt.
+
diff --git a/text/instr_fr.txt b/text/instr_fr.txt
new file mode 100644
index 0000000..d72545c
--- /dev/null
+++ b/text/instr_fr.txt
@@ -0,0 +1,35 @@
+Basic Instructions
+
+Objectives
+Primary Objective: Destroy all other tanks on the landscape!
+Secondary Objective: Upgrade your own tank with better weapons and
+equipment using money earned from tank kills.
+
+Starting a Game:
+1. Click 'Play' on the main menu.
+2. On the Characters menu, set game length in rounds,
+choose players (10 max.) and click `Okay'.
+Human players have purple circles, while computer players have
+green skill bars; more skill bars indicate better computer players.
+3. On the Weapons menu, buy weapons for your tank and
+click `Done' to start the game.
+
+Playing a Game:
+1. Press Tab to select a weapon.
+2. Use the left/right arrow keys to aim the weapon (called Angle).
+3. Use the up/down keys to set the range of the weapon (called Power).
+You should also check the wind direction and strength at the top of
+the screen, as these may affect the Angle and Power required to
+hit your opponent. 
+TIP: Press CTRL while using an arrow key to change Angle
+or Power more slowly.
+4. Press Space to fire the weapon.
+5. If you have bought fuel, you may move your tank using the < and > keys.
+The weapons menu reappears after each round.
+Use money earned during the round to upgrade your tank,
+then click 'Done' to begin the next round.
+The winner of the game is the player who wins the most rounds.
+
+More Information
+There are more detailed instructions about using the menu options in the
+file "Help.txt" which comes with this distribution.
diff --git a/text/instr_it.txt b/text/instr_it.txt
new file mode 100644
index 0000000..169a490
--- /dev/null
+++ b/text/instr_it.txt
@@ -0,0 +1,33 @@
+Istruzioni di Base
+
+Obiettivi
+Obiettivo Primario: Distruggere tutti i tank nel panorama!
+Obiettivo Secondario: Upgradare il vostro tank con le migliori armi ed
+equipaggiamenti usando il denaro preso dai tank uccisi.
+
+Partenza del Gioco:
+1. Cliccare 'Play' sul main menu.
+2. Sul Characters menu, settare la lunghezza dei round,
+scegliere i giocatori (10 max.) e cliccare `Okay'.
+I giocatori Human hanno dei cerchi viola, mentre i giocatori computer hanno
+delle barre verticali verdi; quante piu' barre sono indicate, tanto piu' bravi sono i giocatori.
+3. Sul menu Weapon, pagate le armi per il vostro tank e
+cliccare `Done' per iniziare a giocare.
+
+Giocare un Gioco:
+1. Premere Tab per selezionare un'arma.
+2. Usare i tasti con le frecce sinistra/destra per puntare le armi (chiamato Angolo).
+3. Usare i tasti con le frecce su/giu' per settare il range delle armi (chiamato Potenza).
+Voi potete anche controllare la direzione e la forza del vento nella parte superiore 
+dello schermo, poiche' essi possono avere effetto sull'Angolo e la Potenza di tiro. 
+TIP: Premere CTRL mentre si usa un tasto freccia per cambiare Angolo o Potenza piu' lentamente.
+4. Premere la Barra Spaziatrice per far fuoco con le armi.
+5. Se avete del Carburante, voi potete muovere il vostro tank usando i tasti < oppure >.
+Il Menu delle Armi riappare dopo ogni round.
+Usare il denaro guadagnato durante il round per upgradare il vostro tank,
+quindi cliccare 'Done' per iniziare il round.
+Il vincitore del gioco e' quello che vince piu' round.
+
+Altre Informazioni
+Altre e piu' dettagliate istruzioni sull'uso del Menu Opzioni sono nel
+file "Help.txt" presente in questa distribuzione.
diff --git a/text/instr_ru.txt b/text/instr_ru.txt
new file mode 100644
index 0000000..dd576f3
--- /dev/null
+++ b/text/instr_ru.txt
@@ -0,0 +1,47 @@
+Базовый инструктаж
+
+Цели
+Главная цель: уничтожить все танки противника!
+Второстепенная цель: улучшать свой танк и приобретать новые виды
+вооружения на деньги, полученные за уничтожение противника.
+
+Как начать игру:
+1. Щелкнуть по кнопке "Играть" в главном меню;
+2. В меню "игроки" выставить нужное количество раундов, выбрать
+танки для игры (до 10 боевых единиц включительно) и щёлкнуть
+по кнопке "ОК".
+3. Откроется меню "Вооружение". Закупитесь оружием перед первым
+раундом и нажмите "Готово", чтобы начать игру!
+
+На заметку: танк, управляемый игроком, отмечен
+фиолетовым кружком. Танки под управлением компьютера отмечены
+зелёными полосами. Чем больше зелёных полос, тем сложнее будет
+победить этот танк.
+
+Как играть:
+1. Чтобы сменить тип оружия, которым вы будете стрелять,
+нажмите Tab или Backspace.
+2. Стрелки влево-вправо изменяют угол стрельбы.
+Стрелки вверх-вниз меняют силу выстрела.
+Удерживайте Ctrl для тонкой настройки угла и силы выстрела.
+Не забывайте следить за мощностью ветра на поле боя!
+Указатель силы ветра находится в верху экрана (зелёная или красная
+полоса под надписью "Ветер"). Чем сильнее полоса вытянута влево
+или вправо, тем сильнее ветер будет сносить ваши ракеты в сторону!
+3. Клавиши "<" и ">" ("Б" и "Ю") позволяют танку передвигаться
+влево и вправо, если у вас есть достаточно топлива.
+4. Чтобы выстрелить, нажмите Пробел.
+
+
+После каждого раунда появляется меню "Вооружение". В нём вы можете
+потратить деньги, заработанные в бою, на оружие или снаряжение.
+Для этого курсором щёлкните на те товары, которые хотите купить.
+Правая кнопка мыши продаёт уже купленное или отменяет покупку.
+После того, как вы закупились оружием, нажмите "Готово",
+чтобы начать следующий раунд!
+
+В игре побеждает тот, кто выиграл больше всего раундов.
+
+Дополнительную информацию можно найти в файле "Help.txt",
+который идёт в комплекте с игрой.
+
diff --git a/text/instr_sk.txt b/text/instr_sk.txt
new file mode 100644
index 0000000..d72545c
--- /dev/null
+++ b/text/instr_sk.txt
@@ -0,0 +1,35 @@
+Basic Instructions
+
+Objectives
+Primary Objective: Destroy all other tanks on the landscape!
+Secondary Objective: Upgrade your own tank with better weapons and
+equipment using money earned from tank kills.
+
+Starting a Game:
+1. Click 'Play' on the main menu.
+2. On the Characters menu, set game length in rounds,
+choose players (10 max.) and click `Okay'.
+Human players have purple circles, while computer players have
+green skill bars; more skill bars indicate better computer players.
+3. On the Weapons menu, buy weapons for your tank and
+click `Done' to start the game.
+
+Playing a Game:
+1. Press Tab to select a weapon.
+2. Use the left/right arrow keys to aim the weapon (called Angle).
+3. Use the up/down keys to set the range of the weapon (called Power).
+You should also check the wind direction and strength at the top of
+the screen, as these may affect the Angle and Power required to
+hit your opponent. 
+TIP: Press CTRL while using an arrow key to change Angle
+or Power more slowly.
+4. Press Space to fire the weapon.
+5. If you have bought fuel, you may move your tank using the < and > keys.
+The weapons menu reappears after each round.
+Use money earned during the round to upgrade your tank,
+then click 'Done' to begin the next round.
+The winner of the game is the player who wins the most rounds.
+
+More Information
+There are more detailed instructions about using the menu options in the
+file "Help.txt" which comes with this distribution.
diff --git a/text/kamikaze.pt_BR.txt b/text/kamikaze.pt_BR.txt
new file mode 100644
index 0000000..b9675e3
--- /dev/null
+++ b/text/kamikaze.pt_BR.txt
@@ -0,0 +1,8 @@
+BANZAAAAAIIII!!!
+GERONIMO!!!
+TIIIIIIMBEEEEEER!!!
+YOU'LL NEVER GET ME! HA HA HA!!!
+Fasten your seat belt, 'cause Kansas is going bye-bye!
+Never send a human to do a machine's job.
+BOOM CHICKA WAH-WAH!!!
+Here we go, here we go, here we go, NOW!!!
diff --git a/text/kamikaze.txt b/text/kamikaze.txt
new file mode 100644
index 0000000..b9675e3
--- /dev/null
+++ b/text/kamikaze.txt
@@ -0,0 +1,8 @@
+BANZAAAAAIIII!!!
+GERONIMO!!!
+TIIIIIIMBEEEEEER!!!
+YOU'LL NEVER GET ME! HA HA HA!!!
+Fasten your seat belt, 'cause Kansas is going bye-bye!
+Never send a human to do a machine's job.
+BOOM CHICKA WAH-WAH!!!
+Here we go, here we go, here we go, NOW!!!
diff --git a/text/kamikaze_ES.txt b/text/kamikaze_ES.txt
new file mode 100644
index 0000000..6482cdd
--- /dev/null
+++ b/text/kamikaze_ES.txt
@@ -0,0 +1,8 @@
+BANZAAAAAIIII!!!
+GERONIMO!!!
+TIIIIIIMBEEEEEER!!!
+NUNCA ME ACERTARAS! HA HA HA!!!
+Ajusta tu cintur�n, 'porque Kansas se est� yendo Chau-Chau!
+Nunca env�es a un humano a hacer el trabajo de una m�quina.
+BOOM CHICKA WAH-WAH!!!
+Aqu� vamos, aqu� vamos, aqu� vamos, AHORA!!!
diff --git a/text/kamikaze_de.txt b/text/kamikaze_de.txt
new file mode 100644
index 0000000..820d887
--- /dev/null
+++ b/text/kamikaze_de.txt
@@ -0,0 +1,8 @@
+BANZAAAAAIIII!!!
+GERONIMO!!!
+TIIIIIIMBEEEEEER!!!
+DU KRIEGST MICH NIE! HA HA HA!!!
+Schnall dich an, denn Kansas geht bye bye!
+Schicke niemals einen Menschen für einen Maschinen-Job.
+BOOM CHICKA WAH-WAH!!!
+Here we go, here we go, here we go, NOW!!!
diff --git a/text/kamikaze_fr.txt b/text/kamikaze_fr.txt
new file mode 100644
index 0000000..b9675e3
--- /dev/null
+++ b/text/kamikaze_fr.txt
@@ -0,0 +1,8 @@
+BANZAAAAAIIII!!!
+GERONIMO!!!
+TIIIIIIMBEEEEEER!!!
+YOU'LL NEVER GET ME! HA HA HA!!!
+Fasten your seat belt, 'cause Kansas is going bye-bye!
+Never send a human to do a machine's job.
+BOOM CHICKA WAH-WAH!!!
+Here we go, here we go, here we go, NOW!!!
diff --git a/text/kamikaze_it.txt b/text/kamikaze_it.txt
new file mode 100644
index 0000000..21b1b4a
--- /dev/null
+++ b/text/kamikaze_it.txt
@@ -0,0 +1,8 @@
+BANZAAAAAIIII!!!
+GERONIMO!!!
+SAVOIAAAA!!!
+TU NON MI PRENDERAI MAI! HA HA HA!!!
+Allacciate la vostra cintura di sicurezza, qui non siamo piu' nel Kansas !
+Mai mandare un umano a fare un lavoro da macchina.
+BOOM UGA-UGA CHAKA!!!
+Adesso andiamo, adesso andiamo, adesso andiamo, ... ORA!!!
diff --git a/text/kamikaze_ru.txt b/text/kamikaze_ru.txt
new file mode 100644
index 0000000..6c1c7b4
--- /dev/null
+++ b/text/kamikaze_ru.txt
@@ -0,0 +1,8 @@
+БАНЗА-А-А-А-АЙ!
+А теперь сюрприз вечера. ПОЛУЧАЙТЕ!!
+Я так легко не сдамся! Ха-ха-ха!
+Вы ещё пожалеете!!!
+А теперь - праздничный фейерверк!!!
+Самое время оживить атмосферу ВЕСЁЛЫМ ВЗРЫВОМ!!!
+Сделаем этот раунд заметнее!!
+Я отомщу!!!
diff --git a/text/kamikaze_sk.txt b/text/kamikaze_sk.txt
new file mode 100644
index 0000000..e31e403
--- /dev/null
+++ b/text/kamikaze_sk.txt
@@ -0,0 +1,8 @@
+BANZAAAAAIIII!!!
+GERONIMO!!!
+VVVAAARRRÚÚÚJJJ!!!
+NIKDY MA NEDOSTANEŠ! HA HA HA!!!
+Pripútaj sa, pretože Kansas hovorí bye-bye!
+Nikdy neposielaj človeka robiť prácu stroja.
+BOOM CHICKA WAH-WAH!!!
+Tak sme tu, tak sme tu, tak sme tu, TERAZ!!!
diff --git a/text/retaliation.pt_BR.txt b/text/retaliation.pt_BR.txt
new file mode 100644
index 0000000..2399458
--- /dev/null
+++ b/text/retaliation.pt_BR.txt
@@ -0,0 +1,10 @@
+DIE, 
+YOU ARE DEAD, 
+YOU ARE HISTORY, 
+DOWN WITH YOU, 
+I'LL GET YOU, 
+THAT'S IT, 
+IT'S OVER, 
+REVENGE IS SWEET, 
+GET LOST, 
+WRITE YOUR LAST WILL, 
\ No newline at end of file
diff --git a/text/retaliation.txt b/text/retaliation.txt
new file mode 100644
index 0000000..db9c78e
--- /dev/null
+++ b/text/retaliation.txt
@@ -0,0 +1,10 @@
+DIE, 
+YOU ARE DEAD, 
+YOU ARE HISTORY, 
+DOWN WITH YOU, 
+I'LL GET YOU, 
+THAT'S IT, 
+IT'S OVER, 
+REVENGE IS SWEET, 
+GET LOST, 
+THAT'S THE FINAL STRAW, 
\ No newline at end of file
diff --git a/text/retaliation_ES.txt b/text/retaliation_ES.txt
new file mode 100644
index 0000000..d3cc013
--- /dev/null
+++ b/text/retaliation_ES.txt
@@ -0,0 +1,10 @@
+MUERTO, 
+ESTAS MUERTO, 
+ERES HISTORIA, 
+ABAJO CONTIGO, 
+TE ATRAPARE, 
+ESO ES TODO, 
+SE ACABO, 
+VENGANZA ES DULCE, 
+PIERDETE, 
+ES LA GOTA QUE COLMO EL VASO, 
\ No newline at end of file
diff --git a/text/retaliation_de.txt b/text/retaliation_de.txt
new file mode 100644
index 0000000..c08a400
--- /dev/null
+++ b/text/retaliation_de.txt
@@ -0,0 +1,10 @@
+STIRB, 
+DU BIST TOT, 
+DU BIST GESCHICHTE, 
+NIEDER MIT DIR, 
+ICH KRIEG DICH, 
+DAS WARS, 
+DAS MAß IST VOLL, 
+RACHE IST BLUTWURST, 
+GEH UNTER, 
+MACH DEIN TESTAMENT, 
\ No newline at end of file
diff --git a/text/retaliation_fr.txt b/text/retaliation_fr.txt
new file mode 100644
index 0000000..2399458
--- /dev/null
+++ b/text/retaliation_fr.txt
@@ -0,0 +1,10 @@
+DIE, 
+YOU ARE DEAD, 
+YOU ARE HISTORY, 
+DOWN WITH YOU, 
+I'LL GET YOU, 
+THAT'S IT, 
+IT'S OVER, 
+REVENGE IS SWEET, 
+GET LOST, 
+WRITE YOUR LAST WILL, 
\ No newline at end of file
diff --git a/text/retaliation_it.txt b/text/retaliation_it.txt
new file mode 100644
index 0000000..bbd30a4
--- /dev/null
+++ b/text/retaliation_it.txt
@@ -0,0 +1,10 @@
+MUORI, 
+TU SEI MORTO, 
+TU SEI LA STORIA, 
+A FONDO CON TE, 
+TI PRENDERO', 
+CHI SEI, 
+SEI FUORI, 
+LA RIVINCITA E' DOLCE, 
+SEI PERDUTO, 
+QUESTA E' LA FINE, 
\ No newline at end of file
diff --git a/text/retaliation_ru.txt b/text/retaliation_ru.txt
new file mode 100644
index 0000000..46f9463
--- /dev/null
+++ b/text/retaliation_ru.txt
@@ -0,0 +1,10 @@
+Получай,
+Держи подарочек,
+Мы помним про тебя,
+А теперь твоя очередь,
+Я доберусь до тебя,
+Хватит,
+Довольно,
+Месть,
+Не мозоль мне глаза,
+И тебе достанется,
diff --git a/text/retaliation_sk.txt b/text/retaliation_sk.txt
new file mode 100644
index 0000000..b5b9b12
--- /dev/null
+++ b/text/retaliation_sk.txt
@@ -0,0 +1,10 @@
+PADNI, 
+JE PO TEBE, 
+SI MINULOSŤOU, 
+KONČÍŠ, 
+DOSTANEM ŤA, 
+A JE TO, 
+JE KONIEC, 
+POMSTA JE SLADKÁ, 
+PADAJ, 
+ZAČNI SI PÍSAŤ ZÁVEŤ, 
diff --git a/text/revenge.pt_BR.txt b/text/revenge.pt_BR.txt
new file mode 100644
index 0000000..3a33eb0
--- /dev/null
+++ b/text/revenge.pt_BR.txt
@@ -0,0 +1,16 @@
+Grr!
+Vou esmagar você
+Você é um ser vil e desprezível
+Seu pai é um hamster!
+Sua mãe cheira a azedo!
+Maldito seja!
+Te pego na saída!
+Vou te pegar!
+SEU PORCO!
+Ei, cabeça de abóbora!
+Foi só um arranhãozinho!
+Je ne suis pas un poisson
+Te odeio, te odeio, te odeio!
+Eu vou voltar!
+Você vai pagar por isto!
+Vai se arrepender disto!
diff --git a/text/revenge.txt b/text/revenge.txt
new file mode 100644
index 0000000..2e61596
--- /dev/null
+++ b/text/revenge.txt
@@ -0,0 +1,24 @@
+Grr!
+I worship the ground that awaits your corpse
+You are not even beneath my contempt
+Your father was a hamster!
+Your mother smells of elderberries!
+Curse you!
+I'll get you next time!
+I'll get you!
+YOU RAT!
+Hey, mush-brain!
+It's only a flesh-wound!
+Je ne suis pas un poisson
+I hate you!
+I'll be back!
+You'll suffer for this!
+You'll regret that!
+I'm not dead... yet
+why me?
+That was low
+I'm... speechless
+Oh, I'm so scared!
+I can see a light
+Oh pooh
+You'll only get me over my dead tank
diff --git a/text/revenge_ES.txt b/text/revenge_ES.txt
new file mode 100644
index 0000000..d3cc013
--- /dev/null
+++ b/text/revenge_ES.txt
@@ -0,0 +1,10 @@
+MUERTO, 
+ESTAS MUERTO, 
+ERES HISTORIA, 
+ABAJO CONTIGO, 
+TE ATRAPARE, 
+ESO ES TODO, 
+SE ACABO, 
+VENGANZA ES DULCE, 
+PIERDETE, 
+ES LA GOTA QUE COLMO EL VASO, 
\ No newline at end of file
diff --git a/text/revenge_de.txt b/text/revenge_de.txt
new file mode 100644
index 0000000..4b2ed5b
--- /dev/null
+++ b/text/revenge_de.txt
@@ -0,0 +1,21 @@
+Grr!
+Ich bete den Boden an, der deine Leiche erwartet!
+Ich verspüre nur Verachtung für dich!
+Ich verfluche dich!
+Nächstes Mal kriege ich dich!
+Ich kriege dich!
+DU RATTE!
+Hey, Matschbirne!
+Ist nur 'ne Fleischwunde!
+Ich hasse dich!
+Ich komme wieder!
+Das wirst du mir büßen!
+Das wirst du bereuen!
+Ich bin nicht tot...noch nicht!
+Warum ICH?
+Das war schwach...
+Ich bin ... sprachlos!
+Oh... Ich hab ja sooo dolle Angst...
+Ich kann ein Licht sehen!
+Oh verdammt...
+Ist das dein Ernst?
diff --git a/text/revenge_fr.txt b/text/revenge_fr.txt
new file mode 100644
index 0000000..3d852d0
--- /dev/null
+++ b/text/revenge_fr.txt
@@ -0,0 +1,21 @@
+Grr!
+Je b�nis la terre qui accueillera ton cadavre
+Tu es en-dessous du niveau de mon m�pris
+Ton p�re �tait un hamster !
+Ta m�re ... devant le prisu !
+Sois maudit !
+Je t'aurai la prochaine fois !
+Je t'aurai, je t'aurai !
+T'es un rat !
+He ! T'as un poi-chiche dans la t�te ?
+Juste une �gratignure !
+Je ne suis pas un poisson
+J'te d�teste !
+Je reviendrai !
+Tu le paieras !
+Tu le regretteras !
+Je ne suis pas encore mort !
+Pourquoi moi ?
+C'�tait bas de faire �a !
+Je reste sans voix...
+Ah, mes cicatrices !
diff --git a/text/revenge_it.txt b/text/revenge_it.txt
new file mode 100644
index 0000000..156eb96
--- /dev/null
+++ b/text/revenge_it.txt
@@ -0,0 +1,24 @@
+Grr!
+Benedico la terra che attende il vostro cadavere
+Non siete degni neppure del mio disprezzo
+Vostro padre era un criceto!
+Tua madre puzza di fiori di barbabietola! 
+Siate maledetti!
+Sarai al mio posto, la prossima volta!
+Ti prendero'!
+SEI UN TOPO DI FOGNA!
+Hey, testa di gomma!
+E' solo carne da cannone!
+Sono mica un pesce
+Ti mangio!
+Ritornero'!
+Soffrirai per questo!
+Questo lo rimpiangerai!
+Io sono morto... adesso
+perche' io?
+Quello era basso
+Sono... senza parole
+Oh, come sono sfigato!
+Io posso vedere la luce
+Oh pooh
+Mi prenderai solo passando sopra al mio tank
diff --git a/text/revenge_ru.txt b/text/revenge_ru.txt
new file mode 100644
index 0000000..03d4240
--- /dev/null
+++ b/text/revenge_ru.txt
@@ -0,0 +1,24 @@
+Р-р-р-р!
+И на твой танк напалм приземлится...
+Даже злость на тебя тратить не буду...
+А вне танка разобраться силенок хватит?
+Я до тебя доберусь!
+Мы ещё это обсудим...
+Я тебе это ещё припомню...
+У меня память плохая, поэтому мстить буду долго!!!
+Ах ты крыса бронированная!
+Взял пукалку и давай стрелять, да!?
+Даже начинку не зацепил, мазила!
+Не для моей брони твои ракеты!
+У-у-у-у... Ненавижу!
+Долг платежом красен. Ракеты верну с процентами, соседушка...
+И тебе дам того же попробовать.
+Ты об этом пожалеешь!
+Ха! Я ещё тут!
+Зачем в меня?
+Это было подло.
+Даже слов нет.
+Ага. Так стра-а-ашно!
+Что это? Вспышка?
+Мда...
+Уничтожить? Только через мой раздолбанный танк!
diff --git a/text/revenge_sk.txt b/text/revenge_sk.txt
new file mode 100644
index 0000000..dfa4fb6
--- /dev/null
+++ b/text/revenge_sk.txt
@@ -0,0 +1,21 @@
+Grr!
+Velebim zem, ktora caka na tvoju mrtvolu
+Nie si hoden ani mojho pohrdania
+Tvoj otec bol skrecok!
+Tvoja mama smrdi po ciernej baze!
+Preklinam ta!
+Nabuduce ta dostanem!
+TY KRYSA!
+Hej, rozvareny mozocek!
+Je to len zranenie!
+Neznasam ta!
+Vratim sa!
+Za toto budes trpiet!
+Toto olutujes!
+Nie som mrtvy.. zatial!
+preco ja?
+To bolo podle
+Ja.. nemam slov
+Vidim svetlo
+Do pekla
+Dostanes ma len cez moju mrtvolu
diff --git a/text/suicide.pt_BR.txt b/text/suicide.pt_BR.txt
new file mode 100644
index 0000000..6a7717f
--- /dev/null
+++ b/text/suicide.pt_BR.txt
@@ -0,0 +1,8 @@
+Ui, como dói!
+Eu, bem, estava querendo fazer isto
+Ôpa
+Eu me odeio
+Olha o que você me fez fazer!
+Agora é atirar no próprio pé
+Isto não me parece certo
+
diff --git a/text/suicide.txt b/text/suicide.txt
new file mode 100644
index 0000000..b7cb6e4
--- /dev/null
+++ b/text/suicide.txt
@@ -0,0 +1,16 @@
+Oooo that hurt!
+I, ah, meant to do that
+Oops
+I hate myself
+Look what you made me do!
+Now that is shooting yourself in the foot
+This doesn't feel right
+I am so smart, s-m-r-t
+D-OH!
+Next time, it'll be you!
+Gosh darn it al to heck
+That was a practice shot
+What's this red button do?
+Medic!
+Now that was brillant
+What was I thinking?
diff --git a/text/suicide_ES.txt b/text/suicide_ES.txt
new file mode 100644
index 0000000..abf45c9
--- /dev/null
+++ b/text/suicide_ES.txt
@@ -0,0 +1,16 @@
+Oooo eso duele!
+Yo, ah, cruel para hacer eso
+Oops
+Me odio
+Mira lo que me hiciste!
+Ahora eso te est� disparando en el pie
+Esto no me hace sentir bien
+Soy tan inteligente, s-m-r-t
+D-OH!
+Pr�xima vez, ser�s t�!
+Vaya condenado
+Eso era una pr�ctica de tiro
+Qu� hace este bot�n rojo?
+M�dico!
+Ahora eso fue brillante
+En qu� estaba pensando?
diff --git a/text/suicide_de.txt b/text/suicide_de.txt
new file mode 100644
index 0000000..a988b60
--- /dev/null
+++ b/text/suicide_de.txt
@@ -0,0 +1,16 @@
+Oooh das tat weh!
+Ich, ähh... das war Absicht!
+Oops
+Ich hasse mich.
+Sieh nur wozu du mich gezwungen hast!
+Toll... Schieß ich mir selbst ins Bein.
+Das fühlt sich aber *nicht* richtig an!
+Ich bin ja sooo schlau...
+D-OH!
+Nächstes Mal bist du's!
+Verdammt! Fahrt doch alle zur Hölle!
+Das war nur ein Übungsschuss!
+Wofür ist denn der rote Knopf da?
+SANNIIIIIEHHH!
+Na das war ja brillant.
+Was hab' ich mir nur dabei gedacht?
diff --git a/text/suicide_fr.txt b/text/suicide_fr.txt
new file mode 100644
index 0000000..94245ea
--- /dev/null
+++ b/text/suicide_fr.txt
@@ -0,0 +1,14 @@
+Ahhh j'ai mal !
+j'�tait ... arrrghhll ... pr�destin�...
+Oups !
+Je me ha�s
+Regarde ce que tu m'as fait !
+Maintenant, tu te tires dans le pied !
+�a m'a l'air louche !
+Je suis tellement malin : m-a-l-n
+D-OH !
+Le prochain coup, ce sera toi !
+m... �a m'�nerve !
+C'�tait un tir d'entra�nement !
+C'est quoi le gros bouton rouge, l� ?
+Chissetraque !
diff --git a/text/suicide_it.txt b/text/suicide_it.txt
new file mode 100644
index 0000000..b5b59f2
--- /dev/null
+++ b/text/suicide_it.txt
@@ -0,0 +1,16 @@
+Oooo che male!
+Io, ah, volevo fare cosi'
+Oops
+Mi odio
+Guardate cosa lo avete incitato a fare! 
+Adesso vi sparerei in un piede
+Questo non e' fare qualcosa di bello
+Sono cos� astuto, s-t-t
+D-OH!
+La volta prossima, tocchera' a voi!
+Gosh , andate all'inferno
+Questo e' un colpo basso
+Cos'e' che fa questo pulsante rosso?
+Dottore!
+Adesso e' tutto chiaro
+A cosa stavo pensando?
diff --git a/text/suicide_ru.txt b/text/suicide_ru.txt
new file mode 100644
index 0000000..8390a17
--- /dev/null
+++ b/text/suicide_ru.txt
@@ -0,0 +1,16 @@
+Оу-у-у-у-у...
+Я... э... не туда попал. Честно.
+Ой.
+А у танка документация есть? Наверное, за эту ручку не стоило дергать...
+Смотри, что ты со мной сделал!!
+Теперь я понял, какие повреждения от этого снаряда.
+Опять не так вставил, да что ж такое...
+Какой я умны-ы-ы-ый... В кавычках.
+Блин!
+Видел? Вот это и с тобой будет, когда попаду!
+Блин, сколько можно?
+Испытывал снаряд, ничего такого...
+А, вот для чего эта кнопка...
+Где тут медики?
+Преле-е-естно...
+Надо было в другую сторону. Запомним.
diff --git a/text/suicide_sk.txt b/text/suicide_sk.txt
new file mode 100644
index 0000000..c07ff67
--- /dev/null
+++ b/text/suicide_sk.txt
@@ -0,0 +1,16 @@
+Auuu, to boli!
+Ja, uuh, to bolo schvalne
+Ups
+Neznasam sa
+Pozri, k comu si ma donutil!
+Tomu sa hovori strielat si do paty
+Toto nie je celkom ok
+Som taky sikovny, s-i-k-o-v-n-y
+D-OH!
+Nabuduce to budes ty!
+Oh, do pekla
+To bolo prakticke
+Co urobi tento cerveny gombik?
+Doktora!
+Tak to bolo krasne
+Co som si myslel?
diff --git a/text/war_quotes.txt b/text/war_quotes.txt
new file mode 100644
index 0000000..dc258dd
--- /dev/null
+++ b/text/war_quotes.txt
@@ -0,0 +1,35 @@
+Mankind must put an end to war or war will put an end to mankind - John F. Kennedy
+War is fought by human beings. - Carl von Clausewitz
+War is something absurd, useless, that nothing can justify. - Louis de Cazenave
+Every gun that is made, every warship launched, every rocket fired, signifies, in the final sense, a theft from those who   hunger and are not fed... - Dwight D. Eisenhower
+War cannot be a necessary evil, because non-violence is a necessary good. - John Lewis
+As long as war is regarded as wicked, it will always have its  fascination. - Oscar Wilde
+Only the dead have seen the end of the war. (Plato)
+In war, truth is the first casualty. (Aeschylus)
+War is sweet to those who have never experienced it. (Pindar)
+War spares not the brave but the cowardly. (Anacreon)
+To lead untrained people to war is to throw them away. (Confucius)
+Laws are silent in times of war. (Cicero)
+War gives the right of the conquerors to impose any conditions they please upon the vanquished. (Gaius Julius Caesar)
+The true contempt of an invader is shown by deeds of valour in the field. (Hermocrates of Syracuse)
+In peace, sons bury their fathers; in war, fathers bury their sons. (Herodotus)
+A wise man in times of peace prepares for war. (Horace)
+The man who runs away will fight again. (Menander)
+A small country cannot contend with a great; the few cannot contend with the many; the weak cannot contend with the strong. (Mencius)
+To blunder twice is not allowed in war. (Latin proverbs)
+I am more afraid of our own mistakes than of our enemies'designs. (Pericles)
+He conquers who endures. (Persius)
+An alliance with the powerful is never to be trusted. (Fedrus)
+A good general not only sees the way to victory, he also knows when victory is impossible. (Polybius)
+Pardon one offence and you encourage the commission of many. (Publilius Syrus)
+The cruelty of war makes for peace. (Publius Statius)
+Wars are the dread of mothers. (Horace)
+The fortunes of war are always doubtful. (Seneca)
+The blade itself incites to violence. (Homer)
+Arms keep peace. (Latin proverbs)
+All warfare is based on deception. (Sun Tzu)
+He who knows when he can fight and when he cannot will be victorious. (Sun Tzu)
+In war, numbers alone confer no advantage. Do not advance relying on sheer military power. (Sun Tzu)
+Now in place of the young men urns and ashes are carried home to houses of the fighters. (Aeschylus).
+Beware lest in your anxiety to avoid war you obtain a master. (Demosthenes.)
+A sword is never a killer, it's a tool in the killer's hands. (Seneca)
diff --git a/text/war_quotes_ES.txt b/text/war_quotes_ES.txt
new file mode 100644
index 0000000..f7916ca
--- /dev/null
+++ b/text/war_quotes_ES.txt
@@ -0,0 +1,35 @@
+La Humanidad debe poner un fin a la guerra o la guerra pondr� un fin a la Humanidad - John F. Kennedy
+La guerra es peleada por criaturas humanas. - Carl von Clausewitz
+La guerra es algo absurdo, usualmente, nada puede justificarla. - Louis de Cazenave
+Cada arma est� hecha, cada buque lanzado, cada cohete disparado, significa, en el sentido final, un robo de algunos quienes   son colgados y no alimentados... - Dwight D. Eisenhower
+La guerra no puede ser necesariamente mala, porque la no-violencia es un bien necesario. - John Lewis
+Tan larga como estimada es la guerra es como perversa, siempre tendr� fascinaci�n. - Oscar Wilde
+Solo la muerte ha visto el fin de la guerra. (Plato)
+En guerra, la verdad es la primera v�ctima. (Aeschylus)
+La guerra es dulce para esos que nunca la han experimentado. (Pindar)
+La guerra no le sobra al valiente, pero si al cobarde. (Anacreon)
+Para dirigir gente no entrenada a la guerra es para tirarlos lejos. (Confucius)
+Las leyes son silenciosas en tiempo de guerra. (Cicero)
+War gives the right of the conquerors to impose any conditions they please upon the vanquished. (Gaius Julius Caesar)
+El verdadero desprecio de un invasor es mostrado por la acci�n de valor en el campo. (Hermocrates of Syracuse)
+En paz, los hijos sepultan a sus padres; en guerra, los padres sepultan a sus hijos. (Herodotus)
+Un hombre sabio en tiempos de paz se prepara para la guerra. (Horace)
+El hombre que huye luchar� de nuevo. (Menander)
+Un pueblo peque�o no puede enfrentarse a uno grande; los pocos no pueden enfrentarse a los muchos; el d�bil no puede enfrentarse al fuerte. (Mencius)
+Meter la pata dos veces no est� permitido en la guerra. (Latin proverbs)
+Estoy mas asustado de nuestros propios errores que de nuestros dise�os de enemigos. (Pericles)
+Vencer� quien resiste. (Persius)
+Una alianza con el poderoso nunca puede ser de confianza. (Fedrus)
+Un buen general no solo ve el camino a la victoria, el tambi�n sabe cuando la victoria es imposible. (Polybius)
+Perdona una ofensa y tu animar�s la comisi�n de muchos. (Publilius Syrus)
+La crueldad de la guerra hace la paz. (Publius Statius)
+Las guerras son el pavor de las madres. (Horace)
+Las fortunas de la guerra son siempre dudosas. (Seneca)
+La espada misma incita a la violencia. (Homer)
+Las armas mantienen la paz. (Latin proverbs)
+Todas las guerras est�n basadas en el enga�o. (Sun Tzu)
+Quien conoce cuando puede luchar y cuando no puede ser� victorioso. (Sun Tzu)
+In war, numbers alone confer no advantage. Do not advance relying on sheer military power. (Sun Tzu)
+Now in place of the young men urns and ashes are carried home to houses of the fighters. (Aeschylus).
+Beware lest in your anxiety to avoid war you obtain a master. (Demosthenes.)
+Una espada nunca es una asesina, es una herramienta en las manos del asesino. (Seneca)
diff --git a/text/war_quotes_it.txt b/text/war_quotes_it.txt
new file mode 100644
index 0000000..63f3212
--- /dev/null
+++ b/text/war_quotes_it.txt
@@ -0,0 +1,35 @@
+L'umanit� deve mettere un termine alla guerra o la guerra metter� un termine all'umanit� - John F. Kennedy
+La guerra � combattuta dagli esseri umani. - Carl von Clausewitz
+La guerra � qualche cosa di irragionevole, inutile, che niente pu� giustificare. - Louis de Cazenave
+Ogni cannone forgiato, ogni nave da guerra varata, ogni razzo lanciato, indica, alla fine, che un furto e' stato fatto a coloro che hanno fame e non hanno da sfamarsi... - Dwight D. Eisenhower
+La guerra non pu� essere una malvagit� necessaria, perch� la non-violenza � un bene necessario. - John Lewis
+Finch� la guerra � considerata cattiva, avr� sempre relativo fascino. - Oscar Wilde
+Soltanto i morti hanno visto la conclusione della guerra. (Platone)
+Nella guerra, la verit� � il primo incidente. (Eschilo)
+La guerra � dolce per coloro che non l'hanno mai subita. (Pindaro)
+La guerra risparmia non il coraggioso ma il codardo. (Anacreonte)
+Condurre la gente non addestrata alla guerra � buttarla via. (Confucio)
+Le leggi sono silenziose in tempo della guerra. (Cicerone)
+La guerra d� diritto ai conquistatori di imporre ogni condizione ai vinti.(Caio Giulio Cesare)
+The true contempt of an invader is shown by deeds of valour in the field. (Ermocrate di Siracusa)
+Nella pace, i figli seppelliscono i loro padri; con la guerra, i padri seppelliscono i loro figli. (Erodoto)
+Un uomo saggio in tempo di pace prepara la guerra. (Orazio)
+The man who runs away will fight again. (Menander)
+Un piccolo paese non pu� contendersi con uno grande; i pochi non possono contendersi con i molti; il debole non pu� contendersi con il forte. (Mencio)
+Indugiare due volte non � permesso in guerra. (Proverbio Latino)
+Sono pi� impaurito dei nostri errori che dei progetti dei nostri nemici. (Pericle)
+Conquista chi resiste. (Persio)
+Un'alleanza con il potente non deve dare fiducia. (Fedro)
+Un buon Generale non solo vede la via alla vittoria, ma sa anche quando la vittoria � impossibile. (Polibio)
+Perdonare un'offesa incoraggia il commetterne altre. (Publio Siro)
+La crudelt� della guerra porta alla pace. (Publio Stazio)
+Le guerre sono il terrore delle madri. (Orazio)
+Le fortune della guerra sono sempre dubbiose. (Seneca)
+La spada in se' esorta alla violenza. (Omero)
+La pace si conserva con le armi. (Proverbio Latino)
+Tutta la guerra � basata su inganno. (Sun Tzu)
+Lui sa quando pu� combattere e quando non pu� potr� essere vittorioso. (Sun Tzu)
+Nella guerra, i numeri da soli conferiscono nessun vantaggio. Non contare sul potere militare puro. (Sun Tzu)
+Ora al posto dei giovani uomini, le urne e le ceneri sono trasportate in Patria alle case dei combattenti. (Eschilo).
+Beware lest in your anxiety to avoid war you obtain a master. (Demostene.)
+Una spada non � mai un assassino, e' solo un attrezzo nelle mani di un assassino. (Seneca)
diff --git a/text/war_quotes_ru.txt b/text/war_quotes_ru.txt
new file mode 100644
index 0000000..0c2e5ba
--- /dev/null
+++ b/text/war_quotes_ru.txt
@@ -0,0 +1,21 @@
+Вторжение в соседнюю страну обычно совершается во благо ее граждан. (Борис Кригер)
+Кто говорит, что на войне не страшно, тот ничего не знает о войне. (Юлия Друнина)
+Бряцая оружием, умей им пользоваться. (Борис Кригер)
+Война — это психоз, порожденный чьим-то неумением прозревать взаимоотношения вещей. Наши взаимоотношения с ближними своими. С экономикой, историей. Но прежде всего — с ничто. Со смертью. (Джон Фаулз «Волхв»)
+В любой войне, кто бы ни победил, дети побежденных будут плакать. И считать отцов погибшими за правое дело. (Виктор Точинов)
+Неправда, что война - продолжение политики. Она ее придаток, жалкий и беспомощный. (Сергей Лукьяненко "Осенние визиты")
+Война. Война никогда не меняется. (Отто фон Бисмарк)
+Когда объявлена война, первой ее жертвой становится правда. (Артур Понсонби)
+Война — способ развязывания зубами политического узла, который не поддается языку. (Амброуз Бирс)
+Война — это зло, позорящее человеческий род. (Франсуа Фенелон)
+Война превращает в диких зверей людей, рождённых, чтобы жить братьями. (Вольтер)
+Война - это всего лишь трусливое бегство от проблем мирного времени. (Томас Манн)
+Если хочешь мира, готовься к войне. (Латинская пословица)
+Затевающие войну сами попадают в свои сети. (Иоанн Дамаскин)
+Терпение и смирение нужно иметь и для мира и для войны. (Иоанн Дамаскин)
+Выиграна война, но не мир. (Альберт Эйнштейн)
+Либо человечество покончит с войной, либо война покончит с человечеством. (Д. Кеннеди)
+Война заканчивается тогда, когда не остается никого в живых. (Платон)
+Никогда не знать поражения означает никогда не вступать в борьбу. (Морихэй Уэсиба)
+Побеждают лишь те, кто сражается. (Луи Антуан Сен-Жюст)
+Единство — вот залог победы, в войне иль мире — все равно. (Георг Ролленгаген)
diff --git a/text/weapons.pt_BR.txt b/text/weapons.pt_BR.txt
new file mode 100644
index 0000000..484f817
--- /dev/null
+++ b/text/weapons.pt_BR.txt
@@ -0,0 +1,343 @@
+*WEAPONS*
+Míssil Pequeno
+Produces a low impact explosion
+1500 10 10 0.2 25 0 2 30 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Míssil Médio
+Low yield, small area explosion
+2000 5 15 0.2 40 0 2 40 0 1 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Míssil Grande
+Medium yield, medium area explosion
+4000 3 20 0.2 60 1 3 60 0 2 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Small Nuke
+High yield, large area explosion
+16000 2 40 0.2 100 2 4 100 0 3 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Nuke
+Very high yield, huge explosion
+22000 1 60 0.2 150 2 5 150 0 4 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Death Head
+Massive, deadly explosion
+30000 1 80 0.2 200 3 6 200 0 5 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Spread
+5 Small missiles in a single shot
+5000 3 10 0.2 25 0 2 30 0 0 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Spread
+5 Medium missiles in a single shot
+11000 2 15 0.2 40 0 2 40 0 1 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Large Spread
+5 Large missiles in a single shot
+17000 1 20 0.2 60 1 3 60 0 2 5 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Super Spread
+4 Small Nukes in a single shot
+25000 1 40 0.2 100 2 4 100 0 3 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Death Spread
+3 Nukes in a single shot
+50000 1 60 0.2 150 2 5 150 0 4 3 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Armageddon
+3 Death Heads in a single shot
+100000 1 80 0.2 200 3 6 200 0 5 3 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Chain Missile
+Fires a volly of three small missiles
+4000 3 10 0.2 25 0 2 30 0 0 1 3 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Chain Gun
+Fires a volly of five small missiles
+6000 10 10 0.2 25 0 2 30 0 0 1 5 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Jack Hammer
+Fires a volly of eight small missiles
+8000 16 10 0.2 25 0 2 30 0 0 1 8 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Shaped Charge
+High yield horizontal explosion. All of the energy is focused out to the sides, increasing the damage done but reducing the overall area of the explosion.
+10000 5 10 0.2 100 2 3 100 0 17 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Wide Boy
+Devastating horizontal explosion. All of the energy is focused out to the sides, increasing the damage done but reducing the overall area of the explosion.
+15000 2 10 0.2 200 2 4 200 0 18 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cutter
+Horizontal explosion that will obliterate anything that gets in the way. All of the energy is focused out to the sides, increasing the damage done but reducing the overall area of the explosion in comparison to a similar sized uncontrolled blast.
+20000 1 10 0.2 300 3 5 300 0 19 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Small Roller
+Medium explosive which rolls downhill until it hits something
+2000 3 20 0.2 40 0 2 40 0 6 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Large Roller
+Large explosive which rolls downhill until it hits something
+8000 1 30 0.2 60 1 3 60 0 6 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Death Roller
+Huge explosive which rolls downhill until it hits something
+14000 1 40 0.2 100 2 4 100 0 6 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small MIRV
+Drops a group of large missiles on the ground from above
+20000 1 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 2 1.0 120 0.0 1.0 0 -1 0
+
+Armour Piercing
+A small, powerful shell that knocks out tanks
+2500 5 30 0.2 15 0 2 80 0 27 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Cluster Bomb
+Scatters medium yield bomblets on impact
+10000 3 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 60 0 3.5 0 -1 0
+
+Super Cluster
+Scatters high yield bomblets on impact
+20000 2 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 30 0.0 60 0 3.5 0 -1 0
+
+Funky Bomb
+Unpredictable and highly destructive
+30000 3 50 0.2 200 0 0 200 0 9 1 0 0 3 0 10 27 0.0 360 1.0 0.5 0.1 -1 0
+
+Funky Death
+Unpredictable and extremely destructive
+50000 1 90 0.2 300 2 1 300 0 9 1 0 0 4 0 10 28 0.0 360 1.0 0.5 0.1 -1 0
+
+Funky Bomblet
+Medium yield explosive warhead
+7000 3 5 0.01 40 0 0 50 0 10 1 0 1 1 1 0 -1 0 0 0 0 0 125 1.0
+
+Funky Deathlet
+High yield explosive warhead
+9000 2 9 0.01 100 2 1 90 0 10 1 0 1 3 1 0 -1 0 0 0 0 0 175 1.0
+
+Bomblet
+Medium yield explosive warhead
+3500 3 20 0.2 40 0 2 40 0 8 1 0 0 1 1 0 -1 0 0 0 0 0 -1 0
+
+Super Bomblet
+High yield explosive warhead
+5000 2 40 0.2 60 1 2 65 0 8 1 0 0 3 1 0 -1 0 0 0 0 0 -1 0
+
+Burrower
+Burrows back up to the surface before exploding, good against buried tanks. The Burrower is designed for below-ground use and suffers from high air-resistance.
+7500 3 100 0.4 50 0 2 50 0 25 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Penetrator
+Penetrates below ground before rising to the surface. The Penetrator will either explode on exit from the ground or on contact with buried objects. This missile is designed for burrowing and as a result suffers from high air-resistance.
+20000 2 150 0.4 80 0 2 100 0 26 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Napalm Bomb
+Scatters small quantities of intensely burning napalm on impact
+6000 3 80 0.2 80 1 1 80 0 9 1 0 0 3 0 10 36 0.0 90 0.2 2.5 1.0 -1 0
+
+Medium Napalm Bomb
+Scatters intensely burning napalm on impact
+14000 2 200 0.2 150 1 1 200 0 9 1 0 0 4 0 25 36 0.0 90 0.2 3 1.0 -1 0
+
+Large Napalm Bomb
+Covers the surrounding area with intensely burning napalm on impact
+22000 1 400 0.2 200 1 2 500 0 9 1 0 0 5 0 60 36 0.0 90 0.2 5 1.0 -1 0
+
+Napalm Jelly
+Intensely burning chemical jelly
+2000 5 5 0.5 10 1 10 30 0 0 1 0 0 2 1 0 -1 0 0 0 0 0 -1 0
+
+Driller
+Vertical explosion that will do little damage, but create a deep hole in the ground.
+5000 2 10 0.2 300 3 5 10 0 28 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Tremor
+Produce a small earthquake on impact
+3000 5 30 0.2 40 0 2 10 0 14 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Shock Wave
+Produce a large earthquake on impact
+10000 2 60 0.2 100 2 3 20 0 15 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Tectonic Shift
+Produce a huge earthquake on impact
+30000 1 100 0.2 150 2 4 30 0 16 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Riot Bomb
+Destroy a small volume of dirt without damaging anything else
+2000 5 15 0.2 25 0 2 0 0 23 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Heavy Riot Bomb
+Destroy a large volume of dirt without damaging anything else
+3000 2 30 0.2 100 1 2 0 0 24 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Riot Charge
+Cuts through a cone of dirt directly in front of the gun
+1000 5 15 0.2 50 0 2 0 0 11 1 0 1 1 0 0 -1 0 0 0 0 0 0 0
+
+Riot Blast
+Cuts through a large cone of dirt directly in front of the gun
+2000 2 30 0.2 150 1 2 0 0 12 1 0 1 3 0 0 -1 0 0 0 0 0 0 0
+
+Dirt Ball
+Produce a small sphere of material to bury your opponents
+3000 5 15 0.2 25 0 2 0 0 11 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Large Dirt Ball
+Produce a large sphere of material to bury your opponents
+7000 2 30 0.2 60 1 2 0 0 12 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Super Dirt Ball
+Produce a huge ball of material to bury your opponents
+10000 1 60 0.2 100 2 2 0 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Dirt Spread
+Drop little piles of dirt on your enemies
+4000 2 30 0.2 40 1 2 0 0 12 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cluster MIRV
+Releases a cluster of small missiles on its way down
+10000 2 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 45 0 2.0 0 -1 0
+
+Per Cent Bomb
+Destroys half of the target's armour
+12000 2 30 0.2 30 2 4 0 0 29 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Reducer
+Lowers the explosive power of an enemy's missiles.
+6000 3 25 0.3 30 2 4 0 0 30 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Laser
+A 50kW laser beam.
+5000 5 1 0.0 2 0 0 30 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Laser
+A 100kW laser beam
+10000 3 1 0.0 5 0 0 65 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Large Laser
+A powerful 200kW laser beam
+15000 2 1 0.0 9 0 0 150 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+*NATURALS*
+Small Meteor
+A small chunk of rock from the skies
+0 1 15 0.2 25 0 0 5 0 20 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Meteor
+A medium chunk of rock from the skies
+0 1 20 0.2 40 0 0 10 0 21 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Large Meteor
+A large chunk of rock from the skies
+0 1 25 0.2 60 1 1 20 0 22 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Small Lightning Bolt
+A weak bolt of lightning.
+0 1 1 0.0 1 0 0 5 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Lightning Bolt
+A bolt of lightning
+0 1 1 0.0 4 0 0 15 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Large Lightning Bolt
+A powerful bolt of lightning
+0 1 1 0.0 7 0 0 35 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+*ITEMS*
+Teleport
+Teleports the tank to a random location
+5000 2 1 3 11
+
+Swapper
+Swap places with another tank
+10000 2 1 4 11
+
+Mass Teleport
+Teleports all tanks on the screen
+15000 2 1 4 11
+
+Fan
+Change the wind strength and direction
+2500 3 1 3 2
+
+Vengeance
+A small self-destruct or auto-destruct device, if you've got to go, why not take someone with you?
+20000 1 1 2 0 0 21
+
+Dying Wrath
+A large self/auto-destruct device. Mutually Assured Destruction.
+40000 1 1 3 0 21 3
+
+Fatal Fury
+End it all in style
+60000 1 1 4 0 22 3
+
+Light Shield
+A small amount of protection from damage
+10000 3 0 1 0 50 0 0 255 0 1
+
+Medium Shield
+Protects against  damage
+20000 2 0 2 0 100 0 64 255 0 3
+
+Heavy Shield
+A large amount of protection from damage
+30000 2 0 4 0 150 0 128 255 64 6
+
+Light Repulsor Shield
+Lightly repels enemy missiles
+10000 3 0 2 0 10 250 128 0 255 1
+
+Medium Repulsor Shield
+Repels enemy missiles
+20000 2 0 3 0 20 500 192 64 255 3
+
+Heavy Repulsor Shield
+Strongly repels enemy missiles
+40000 1 0 5 0 40 1000 255 128 255 6
+
+Armour Plating
+Permanently add a small increase to the damage your tanks can take. Each additional purchase adds a slightly smaller amount to your tank's armour.
+20000 1 0 2 0 300
+
+Plasteel Plating
+Permanently increase the damage your tanks can take. Each additional purchase adds a slightly smaller amount to your tank's armour.
+40000 1 0 4 0 2155
+
+Intensity Amplifier
+A small permanent increase to the damage done by your weapons. The efficiency decreases and therefore each additional purchase has a reduced affect.
+21000 1 0 3 0 0.10
+
+Violent Force
+Permanently increase the damage done by your weapons. The efficiency decreases and as a result each additional purchase provides a smaller increase.
+50000 1 0 3 0 0.30
+
+Slick Projectiles
+A Teflon coating for projectiles to reduce drag and the affect of the wind
+1000 50 0 3 0 0.5
+
+Dimpled Projectiles
+Small dimples in the skin of projectiles for massive reduction in drag
+2000 50 0 4 0 0.1
+
+Parachute
+Allows the tank to float gently to the ground
+5000 10 0 0 0 0 0
+
+Auto-repair kit
+Repairs the tank a little each turn. Each additional kit provides a slightly smaller increase to your armour.
+10000 1 0 2 0 0 0
+
+Fuel
+Allows the tank to move across level terran.
+1000 10 0 2 0 0 0
+
+Rocket
+Launches the tank into the air.
+2000 2 1 4 0 0 0
+
+SDI Missile Defense
+Offers some protection against incoming missiles.
+10000 1 0 5 0 0
+
diff --git a/text/weapons.txt b/text/weapons.txt
new file mode 100644
index 0000000..cb5b8eb
--- /dev/null
+++ b/text/weapons.txt
@@ -0,0 +1,343 @@
+*WEAPONS*
+Small Missile
+Produces a low impact explosion
+1500 10 10 0.2 25 0 2 30 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Missile
+Low yield, small area explosion
+2000 5 15 0.2 40 0 2 40 0 1 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Large Missile
+Medium yield, medium area explosion
+4000 3 20 0.2 60 1 3 60 0 2 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Small Nuke
+High yield, large area explosion
+16000 2 40 0.2 100 2 4 100 0 3 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Nuke
+Very high yield, huge explosion
+22000 1 60 0.2 150 2 5 150 0 4 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Death Head
+Massive, deadly explosion
+30000 1 80 0.2 200 3 6 200 0 5 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Spread
+5 Small missiles in a single shot
+5000 3 10 0.2 25 0 2 30 0 0 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Spread
+5 Medium missiles in a single shot
+11000 2 15 0.2 40 0 2 40 0 1 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Large Spread
+5 Large missiles in a single shot
+17000 1 20 0.2 60 1 3 60 0 2 5 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Super Spread
+4 Small Nukes in a single shot
+25000 1 40 0.2 100 2 4 100 0 3 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Death Spread
+3 Nukes in a single shot
+50000 1 60 0.2 150 2 5 150 0 4 3 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Armageddon
+3 Death Heads in a single shot
+100000 1 80 0.2 200 3 6 200 0 5 3 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Chain Missile
+Fires a volly of three small missiles
+4000 3 10 0.2 25 0 2 30 0 0 1 3 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Chain Gun
+Fires a volly of five small missiles
+6000 10 10 0.2 25 0 2 30 0 0 1 5 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Jack Hammer
+Fires a volly of eight small missiles
+8000 16 10 0.2 25 0 2 30 0 0 1 8 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Shaped Charge
+High yield horizontal explosion. All of the energy is focused out to the sides, increasing the damage done but reducing the overall area of the explosion.
+10000 5 10 0.2 100 2 3 100 0 17 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Wide Boy
+Devastating horizontal explosion. All of the energy is focused out to the sides, increasing the damage done but reducing the overall area of the explosion.
+15000 2 10 0.2 200 2 4 200 0 18 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cutter
+Horizontal explosion that will obliterate anything that gets in the way. All of the energy is focused out to the sides, increasing the damage done but reducing the overall area of the explosion in comparison to a similar sized uncontrolled blast.
+20000 1 10 0.2 300 3 5 300 0 19 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Small Roller
+Medium explosive which rolls downhill until it hits something
+2000 3 20 0.2 40 0 2 40 0 6 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Large Roller
+Large explosive which rolls downhill until it hits something
+8000 1 30 0.2 60 1 3 60 0 6 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Death Roller
+Huge explosive which rolls downhill until it hits something
+14000 1 40 0.2 100 2 4 100 0 6 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small MIRV
+Drops a group of large missiles on the ground from above
+20000 1 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 2 1.0 120 0.0 1.0 0 -1 0
+
+Armour Piercing
+A small, powerful shell that knocks out tanks
+2500 5 30 0.2 15 0 2 80 0 27 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Cluster Bomb
+Scatters medium yield bomblets on impact
+10000 3 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 60 0 3.5 0 -1 0
+
+Super Cluster
+Scatters high yield bomblets on impact
+20000 2 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 30 0.0 60 0 3.5 0 -1 0
+
+Funky Bomb
+Unpredictable and highly destructive
+30000 3 50 0.2 200 0 0 200 0 9 1 0 0 3 0 10 27 0.0 360 1.0 0.5 0.1 -1 0
+
+Funky Death
+Unpredictable and extremely destructive
+50000 1 90 0.2 300 2 1 300 0 9 1 0 0 4 0 10 28 0.0 360 1.0 0.5 0.1 -1 0
+
+Funky Bomblet
+Medium yield explosive warhead
+7000 3 5 0.01 40 0 0 50 0 10 1 0 1 1 1 0 -1 0 0 0 0 0 125 1.0
+
+Funky Deathlet
+High yield explosive warhead
+9000 2 9 0.01 100 2 1 90 0 10 1 0 1 3 1 0 -1 0 0 0 0 0 175 1.0
+
+Bomblet
+Medium yield explosive warhead
+3500 3 20 0.2 40 0 2 40 0 8 1 0 0 1 1 0 -1 0 0 0 0 0 -1 0
+
+Super Bomblet
+High yield explosive warhead
+5000 2 40 0.2 60 1 2 65 0 8 1 0 0 3 1 0 -1 0 0 0 0 0 -1 0
+
+Burrower
+Burrows back up to the surface before exploding, good against buried tanks. The Burrower is designed for below-ground use and suffers from high air-resistance.
+7500 3 100 0.4 50 0 2 50 0 25 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Penetrator
+Penetrates below ground before rising to the surface. The Penetrator will either explode on exit from the ground or on contact with buried objects. This missile is designed for burrowing and as a result suffers from high air-resistance.
+20000 2 150 0.4 80 0 2 100 0 26 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Napalm Bomb
+Scatters small quantities of intensely burning napalm on impact
+6000 3 80 0.2 80 1 1 80 0 9 1 0 0 3 0 10 36 0.0 90 0.2 2.5 1.0 -1 0
+
+Medium Napalm Bomb
+Scatters intensely burning napalm on impact
+14000 2 200 0.2 150 1 1 200 0 9 1 0 0 4 0 25 36 0.0 90 0.2 3 1.0 -1 0
+
+Large Napalm Bomb
+Covers the surrounding area with intensely burning napalm on impact
+22000 1 400 0.2 200 1 2 500 0 9 1 0 0 5 0 60 36 0.0 90 0.2 5 1.0 -1 0
+
+Napalm Jelly
+Intensely burning chemical jelly
+2000 5 5 0.5 10 1 10 30 0 0 1 0 0 2 1 0 -1 0 0 0 0 0 -1 0
+
+Driller
+Vertical explosion that will do little damage, but create a deep hole in the ground.
+5000 2 10 0.2 300 3 5 10 0 28 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Tremor
+Produce a small earthquake on impact
+3000 5 30 0.2 40 0 2 10 0 14 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Shock Wave
+Produce a large earthquake on impact
+10000 2 60 0.2 100 2 3 20 0 15 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Tectonic Shift
+Produce a huge earthquake on impact
+30000 1 100 0.2 150 2 4 30 0 16 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Riot Bomb
+Destroy a small volume of dirt without damaging anything else
+2000 5 15 0.2 25 0 2 0 0 23 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Heavy Riot Bomb
+Destroy a large volume of dirt without damaging anything else
+3000 2 30 0.2 100 1 2 0 0 24 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Riot Charge
+Cuts through a cone of dirt directly in front of the gun
+1000 5 15 0.2 50 0 2 0 0 11 1 0 1 1 0 0 -1 0 0 0 0 0 0 0
+
+Riot Blast
+Cuts through a large cone of dirt directly in front of the gun
+2000 2 30 0.2 150 1 2 0 0 12 1 0 1 3 0 0 -1 0 0 0 0 0 0 0
+
+Dirt Ball
+Produce a small sphere of material to bury your opponents
+3000 5 15 0.2 25 0 2 0 0 11 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Large Dirt Ball
+Produce a large sphere of material to bury your opponents
+7000 2 30 0.2 60 1 2 0 0 12 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Super Dirt Ball
+Produce a huge ball of material to bury your opponents
+10000 1 60 0.2 100 2 2 0 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Dirt Spread
+Drop little piles of dirt on your enemies
+4000 2 30 0.2 40 1 2 0 0 12 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cluster MIRV
+Releases a cluster of small missiles on its way down
+10000 2 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 45 0 2.0 0 -1 0
+
+Per Cent Bomb
+Destroys half of the target's armour
+12000 2 30 0.2 30 2 4 0 0 29 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Reducer
+Lowers the explosive power of an enemy's missiles.
+6000 3 25 0.3 30 2 4 0 0 30 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Laser
+A 50kW laser beam.
+5000 5 1 0.0 2 0 0 30 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Laser
+A 100kW laser beam
+10000 3 1 0.0 5 0 0 65 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Large Laser
+A powerful 200kW laser beam
+15000 2 1 0.0 9 0 0 150 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+*NATURALS*
+Small Meteor
+A small chunk of rock from the skies
+0 1 15 0.2 25 0 0 5 0 20 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Meteor
+A medium chunk of rock from the skies
+0 1 20 0.2 40 0 0 10 0 21 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Large Meteor
+A large chunk of rock from the skies
+0 1 25 0.2 60 1 1 20 0 22 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Small Lightning Bolt
+A weak bolt of lightning.
+0 1 1 0.0 1 0 0 5 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Lightning Bolt
+A bolt of lightning
+0 1 1 0.0 4 0 0 15 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Large Lightning Bolt
+A powerful bolt of lightning
+0 1 1 0.0 7 0 0 35 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+*ITEMS*
+Teleport
+Teleports the tank to a random location
+5000 2 1 3 11
+
+Swapper
+Swap places with another tank
+10000 2 1 4 11
+
+Mass Teleport
+Teleports all tanks on the screen
+15000 2 1 4 11
+
+Fan
+Change the wind strength and direction
+2500 3 1 3 2
+
+Vengeance
+A small self-destruct or auto-destruct device, if you've got to go, why not take someone with you?
+20000 1 1 2 0 0 21
+
+Dying Wrath
+A large self/auto-destruct device. Mutually Assured Destruction.
+40000 1 1 3 0 21 3
+
+Fatal Fury
+End it all in style
+60000 1 1 4 0 22 3
+
+Light Shield
+A small amount of protection from damage
+10000 3 0 1 0 50 0 0 255 0 1
+
+Medium Shield
+Protects against  damage
+20000 2 0 2 0 100 0 64 255 0 3
+
+Heavy Shield
+A large amount of protection from damage
+30000 2 0 4 0 150 0 128 255 64 6
+
+Light Repulsor Shield
+Lightly repels enemy missiles
+10000 3 0 2 0 10 250 128 0 255 1
+
+Medium Repulsor Shield
+Repels enemy missiles
+20000 2 0 3 0 20 500 192 64 255 3
+
+Heavy Repulsor Shield
+Strongly repels enemy missiles
+40000 1 0 5 0 40 1000 255 128 255 6
+
+Armour Plating
+Permanently add a small increase to the damage your tanks can take. Each additional purchase adds a slightly smaller amount to your tank's armour.
+20000 1 0 2 0 300
+
+Plasteel Plating
+Permanently increase the damage your tanks can take. Each additional purchase adds a slightly smaller amount to your tank's armour.
+40000 1 0 4 0 2155
+
+Intensity Amplifier
+A small permanent increase to the damage done by your weapons. The efficiency decreases and therefore each additional purchase has a reduced affect.
+21000 1 0 3 0 0.10
+
+Violent Force
+Permanently increase the damage done by your weapons. The efficiency decreases and as a result each additional purchase provides a smaller increase.
+50000 1 0 3 0 0.30
+
+Slick Projectiles
+A Teflon coating for projectiles to reduce drag and the affect of the wind
+1000 50 0 3 0 0.5
+
+Dimpled Projectiles
+Small dimples in the skin of projectiles for massive reduction in drag
+2000 50 0 4 0 0.1
+
+Parachute
+Allows the tank to float gently to the ground
+5000 10 0 0 0 0 0
+
+Auto-repair kit
+Repairs the tank a little each turn. Each additional kit provides a slightly smaller increase to your armour.
+10000 1 0 2 0 0 0
+
+Fuel
+Allows the tank to move across level terran.
+1000 10 0 2 0 0 0
+
+Rocket
+Launches the tank into the air.
+2000 2 1 4 0 0 0
+
+SDI Missile Defense
+Offers some protection against incoming missiles.
+10000 1 0 5 0 0
+
diff --git a/text/weapons_ES.txt b/text/weapons_ES.txt
new file mode 100644
index 0000000..a5c60f7
--- /dev/null
+++ b/text/weapons_ES.txt
@@ -0,0 +1,343 @@
+*WEAPONS*
+Misil peque�o
+Produce un bajo impacto de explosi�n
+1500 10 10 0.2 25 0 2 30 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Misil medio
+Bajo rendimiento, peque�a �rea de explosi�n
+2000 5 15 0.2 40 0 2 40 0 1 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Misil largo
+Rendimiento medio, �re media de explosi�n
+4000 3 20 0.2 60 1 3 60 0 2 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Peque�a arma nuclear
+Alto rendimiento, �rea larga de explosi�n
+16000 2 40 0.2 100 2 4 100 0 3 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Arma nuclear
+Muy alto rendimiento, enorme explosi�n
+22000 1 60 0.2 150 2 5 150 0 4 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cabeza de muerte
+Masiva, explosi�n mortal
+30000 1 80 0.2 200 3 6 200 0 5 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Peque�a propagaci�n
+5 Peque�os misiles en un �nico tiro
+5000 3 10 0.2 25 0 2 30 0 0 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Media propagaci�n
+5 Misiles medios en un �nico disparo
+11000 2 15 0.2 40 0 2 40 0 1 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Larga propagaci�n
+5 Largos misiles en un solo dispao
+17000 1 20 0.2 60 1 3 60 0 2 5 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Super propagaci�n
+4 Peque�as armas nucleares en un solo disparo
+25000 1 40 0.2 100 2 4 100 0 3 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Propagaci�n de muerte
+3 Armas nucleares en un solo disparo
+50000 1 60 0.2 150 2 5 150 0 4 3 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Armagedon
+3 Cabezas de muerte en un solo disparo
+100000 1 80 0.2 200 3 6 200 0 5 3 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Cadena de misiles
+Disparos de tres peque�os misiles
+4000 3 10 0.2 25 0 2 30 0 0 1 3 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Ca�on de cadenas
+Dispara 5 peque�os misiles
+6000 10 10 0.2 25 0 2 30 0 0 1 5 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Jack Hammer
+Disparo de 8 peque�os misiles
+8000 16 10 0.2 25 0 2 30 0 0 1 8 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Carga formada
+Alto rendimiento de explosi�n horizontal. Toda la energ�a es enfocada fuera de los lados, aumentado el da�o hecho pero reduciendo el area total de explosi�n.
+10000 5 10 0.2 100 2 3 100 0 17 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Chico amplio
+Explosi�n devastadora horizontal. Toda la energ�a es enfocada fuera de los lados, aumentado el da�o hecho pero reduciendo el area total de explosi�n.
+15000 2 10 0.2 200 2 4 200 0 18 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cutter
+Explosi�n Horizontal que arrasar� con algo del camino. Toda la energ�a es enfocada fuera de los lados, aumentado el da�o hecho pero reduciendo el area total de explosi�n en comparaci�n de una descontrolada explosi�n.
+20000 1 10 0.2 300 3 5 300 0 19 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Pequ�a apisonadora
+Explosi�n media cuando la rueda golpee algo
+2000 3 20 0.2 40 0 2 40 0 6 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Larga Apisonadora
+Larga explosi�n cuando la rueda golpee algo
+8000 1 30 0.2 60 1 3 60 0 6 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Apisonadora de muerte
+Enorme explosi�n cuando la rueda golpee algo
+14000 1 40 0.2 100 2 4 100 0 6 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Peque�a MIRV
+Caida de un grupo de misiles largos desde el suelo
+20000 1 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 2 1.0 120 0.0 1.0 0 -1 0
+
+Armadura penetrante
+Un peque�o, poderoso proyectil que noquea tanques
+2500 5 30 0.2 15 0 2 80 0 27 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Grupo de Bombas
+Medio rendimiento de impacto y dispersaci�n de Bombas
+10000 3 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 60 0 3.5 0 -1 0
+
+Super Bombas
+Alto rendimiento de impacto y dispersaci�n de Bombas
+20000 2 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 30 0.0 60 0 3.5 0 -1 0
+
+Bomba divertida
+Impredecible y altamente destructiva
+30000 3 50 0.2 200 0 0 200 0 9 1 0 0 3 0 10 27 0.0 360 1.0 0.5 0.1 -1 0
+
+Muerte divertida
+Impredecible y extremadamente destructiva
+50000 1 90 0.2 300 2 1 300 0 9 1 0 0 4 0 10 28 0.0 360 1.0 0.5 0.1 -1 0
+
+Divertido bombazo
+Rendimiento medio de explosi�n de ojiva
+7000 3 5 0.01 40 0 0 50 0 10 1 0 1 1 1 0 -1 0 0 0 0 0 125 1.0
+
+Mortalmente Divertido
+Alto rendimiento de explosi�n de ojiva
+9000 2 9 0.01 100 2 1 90 0 10 1 0 1 3 1 0 -1 0 0 0 0 0 175 1.0
+
+Bombazo
+Medio rendimiento de explosi�n de ojiva
+3500 3 20 0.2 40 0 2 40 0 8 1 0 0 1 1 0 -1 0 0 0 0 0 -1 0
+
+Super Bombazo
+Alto rendimiento de explosi�n de ojiva
+5000 2 40 0.2 60 1 2 65 0 8 1 0 0 3 1 0 -1 0 0 0 0 0 -1 0
+
+Burrower
+Burrows llegan a la superficie antes de explotar, bien contra tanques. El Burrower est� dise�ado para estar abajo y salir a la superficie con alta resistencia.
+7500 3 100 0.4 50 0 2 50 0 25 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Penetrador
+Penetradores van abajo antes de ascender a la superficie. El Penetrador explotar� al salir y tener contacto con cualquier objeto.
+20000 2 150 0.4 80 0 2 100 0 26 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Peque�a Bomba  Napalm 
+Peque�as cantidades de dispersaci�n de Napales de intensamente impacto
+6000 3 80 0.2 80 1 1 80 0 9 1 0 0 3 0 10 36 0.0 90 0.2 2.5 1.0 -1 0
+
+Media Bomba  Napalm 
+Quemadura intensa de impacto de Napalm
+14000 2 200 0.2 150 1 1 200 0 9 1 0 0 4 0 25 36 0.0 90 0.2 3 1.0 -1 0
+
+Larga Bomba Napalm
+Cobertura circundante del area con intensamente ardimiento al impacto
+22000 1 400 0.2 200 1 2 500 0 9 1 0 0 5 0 60 36 0.0 90 0.2 5 1.0 -1 0
+
+Pasta Napalm
+Ardimiento Intensamente qu�mico
+2000 5 5 0.5 10 1 10 30 0 0 1 0 0 2 1 0 -1 0 0 0 0 0 -1 0
+
+Taladror
+Explosi�n vertical que  hace un peque�o da�o, pero crea un profundo hoyo en el suelo.
+5000 2 10 0.2 300 3 5 10 0 28 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Temblor
+Produce un peque�o terremoto al impacto
+3000 5 30 0.2 40 0 2 10 0 14 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Ola de impresi�n
+Produce un largo temblor de impacto
+10000 2 60 0.2 100 2 3 20 0 15 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cambio Tect�nico
+Produce un enorme temblor al impacto
+30000 1 100 0.2 150 2 4 30 0 16 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Boma Disturbios
+Destruye un peque�o volumen de suciedad sin perjudicar algo m�s
+2000 5 15 0.2 25 0 2 0 0 23 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Pesada Bomba de Disturbios
+Destruye un largo volumen de suciedad sin perjudicar algo m�s
+3000 2 30 0.2 100 1 2 0 0 24 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Carga de Disturbios
+Cortes a trav�s de un cono que va directamente al frente del arma
+1000 5 15 0.2 50 0 2 0 0 11 1 0 1 1 0 0 -1 0 0 0 0 0 0 0
+
+Explosi�n de Disturbios
+Cortes a trav�s de un largo cono que va directamente al frente del arma
+2000 2 30 0.2 150 1 2 0 0 12 1 0 1 3 0 0 -1 0 0 0 0 0 0 0
+
+Bola de suciedad
+PProduce una peque�a esfera de material que da�a a tus oponentes
+3000 5 15 0.2 25 0 2 0 0 11 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Larga Bola de Suciedad Dirt Ball
+Produce una larga esfera de material que da�a a tus oponentes 
+7000 2 30 0.2 60 1 2 0 0 12 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Super Bola de Suciedad
+Produce una enorme esfera de material que da�a a tus oponentes 
+10000 1 60 0.2 100 2 2 0 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Peque�a propagaci�n de Suciedad
+Peque�a gota de suciedad en tus enemigos
+4000 2 30 0.2 40 1 2 0 0 12 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Grupo MIRV
+Lanzamiento de peque�os misiles en caidas
+10000 2 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 45 0 2.0 0 -1 0
+
+Bomba Por Ciento
+Destruye la mitad de protecci�n de las armaduras
+12000 2 30 0.2 30 2 4 0 0 29 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Reductor
+Baja el poder de explosion de los misiles enemigos.
+6000 3 25 0.3 30 2 4 0 0 30 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Peque�o Laser
+Emite 50kW de laser.
+5000 5 1 0.0 2 0 0 30 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Laser Medio
+Emite 100kW de laser
+10000 3 1 0.0 5 0 0 65 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Laser Largo
+Emite poderosos 200kW de laser
+15000 2 1 0.0 9 0 0 150 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+*NATURALS*
+Peque�o Meteoro
+Un peque�o trozo de roca de los cielos
+0 1 15 0.2 25 0 0 5 0 20 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Meteoro Medio
+Un  trozo mediano de roca de los cielos
+0 1 20 0.2 40 0 0 10 0 21 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Meteoro Largo
+Un  trozo largo de roca de los cielos
+0 1 25 0.2 60 1 1 20 0 22 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Peque�o rayo rel�mpago
+Un d�bil rayo de rel�mpago.
+0 1 1 0.0 1 0 0 5 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Medio rayo rel�mpago
+Un rayo de rel�mpago
+0 1 1 0.0 4 0 0 15 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Largo  rayo rel�mpago 
+Un poderoso rayo de rel�mpago
+0 1 1 0.0 7 0 0 35 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+*ITEMS*
+Teletransportador
+Tele transporta el tanque a un lugar aleatorio
+5000 2 1 3 11
+
+Cambiador
+Cambia lugares con otro tanque
+10000 2 1 4 11
+
+Gran Teletransportador
+Tele transporta todos los tanques de la pantalla
+15000 2 1 4 11
+
+Ventilador
+Cambia la fuerza y direcci�n del viento
+2500 3 1 3 2
+
+Venganza
+Un peque�o dispositivo auto-destructor, si tienes que irte, por qu� no llevarte a alguien contigo?
+20000 1 1 2 0 0 21
+
+Ira Moribunda
+Un dispositivo largo de auto-destrucci�n. Destrucci�n Mutuamente Segura.
+40000 1 1 3 0 21 3
+
+Furia Fatal
+Acabalo todo con Estilo
+60000 1 1 4 0 22 3
+
+Luz Protectora
+Una peque�a cantidad de protecci�n de da�os
+10000 3 0 1 0 50 0 0 255 0 1
+
+Escudo Medio
+Protecci�n contra da�os
+20000 2 0 2 0 100 0 64 255 0 3
+
+Escudo Pesado
+Una larga cantidad de protecci�n de da�os 
+30000 2 0 4 0 150 0 128 255 64 6
+
+Escudo Repulsor de Luz
+Repele ligeramente los misiles enemigos
+10000 3 0 2 0 10 250 128 0 255 1
+
+Escudo Repulsor Medio
+Repele los misiles enemigos
+20000 2 0 3 0 20 500 192 64 255 3
+
+Pesado Escudo Repulsor
+Repele fuertemente los misiles enemigos
+40000 1 0 5 0 40 1000 255 128 255 6
+
+Armadura Blindada
+Permanentemente a�ade un peque�o incremento al da�o que tus tanques pueden llevar. Cada compra adicional a�ade un peque�o monto a la armadura de tu tanque.
+20000 1 0 2 0 300
+
+Plasteel Plating
+Permanentemente a�ade un peque�o incremento al da�o que tus tanques pueden llevar. Cada compra adicional a�ade un peque�o monto a la armadura de tu tanque.
+40000 1 0 4 0 2155
+
+Amplifcador de Intensidad
+Un permanemte peque�o incremento al da�o hecho por tus armas. La eficiencia disminuye y por tanto cada compra adicional tiene un afecto reducido.
+21000 1 0 3 0 0.10
+
+Fuerza Violenta
+Un permanemte peque�o incremento al da�o hecho por tus armas. La eficiencia disminuye y como un resultado de compra adicional provee un peque�o incremento.
+50000 1 0 3 0 0.30
+
+Proyectiles Mejorados
+Una capa de Teflon para proyectiles que reduce el arrastre y afecta al viento
+1000 50 0 3 0 0.5
+
+Proyectiles Perforados
+Peque�os hoyuelos en la piel de los proyectiles para la reducci�n masica en el arrastre
+2000 50 0 4 0 0.1
+
+Paraca�das
+Permite al tanque flotar con delicadeza al suelo
+5000 10 0 0 0 0 0
+
+Kit de Auto-Reparaci�n
+Repara un poco el tanque en cada turno. Cada kit adicional provee un peque�o increment a tu armadura.
+10000 1 0 2 0 0 0
+
+Combustible
+Permite al tanque moverse en el terreno.
+1000 10 0 2 0 0 0
+
+Cohete
+Lanzamientos del tanque al aire.
+2000 2 1 4 0 0 0
+
+SDI Missile Defensa
+Ofrcece alguna protecci�n contra la llegada de misiles.
+10000 1 0 5 0 0
+
diff --git a/text/weapons_de.txt b/text/weapons_de.txt
new file mode 100644
index 0000000..7f98eb0
--- /dev/null
+++ b/text/weapons_de.txt
@@ -0,0 +1,343 @@
+*WEAPONS*
+Kleine Rakete
+Kleine Explosion beim Einschlag.
+1500 10 10 0.2 25 0 2 30 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Mittlere Rakete
+Kleine Wirkung, kleinflächige Explosion.
+2000 5 15 0.2 40 0 2 40 0 1 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Große Rakete
+Mittlerer Wirkung, mittelflächige Explosion.
+4000 3 20 0.2 60 1 3 60 0 2 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Kleine Atombombe
+Große Wirkung, großflächige Explosion.
+16000 2 40 0.2 100 2 4 100 0 3 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Atombombe
+Sehr große Wirkung, riesige Explosion.
+22000 1 60 0.2 150 2 5 150 0 4 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Totenkopf
+Massive, tötliche Explosion.
+30000 1 80 0.2 200 3 6 200 0 5 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Kleiner Streuer
+5 Kleine Raketen mit einem Schuss.
+5000 3 10 0.2 25 0 2 30 0 0 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Mittlerer Streuer
+5 Mittlere Raketen mit einem Schuss.
+11000 2 15 0.2 40 0 2 40 0 1 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Großer Streuer
+5 Große Raketen mit einem Schuss.
+17000 1 20 0.2 60 1 3 60 0 2 5 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Super Streuer
+4 Kleine Atombomben mit einem Schuss.
+25000 1 40 0.2 100 2 4 100 0 3 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Todesstreuer
+3 Atombomben mit einem Schuss.
+50000 1 60 0.2 150 2 5 150 0 4 3 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Armageddon
+3 Totenköpfe mit einem Schuss.
+100000 1 80 0.2 200 3 6 200 0 5 3 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Kleine Raktenkette
+Feuert drei kleine Rakten nacheinander ab.
+4000 3 10 0.2 25 0 2 30 0 0 1 3 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Raketenkette
+Feuert fünf kleine Rakten nacheinander ab.
+6000 10 10 0.2 25 0 2 30 0 0 1 5 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Jack Hammer
+Feuert acht kleine Rakten nacheinander ab.
+8000 16 10 0.2 25 0 2 30 0 0 1 8 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Shaped Charge
+Hoch wirksame horizontale Explosion. Die gesamte Energie ist zu den Seiten fokusiert und erhöht den Schaden und verdampft die gesamte Umgebung im Bereich der Explosion.
+10000 5 10 0.2 100 2 3 100 0 17 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Wide Boy
+Verheerende horizontale Explosion. Die gesamte Energie ist zu den Seiten fokusiert und erhöht den Schaden und verdampft die gesamte Umgebung im Bereich der Explosion.
+15000 2 10 0.2 200 2 4 200 0 18 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cutter
+Horizontale Explosion die alles auslöscht, was in ihren Weg kommt. Die gesamte Energie ist zu den Seiten fokusiert und erhöht den Schaden und verdampft die gesamte Umgebung im Bereich der Explosion, vergleichbar mit einer ebensogrßen unkontrollierten Sprengung.
+20000 1 10 0.2 300 3 5 300 0 19 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Kleiner Roller
+Mittel explosiver Sprengsatz, der den Berg hinunter rollt bis er etwas trifft.
+2000 3 20 0.2 40 0 2 40 0 6 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Großer Roller
+Großer explosiver Sprengsatz, der den Berg hinunter rollt bis er etwas trifft.
+8000 1 30 0.2 60 1 3 60 0 6 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Todesroller
+Riesiger explosiver Sprengsatz, der den Berg hinunter rollt bis er etwas trifft.
+14000 1 40 0.2 100 2 4 100 0 6 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Kleiner MIRV
+Wirft eine Gruppe großer Raketen von oben auf das Zielgebiet.
+20000 1 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 2 1.0 120 0.0 1.0 0 -1 0
+
+Rüstungsknacker
+Eine kleine, wirksame Granatedie die Panzer zerstören kann.
+2500 5 30 0.2 15 0 2 80 0 27 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Cluster Bombe
+Streut einen mittelwirksamen Bombentepich, der beim Aufschlag explodiert.
+10000 3 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 60 0 3.5 0 -1 0
+
+Super Cluster
+Streut einen hochwirksamen Bombentepich, der beim Aufschlag explodiert.
+20000 2 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 30 0.0 60 0 3.5 0 -1 0
+
+Funky Bombe
+Unberechenbar und hoch zerstörerisch.
+30000 3 50 0.2 200 0 0 200 0 9 1 0 0 3 0 10 27 0.0 360 1.0 0.5 0.1 -1 0
+
+Funky Tod
+Unberechenbar und extrem zerstörerisch.
+50000 1 90 0.2 300 2 1 300 0 9 1 0 0 4 0 10 28 0.0 360 1.0 0.5 0.1 -1 0
+
+Funky Bombenteppich
+Mittel wirksamer explosiver Sprengkopf.
+7000 3 5 0.01 40 0 0 50 0 10 1 0 1 1 1 0 -1 0 0 0 0 0 125 1.0
+
+Funky Todesteppich
+Hoch wirksamer explosiver Sprengkopf.
+9000 2 9 0.01 100 2 1 90 0 10 1 0 1 3 1 0 -1 0 0 0 0 0 175 1.0
+
+Bombenteppich
+Mittel wirksamer explosiver Sprengkopf.
+3500 3 20 0.2 40 0 2 40 0 8 1 0 0 1 1 0 -1 0 0 0 0 0 -1 0
+
+Super Bombenteppich
+Hoch wirksamer explosiver Sprengkopf.
+5000 2 40 0.2 60 1 2 65 0 8 1 0 0 3 1 0 -1 0 0 0 0 0 -1 0
+
+Erdfresser
+Bohrt sich zurück zur Oberfläche bevor er explodiert. Gut gegen unterirdische Panzer. Der Erdfresser ist für unterirdische Einsätze entwickelt und leidet unter hohem Luftwiderstand.
+7500 3 100 0.4 50 0 2 50 0 25 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Penetrator
+Bohrt sich unter die Oberfläche bevor er wieder zur Oberfläche kommt. The Penetrator explodiert entweder beim erreichen der Oberfläche oder bei Kontakt mit einem verschütteten Objekt. Diese Rakete ist für unterirdische Einsätze entwickelt und leidet unter hohem Luftwiderstand.
+20000 2 150 0.4 80 0 2 100 0 26 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Kleine Napalmbombe
+Streut beim Einschlag kleine Mengen intensiv brennenden Napalms.
+6000 3 80 0.2 80 1 1 80 0 9 1 0 0 3 0 10 36 0.0 90 0.2 2.5 1.0 -1 0
+
+Mittlere Napalmbombe
+Streut beim Einschlag intensiv brennendes Napalm.
+14000 2 200 0.2 150 1 1 200 0 9 1 0 0 4 0 25 36 0.0 90 0.2 3 1.0 -1 0
+
+Große Napalmbombe
+Überzieht die Umgebung beim Einschlag mit intensiv brennendem Napalm.
+22000 1 400 0.2 200 1 2 500 0 9 1 0 0 5 0 60 36 0.0 90 0.2 5 1.0 -1 0
+
+Napalmgel
+Intensiv brennendes chemisches Gel.
+2000 5 5 0.5 10 1 10 30 0 0 1 0 0 2 1 0 -1 0 0 0 0 0 -1 0
+
+Bohrer
+Vertikale Explosion, die kleinen Schaden anrichtet, aber ein tiefes Loch in die Oberfläche macht.
+5000 2 10 0.2 300 3 5 10 0 28 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Tremor
+Erzeugt beim Einschlag ein kleines Erdbeben.
+3000 5 30 0.2 40 0 2 10 0 14 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Schockwelle
+Erzeugt beim Einschlag ein großes Erdbeben.
+10000 2 60 0.2 100 2 3 20 0 15 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Tektonische Bombe
+Erzeugt beim Einschlag ein riesiges Erdbeben.
+30000 1 100 0.2 150 2 4 30 0 16 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Rebellenbombe
+Zerstört eine kleine Menge Erde ohne etwas anderes zu zerstören.
+2000 5 15 0.2 25 0 2 0 0 23 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Große Rebellenbombe
+Zerstört eine große Menge Erde ohne etwas anderes zu zerstören.
+3000 2 30 0.2 100 1 2 0 0 24 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Kleiner Unruhestifter
+Schneidet einen Kegel aus dem Untergrund, direkt vor der Mündung.
+1000 5 15 0.2 50 0 2 0 0 11 1 0 1 1 0 0 -1 0 0 0 0 0 0 0
+
+Großer Unruhestifter
+Schneidet einen großen Kegel aus dem Untergrund, direkt vor der Mündung.
+2000 2 30 0.2 150 1 2 0 0 12 1 0 1 3 0 0 -1 0 0 0 0 0 0 0
+
+Dreckball
+Erzeugt einen kleinen Hügel um den Gegner zu verschütten.
+3000 5 15 0.2 25 0 2 0 0 11 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Großer Dreckball
+Erzeugt einen großen Hügel um den Gegner zu verschütten.
+7000 2 30 0.2 60 1 2 0 0 12 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Super Dreckball
+Erzeugt einen riesen Hügel um den Gegner zu verschütten.
+10000 1 60 0.2 100 2 2 0 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Kleiner Dreckball
+Drop little piles of dirt on your enemies
+4000 2 30 0.2 40 1 2 0 0 12 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cluster MIRV
+Wirft eine Gruppe kleiner Raketen von oben auf das Zielgebiet.
+10000 2 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 45 0 2.0 0 -1 0
+
+Prozent Bombe
+Zerstört die Hälfte der gegnerischen Panzerung.
+12000 2 30 0.2 30 2 4 0 0 29 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Reduzierer
+Vermindert die Kraft gegnerischer Waffen.
+6000 3 25 0.3 30 2 4 0 0 30 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Kleiner Laser
+Ein 50kW Laserstrahl.
+5000 5 1 0.0 2 0 0 30 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Mittlerer Laser
+Ein 100kW Laserstrahl.
+10000 3 1 0.0 5 0 0 65 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Großer Laser
+Ein kraftvoller 200kW Laserstrahl.
+15000 2 1 0.0 9 0 0 150 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+*NATURALS*
+Kleiner Meteor
+Ein kleiner Felsbrocken vom Himmel.
+0 1 15 0.2 25 0 0 5 0 20 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Mittlerer Meteor
+Ein mittlerer Felsbrocken vom Himmel.
+0 1 20 0.2 40 0 0 10 0 21 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Großer Meteor
+Ein großer Felsbrocken vom Himmel.
+0 1 25 0.2 60 1 1 20 0 22 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Kleiner Blitz
+Ein schwacher Blitz.
+0 1 1 0.0 1 0 0 5 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Mittlerer Blitz
+Ein Blitz.
+0 1 1 0.0 4 0 0 15 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Großer Blitz - Kugelbllitz
+Ein starker Blitz.
+0 1 1 0.0 7 0 0 35 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+*ITEMS*
+Teleport
+Teleportiert den Panzer an einen zufälligen Ort.
+5000 2 1 3 11
+
+Tausch
+Tauscht mit einem anderen Panzer den Platz.
+10000 2 1 4 11
+
+Massenteleportation
+Teleportiert alle Panzer auf dem Bildschirm.
+15000 2 1 4 11
+
+Ventilator
+Ändert Windstärke und -richtung.
+2500 3 1 3 2
+
+Vengeance
+Ein kleiner Selbstzerstörer. Wenn Du gehen musst, warum nicht noch jemanden mitnehmen?
+20000 1 1 2 0 0 21
+
+Todeswut
+Ein großer Selbstzerstörer. Gleichgewicht des Schreckens.
+40000 1 1 3 0 21 3
+
+Tödliche Raserei
+Beendet jedes Laben.
+60000 1 1 4 0 22 3
+
+Schwaches Schild
+Ein kleiner Schutz.
+10000 3 0 1 0 50 0 0 255 0 1
+
+Mittleres Schild
+Schutz gegen Schaden.
+20000 2 0 2 0 100 0 64 255 0 3
+
+Schweres Schild
+EIn starker Schutz.
+30000 2 0 4 0 150 0 128 255 64 6
+
+Kleines Kraftfeld
+Lässt feindliche Raketen leicht abprallen.
+10000 3 0 2 0 10 250 128 0 255 1
+
+Mittleres Kraftfeld
+Lässt feindliche Raketen abprallen.
+20000 2 0 3 0 20 500 192 64 255 3
+
+Starkes Kraftfeld
+Lässt feindliche Raketen stark abprallen.
+40000 1 0 5 0 40 1000 255 128 255 6
+
+Verstärkte Rüstung
+Erhöht die Treffer, die Dein Panzer einstecken kann ein wenig. Jeder weitere Kauf verstärkt die Rüstung Deines Panzers ein wenig.
+20000 1 0 2 0 300
+
+Plastahl Rüstung
+Erhöht die Treffer, die Dein Panzer einstecken kann ein wenig. Jeder weitere Kauf verstärkt die Rüstung Deines Panzers ein wenig.
+40000 1 0 4 0 2155
+
+Intensiver Verstärker
+Eine kleine permanente Erhöhung des Schadens, den Deine Waffe anrichtet. Mit jedem Kauf zeigt der Verstärker weniger Wirkung, so dass weiter Käufe weniger zusätzlichen Schaden bringen.
+21000 1 0 3 0 0.10
+
+Brutaler Verstärker
+Eine permanente Erhöhung des Schadens, den Deine Waffe anrichtet. Mit jedem Kauf zeigt der Verstärker weniger Wirkung, so dass weiter Käufe weniger zusätzlichen Schaden bringen.
+50000 1 0 3 0 0.30
+
+Glatte Projektile
+Eine Teflonbeschichtung reduziert den Luftwiderstand und den Effekt des Windes.
+1000 50 0 3 0 0.5
+
+Genoppte Projektile
+Kleine Noppen auf der Oberfläche der Projektile sorgen für eine massive Reduzierung des Luftwiderstandes.
+2000 50 0 4 0 0.1
+
+Fallschirm
+Erlaubt es dem Panzer sanft auf dem Boden zu landen.
+5000 10 0 0 0 0 0
+
+Reparatursatz
+Repariert den Panzer jede Runde ein wenig. Jeder weitere Reparatursatz unterstützt die Reparatur ein bisschen weniger.
+10000 1 0 2 0 0 0
+
+Benzin
+Erlaubt es dem Panzer, sich auf ebenem Gelände zu bewegen.
+1000 10 0 2 0 0 0
+
+Rakete
+Schießt den Panzer in die Luft.
+2000 2 1 4 0 0 0
+
+SDI Missile Defense System
+Bietet Schutz gegen ankommende Geschosse.
+10000 1 0 5 0 0
+
diff --git a/text/weapons_fr.txt b/text/weapons_fr.txt
new file mode 100644
index 0000000..cb5b8eb
--- /dev/null
+++ b/text/weapons_fr.txt
@@ -0,0 +1,343 @@
+*WEAPONS*
+Small Missile
+Produces a low impact explosion
+1500 10 10 0.2 25 0 2 30 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Missile
+Low yield, small area explosion
+2000 5 15 0.2 40 0 2 40 0 1 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Large Missile
+Medium yield, medium area explosion
+4000 3 20 0.2 60 1 3 60 0 2 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Small Nuke
+High yield, large area explosion
+16000 2 40 0.2 100 2 4 100 0 3 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Nuke
+Very high yield, huge explosion
+22000 1 60 0.2 150 2 5 150 0 4 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Death Head
+Massive, deadly explosion
+30000 1 80 0.2 200 3 6 200 0 5 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Spread
+5 Small missiles in a single shot
+5000 3 10 0.2 25 0 2 30 0 0 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Spread
+5 Medium missiles in a single shot
+11000 2 15 0.2 40 0 2 40 0 1 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Large Spread
+5 Large missiles in a single shot
+17000 1 20 0.2 60 1 3 60 0 2 5 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Super Spread
+4 Small Nukes in a single shot
+25000 1 40 0.2 100 2 4 100 0 3 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Death Spread
+3 Nukes in a single shot
+50000 1 60 0.2 150 2 5 150 0 4 3 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Armageddon
+3 Death Heads in a single shot
+100000 1 80 0.2 200 3 6 200 0 5 3 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Chain Missile
+Fires a volly of three small missiles
+4000 3 10 0.2 25 0 2 30 0 0 1 3 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Chain Gun
+Fires a volly of five small missiles
+6000 10 10 0.2 25 0 2 30 0 0 1 5 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Jack Hammer
+Fires a volly of eight small missiles
+8000 16 10 0.2 25 0 2 30 0 0 1 8 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Shaped Charge
+High yield horizontal explosion. All of the energy is focused out to the sides, increasing the damage done but reducing the overall area of the explosion.
+10000 5 10 0.2 100 2 3 100 0 17 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Wide Boy
+Devastating horizontal explosion. All of the energy is focused out to the sides, increasing the damage done but reducing the overall area of the explosion.
+15000 2 10 0.2 200 2 4 200 0 18 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cutter
+Horizontal explosion that will obliterate anything that gets in the way. All of the energy is focused out to the sides, increasing the damage done but reducing the overall area of the explosion in comparison to a similar sized uncontrolled blast.
+20000 1 10 0.2 300 3 5 300 0 19 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Small Roller
+Medium explosive which rolls downhill until it hits something
+2000 3 20 0.2 40 0 2 40 0 6 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Large Roller
+Large explosive which rolls downhill until it hits something
+8000 1 30 0.2 60 1 3 60 0 6 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Death Roller
+Huge explosive which rolls downhill until it hits something
+14000 1 40 0.2 100 2 4 100 0 6 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small MIRV
+Drops a group of large missiles on the ground from above
+20000 1 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 2 1.0 120 0.0 1.0 0 -1 0
+
+Armour Piercing
+A small, powerful shell that knocks out tanks
+2500 5 30 0.2 15 0 2 80 0 27 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Cluster Bomb
+Scatters medium yield bomblets on impact
+10000 3 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 60 0 3.5 0 -1 0
+
+Super Cluster
+Scatters high yield bomblets on impact
+20000 2 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 30 0.0 60 0 3.5 0 -1 0
+
+Funky Bomb
+Unpredictable and highly destructive
+30000 3 50 0.2 200 0 0 200 0 9 1 0 0 3 0 10 27 0.0 360 1.0 0.5 0.1 -1 0
+
+Funky Death
+Unpredictable and extremely destructive
+50000 1 90 0.2 300 2 1 300 0 9 1 0 0 4 0 10 28 0.0 360 1.0 0.5 0.1 -1 0
+
+Funky Bomblet
+Medium yield explosive warhead
+7000 3 5 0.01 40 0 0 50 0 10 1 0 1 1 1 0 -1 0 0 0 0 0 125 1.0
+
+Funky Deathlet
+High yield explosive warhead
+9000 2 9 0.01 100 2 1 90 0 10 1 0 1 3 1 0 -1 0 0 0 0 0 175 1.0
+
+Bomblet
+Medium yield explosive warhead
+3500 3 20 0.2 40 0 2 40 0 8 1 0 0 1 1 0 -1 0 0 0 0 0 -1 0
+
+Super Bomblet
+High yield explosive warhead
+5000 2 40 0.2 60 1 2 65 0 8 1 0 0 3 1 0 -1 0 0 0 0 0 -1 0
+
+Burrower
+Burrows back up to the surface before exploding, good against buried tanks. The Burrower is designed for below-ground use and suffers from high air-resistance.
+7500 3 100 0.4 50 0 2 50 0 25 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Penetrator
+Penetrates below ground before rising to the surface. The Penetrator will either explode on exit from the ground or on contact with buried objects. This missile is designed for burrowing and as a result suffers from high air-resistance.
+20000 2 150 0.4 80 0 2 100 0 26 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Napalm Bomb
+Scatters small quantities of intensely burning napalm on impact
+6000 3 80 0.2 80 1 1 80 0 9 1 0 0 3 0 10 36 0.0 90 0.2 2.5 1.0 -1 0
+
+Medium Napalm Bomb
+Scatters intensely burning napalm on impact
+14000 2 200 0.2 150 1 1 200 0 9 1 0 0 4 0 25 36 0.0 90 0.2 3 1.0 -1 0
+
+Large Napalm Bomb
+Covers the surrounding area with intensely burning napalm on impact
+22000 1 400 0.2 200 1 2 500 0 9 1 0 0 5 0 60 36 0.0 90 0.2 5 1.0 -1 0
+
+Napalm Jelly
+Intensely burning chemical jelly
+2000 5 5 0.5 10 1 10 30 0 0 1 0 0 2 1 0 -1 0 0 0 0 0 -1 0
+
+Driller
+Vertical explosion that will do little damage, but create a deep hole in the ground.
+5000 2 10 0.2 300 3 5 10 0 28 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Tremor
+Produce a small earthquake on impact
+3000 5 30 0.2 40 0 2 10 0 14 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Shock Wave
+Produce a large earthquake on impact
+10000 2 60 0.2 100 2 3 20 0 15 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Tectonic Shift
+Produce a huge earthquake on impact
+30000 1 100 0.2 150 2 4 30 0 16 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Riot Bomb
+Destroy a small volume of dirt without damaging anything else
+2000 5 15 0.2 25 0 2 0 0 23 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Heavy Riot Bomb
+Destroy a large volume of dirt without damaging anything else
+3000 2 30 0.2 100 1 2 0 0 24 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Riot Charge
+Cuts through a cone of dirt directly in front of the gun
+1000 5 15 0.2 50 0 2 0 0 11 1 0 1 1 0 0 -1 0 0 0 0 0 0 0
+
+Riot Blast
+Cuts through a large cone of dirt directly in front of the gun
+2000 2 30 0.2 150 1 2 0 0 12 1 0 1 3 0 0 -1 0 0 0 0 0 0 0
+
+Dirt Ball
+Produce a small sphere of material to bury your opponents
+3000 5 15 0.2 25 0 2 0 0 11 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Large Dirt Ball
+Produce a large sphere of material to bury your opponents
+7000 2 30 0.2 60 1 2 0 0 12 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Super Dirt Ball
+Produce a huge ball of material to bury your opponents
+10000 1 60 0.2 100 2 2 0 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Dirt Spread
+Drop little piles of dirt on your enemies
+4000 2 30 0.2 40 1 2 0 0 12 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cluster MIRV
+Releases a cluster of small missiles on its way down
+10000 2 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 45 0 2.0 0 -1 0
+
+Per Cent Bomb
+Destroys half of the target's armour
+12000 2 30 0.2 30 2 4 0 0 29 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Reducer
+Lowers the explosive power of an enemy's missiles.
+6000 3 25 0.3 30 2 4 0 0 30 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Laser
+A 50kW laser beam.
+5000 5 1 0.0 2 0 0 30 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Laser
+A 100kW laser beam
+10000 3 1 0.0 5 0 0 65 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Large Laser
+A powerful 200kW laser beam
+15000 2 1 0.0 9 0 0 150 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+*NATURALS*
+Small Meteor
+A small chunk of rock from the skies
+0 1 15 0.2 25 0 0 5 0 20 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Meteor
+A medium chunk of rock from the skies
+0 1 20 0.2 40 0 0 10 0 21 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Large Meteor
+A large chunk of rock from the skies
+0 1 25 0.2 60 1 1 20 0 22 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Small Lightning Bolt
+A weak bolt of lightning.
+0 1 1 0.0 1 0 0 5 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Medium Lightning Bolt
+A bolt of lightning
+0 1 1 0.0 4 0 0 15 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Large Lightning Bolt
+A powerful bolt of lightning
+0 1 1 0.0 7 0 0 35 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+*ITEMS*
+Teleport
+Teleports the tank to a random location
+5000 2 1 3 11
+
+Swapper
+Swap places with another tank
+10000 2 1 4 11
+
+Mass Teleport
+Teleports all tanks on the screen
+15000 2 1 4 11
+
+Fan
+Change the wind strength and direction
+2500 3 1 3 2
+
+Vengeance
+A small self-destruct or auto-destruct device, if you've got to go, why not take someone with you?
+20000 1 1 2 0 0 21
+
+Dying Wrath
+A large self/auto-destruct device. Mutually Assured Destruction.
+40000 1 1 3 0 21 3
+
+Fatal Fury
+End it all in style
+60000 1 1 4 0 22 3
+
+Light Shield
+A small amount of protection from damage
+10000 3 0 1 0 50 0 0 255 0 1
+
+Medium Shield
+Protects against  damage
+20000 2 0 2 0 100 0 64 255 0 3
+
+Heavy Shield
+A large amount of protection from damage
+30000 2 0 4 0 150 0 128 255 64 6
+
+Light Repulsor Shield
+Lightly repels enemy missiles
+10000 3 0 2 0 10 250 128 0 255 1
+
+Medium Repulsor Shield
+Repels enemy missiles
+20000 2 0 3 0 20 500 192 64 255 3
+
+Heavy Repulsor Shield
+Strongly repels enemy missiles
+40000 1 0 5 0 40 1000 255 128 255 6
+
+Armour Plating
+Permanently add a small increase to the damage your tanks can take. Each additional purchase adds a slightly smaller amount to your tank's armour.
+20000 1 0 2 0 300
+
+Plasteel Plating
+Permanently increase the damage your tanks can take. Each additional purchase adds a slightly smaller amount to your tank's armour.
+40000 1 0 4 0 2155
+
+Intensity Amplifier
+A small permanent increase to the damage done by your weapons. The efficiency decreases and therefore each additional purchase has a reduced affect.
+21000 1 0 3 0 0.10
+
+Violent Force
+Permanently increase the damage done by your weapons. The efficiency decreases and as a result each additional purchase provides a smaller increase.
+50000 1 0 3 0 0.30
+
+Slick Projectiles
+A Teflon coating for projectiles to reduce drag and the affect of the wind
+1000 50 0 3 0 0.5
+
+Dimpled Projectiles
+Small dimples in the skin of projectiles for massive reduction in drag
+2000 50 0 4 0 0.1
+
+Parachute
+Allows the tank to float gently to the ground
+5000 10 0 0 0 0 0
+
+Auto-repair kit
+Repairs the tank a little each turn. Each additional kit provides a slightly smaller increase to your armour.
+10000 1 0 2 0 0 0
+
+Fuel
+Allows the tank to move across level terran.
+1000 10 0 2 0 0 0
+
+Rocket
+Launches the tank into the air.
+2000 2 1 4 0 0 0
+
+SDI Missile Defense
+Offers some protection against incoming missiles.
+10000 1 0 5 0 0
+
diff --git a/text/weapons_it.txt b/text/weapons_it.txt
new file mode 100644
index 0000000..50356a1
--- /dev/null
+++ b/text/weapons_it.txt
@@ -0,0 +1,343 @@
+*WEAPONS*
+Missile Piccolo
+Produce una piccola esplosione all'impatto
+1500 10 10 0.2 25 0 2 30 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Missile Medio
+Basso rendimento, piccola area esplosione
+2000 5 15 0.2 40 0 2 40 0 1 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Missile Grande
+Medio rendimento, media area esplosione
+4000 3 20 0.2 60 1 3 60 0 2 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Bomba Nucleare Piccola
+Alto rendimento, larga area esplosione
+16000 2 40 0.2 100 2 4 100 0 3 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Bomba Nucleare
+Altissimo rendimento, enorme area esplosione
+22000 1 60 0.2 150 2 5 150 0 4 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Testata della Morte
+Massivo, esplosione mortale
+30000 1 80 0.2 200 3 6 200 0 5 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Piccola Diffusione
+5 Piccoli missili in un sigolo colpo
+5000 3 10 0.2 25 0 2 30 0 0 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Media Diffusione
+5 Medio missili in un sigolo colpo
+11000 2 15 0.2 40 0 2 40 0 1 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Grande Diffusione
+5 Grandi missili in un sigolo colpo
+17000 1 20 0.2 60 1 3 60 0 2 5 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Super Diffusione
+4 Piccole Bombe Nucleari in un sigolo colpo
+25000 1 40 0.2 100 2 4 100 0 3 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Mortale Diffusione
+3 Bombe Nucleari in un sigolo colpo
+50000 1 60 0.2 150 2 5 150 0 4 3 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Armageddon
+3 Testate della Morte in un sigolo colpo
+100000 1 80 0.2 200 3 6 200 0 5 3 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Missile Concatenato
+Fuoco con un colpo di tre piccoli missili
+4000 3 10 0.2 25 0 2 30 0 0 1 3 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Cannone Concatenato
+Fuoco con un colpo di cinque piccoli missili
+6000 10 10 0.2 25 0 2 30 0 0 1 5 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Jack Hammer
+Fuoco con un colpo di otto piccoli missili
+8000 16 10 0.2 25 0 2 30 0 0 1 8 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Shaped Charge
+Esplosione orizzontale ad alto rendimento. Tutta l'energia e' focalizzata sui lati, incrementando la distruzione, ma riducendo l'area dell'esplosione.
+10000 5 10 0.2 100 2 3 100 0 17 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Wide Boy
+Esplosione orizzontale devastante. Tutta l'energia e' focalizzata sui lati, incrementando la distruzione, ma riducendo l'area dell'esplosione.
+15000 2 10 0.2 200 2 4 200 0 18 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cutter
+Esplosione orizzontale che cancellera' tutto quello che trovera' per la strada. Tutta l'energia e' focalizzata sui lati, incrementando la distruzione, ma riducendo l'area dell'esplosione similarmente a quanto ottenuto con uno scoppio incontrollato.
+20000 1 10 0.2 300 3 5 300 0 19 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Roller Piccolo
+Esplosione Media con dispositivo rotolante che esplodera' quando tocchera' qualcosa.
+2000 3 20 0.2 40 0 2 40 0 6 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Roller Grande
+Esplosione Grande con dispositivo rotolante che esplodera' quando tocchera' qualcosa.
+8000 1 30 0.2 60 1 3 60 0 6 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Roller della Morte
+Esplosione Enorme con dispositivo rotolante che esplodera' quando tocchera' qualcosa.
+14000 1 40 0.2 100 2 4 100 0 6 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+MIRV Piccolo
+Caduta un gruppo di grandi missili.
+20000 1 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 2 1.0 120 0.0 1.0 0 -1 0
+
+Perforatore di Corazza
+Un piccolo, potentissimo perforatore di corazza dei tank
+2500 5 30 0.2 15 0 2 80 0 27 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Bomba Cluster
+Spargimenti a Medio rendimento di mazzi di bombe a impatto
+10000 3 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 60 0 3.5 0 -1 0
+
+Super Cluster
+Spargimenti ad Alto rendimento di mazzi di bombe a impatto
+20000 2 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 30 0.0 60 0 3.5 0 -1 0
+
+Bomba Funky
+Imprevedibile ed altamente distruttivo
+30000 3 50 0.2 200 0 0 200 0 9 1 0 0 3 0 10 27 0.0 360 1.0 0.5 0.1 -1 0
+
+Funky Mortale
+Imprevedibile ed estremamente distruttivo
+50000 1 90 0.2 300 2 1 300 0 9 1 0 0 4 0 10 28 0.0 360 1.0 0.5 0.1 -1 0
+
+Proietto Funky
+Testata esplosiva a medio rendimento
+7000 3 5 0.01 40 0 0 50 0 10 1 0 1 1 1 0 -1 0 0 0 0 0 125 1.0
+
+Funky Quasi Mortale
+Testata esplosiva ad alto rendimento
+9000 2 9 0.01 100 2 1 90 0 10 1 0 1 3 1 0 -1 0 0 0 0 0 175 1.0
+
+Proietto
+Testata esplosiva a medio rendimento
+3500 3 20 0.2 40 0 2 40 0 8 1 0 0 1 1 0 -1 0 0 0 0 0 -1 0
+
+Super Proietto
+Testata esplosiva ad alto rendimento
+5000 2 40 0.2 60 1 2 65 0 8 1 0 0 3 1 0 -1 0 0 0 0 0 -1 0
+
+Scavatore
+Scava nel terreno fino alla superficie prima dell'esplosione, buono contro i carri armati sepolti. Lo Scavatore � progettato per uso sotterraneo e soffre di conseguenza all'esposiizone all'aria.
+7500 3 100 0.4 50 0 2 50 0 25 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Penetratore
+Penetra sepolto prima di sorgere alla superficie. Il Penetratore esploder� sia all'uscita dal suolo, sia al contatto con gli oggetti sepolti. Questo missile � disegnato per scavare e soffre di conseguenza all'esposiizone all'aria.
+20000 2 150 0.4 80 0 2 100 0 26 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Piccola Bomba al Napalm
+Copre l'area circostante con piccole quantita' di napalm intensamente in fiamme dopo l'impatto
+6000 3 80 0.2 80 1 1 80 0 9 1 0 0 3 0 10 36 0.0 90 0.2 2.5 1.0 -1 0
+
+Media Bomba al Napalm
+Copre l'area circostante con napalm intensamente in fiamme dopo l'impatto
+14000 2 200 0.2 150 1 1 200 0 9 1 0 0 4 0 25 36 0.0 90 0.2 3 1.0 -1 0
+
+Grande Bomba al Napalm
+Copre l'area circostante con grandi quantita' di napalm intensamente in fiamme dopo l'impatto
+22000 1 400 0.2 200 1 2 500 0 9 1 0 0 5 0 60 36 0.0 90 0.2 5 1.0 -1 0
+
+Napalm Gelatina
+Gelatina chimica intensamente combustibile
+2000 5 5 0.5 10 1 10 30 0 0 1 0 0 2 1 0 -1 0 0 0 0 0 -1 0
+
+Perforatrice
+Esplosione Verticale che provoca un piccolo danno, ma crea un profondo buco nel terreno.
+5000 2 10 0.2 300 3 5 10 0 28 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Tremor
+Produce un piccolo terremoto all'impatto
+3000 5 30 0.2 40 0 2 10 0 14 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Onda d'urto
+Produce un grande terremoto all'impatto
+10000 2 60 0.2 100 2 3 20 0 15 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Spostamento tettonico
+Produce un enorme terremoto all'impatto
+30000 1 100 0.2 150 2 4 30 0 16 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Bomba Anti-Sommossa
+Distrugge un piccolo volume di sporcizia senza danneggiare nulla
+2000 5 15 0.2 25 0 2 0 0 23 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Pesante Bomba Anti-Sommossa
+Distrugge un grande volume di sporcizia senza danneggiare nulla
+3000 2 30 0.2 100 1 2 0 0 24 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Multi Bomba Anti-Sommossa
+Taglia un cono di sporcizia direttamente davanti al cannone
+1000 5 15 0.2 50 0 2 0 0 11 1 0 1 1 0 0 -1 0 0 0 0 0 0 0
+
+Bomba Anti-Sommossa Esplodente
+Taglia un grande cono di sporcizia direttamente davanti al cannone
+2000 2 30 0.2 150 1 2 0 0 12 1 0 1 3 0 0 -1 0 0 0 0 0 0 0
+
+Palla Sporca
+Produce una piccola sfera di materiale per seppellire i vostri avversari
+3000 5 15 0.2 25 0 2 0 0 11 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Grande Palla Sporca
+Produce una grande sfera di materiale per seppellire i vostri avversari
+7000 2 30 0.2 60 1 2 0 0 12 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Super Palla Sporca
+Produce una enorme sfera di materiale per seppellire i vostri avversari
+10000 1 60 0.2 100 2 2 0 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Sporcizia a Piccola Diffusione
+Fa cadere dei piccoli mucchi di sporcizia sui vostri nemici
+4000 2 30 0.2 40 1 2 0 0 12 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cluster MIRV
+Libera un mazzo di piccoli missili su quello che trova
+10000 2 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 45 0 2.0 0 -1 0
+
+Bomba Percentuale
+Distrugge meta' della corazza dell'obiettivo
+12000 2 30 0.2 30 2 4 0 0 29 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Riduttore
+Abbassa la potenza esplosiva dei missili nemici.
+6000 3 25 0.3 30 2 4 0 0 30 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Laser Piccolo
+Raggio Laser a 50kW.
+5000 5 1 0.0 2 0 0 30 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Laser Medio
+Raggio Laser a 100kW.
+10000 3 1 0.0 5 0 0 65 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Laser Grande
+Raggio Laser a 200kW.
+15000 2 1 0.0 9 0 0 150 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+*NATURALS*
+Meteorite Piccolo
+Un piccolo pezzo di roccia dallo spazio
+0 1 15 0.2 25 0 0 5 0 20 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Meteorite Medio
+Un pezzo medio di roccia dallo spazio
+0 1 20 0.2 40 0 0 10 0 21 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Meteorite Grande
+Un grande pezzo di roccia dallo spazio
+0 1 25 0.2 60 1 1 20 0 22 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Lampo Piccolo
+Un piccolo fulmine dal cielo.
+0 1 1 0.0 1 0 0 5 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Lampo Medio
+Un fulmine medio dal cielo.
+0 1 1 0.0 4 0 0 15 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Lampo Grande
+Un gran fulmine dal cielo.
+0 1 1 0.0 7 0 0 35 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+*ITEMS*
+Teletrasporto
+Teletrasporta il tank in una posizione random.
+5000 2 1 3 11
+
+Swapper
+Scambia il posto con un altro tank
+10000 2 1 4 11
+
+Teletrasporto Massiccio
+Teletrasporta tutti i tank sullo schermo.
+15000 2 1 4 11
+
+Fan
+Cambia il vento in forza e direzione
+2500 3 1 3 2
+
+Vendetta
+Un piccolo dispositivo di auto-distruzione, se avete deciso di andarvene, perche' non prenderne qualcuno con voi?
+20000 1 1 2 0 0 21
+
+Rabbia di Morte
+Un gran dispositivo di auto-distruzione. Distruzione reciprocamente assicurata.
+40000 1 1 3 0 21 3
+
+Furia Fatale
+Fa finire tutto in grande stile
+60000 1 1 4 0 22 3
+
+Scudo Leggero
+Da una piccola protezione dalla distruzione
+10000 3 0 1 0 50 0 0 255 0 1
+
+Scudo Medio
+Protegge dalla distruzione
+20000 2 0 2 0 100 0 64 255 0 3
+
+Scudo Pesante
+Da una grande protezione dalla distruzione
+30000 2 0 4 0 150 0 128 255 64 6
+
+Schermo di Repulsione Leggero
+Respinge leggermente i missili nemici
+10000 3 0 2 0 10 250 128 0 255 1
+
+Schermo di Repulsione Medio
+Respinge i missili nemici
+20000 2 0 3 0 20 500 192 64 255 3
+
+Schermo di Repulsione Pesante
+Respinge pesantemente i missili nemici
+40000 1 0 5 0 40 1000 255 128 255 6
+
+Rinforzo Corazzatura
+Aggiunge permanentemente un piccolo aumento di resistenza alla corazza del tank diminuendo cosi' il danno inferto ai vostri tank.
+20000 1 0 2 0 300
+
+Rinforzo Corazzatura in Acciaio
+Aggiunge permanentemente un aumento di resistenza alla corazza del tank diminuendo cosi' il danno inferto ai vostri tank.
+40000 1 0 4 0 2155
+
+Amplificatore di Intensita'
+Permette un piccolo e permanente incremento ai danni fatti dalle vostre armi. L'efficienza diminuisce e quindi ogni acquisto supplementare ha un'influenza riduttrice.
+21000 1 0 3 0 0.10
+
+Forza Violenta
+Permette un permanente incremento ai danni fatti dalle vostre armi. L'efficienza diminuisce e quindi ogni acquisto supplementare ha un'influenza riduttrice.
+50000 1 0 3 0 0.30
+
+Proiettili Lucidi
+Un rivestimento di Teflon riduce la resistenza e l'influenza del vento sui vostri proiettili
+1000 50 0 3 0 0.5
+
+Proiettili Scanalati
+Piccole fossette nella superficie dei proiettili per una riduzione voluminosa della resistenza all'aria
+2000 50 0 4 0 0.1
+
+Paracadute
+Permette al tank di fluttuare lentamente a terra
+5000 10 0 0 0 0 0
+
+Kit Auto-Riparazione
+Ripara il tank un poco ogni volta. Ogni volta fornisce un piccolo aumento alla vostra corazza.
+10000 1 0 2 0 0 0
+
+Benzina
+Permette al tank di muoversi sul terreno.
+1000 10 0 2 0 0 0
+
+Razzo
+Solleva il tank nell'aria.
+2000 2 1 4 0 0 0
+
+Difesa anti missile - SDI
+Offre una certa protezione contro i missili ricevuti.
+10000 1 0 5 0 0
+
diff --git a/text/weapons_ru.txt b/text/weapons_ru.txt
new file mode 100644
index 0000000..f265e23
--- /dev/null
+++ b/text/weapons_ru.txt
@@ -0,0 +1,343 @@
+*WEAPONS*
+Ракета
+Слабый взрыв, малая мощность. Достаточно для того, чтобы добить танк противника.
+1500 10 10 0.2 25 0 2 30 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Средняя ракета
+Небольшая мощность, небольшая площадь поражения. Разумное качество по разумной цене.
+2000 5 15 0.2 40 0 2 40 0 1 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Большая ракета
+Средняя мощность, средняя площадь поражения. Способна серьёзно задеть противника.
+4000 3 20 0.2 60 1 3 60 0 2 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Малая ядерная бомба
+Мощный взрыв, большая площадь поражения. Неприятный сюрприз для большинства танков.
+16000 2 40 0.2 100 2 4 100 0 3 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Ядерная бомба
+Очень мощный взрыв, огромная площадь поражения. Кто там не надел очки?
+22000 1 60 0.2 150 2 5 150 0 4 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Ядрен-батон (Death Head)
+Офигенно мощный бабах. Достанет кого угодно.
+30000 1 80 0.2 200 3 6 200 0 5 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Малый веер
+5 малых ракет за один выстрел. Удобно, если нужно накрыть нескольких раненых противников за раз.
+5000 3 10 0.2 25 0 2 30 0 0 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Средний веер
+5 средних ракет за один выстрел. Уже повод для беспокойства.
+11000 2 15 0.2 40 0 2 40 0 1 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Большой веер
+5 больших ракет за один выстрел. Опасное оружие в руках умелого танкиста.
+17000 1 20 0.2 60 1 3 60 0 2 5 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Супер-веер
+4 малых ядерных бомбы за один выстрел. Смех злого гения прилагается.
+25000 1 40 0.2 100 2 4 100 0 3 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Смертельный веер
+3 ядерных бомбы за один выстрел. Не забудьте надеть очки.
+50000 1 60 0.2 150 2 5 150 0 4 3 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Армагеддон
+3 ядрен-батона за один выстрел. Гарантированное избавление от тараканов и клопов на поле боя!
+100000 1 80 0.2 200 3 6 200 0 5 3 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Очередь
+Выстреливает 3 ракеты одну за другой. Для тех, кто хочет пощекотать противнику нервы.
+4000 3 10 0.2 25 0 2 30 0 0 1 3 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Пулемет
+Выстреливает 5 ракет одну за другой. Способен продолбить яму в грунте.
+6000 10 10 0.2 25 0 2 30 0 0 1 5 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Молотилка
+Выстреливает 8 ракет одну за другой. Начинающий набор танкиста-дятла.
+8000 16 10 0.2 25 0 2 30 0 0 1 8 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Резачок
+Мощный горизонтальный взрыв. Вся энергия фокусируется по сторонам, что увеличивает мощность, но уменьшает площадь поражения.
+10000 5 10 0.2 100 2 3 100 0 17 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Резак
+Опустошительный горизонтальный взрыв. Вся энергия фокусируется по сторонам, что позволяет пробить любой щит, но уменьшает шансы зацепить врага.
+15000 2 10 0.2 200 2 4 200 0 18 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Потрошитель
+Горизонтальный взрыв, сметающий всё на своем пути. Вся энергия фокусируется по сторонам, прорезая любую броню, бетон и грунт.
+20000 1 10 0.2 300 3 5 300 0 19 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Каток
+Заряд средней мощности, который катится под горку, пока не столкнется с препятствием. Полезен против противника, который расположился на склоне.
+2000 3 20 0.2 40 0 2 40 0 6 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Большой каток
+Заряд большой мощности, который катится под горку, пока не столкнется с препятствием. Многие танкисты предпочитают встречу с лавиной.
+8000 1 30 0.2 60 1 3 60 0 6 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Танкоукладчик
+Заряд огромной мощности, способный укатать любой танк в прямом смысле этого слова.
+14000 1 40 0.2 100 2 4 100 0 6 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+РГЧ-ИН "Рогач"
+Ракета с Разделяющейся Головной Частью. Обрушивает с высоты на наземную цель группу больших ракет. Превращает точку попадания в подобие лунной поверхности.
+20000 1 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 2 1.0 120 0.0 1.0 0 -1 0
+
+Бронебойный снаряд
+Небольшой, но очень мощный снаряд - сила взрыва концентрируется в одной точке, что позволяет пробить любую защиту.
+2500 5 30 0.2 15 0 2 80 0 27 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Кассетная бомба
+При срабатывании выбрасывает 5 средних ракет. Эффективна против врагов, собравшихся в группы.
+10000 3 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 60 0 3.5 0 -1 0
+
+Супер-кассетная бомба
+При срабатывании выбрасывает 5 больших ракет. Разрушительный фейерверк в тылу врага.
+20000 2 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 30 0.0 60 0 3.5 0 -1 0
+
+Шариковая бомба
+Экспериментальная бомба, сделанная на заводе по производству шариков для пинг-понга. Непредсказуема и смертельна.
+30000 3 50 0.2 200 0 0 200 0 9 1 0 0 3 0 10 27 0.0 360 1.0 0.5 0.1 -1 0
+
+Шариковая смерть
+Улучшенная версия шариковой бомбы, сделанная на заводе по производству баскетбольных мячей. Непредсказуема и офигенно разрушительна.
+50000 1 90 0.2 300 2 1 300 0 9 1 0 0 4 0 10 28 0.0 360 1.0 0.5 0.1 -1 0
+
+Воздушный шарик
+Летающая боеголовка средней мощности.
+7000 3 5 0.01 40 0 0 50 0 10 1 0 1 1 1 0 -1 0 0 0 0 0 125 1.0
+
+Бомбаэростат
+Летающая боеголовка большой мощности.
+9000 2 9 0.01 100 2 1 90 0 10 1 0 1 3 1 0 -1 0 0 0 0 0 175 1.0
+
+Бомбочка
+Боеголовка средней мощности. Для использования в кассетных бомбах, авиаударах и фейерверках.
+3500 3 20 0.2 40 0 2 40 0 8 1 0 0 1 1 0 -1 0 0 0 0 0 -1 0
+
+Супер-бомбочка
+Боеголовка большой мощности. Руками не трогать.
+5000 2 40 0.2 60 1 2 65 0 8 1 0 0 3 1 0 -1 0 0 0 0 0 -1 0
+
+Крот
+Вонзается в поверхность и проходит некоторый путь под землёй по параболе, прежде чем взорваться, что удобно против закопанных танков. Крот предназначен для движения под землей и не слишком-то хорошо летает в воздухе.
+7500 3 100 0.4 50 0 2 50 0 25 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Большой крот
+Движется под землей до выхода на поверхность или до попадания в зарытый танк. Большой крот расчитан на движение под землей, поэтому страдает от сильного сопротивления воздуха.
+20000 2 150 0.4 80 0 2 100 0 26 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Малый напалм
+Снаряд с горючими веществами. При срабатывании разбрызгивает немного горящего напалма. Напалм почти не разрушает грунт, но подвержен влиянию ветра.
+6000 3 80 0.2 80 1 1 80 0 9 1 0 0 3 0 10 36 0.0 90 0.2 2.5 1.0 -1 0
+
+Средний напалм
+Снаряд с горючими веществами. Разбрызгивает горящий напалм при срабатывании. Более мощная и более эффективная модификация.
+14000 2 200 0.2 150 1 1 200 0 9 1 0 0 4 0 25 36 0.0 90 0.2 3 1.0 -1 0
+
+Большой напалм
+Снаряд с горючими веществами. Заливает напалмом всё в округе. Проверьте направление ветра перед выстрелом.
+22000 1 400 0.2 200 1 2 500 0 9 1 0 0 5 0 60 36 0.0 90 0.2 5 1.0 -1 0
+
+Липкий напалм
+Горючее искуственное желе.
+2000 5 5 0.5 10 1 10 30 0 0 1 0 0 2 1 0 -1 0 0 0 0 0 -1 0
+
+Ямокопатель
+При попадании снаряд создает глубокий вертикальный тоннель, почти не нанося повреждений. Первоначально использовался компаниями при поиске нефти и газа на планетах.
+5000 2 10 0.2 300 3 5 10 0 28 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Дрожь земли
+При срабатывании вызывает слабое землетрясение. Малоэффективный, но назойливый снаряд.
+3000 5 30 0.2 40 0 2 10 0 14 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Ударная волна
+Вызывает большое землетрясение. Опасен для неподготовленных танков.
+10000 2 60 0.2 100 2 3 20 0 15 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Тектонический сдвиг
+Вызывает кошмарное землетрясение. Не кантовать.
+30000 1 100 0.2 150 2 4 30 0 16 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Уборщик (Riot Bomb)
+Убирает немного грунта, не повреждая броню и технику. Используется для раскопок на поле боевых действий.
+2000 5 15 0.2 25 0 2 0 0 23 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Heavy Riot Bomb
+Убирает уйму грунта, не повреждая броню и технику. Используется для обнаружения подземных вражеских лагерей.
+3000 2 30 0.2 100 1 2 0 0 24 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Малый дворник
+Очищает от грязи небольшой просвет перед дулом пушки. Предмет первой необходимости на поле боя.
+1000 5 15 0.2 50 0 2 0 0 11 1 0 1 1 0 0 -1 0 0 0 0 0 0 0
+
+Большой дворник
+Очищает от грязи большую площадь перед дулом пушки. Улучшенная и в разы более эффективная модификация дворника.
+2000 2 30 0.2 150 1 2 0 0 12 1 0 1 3 0 0 -1 0 0 0 0 0 0 0
+
+Комок грязи
+Небольшой шар из грунта, способный закопать оппонента. Грязь легко уничтожается и расчищается.
+3000 5 15 0.2 25 0 2 0 0 11 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Большой комок грязи
+Большой грунтовый шар для закапывания оппонентов. Полезен против тех, кто умеет откапывать танки только ракетами.
+7000 2 30 0.2 60 1 2 0 0 12 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Говномет
+Уйма грязи на голову врага. Для полноты ощущений ещё и воняет.
+10000 1 60 0.2 100 2 2 0 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Small Dirt Spread
+Drop little piles of dirt on your enemies
+4000 2 30 0.2 40 1 2 0 0 12 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Cluster MIRV
+Releases a cluster of small missiles on its way down
+10000 2 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 45 0 2.0 0 -1 0
+
+Per Cent Bomb
+Destroys half of the target's armour
+12000 2 30 0.2 30 2 4 0 0 29 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Reducer
+Lowers the explosive power of an enemy's missiles.
+6000 3 25 0.3 30 2 4 0 0 30 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Малый лазер
+Луч мощностью 50КВт. Способен прожечь лист железа или грунт.
+5000 5 1 0.0 2 0 0 30 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Средний лазер
+Луч мощностью 100КВт. Отличный способ прожечь броню врага.
+10000 3 1 0.0 5 0 0 65 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Большой лазер
+200-киловаттный прожигатель. Злые гении, это ваш выбор!
+15000 2 1 0.0 9 0 0 150 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+*NATURALS*
+Метеорит
+Камешек с небес. Лучше его не ловить.
+0 1 15 0.2 25 0 0 5 0 20 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Метеор
+Осколок небесной тверди. Несовместим с целым танком.
+0 1 20 0.2 40 0 0 10 0 21 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Большой метеор
+Обломок небесной тверди. Гнев небес вобьет в грунт любого грешника.
+0 1 25 0.2 60 1 1 20 0 22 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Малая молния
+Слабенький разряд. Мешает радиосвязи, добивает больных и ослабевших.
+0 1 1 0.0 1 0 0 5 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Молния
+Обычный разряд молнии. Выжигает бортовую электронику. Не лови - убьет!
+0 1 1 0.0 4 0 0 15 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Большая молния
+Убийственный разряд. Кто сказал, что бывают тугоплавкие металлы?
+0 1 1 0.0 7 0 0 35 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+*ITEMS*
+Телепорт
+Перебрасывает танк в случайную точку под землёй или в воздухе.
+5000 2 1 3 11
+
+Обменник
+Меняет танк местами с другим танком.
+10000 2 1 4 11
+
+Миксер
+Телепортирует в случайные точки все танки на поле боя.
+15000 2 1 4 11
+
+Ветродуй
+Меняет направление и силу ветра.
+2500 3 1 3 2
+
+Завещание
+Небольшой самоликвидатор или автоликвидатор: если уж тебя попросили на выход, почему бы не прихватить кого-нибудь с собой?
+20000 1 1 2 0 0 21
+
+Месть покойника
+Большой набор самоликвидации. Ты мне - я тебе.
+40000 1 1 3 0 21 3
+
+Убийственная ярость
+Закончим всё это красиво.
+60000 1 1 4 0 22 3
+
+Малый щит
+Противопульная дополнительная броня. Для тех, кому нужна дополнительная защита.
+10000 3 0 1 0 50 0 0 255 0 1
+
+Средний щит
+Хорошая дополнительная броня. Нужна защита от мощных ракет? Возьми этот модуль!
+20000 2 0 2 0 100 0 64 255 0 3
+
+Тяжелый щит
+Особо прочная дополнительная броня. Способна выдержать даже авиаудар.
+30000 2 0 4 0 150 0 128 255 64 6
+
+Слабое силовое поле
+Отталкивает вражеские снаряды. Не защищает от взрывной волны.
+10000 3 0 2 0 10 250 128 0 255 1
+
+Силовое поле
+Хорошо отталкивает вражеские снаряды, плохо защищает от взрывов.
+20000 2 0 3 0 20 500 192 64 255 3
+
+Мощное силовое поле
+Отлично отталкивает вражеские снаряды, направленные точно в танк.
+40000 1 0 5 0 40 1000 255 128 255 6
+
+Навесная броня
+Усиливает броню танка до конца игры. Каждая новая пластина дает чуть меньший эффект, нежели предыдущая.
+20000 1 0 2 0 300
+
+Эгида
+Особо прочная навесная броня. Усиливает броню танка до конца игры. Каждая новая пластина дает чуть меньший эффект, нежели предыдущая.
+40000 1 0 4 0 2155
+
+Усилитель боевой мощи
+До конца игры немного увеличивает убойную силу ваших снарядов. Каждый новый усилитель оказывает немного меньший эффект по сравнению с предыдущим.
+21000 1 0 3 0 0.10
+
+Убийственный усилитель
+До конца игры существенно увеличивает убойную силу ваших снарядов. Каждый новый усилитель оказывает немного меньший эффект по сравнению с предыдущим.
+50000 1 0 3 0 0.30
+
+Тефлоновое покрытие
+Тефлоновая оболочка зарядов уменьшает влияние ветра на траекторию выстрела.
+1000 50 0 3 0 0.5
+
+Сверлёные снаряды
+Небольшие отверстия в боеголовках существенно повышают их устойчивость к воздействию ветра.
+2000 50 0 4 0 0.1
+
+Парашют
+Оказавшись в воздухе или потеряв почву под ногами, танк не падает, а плавно опускается на землю. В полете можно управлять направлением, расходуя ТОПЛИВО, если оно есть.
+5000 10 0 0 0 0 0
+
+Авторемонтник
+С каждым ходом устраняет часть полученных повреждений. Каждый новый ремонтник работает чуть менее эффективно, чем предыдущий.
+10000 1 0 2 0 0 0
+
+Топливо
+Позволяет танку двигаться по ровной местности и планировать в сторону при парашютировании.
+1000 10 0 2 0 0 0
+
+Двигатель "ВВП"
+Поднимает танк в воздух, что позволяет перелетать с места на место.
+2000 2 1 4 0 0 0
+
+SDI Missile Defense
+Offers some protection against incoming missiles.
+10000 1 0 5 0 0
+
diff --git a/text/weapons_sk.txt b/text/weapons_sk.txt
new file mode 100644
index 0000000..e854bd0
--- /dev/null
+++ b/text/weapons_sk.txt
@@ -0,0 +1,343 @@
+*WEAPONS*
+Malá strela
+Pri kontakte spôsobí malú explóziu
+1500 10 10 0.2 25 0 2 30 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Stredná strela
+Malá ráž, malá veľkosť explózie
+2000 5 15 0.2 40 0 2 40 0 1 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Veľká strela
+Stredná ráž, stredná veľkosť explózie
+4000 3 20 0.2 60 1 3 60 0 2 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Malá jadrová bomba
+Veľká ráž, veľká explózia
+16000 2 40 0.2 100 2 4 100 0 3 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Jadrová bomba
+Veľmi veľká ráž, obrovská explózia
+22000 1 60 0.2 150 2 5 150 0 4 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Vraždiaca bomba
+Obrovská smrtiaca explózia
+30000 1 80 0.2 200 3 6 200 0 5 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Ľahké kobercové bombardovanie
+5 malý striel v jednom výstrele
+5000 3 10 0.2 25 0 2 30 0 0 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Stredné kobercové bombardovanie
+5 stredných striel v jednom výstrele
+11000 2 15 0.2 40 0 2 40 0 1 5 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Ťažké kobercové bombardovanie
+5 veľkých striel v jednom výstrele
+17000 1 20 0.2 60 1 3 60 0 2 5 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Superkobercové bombardovanie
+4 malé jadrové bomby v jednom výstrele
+25000 1 40 0.2 100 2 4 100 0 3 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Smrtiace kobercové bombardovanie
+3 jadrové bomby v jednom výstrele
+50000 1 60 0.2 150 2 5 150 0 4 3 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Armagedon
+3 smrtiace hlavice v jednom výstrele
+100000 1 80 0.2 200 3 6 200 0 5 3 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Reťazové strely
+Vypáli skupinku troch malých striel
+4000 3 10 0.2 25 0 2 30 0 0 1 3 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Samopal
+Vypáli skupinku piatich malých striel
+6000 10 10 0.2 25 0 2 30 0 0 1 5 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Pneumatické kladivo
+Vypáli skupinku ôsmych malých striel
+8000 16 10 0.2 25 0 2 30 0 0 1 8 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Kumulatívna nálož
+Veľká horizontálna explózia. Všetka energia je rozprestrená do strán, čím sa zvyšuje škoda, no zmenšuje oblasť, na ktorú explózia pôsobí.
+10000 5 10 0.2 100 2 3 100 0 17 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Wide Boy
+Zničujúca horizontálna explózia. Všetka energia je rozprestrená do strán, čím sa zvyšuje škoda, no zmenšuje oblasť, na ktorú explózia pôsobí.
+15000 2 10 0.2 200 2 4 200 0 18 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Orezávač
+Horizontálna explózia, ktorá vyhladí všetko, čo jej príde do cesty. Všetka energia je rozprestrená do strán, čím sa zvyšuje škoda, no zmenšuje oblasť, na ktorú explózia pôsobí v porovnaní s neriadenou detonáciou podobnej sily.
+20000 1 10 0.2 300 3 5 300 0 19 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Malý valcovač
+Stredná trhavina, ktorá sa valí z kopca až kým do niečo nenarazí
+2000 3 20 0.2 40 0 2 40 0 6 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Veľký valcovač
+Silná trhavina, ktorá sa valí z kopca až kým do niečo nenarazí
+8000 1 30 0.2 60 1 3 60 0 6 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Smrtiaci valcovač
+Veľmi silná trhavina, ktorá sa valí z kopca až kým do niečo nenarazí
+14000 1 40 0.2 100 2 4 100 0 6 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Malá MIRV
+Spustí z neba skupinu veľkých striel
+20000 1 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 2 1.0 120 0.0 1.0 0 -1 0
+
+Trhač brnenia
+Malý silný náboj, ktorý dokáže zničiť tank
+2500 5 30 0.2 15 0 2 80 0 27 1 0 0 2 0 0 -1 0 0 0 0 0 -1 0
+
+Trieštivá bomba
+Rozhodí bombičky o strednej ráži, ktoré vybuchujú pri kontakte
+10000 3 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 60 0 3.5 0 -1 0
+
+Supertrieštivá bomba
+Rozhodí bombičky o veľkej ráži, ktoré vybuchujú pri kontakte
+20000 2 200 0.2 250 1 2 300 0 7 1 0 0 4 0 5 30 0.0 60 0 3.5 0 -1 0
+
+Podivná bomba
+Nepredvídateľná a vysoko deštruktívna
+30000 3 50 0.2 200 0 0 200 0 9 1 0 0 3 0 10 27 0.0 360 1.0 0.5 0.1 -1 0
+
+Podivná smrť
+Nepredvídateľná a extrémne deštruktívna
+50000 1 90 0.2 300 2 1 300 0 9 1 0 0 4 0 10 28 0.0 360 1.0 0.5 0.1 -1 0
+
+Podivná bombička
+Výbušná hlavica o strednej ráži
+7000 3 5 0.01 40 0 0 50 0 10 1 0 1 1 1 0 -1 0 0 0 0 0 125 1.0
+
+Podivná smrtiaca bombička
+Výbušná hlavica o veľkej ráži
+9000 2 9 0.01 100 2 1 90 0 10 1 0 1 3 1 0 -1 0 0 0 0 0 175 1.0
+
+Bombička
+Výbušná hlavica o strednej ráži
+3500 3 20 0.2 40 0 2 40 0 8 1 0 0 1 1 0 -1 0 0 0 0 0 -1 0
+
+Superbombička
+Výbušná hlavica o veľkej ráži
+5000 2 40 0.2 60 1 2 65 0 8 1 0 0 3 1 0 -1 0 0 0 0 0 -1 0
+
+Zavŕtavač
+Najprv sa zavŕta do povrchu, dobrá zbraň na zahrabané tanky. Zavŕtavač je určený pre použitie pod povrchom a nemá rád veľký odpor vzduchu.
+7500 3 100 0.4 50 0 2 50 0 25 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Prenikač
+Podpovrchová zbraň, ktoré po čase začne stúpať na povrch. Prenikač exploduje buď pri kontakte s povrchom alebo pri kontakte so zahrabanými objektami. Táto strela je určená pre hrabanie a preto nemá rada veľký odpor vzduchu.
+20000 2 150 0.4 80 0 2 100 0 26 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Malá napalmová bomba
+Rozhodí malé množstvo napalmu, ktorý pri kontakte intenzívne horí
+6000 3 80 0.2 80 1 1 80 0 9 1 0 0 3 0 10 36 0.0 90 0.2 2.5 1.0 -1 0
+
+Stredná napalmová bomba
+Rozhodí napalm, ktorý pri kontakte intenzívne horí
+14000 2 200 0.2 150 1 1 200 0 9 1 0 0 4 0 25 36 0.0 90 0.2 3 1.0 -1 0
+
+Veľká napalmová bomba
+Pokryje okolitú oblasť napalmom, ktorý pri kontakte intenzívne horí
+22000 1 400 0.2 200 1 2 500 0 9 1 0 0 5 0 60 36 0.0 90 0.2 5 1.0 -1 0
+
+Napalmové želé
+Intenzívne horiace chemické želé
+2000 5 5 0.5 10 1 10 30 0 0 1 0 0 2 1 0 -1 0 0 0 0 0 -1 0
+
+Vŕtač
+Vertikálna explózia, ktorý urobí malú škodu, ale vytvorí hlbokú dieru v zemi.
+5000 2 10 0.2 300 3 5 10 0 28 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Otras
+Pri kontakte spôsobí malé zemetrasenie
+3000 5 30 0.2 40 0 2 10 0 14 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Tlaková vlna
+Pri kontakte spôsobí veľké zemetrasenie
+10000 2 60 0.2 100 2 3 20 0 15 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Tektonický posun
+Pri kontakte spôsobí obrovské zemetrasenie
+30000 1 100 0.2 150 2 4 30 0 16 1 0 0 5 0 0 -1 0 0 0 0 0 -1 0
+
+Hlučná bomba
+Zničí malé množstvo zeme bez toho, aby poškodila čokoľvek iné
+2000 5 15 0.2 25 0 2 0 0 23 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Veľká hlučná bomba
+Zničí veľké množstvo zeminy bez toho, aby poškodila čokoľvek iné
+3000 2 30 0.2 100 1 2 0 0 24 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Hlučná nálož
+Priamo pred zbraňou vyreže do zeminy kužeľ
+1000 5 15 0.2 50 0 2 0 0 11 1 0 1 1 0 0 -1 0 0 0 0 0 0 0
+
+Hlučná detonácia
+Priamo pred zbraňou vyreže do zeminy veľký kužeľ
+2000 2 30 0.2 150 1 2 0 0 12 1 0 1 3 0 0 -1 0 0 0 0 0 0 0
+
+Guľa so zeminou
+Vytvorí malú guľku materiálu pre pochovanie vašich súperov
+3000 5 15 0.2 25 0 2 0 0 11 1 0 0 1 0 0 -1 0 0 0 0 0 -1 0
+
+Veľká guľa so zeminou
+Vytvorí veľkú guľu materiálu pre pochovanie vašich súperov
+7000 2 30 0.2 60 1 2 0 0 12 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Superguľa so zeminou
+Vytvorí obrovskú guľu materiálu pre pochovanie vašich súperov
+10000 1 60 0.2 100 2 2 0 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Slabý nános zeminy
+Zhodí malé kôpky zeminy na vašich nepriateľov
+4000 2 30 0.2 40 1 2 0 0 12 4 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Trieštivé MIRV
+Vypustí skupinku malých striel smerom dolu
+10000 2 100 0.2 150 0 2 200 0 7 1 0 0 2 0 5 29 0.0 45 0 2.0 0 -1 0
+
+Percentuálna bomba
+Zničí polovicu brnenia cieľa
+12000 2 30 0.2 30 2 4 0 0 29 1 0 0 3 0 0 -1 0 0 0 0 0 -1 0
+
+Redukovač
+Znižuje explozívnu silu nepriateľských striel.
+6000 3 25 0.3 30 2 4 0 0 30 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Malý laser
+50kW laserový lúč
+5000 5 1 0.0 2 0 0 30 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Stredný laser
+100kW laserový lúč
+10000 3 1 0.0 5 0 0 65 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+Veľký laser
+Silný 200kW laserový lúč
+15000 2 1 0.0 9 0 0 150 0 13 1 0 0 4 0 0 -1 0 0 0 0 0 -1 0
+
+*NATURALS*
+Malý meteorit
+Malé kusy skál z oblohy
+0 1 15 0.2 25 0 0 5 0 20 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Stredný meteorit
+Stredne veľké kusy skál z oblohy
+0 1 20 0.2 40 0 0 10 0 21 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Veľký meteorit
+Veľké kusy skál z oblohy
+0 1 25 0.2 60 1 1 20 0 22 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Slabý blesk
+Slabý blesk
+0 1 1 0.0 1 0 0 5 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Stredný blesk
+Stredne silný blesk
+0 1 1 0.0 4 0 0 15 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+Silný blesk
+Silný blesk
+0 1 1 0.0 7 0 0 35 0 0 1 0 0 0 0 0 -1 0 0 0 0 0 -1 0
+
+*ITEMS*
+Teleport
+Teleportuje tank na náhodné miesto
+5000 2 1 3 11
+
+Výmena
+Výmena miesta s iným tankom
+10000 2 1 4 11
+
+Hromadný teleport
+Teleportuje všetky tanky na obrazovke
+15000 2 1 4 11
+
+Ventilátor
+Zmení silu a smer vetra
+2500 3 1 3 2
+
+Pomsta
+Malé samo a autodeštrukčné zariadenie. Keď už musíte skončiť, tak prečo nevziať niekoho so sebou?
+20000 1 1 2 0 0 21
+
+Smrteľný hnev
+Veľké samo/autodeštrukčné zariadenie. Vzájomne zaistená deštrukcia.
+40000 1 1 3 0 21 3
+
+Osudové zúrenie
+Štýlové zakončenie
+60000 1 1 4 0 22 3
+
+Ľahký štít
+Malé množstvo ochrany pred poškodením
+10000 3 0 1 0 50 0 0 255 0 1
+
+Stredný štít
+Chráni pred poškodením
+20000 2 0 2 0 100 0 64 255 0 3
+
+Ťažký štít
+Veľké množstvo ochrany pred poškodením
+30000 2 0 4 0 150 0 128 255 64 6
+
+Ľahký odkloňovač striel
+Jemne odkloní nepriateľské strely
+10000 3 0 2 0 10 250 128 0 255 1
+
+Stredný odkloňovač striel
+Odkloní nepriateľské strely
+20000 2 0 3 0 20 500 192 64 255 3
+
+Ťažký odkloňovač striel
+Výrazne odkloní nepriateľské strely
+40000 1 0 5 0 40 1000 255 128 255 6
+
+Bežné opancierovanie
+Permanentne zvýši množstvo škody, ktorému váš tank dokáže odolať. Každý dodatočný nákup pridá o niečo menšie množstvo pancieru vášmu tanku.
+20000 1 0 2 0 300
+
+Plasteelové opancierovanie
+Permanentne zvýši množstvo škody, ktorému váš tank dokáže odolať. Každý dodatočný nákup pridá o niečo menšie množstvo pancieru vášmu tanku.
+40000 1 0 4 0 2155
+
+Zosilnenie intenzity
+Malé permanentné zvýšenie účinnosti vašich zbraní. Účinnosť má klesajúcu tendenciu a tak každý dodatočný nákup má stále slabší efekt.
+21000 1 0 3 0 0.10
+
+Mohutná sila
+Permanentné zvýšenie účinnosti vašich zbraní. Účinnosť má klesajúcu tendenciu a tak každý dodatočný nákup má stále slabší efekt.
+50000 1 0 3 0 0.30
+
+Klzké projektily
+Teflónová vrstva pre projektily, ktoré znížia odpor a účinok vetra
+1000 50 0 3 0 0.5
+
+Dierkované projektily
+Malé dierky v plášti projektilov pre veľké zníženie odporu
+2000 50 0 4 0 0.1
+
+Padák
+Umožní tanku pomaly klesať k zemi
+5000 10 0 0 0 0 0
+
+Súprava pre opravu
+Po každom ťahu opravuje tank. Každá ďalšia súprava poskytuje o niečo menšie brnenie.
+10000 1 0 2 0 0 0
+
+Palivo
+Umožňuje tanku pohybovať sa po vodorovnom teréne.
+1000 10 0 2 0 0 0
+
+Raketa
+Vypustí tank do vzduchu.
+2000 2 1 4 0 0 0
+
+SDI raketová obrana
+Poskytuje určitú ochranu proti prichádzajúcim strelám.
+10000 1 0 5 0 0
+
diff --git a/title/.directory b/title/.directory
new file mode 100644
index 0000000..43701d7
--- /dev/null
+++ b/title/.directory
@@ -0,0 +1,3 @@
+[Dolphin]
+ShowPreview=true
+Timestamp=2010,1,15,8,34,14
diff --git a/title/0.bmp b/title/0.bmp
new file mode 100644
index 0000000..6d7f528
Binary files /dev/null and b/title/0.bmp differ
diff --git a/title/1.bmp b/title/1.bmp
new file mode 100644
index 0000000..e2b543f
Binary files /dev/null and b/title/1.bmp differ
diff --git a/title/2.bmp b/title/2.bmp
new file mode 100644
index 0000000..e2b543f
Binary files /dev/null and b/title/2.bmp differ
diff --git a/title/3.bmp b/title/3.bmp
new file mode 100644
index 0000000..e2b543f
Binary files /dev/null and b/title/3.bmp differ
diff --git a/unicode.dat b/unicode.dat
new file mode 100644
index 0000000..331fc61
Binary files /dev/null and b/unicode.dat differ

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/atanks.git



More information about the Pkg-games-commits mailing list