From: Simon Tatham Date: Sat, 16 Jan 2021 14:28:18 +0000 (+0000) Subject: New upstream version 1.18 X-Git-Tag: upstream/1.18^0 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~sgtatham/git?a=commitdiff_plain;h=28e4091c1dd856b5c19df39846dbd60e1690197f;p=chroma-debian.git New upstream version 1.18 --- diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..7a1b3ab --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,89 @@ +1.18 (10th January 2021) +========================= + * fixed problems to allow building on Ubuntu 20.04 + +1.17 (26th April 2019) +======================= + * fixed problem when undoing moves in XOR that led to player dying + +1.16 (9th January 2019) +======================== + * included browser version + * simplified shadow display code + * fixed error with replay speed + * convert2chroma.pl can now extract BBC Procyon levels + +1.15 (20th April 2013) +========================== + * fixed XML parser to avoid infinite loop on Raspberry Pi + * fixed a couple of warnings during compilation + +1.14 (12th December 2011) +========================== + * fixed Makefile problem to allow building on Ubuntu 11.10 + +1.13 (14th July 2010) +====================== + * loading a position whilst replaying another no longer continues the replay + +1.12 (22nd April 2010) +======================= + * when a player dies in XOR, the other player is now swapped in automatically + +1.11 (18th March 2010) +======================= + * walls no long erroneously appear when undoing explosions in XOR darkness + +1.10 (8th March 2010) +====================== + * replay and loading of positions from other levels now works as expected + * hopefully the final tidying of the position filtering code + +1.09 (2nd March 2010) +====================== + * in chroma, player swapping now only occurs once per keypress + * slightly tidier position filtering code + +1.08 (1st March 2010) +====================== + * only saved positions for the current level are shown by default + * invisible menu entries are now actually invisible in chroma-curses + +1.07 (15th February 2010) +========================== + * fixed a problem with exploding movers in certain pathological conditions + * made it clearer that Enigma's exact engine only works with red pieces + * fixed a problem with undo in certain pathological conditions + +1.06 (8th February 2010) +========================= + * fixed an annoying segfault when exporting solutions + * exported solutions are no longer world readable + +1.05 (4th February 2010) +========================= + * changes to configure.ac and *display.c to allow building on NetBSD + +1.04 (2nd February 2010) +========================= + * in chroma-curses, you can no longer swap pieces during a replay + * chroma-curses now gets the move counter correct when undoing + +1.03 (1st February 2010) +========================= + * fixed regression failure in Enigma "exact" game engine + * Makefile.in change to allow building on FreeBSD + +1.02 (29th January 2010) +========================= + * improved resolution handling + * "curses emulation" graphics scheme can now be resized like any other + +1.01 (22nd January 2010) +========================= + * fixed a problem with the display being rotated on some systems + +1.00 (21st January 2010) +========================= +Original release. + diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..b83f24b --- /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. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 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. + + , 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/INSTALL b/INSTALL new file mode 100644 index 0000000..e8ada92 --- /dev/null +++ b/INSTALL @@ -0,0 +1,50 @@ +Installation +============ +Chroma uses the standard procedure for compilation and installation: + + ./configure + make + make install + +By default, this will attempt to build both the graphical (SDL) and the +terminal (curses) versions of Chroma, although the configure script may be +given either '--disable-curses' or '--disable-sdl' as options if required. + +Dependencies +============ +The SDL version of Chroma requires the following libraries: + + * SDL + http://www.libsdl.org/ + + * SDL_image + http://www.libsdl.org/projects/SDL_image/ + + * FreeType 2 + http://www.freetype.org/ + +It also uses the font "DejaVu Sans" - see graphics/font.txt for its licence: + + * DejaVu fonts + http://dejavu.sourceforge.net/ + +The curses version of Chroma requires a curses library such as: + + * ncurses + http://www.gnu.org/software/ncurses/ + +Both versions require: + + * gettext + http://www.gnu.org/software/gettext/ + +Most linux distributions should have pre-built packages for all of these. Note +that you will require both the library and development (often -devel) packages. + +Cross-compilation for Windows +============================= +Chroma may be cross-compiled for Windows using MinGW (http://www.mingw.org/). +A separate Makefile.mingw is provided for this purpose, although you will need +to ensure the libraries mentioned above are present in your MinGW installation. +PDCurses (http://pdcurses.sourceforge.net/) may be used in place of ncurses. + diff --git a/Makefile.in b/Makefile.in new file mode 100644 index 0000000..ec589da --- /dev/null +++ b/Makefile.in @@ -0,0 +1,64 @@ +CC = @CC@ +INSTALL = @INSTALL@ + +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +datadir = @datadir@ +datarootdir = @datarootdir@ + +CFLAGS = @CFLAGS@ @CPPFLAGS@ -DCHROMA_CURSES_HEADER=\<@CURSES@.h\> -DCHROMA_DATA_DIR=\"${datadir}/chroma/\" +INSTALL = @INSTALL@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ + +all: @TARGETS@ + +OBJECTS_COMMON = main.o level.o engine.o menu.o colours.o util.o enigma.o xor.o editor.o xmlparser.o names.o +OBJECTS_CURSES = cursesdisplay.o cursesmenudisplay.o +OBJECTS_SDL = sdldisplay.o sdlshadowdisplay.o sdlmenudisplay.o sdlfont.o sdlscreen.o graphics.o + +chroma-curses: $(OBJECTS_COMMON) $(OBJECTS_CURSES) + $(CC) -o chroma-curses $(OBJECTS_COMMON) $(OBJECTS_CURSES) $(LDFLAGS) $(LIBS) + +chroma-sdl: $(OBJECTS_COMMON) $(OBJECTS_SDL) + $(CC) -o chroma $(OBJECTS_COMMON) $(OBJECTS_SDL) $(LDFLAGS) $(LIBS) + +clean: @TARGETSCLEAN@ + -rm $(OBJECTS_COMMON) + +clean-curses: + -rm $(OBJECTS_CURSES) chroma-curses + +clean-sdl: + -rm $(OBJECTS_SDL) chroma + +install: @TARGETSINSTALL@ + for datafolder in colours help levels levels/* locale locale/* locale/*/*; do \ + if [ -d $$datafolder ]; then \ + ${INSTALL} -d $(DESTDIR)$(datadir)/chroma/$$datafolder; \ + fi; \ + done + for datafile in colours/* help/* levels/* levels/*/* locale/* locale/*/* locale/*/*/*; do \ + if [ -f $$datafile ]; then \ + ${INSTALL} $$datafile $(DESTDIR)$(datadir)/chroma/$$datafile; \ + fi; \ + done + +install-curses: + ${INSTALL} -d $(DESTDIR)$(bindir) + ${INSTALL} chroma-curses $(DESTDIR)$(bindir)/chroma-curses + +install-sdl: + ${INSTALL} -d $(DESTDIR)$(bindir) + ${INSTALL} chroma $(DESTDIR)$(bindir)/chroma + for datafile in graphics graphics/*; do \ + if [ -d $$datafile ]; then \ + ${INSTALL} -d $(DESTDIR)$(datadir)/chroma/$$datafile; \ + fi; \ + done + for datafile in graphics/* graphics/*/*; do \ + if [ -f $$datafile ]; then \ + ${INSTALL} $$datafile $(DESTDIR)$(datadir)/chroma/$$datafile; \ + fi; \ + done diff --git a/Makefile.mingw b/Makefile.mingw new file mode 100644 index 0000000..ca2e3e8 --- /dev/null +++ b/Makefile.mingw @@ -0,0 +1,38 @@ +TMPDIR = /tmp/chroma-win32 +LINK = gcc +LFLAGS = -L/usr/local/cross-tools/lib/ + +WINDRES = i386-mingw32msvc-windres + +OBJECTSCOMMON = main.o level.o engine.o menu.o colours.o util.o enigma.o xor.o editor.o xmlparser.o names.o +OBJECTSCURSES = cursesdisplay.o cursesmenudisplay.o iconcurses.o +OBJECTSSDL = sdldisplay.o sdlshadowdisplay.o sdlmenudisplay.o sdlfont.o sdlscreen.o graphics.o iconsdl.o + +all: chromacurses chromasdl + +iconsdl.o: iconsdl.rc iconsdl.ico + $(WINDRES) -o iconsdl.o iconsdl.rc + +iconcurses.o: iconcurses.rc iconcurses.ico + $(WINDRES) -o iconcurses.o iconcurses.rc + +chromacurses: $(OBJECTSCOMMON) $(OBJECTSCURSES) + $(LINK) $(LFLAGS) -o chroma-curses.exe $(OBJECTSCOMMON) $(OBJECTSCURSES) -lpdcurses -lintl + +chromasdl: $(OBJECTSCOMMON) $(OBJECTSSDL) + $(LINK) $(LFLAGS) -o chroma.exe $(OBJECTSCOMMON) $(OBJECTSSDL) -lSDL -lSDL_image -mwindows -lfreetype -lintl + +clean: + -rm $(OBJECTSCOMMON) $(OBJECTSCURSES) $(OBJECTSSDL) $(OBJECTSVALIDATE) chroma.exe chroma-curses.exe chroma-setup.exe chroma-win32.zip + +install: + -rm -rf $(TMPDIR) + mkdir $(TMPDIR) + cp *.exe *.dll $(TMPDIR) + cp -r graphics/ $(TMPDIR) + cp -r colours/ $(TMPDIR) + cp -r locale/ $(TMPDIR) + mkdir $(TMPDIR)/levels/ + cp -r levels/chroma-1/ levels/chroma-2/ levels/regression/ $(TMPDIR)/levels/ + zip -r chroma-win32.zip $(TMPDIR) + diff --git a/README b/README new file mode 100644 index 0000000..f8d8038 --- /dev/null +++ b/README @@ -0,0 +1,102 @@ +Chroma 1.18 (10th January 2021) +================================ +Chroma is an abstract puzzle game. A variety of colourful shapes are arranged +in a series of increasingly complex patterns, forming fiendish traps that must +be disarmed and mysterious puzzles that must be manipulated in order to give +up their subtle secrets. Initially so straightforward that anyone can pick it +up and begin to play, yet gradually becoming difficult enough to tax even the +brightest of minds. Have you got what it takes to solve Chroma? + +Installing +========== +See INSTALL for details of how to compile and install Chroma from the tarball. + +Playing +======= +Run `chroma` for the graphical version of Chroma, or `chroma-curses` for a +minimal, text based version that runs in a terminal or a command window. + +There are twenty one levels, split into two sets - nine intended for beginners, +providing a step-by-step introduction to the mechanics of Chroma's building +blocks, and a further twelve for those in search of a real challenge. You can +play them in any order, but you'll probably find it useful to build up +experience on the earlier levels before tacking the later ones. + +In each level, the goal is to use your two player pieces to collect all of the +stars before leaving through the door. Other pieces such as circles, squares, +triangles and dots serve to help or hinder you in this quest. Part of the +challenge of Chroma is understanding exactly how these pieces interact with +one another - you'll need to experiment until you discover how their differing +properties can best be used to your advantage. To this end, the full range of +pieces is introduced over the first six levels of each set. + +There are two octagonal player pieces, of which one is active, and may be +moved using the arrow keys. To swap control to the other player piece, press +[SPACE] or [ENTER] - its colour will change to reflect this. Initially, many of +the puzzles can be solved using only one of the player pieces, but as the +levels get harder, you'll find it necessary to carefully co-ordinate the moves +of both of them in order to achieve your objective. + +If you make a mistake, you can press [DELETE] to undo as many moves as you +wish, allowing you to move in a different way or press [INSERT] to redo moves +that have been previously undone. Once a move has been made, however, you must +wait for its full consequences to take effect before you can move again. In the +graphical version, holding [SHIFT] down will speed things up, whereas [CTRL] +will slow things down, allowing you to observe the changes in more detail. +[F] will bring the pieces to their ultimate state of rest immediately. + +Pressing [ESCAPE] will present you with a menu, from which you can save your +position, load a previous position, or return to the level selection menu, as +well as allowing you to revert to the last position loaded. At the start of a +level, you can also replay the moves from a previously saved position. When +doing so, [LEFT] reverses the replay, [UP] or [DOWN] pauses it, and [RIGHT] +continues. Should you wish to stop the replay and start making moves again, +return to the menu with [ESCAPE], then press [T]. + +The Display Options menu allows you to change the graphics used, as well as +the size of the screen and the speed of the game. You can also change the keys +used and how the mouse works, and save these changes for future use if desired. + +Level Editor +============ +Selecting [E] from the title screen allows you to design your own levels. To +start with a blank level, press [L] and then [C]. You can now press [Q] to +enter the level editor itself. Use the arrow keys to move the cursor, and +[PAGE-UP] and [PAGE-DOWN] to change the currently selected piece. Pressing +[SPACE] or [ENTER] will place a piece under the cursor, and pressing [Q] will +return you to the editing menu, from which you can save your work, test the +level, or verify it to ensure that it contains no errors. The Level Options +menu allows you to give your level a title, change its size and rotate it. + +Browser Version +=============== +The "browser" directory contains all the files necessary to play Chroma in a +standards compliant browser. For Chrome, add --allow-file-access-from-files to +the browser's command line or use a different brwoser or local web server. + +Website +======= +Visit the Chroma website at http://level7.org.uk/chroma/ + +Comments and suggestions regarding Chroma are always welcome! Email chroma (at) +level7 (dot) org (dot) uk, including the word "chroma" in your subject line to +boost your chances of beating the unfortunately necessary spam filter. + +Copyright and Licence +===================== +Chroma is Copyright (C) 2010-2021 Amf + +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 + diff --git a/actions.h b/actions.h new file mode 100644 index 0000000..8f6ce8d --- /dev/null +++ b/actions.h @@ -0,0 +1,54 @@ +/* + actions.h + + Copyright (C) 2010-2019 Amf + + 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 +*/ + +enum +{ + ACTION_NONE, + ACTION_QUIT, + ACTION_REDRAW, + ACTION_FAST, + ACTION_LEFT, + ACTION_RIGHT, + ACTION_UP, + ACTION_DOWN, + ACTION_SWAP, + ACTION_UNDO, + ACTION_REDO, + ACTION_PIECE_LEFT, + ACTION_PIECE_RIGHT, + ACTION_HIDE, + ACTION_PAUSE, + ACTION_FASTER, + ACTION_SLOWER, + + ACTION_MOUSE_CLICK, + ACTION_MOUSE_DRAG, + ACTION_MOUSE_DRAG_OR_CLICK, + + ACTION_MAX +}; + +#define ACTION_PAGE_UP ACTION_PIECE_LEFT +#define ACTION_PAGE_DOWN ACTION_PIECE_RIGHT +#define ACTION_ENTER ACTION_SWAP +#define ACTION_DELETE ACTION_UNDO + +#define ACTION_KEY_MIN ACTION_NONE +#define ACTION_KEY_MAX ACTION_SLOWER + 1 diff --git a/browser/chroma-script.js b/browser/chroma-script.js new file mode 100644 index 0000000..6d4ef5c --- /dev/null +++ b/browser/chroma-script.js @@ -0,0 +1,7396 @@ +const graphics_sets = [ + { set: "zen", key: "Z", title: "Zen", preview: "preview-zen.svg", sheet: "graphics-zen.svg", xml: "graphics-zen.xml" }, + { set: "marble", key: "M", title: "Marble", preview: "preview-marble.svg", sheet: "graphics-marble.svg", xml: "graphics-marble.xml" }, + { set: "neon", key: "N", title: "Neon", preview: "preview-neon.svg", sheet: "graphics-neon.svg", xml: "graphics-neon.xml" }, + { set: "xor", key: "X", title: "XOR", preview: "preview-xor.svg", sheet: "graphics-xor.png", xml: "graphics-xor.xml" } +]; + +const graphics_sizes = [ + { size: "0", key: "0", title: "Scale to fit" }, + { size: "16", key: "1", title: "16x16" }, + { size: "24", key: "2", title: "24x24" }, + { size: "32", key: "3", title: "32x32" }, + { size: "48", key: "4", title: "48x48" }, + { size: "64", key: "5", title: "64x64" }, + { size: "96", key: "6", title: "96x96" }, + { size: "128", key: "7", title: "128x128" }, + { size: "-1", key: "C", title: "Custom" } +]; + +const slider_positions = [1, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2, 2.2, 2.4, 2.6, 2.8, 3, 3.2, 3.4, 3.6, 3.8, 4, 4.2, 4.4, 4.6, 4.8, 5, 5.5, 6, 6.5, 7, 7.5, 8, 8.5, 9, 9.5]; + +const font_name = "Sans-Serif"; + +const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; +const months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + +const MOVE_LEFT = 0; +const MOVE_UP = 1; +const MOVE_RIGHT = 2; +const MOVE_DOWN = 3; +const MOVE_NONE = 4; +const MOVE_SWAP = 5; +const MOVE_SWAPPED = 6; +const MOVE_UNKNOWN = 7; +const MOVE_REDO = 8; +const MOVE_UNDO = 9; + +const MOVER_FAST = 1; +const MOVER_UNDO = 2; +const MOVER_STORE = 4; + +const PIECE_SPACE = 0; +const PIECE_WALL = 1; +const PIECE_PLAYER_ONE = 2; +const PIECE_PLAYER_TWO = 3; +const PIECE_STAR = 4; +const PIECE_DOTS = 5; +const PIECE_DOOR = 6; +const PIECE_CIRCLE = 7; +const PIECE_ARROW_RED_LEFT = 8; +const PIECE_ARROW_RED_UP = 9; +const PIECE_ARROW_RED_RIGHT = 10; +const PIECE_ARROW_RED_DOWN = 11; +const PIECE_BOMB_RED_LEFT = 12; +const PIECE_BOMB_RED_UP = 13; +const PIECE_BOMB_RED_RIGHT = 14; +const PIECE_BOMB_RED_DOWN = 15; +const PIECE_ARROW_GREEN_LEFT = 16; +const PIECE_ARROW_GREEN_UP = 17; +const PIECE_ARROW_GREEN_RIGHT = 18; +const PIECE_ARROW_GREEN_DOWN = 19; +const PIECE_BOMB_GREEN_LEFT = 20; +const PIECE_BOMB_GREEN_UP = 21; +const PIECE_BOMB_GREEN_RIGHT = 22; +const PIECE_BOMB_GREEN_DOWN = 23; +const PIECE_ARROW_BLUE_LEFT = 24; +const PIECE_ARROW_BLUE_UP = 25; +const PIECE_ARROW_BLUE_RIGHT = 26; +const PIECE_ARROW_BLUE_DOWN = 27; +const PIECE_BOMB_BLUE_LEFT = 28; +const PIECE_BOMB_BLUE_UP = 29; +const PIECE_BOMB_BLUE_RIGHT = 30; +const PIECE_BOMB_BLUE_DOWN = 31; +const PIECE_CIRCLE_DOUBLE = 32; +const PIECE_DOTS_DOUBLE = 33; +const PIECE_DOTS_X = 34; +const PIECE_DOTS_Y = 35; +const PIECE_SWITCH = 36; +const PIECE_TELEPORT = 37; +const PIECE_MAP_TOP_LEFT = 38; +const PIECE_MAP_TOP_RIGHT = 39; +const PIECE_MAP_BOTTOM_LEFT = 40; +const PIECE_MAP_BOTTOM_RIGHT = 41; +const PIECE_DARKNESS = 42; +const PIECE_EXPLOSION_RED_LEFT = 43; +const PIECE_EXPLOSION_RED_HORIZONTAL = 44; +const PIECE_EXPLOSION_RED_RIGHT = 45; +const PIECE_EXPLOSION_RED_TOP = 46; +const PIECE_EXPLOSION_RED_VERTICAL = 47; +const PIECE_EXPLOSION_RED_BOTTOM = 48; +const PIECE_EXPLOSION_GREEN_LEFT = 49; +const PIECE_EXPLOSION_GREEN_HORIZONTAL = 50; +const PIECE_EXPLOSION_GREEN_RIGHT = 51; +const PIECE_EXPLOSION_GREEN_TOP = 52; +const PIECE_EXPLOSION_GREEN_VERTICAL = 53; +const PIECE_EXPLOSION_GREEN_BOTTOM = 54 ; +const PIECE_EXPLOSION_BLUE_LEFT = 55; +const PIECE_EXPLOSION_BLUE_HORIZONTAL = 56; +const PIECE_EXPLOSION_BLUE_RIGHT = 57; +const PIECE_EXPLOSION_BLUE_TOP = 58; +const PIECE_EXPLOSION_BLUE_VERTICAL = 59; +const PIECE_EXPLOSION_BLUE_BOTTOM = 60; + +const PIECE_EXPLOSION_NEW_RED_LEFT = 61; +const PIECE_EXPLOSION_NEW_RED_HORIZONTAL = 62; +const PIECE_EXPLOSION_NEW_RED_RIGHT = 63; +const PIECE_EXPLOSION_NEW_RED_TOP = 64; +const PIECE_EXPLOSION_NEW_RED_VERTICAL = 65; +const PIECE_EXPLOSION_NEW_RED_BOTTOM = 66; +const PIECE_EXPLOSION_NEW_GREEN_LEFT = 67; +const PIECE_EXPLOSION_NEW_GREEN_HORIZONTAL = 68; +const PIECE_EXPLOSION_NEW_GREEN_RIGHT = 69; +const PIECE_EXPLOSION_NEW_GREEN_TOP = 70; +const PIECE_EXPLOSION_NEW_GREEN_VERTICAL = 71; +const PIECE_EXPLOSION_NEW_GREEN_BOTTOM = 72; +const PIECE_EXPLOSION_NEW_BLUE_LEFT = 73; +const PIECE_EXPLOSION_NEW_BLUE_HORIZONTAL = 74; +const PIECE_EXPLOSION_NEW_BLUE_RIGHT = 75; +const PIECE_EXPLOSION_NEW_BLUE_TOP = 76; +const PIECE_EXPLOSION_NEW_BLUE_VERTICAL = 77; +const PIECE_EXPLOSION_NEW_BLUE_BOTTOM = 78; + +const PIECE_CURSOR = 79; +const PIECE_GONE = 80; +const PIECE_UNKNOWN = 81; + +const PIECE_EXPLOSION_FIRST = PIECE_EXPLOSION_RED_LEFT; +const PIECE_EXPLOSION_LAST = PIECE_EXPLOSION_BLUE_BOTTOM; +const PIECE_EXPLOSION_NEW_FIRST = PIECE_EXPLOSION_NEW_RED_LEFT; +const PIECE_EXPLOSION_NEW_LAST = PIECE_EXPLOSION_NEW_BLUE_BOTTOM; +const PIECE_EXPLOSION_NEW_OFFSET = (PIECE_EXPLOSION_NEW_FIRST - PIECE_EXPLOSION_FIRST); +const PIECE_MOVERS_FIRST = PIECE_ARROW_RED_LEFT; +const PIECE_MOVERS_LAST = PIECE_BOMB_BLUE_DOWN; +const PIECE_MAX = PIECE_GONE; + +const PIECE_XOR_MAGUS = PIECE_PLAYER_ONE; +const PIECE_XOR_QUESTOR = PIECE_PLAYER_TWO; +const PIECE_XOR_DOTS = PIECE_DOTS_X; +const PIECE_XOR_WAVES = PIECE_DOTS_Y; +const PIECE_XOR_CHICKEN = PIECE_ARROW_RED_LEFT; +const PIECE_XOR_V_BOMB = PIECE_BOMB_RED_LEFT; +const PIECE_XOR_FISH = PIECE_ARROW_RED_DOWN; +const PIECE_XOR_H_BOMB = PIECE_BOMB_RED_DOWN; +const PIECE_XOR_DOLL = PIECE_CIRCLE; +const PIECE_XOR_MASK = PIECE_STAR; + +/* l u r d n s w */ +const move_x = [-1, 0, 1, 0, 0, 0, 0]; +const move_y = [0, -1, 0, 1, 0, 0, 0]; + +const enigma_move_order = [MOVE_DOWN, MOVE_RIGHT, MOVE_LEFT, MOVE_UP]; + +const xor_teleport_order = [MOVE_RIGHT, MOVE_UP, MOVE_LEFT, MOVE_DOWN]; + +const MODE_CHROMA = 0; +const MODE_XOR = 1; +const MODE_ENIGMA = 2; + +const LEVELFLAG_MOVES = 1; +const LEVELFLAG_STARS = 2; +const LEVELFLAG_SWITCH = 4; +const LEVELFLAG_EXIT = 8; +const LEVELFLAG_SOLVED = 16; +const LEVELFLAG_FAILED = 32; +const LEVELFLAG_PAUSED = 64; +const LEVELFLAG_UNDO = 128; +const LEVELFLAG_TESTING = 256; +const LEVELFLAG_MAP = 512; +const LEVELFLAG_NOUNDO = 1024; + +const MAPPED_TOP_LEFT = 1; +const MAPPED_TOP_RIGHT = 2; +const MAPPED_BOTTOM_LEFT = 4; +const MAPPED_BOTTOM_RIGHT = 8; + +const GRAPHICS_BEVEL = 1 +const GRAPHICS_BEVEL_SHADOW = 2 +const GRAPHICS_BEVEL16 = 4 +const GRAPHICS_RANDOM = 8 +const GRAPHICS_KEY = 16 +const GRAPHICS_MOVER = 32 +const GRAPHICS_TILE = 64 +const GRAPHICS_ANIMATE = 128 +const GRAPHICS_LEVEL = 256 +const GRAPHICS_CLONE = 512 +const GRAPHICS_SCALE = 1024 + +const GRAPHICS_CURSES = 1 +const GRAPHICS_ZORDER = 2 +const GRAPHICS_BACKGROUND = 4 +const GRAPHICS_TRANSLATE = 8 + +const BEVEL_BASE = 0x10000 +const BEVEL_L = (BEVEL_BASE * 1) +const BEVEL_R = (BEVEL_BASE * 2) +const BEVEL_U = (BEVEL_BASE * 4) +const BEVEL_D = (BEVEL_BASE * 8) +const BEVEL_TL = (BEVEL_BASE * 16) +const BEVEL_TR = (BEVEL_BASE * 32) +const BEVEL_BL = (BEVEL_BASE * 64) +const BEVEL_BR = (BEVEL_BASE * 128) +const BEVEL_ALL = (BEVEL_BASE * 255) + +const SHADOW_BASE = 0x1000000 +const SHADOW_TOP_LEFT = 1 +const SHADOW_TOP = 2 +const SHADOW_TOP_RIGHT = 4 +const SHADOW_LEFT = 8 +const SHADOW_MIDDLE = 16 +const SHADOW_RIGHT = 32 +const SHADOW_BOTTOM_LEFT = 64 +const SHADOW_BOTTOM = 128 +const SHADOW_BOTTOM_RIGHT = 256 + +const IMAGE_PIECE = 0 +const IMAGE_SHADOW = 1 +const IMAGE_SMALL = 2 +const IMAGE_MAX = 3 + +const SIZE_PIECES = 1 +const SIZE_SMALL = 2 + +const shadow_flags = + [ + SHADOW_TOP_LEFT, SHADOW_TOP, SHADOW_TOP_RIGHT, + SHADOW_LEFT, SHADOW_MIDDLE, SHADOW_RIGHT, + SHADOW_BOTTOM_LEFT, SHADOW_BOTTOM, SHADOW_BOTTOM_RIGHT + ]; + +mouse_move = MOVE_NONE; +mouse_recent_event = false; +mouse_target = false; +mouse_target_x = 0; +mouse_target_y = 0; + +function initialise() +{ + document.getElementById("missing").textContent = "Please wait"; + document.getElementById("missing-levels").style.display = "block"; + document.getElementById("instructions").style.display = "none"; + + options = new Object; + options.previous_delay = 100; + options.storage = (localStorage.length != 0); + options.others = false; + + if(window.location.href.indexOf("?debug") != -1 || window.location.href.indexOf("?hidden") != -1) + options.show_hidden = true; + else + options.show_hidden = false; + + default_preferences(); + load_preferences(); + + screen = new Object; + screen.width = 0; + screen.height = 0; + screen.canvas = null; + screen.context = null; + screen.bar = new Object; + screen.bar.height = 0; + screen.bar.canvas = null; + screen.bar.context = null; + screen.bar.lines = 0; + screen.map = new Object; + screen.map.pixel_width = 0; + screen.map.pixel_height = 0; + screen.map.width = 0; + screen.map.height = 0; + screen.map.canvas = null; + screen.map.context = null; + screen.offset_x = 0; + screen.offset_y = 0; + + menu = new Object; + menu.state = true; + menu.becoming = true; + + graphics = new Object; + graphics.missing_sheet = true; + graphics.missing_xml = true; + graphics.set = ""; + graphics.width = 0; + graphics.height = 0; + graphics.offset_x = 0; + graphics.offset_y = 0; + graphics.sheets = []; + graphics.xml = []; + graphics.image = []; + graphics.image_flags = []; + graphics.small_width = 0; + graphics.small_height = 0; + graphics.small_image = []; + graphics.shadows = []; + graphics.shadow_image = []; + graphics.shadow_offset_x = []; + graphics.shadow_offset_y = []; + graphics.shadow_width = []; + graphics.shadow_height = []; + graphics.shadow_z = []; + graphics.shift = false; + graphics.ctrl = false; + graphics.map_colours = []; + + levels = new Object; + levels.xml = null; + levels.file = "levels.xml"; + level = null; + level_replay = null; + + toggle_keypad(options.keypad); + + window.onresize = screen_resize; + + levels_load(); +} + +function levels_load() +{ + document.getElementById("missing-levels").style.display = "block"; + + var xhr = new XMLHttpRequest(); + xhr.open("GET", levels.file); + xhr.onerror = function() { this.onerror = null; document.getElementById("error-levels").textContent = "Unable to load "+levels.file +" ("+(xhr.statusText == "" ? "If using Chrome, add --allow-file-access-from-files to the browser's command line, access via a different browser or a local web server, or play online at www.level7.org.uk/chroma/ )" : xhr.statusText); } + xhr.onload = function() { levels.xml = xhr.responseText; levels_loaded(); } + xhr.send(); +} + +function levels_loaded() +{ + document.getElementById("missing-levels").style.display = "none"; + document.getElementById("missing").style.display = "none"; + document.getElementById("items").style.display = "block"; + + levels.parser = new DOMParser(); + levels.dom = levels.parser.parseFromString(levels.xml, "text/xml"); + + var sets = levels.dom.getElementsByTagName("set"); + for(var s = 0; s < sets.length; s ++) + { + if(sets[s].getAttribute("type") != null && sets[s].getAttribute("type") != "chroma") + options.others = true; + } + + if(!options.others) + document.styleSheets[0].insertRule(".other { display: none; }"); + + main_menu(); +} + +function graphics_load(set) +{ + var sheet, xml; + + if(graphics.sheets[set] == null || graphics.xml[set] == null) + { + graphics.missing_sheet = true; + graphics.missing_xml = true; + graphics.loading = set; + + document.getElementById("missing").style.display = "block"; + document.getElementById("missing-sheet").style.display = "block"; + document.getElementById("missing-xml").style.display = "block"; + document.getElementById("items").style.display = "none"; + + for(var s = 0; s < graphics_sets.length; s ++) + { + if(graphics_sets[s].set == set) + { + sheet = graphics_sets[s].sheet; + xml = graphics_sets[s].xml; + } + } + + graphics.sheets[set] = new Image; + graphics.sheets[set].src = sheet; + + graphics.sheets[set].onerror = function() { this.onerror = null; graphics.sheets[set] = null; document.getElementById("error-sheet").textContent = "Unable to load "+sheet; setTimeout(function() { document.getElementById("items").style.display = "block"; document.getElementById("missing").style.display = "none"; document.getElementById("missing-sheet").style.display = "none"} , 1000); } + graphics.sheets[set].onload = function() { graphics.missing_sheet = false; graphics_loaded(); } + + setTimeout(graphics_load_check, 250); + + var xhr = new XMLHttpRequest(); + xhr.open("GET", xml); + xhr.onerror = function() { this.onerror = null; graphics.sheets[set] = null; document.getElementById("error-xml").textContent = "Unable to load "+xml+" ("+xhr.statusText+")"; setTimeout(function() { document.getElementById("items").style.display = "block"; document.getElementById("missing").style.display = "none"; document.getElementById("missing-xml").style.display = "none"} , 1000); } + xhr.onload = function() { graphics.missing_xml = false; graphics.xml[graphics.loading] = xhr.responseText; graphics_loaded(); } + xhr.send(); + } + else + { + graphics_loaded(); + } +} + +/* For Firefox and any other browsers incapable of firing an onload for svg images */ +function graphics_load_check() +{ + if(graphics.sheets[graphics.loading] != null) + { + if(graphics.sheets[graphics.loading].complete) + { + graphics.missing_sheet = false; + graphics_loaded(); + } + } + + if(graphics.missing_sheet == true) + setTimeout(graphics_load_check, 250); +} + +function graphics_loaded() +{ + if(graphics.sheets[graphics.set] != null && graphics.sheets[graphics.set] > 0) + graphics.missing_sheet = false; + + if(!graphics.missing_sheet) + document.getElementById("missing-sheet").style.display = "none"; + if(!graphics.missing_xml) + document.getElementById("missing-xml").style.display = "none"; + + if(graphics.missing_sheet || graphics.missing_xml) + return; + + document.getElementById("missing").style.display = "none"; + document.getElementById("items").style.display = "block"; + + graphics_render(); +} + +function graphics_render() +{ + if(level == null) + return; + + var set = options.graphics; + if(level.mode == MODE_XOR && options.graphics_xor) + set = "xor"; + + if(graphics.sheets[set] == null) + { + graphics_load(set); + return; + } + + screen.canvas = document.getElementById("screen"); + screen.bar.canvas = document.getElementById("bar"); + screen.map.canvas = document.getElementById("map"); + + /* XOR partial display */ + if(level.mode == MODE_XOR && options.xor_display) + { + var square = Math.min(window.innerWidth, window.innerHeight); + + /* Allow space on sides if landscape screen */ + if(square < window.innerWidth && square > 0.66 * window.innerWidth) + square = 0.66 * window.innerWidth; + /* Allow space below if portrait screen */ + else if(square < window.innerHeight && square > 0.66 * window.innerHeight) + square = 0.66 * window.innerHeight; + + square = Math.floor(square / 32) * 32; + + screen.canvas.height = screen.height = square; + screen.canvas.width = screen.width = square; + + screen.canvas.style.position= "fixed"; + screen.bar.canvas.style.position= "fixed"; + screen.map.canvas.style.position= "fixed"; + + /* Landscape screen */ + if(window.innerWidth > window.innerHeight) + { + screen.offset_x = Math.floor((window.innerWidth - screen.width) / 2); + screen.offset_y = Math.floor((window.innerHeight - screen.height) / 2); + screen.canvas.style.left = screen.offset_x + "px"; + screen.canvas.style.top = screen.offset_y + "px"; + + screen.map.pixel_width = screen.map.pixel_height = Math.floor((window.innerWidth - screen.width) / (2 * level.width)); + + screen.map.canvas.width = screen.map.width = level.width * screen.map.pixel_width; + screen.map.canvas.height = screen.map.height = level.height * screen.map.pixel_height; + + screen.map.canvas.style.left = (window.innerWidth - screen.map.width) + "px"; + screen.map.canvas.style.top = (window.innerHeight - screen.map.height) + "px"; + + screen.bar.height = Math.max(32, screen.map.pixel_width * 8); + screen.bar.lines = 2; + screen.bar.width = Math.floor((window.innerWidth - screen.width) / 2); + screen.bar.canvas.height = screen.bar.height * screen.bar.lines; + screen.bar.canvas.width = screen.bar.width; + + screen.bar.canvas.style.left = "0px"; + screen.bar.canvas.style.top = (window.innerHeight - screen.bar.height * screen.bar.lines) + "px"; + } + /* Portrait screen */ + else + { + screen.offset_x = Math.floor((window.innerWidth - screen.width) / 2); + screen.offset_y = Math.floor((window.innerHeight - screen.height) / 2); + screen.canvas.style.left = screen.offset_x + "px"; + screen.canvas.style.top = screen.offset_y + "px"; + + screen.map.pixel_width = screen.map.pixel_height = Math.floor((window.innerHeight - screen.height - 16) / (2 * level.height)); + + screen.map.canvas.width = screen.map.width = level.width * screen.map.pixel_width; + screen.map.canvas.height = screen.map.height = level.height * screen.map.pixel_height; + + screen.map.canvas.style.left = (window.innerWidth - screen.map.width) + "px"; + screen.map.canvas.style.top = (window.innerHeight - screen.map.height) + "px"; + + screen.bar.height = Math.max(32, screen.map.pixel_width * 8); + screen.bar.lines = 2; + screen.bar.width = window.innerWidth - screen.map.width; + screen.bar.canvas.height = screen.bar.height * screen.bar.lines; + screen.bar.canvas.width = screen.bar.width; + + screen.bar.canvas.style.left = "0px"; + screen.bar.canvas.style.top = (window.innerHeight - screen.bar.height * screen.bar.lines) + "px"; + } + } + /* Regular display */ + else + { + screen.offset_x = 0; + screen.offset_y = 0; + + screen.bar.lines = 1; + screen.bar.height = Math.floor(window.innerHeight / 24); + screen.bar.width = window.innerWidth; + + screen.canvas.height = screen.height = window.innerHeight - screen.bar.height; + screen.canvas.width = screen.width = window.innerWidth; + + screen.canvas.style.position= "fixed"; + screen.canvas.style.left = "0px"; + screen.canvas.style.top = "0px"; + + screen.bar.canvas.height = screen.bar.height; + screen.bar.canvas.width = screen.bar.width; + + screen.bar.canvas.style.position= "fixed"; + screen.bar.canvas.style.left = "0px"; + screen.bar.canvas.style.top = screen.height + "px"; + + screen.map.canvas.style.display = "none"; + } + + if(screen.canvas.getContext) + { + screen.context = screen.canvas.getContext("2d", { alpha: false }); + screen.context.fillStyle = "#000"; + screen.context.fillRect(0, 0, screen.width, screen.height); + } + else + { + alert("Unable to get screen context"); + return; + } + + if(screen.bar.canvas.getContext) + { + screen.bar.context = screen.bar.canvas.getContext("2d", { alpha: false }); + screen.bar.context.fillStyle = "#000"; + screen.bar.context.fillRect(0, 0, screen.width, screen.bar.height * screen.bar.lines); + } + else + { + alert("Unable to get bar context"); + return; + } + + if(screen.map.canvas.getContext) + { + screen.map.context = screen.map.canvas.getContext("2d", { alpha: false }); + screen.map.context.fillStyle = "#000"; + screen.map.context.fillRect(0, 0, screen.map.width, screen.map.height); + } + else + { + alert("Unable to get map context"); + return; + } + + var ox = graphics.width; + var oy = graphics.height; + var os = graphics.set; + var osh = graphics.small_height; + + /* XOR partial display */ + if(level.mode == MODE_XOR && options.xor_display) + { + var granularity = 2; + graphics.width = graphics.height = granularity * Math.floor(screen.height / (granularity * 8)); + } + /* Scale to fit screen */ + else if(options.graphics_size == 0) + { + var granularity = 2; + graphics.width = granularity * Math.floor(screen.width / (granularity * level.width)); + graphics.height = granularity * Math.floor(screen.height / (granularity * level.height)); + + graphics.width = Math.min(graphics.width, graphics.height); + graphics.height = Math.min(graphics.width, graphics.height); + } + /* Custom size */ + else if(options.graphics_size == -1) + graphics.width = graphics.height = options.graphics_custom_size; + /* Fixed size */ + else + graphics.width = graphics.height = options.graphics_size; + + graphics.small_height = graphics.small_width = Math.floor(screen.bar.height * 0.9); + + if(ox == graphics.width && oy == graphics.height && os == set && osh == graphics.small_height) + { + graphics_return_after_rendering(); + return; + } + + graphics.set = set; + + document.getElementById("missing-render").style.display = "block"; + document.getElementById("missing").style.display = "block"; + document.getElementById("items").style.display = "none"; + + setTimeout(graphics_scale_images, 10); +} + +function graphics_scale_images() +{ + var small, width, height, rescale; + + graphics.image = []; + graphics.small_image = []; + graphics.shadows = []; + graphics.shadow_image = []; + graphics.shadow_start_x = []; + graphics.shadow_offset_x = []; + graphics.shadow_start_y = []; + graphics.shadow_offset_y = []; + graphics.shadow_width = []; + graphics.shadow_height = []; + graphics.shadow_z = []; + graphics.shadow_flags = []; + graphics.map_colours = []; + + for(var p = 0; p < PIECE_MAX; p ++) + { + graphics.shadow_offset_x[p] = [0, 0, 0, 0, 0, 0, 0, 0, 0]; + graphics.shadow_offset_y[p] = [0, 0, 0, 0, 0, 0, 0, 0, 0]; + graphics.shadow_start_x[p] = [0, 0, 0, 0, 0, 0, 0, 0, 0]; + graphics.shadow_start_y[p] = [0, 0, 0, 0, 0, 0, 0, 0, 0]; + graphics.shadow_width[p] = [0, 0, 0, 0, 0, 0, 0, 0, 0]; + graphics.shadow_height[p] = [0, 0, 0, 0, 0, 0, 0, 0, 0]; + graphics.shadow_z[p] = 0; + } + + /* Workaround Firefox's poor rendering at odd sizes, especially obvious with "zen" */ + rescale = 1; + if(options.graphics == "zen" && graphics.width % 8 != 0 && graphics.height % 8 != 0 && graphics.width < 64) + rescale = 4; + + var parser = new DOMParser(); + graphics.dom = parser.parseFromString(graphics.xml[graphics.set], "text/xml"); + + var shadows = graphics.dom.getElementsByTagName("shadow"); + for(var s = 0; s < shadows.length; s ++) + { + var shadow = new Object; + shadow.x = parseInt(shadows[s].getAttribute("x")); + shadow.y = parseInt(shadows[s].getAttribute("y")); + graphics.shadows.push(shadow); + } + + var pieces = graphics.dom.getElementsByTagName("piece"); + for(var p = 0; p < pieces.length; p ++) + { + piece = eval("PIECE_" + (pieces[p].getAttribute("name").toUpperCase())); + + graphics.image_flags[piece] = 0; + + if(pieces[p].getAttribute("tile") == "yes") + graphics.image_flags[piece] |= GRAPHICS_TILE; + + if(pieces[p].getAttribute("bevel") == "piece") + graphics.image_flags[piece] |= GRAPHICS_BEVEL; + if(pieces[p].getAttribute("bevel") == "shadow") + graphics.image_flags[piece] |= GRAPHICS_BEVEL_SHADOW; + if(pieces[p].getAttribute("bevel") == "piece shadow") + graphics.image_flags[piece] |= GRAPHICS_BEVEL | GRAPHICS_BEVEL_SHADOW; + if(pieces[p].getAttribute("bevel") == "16") + graphics.image_flags[piece] |= GRAPHICS_BEVEL16; + + if(pieces[p].getAttribute("level") == "yes") + graphics.image_flags[piece] |= GRAPHICS_LEVEL; + + var clones = pieces[p].getElementsByTagName("clone"); + if(clones.length > 0 && clones[0].getAttribute("piece") != null) + { + var c = eval("PIECE_" + clones[0].getAttribute("piece").toUpperCase()); + graphics.image_flags[piece] = graphics.image_flags[c]; + graphics.image[piece] = graphics.image[c]; + graphics.small_image[piece] = graphics.small_image[c]; + graphics.shadow_image[piece] = graphics.shadow_image[c]; + + graphics.shadow_offset_x[piece][9] = graphics.shadow_offset_x[c][9]; + graphics.shadow_offset_y[piece][9] = graphics.shadow_offset_y[c][9]; + graphics.shadow_width[piece][9] = graphics.shadow_width[c][9]; + graphics.shadow_height[piece][9] = graphics.shadow_height[c][9]; + + } + + var images = pieces[p].getElementsByTagName("image"); + for(var i = 0; i < images.length; i ++) + { + if(images[i].getAttribute("type") == "small") + { + small = true; + width = graphics.small_width; + height = graphics.small_height; + } + else + { + small = false; + width = graphics.width; + height = graphics.height; + } + + if(rescale != 1) + { + width = width * rescale; + height = height * rescale; + } + + var canvas = document.createElement("canvas"); + + var context = canvas.getContext("2d"); + + var dw = images[i].getAttribute("width") != null ? images[i].getAttribute("width") : 1; + var dh = images[i].getAttribute("height") != null ? images[i].getAttribute("height") : 1; + + if(dw != 1) + width = width * dw; + if(dh != 1) + height = height * dh; + + canvas.width = width; + canvas.height = height; + + if(graphics.set == "xor") + context.imageSmoothingEnabled = false; + + if(images[i].getAttribute("colour") != null) + { + context.fillStyle = images[i].getAttribute("colour"); + context.fillRect(0, 0, width, height); + + } + else if(images[i].getAttribute("file") != null && images[i].getAttribute("file") == "svg:") + { + var x = images[i].getAttribute("x") != null ? images[i].getAttribute("x") : 0; + var y = images[i].getAttribute("y") != null ? images[i].getAttribute("y") : 0; + var w = images[i].getAttribute("w") != null ? images[i].getAttribute("w") : 100; + var h = images[i].getAttribute("h") != null ? images[i].getAttribute("h") : 100; + var rotate = images[i].getAttribute("rotate") != null ? images[i].getAttribute("rotate") : 0; + + + if(rotate != 0) + { + context.save(); + context.translate(width / 2, height / 2); + context.rotate(rotate * Math.PI / 180); + context.drawImage(graphics.sheets[graphics.set], x, y, w, h, Math.floor(-width / 2), Math.floor(-height / 2), width, height); + + context.restore(); + } + else + context.drawImage(graphics.sheets[graphics.set], x, y, w, h, 0, 0, width, height); + + } + + if(rescale != 1) + { + width = width / rescale; + height = height / rescale; + + var rescaled = document.createElement("canvas"); + rescaled.width = width; + rescaled.height = height; + + context = rescaled.getContext("2d"); + + context.drawImage(canvas, 0, 0, width * rescale, height * rescale, 0, 0, width, height); + canvas = rescaled; + } + + if(small) + { + if(graphics.small_image[piece] == null) + graphics.small_image[piece] = canvas; + else + { + var montage = document.createElement("canvas"); + montage.width = graphics.small_image[piece].width + canvas.width; + montage.height = Math.max(graphics.small_image[piece].height, canvas.height); + + var context = montage.getContext("2d"); + context.drawImage(graphics.small_image[piece], 0, 0); + context.drawImage(canvas, graphics.small_image[piece].width, 0); + + graphics.small_image[piece] = montage; + } + } + else if(images[i].getAttribute("type") == "shadow") + { + + if(images[i].getAttribute("z") != null) + graphics.shadow_z[p] = parseInt(images[i].getAttribute("z")); + + if(images[i].getAttribute("exclude-middle") == "yes") + { + var ox = images[i].getAttribute("ox") != null ? images[i].getAttribute("ox") : 0; + var oy = images[i].getAttribute("oy") != null ? images[i].getAttribute("oy") : 0; + + context.clearRect(-ox * graphics.width, -oy * graphics.height, graphics.width, graphics.height); + } + + if(graphics.shadow_image[piece] == null) + { + graphics.shadow_image[piece] = canvas; + + /* Store offsets if this is the first shadow image */ + var ox = images[i].getAttribute("ox") != null ? images[i].getAttribute("ox") : 0; + var oy = images[i].getAttribute("oy") != null ? images[i].getAttribute("oy") : 0; + + graphics.shadow_offset_x[piece][9] = graphics.width * ox; + graphics.shadow_offset_y[piece][9] = graphics.height * oy; + graphics.shadow_width[piece][9] = width; + graphics.shadow_height[piece][9] = height; + } + else + { + var montage = document.createElement("canvas"); + montage.width = graphics.shadow_image[piece].width + canvas.width; + montage.height = Math.max(graphics.shadow_image[piece].height, canvas.height); + + var context = montage.getContext("2d"); + context.drawImage(graphics.shadow_image[piece], 0, 0); + context.drawImage(canvas, graphics.shadow_image[piece].width, 0); + + graphics.shadow_image[piece] = montage; + } + } + else + { + if(graphics.image[piece] == null) + graphics.image[piece] = canvas; + else + { + var montage = document.createElement("canvas"); + montage.width = graphics.image[piece].width + canvas.width; + montage.height = Math.max(graphics.image[piece].height, canvas.height); + + var context = montage.getContext("2d"); + context.drawImage(graphics.image[piece], 0, 0); + context.drawImage(canvas, graphics.image[piece].width, 0); + + graphics.image[piece] = montage; + } + } + + } + } + + if(graphics.shadows.length > 0) + { + /* Calculate quadrants for shadow images */ + for(var p = 0; p < PIECE_MAX; p ++) + { + if(graphics.shadow_image[p] != null) + { + if(graphics.shadow_z[p] != 0) + graphics.flags |= GRAPHICS_ZORDER; + + var width = graphics.shadow_width[p][9]; + var height = graphics.shadow_height[p][9]; + var offset_x = graphics.shadow_offset_x[p][9]; + var offset_y = graphics.shadow_offset_y[p][9]; + + for(j = 0; j < 3; j ++) + { + for(k = 0; k < 3; k ++) + { + x = (j - 1) * graphics.width - offset_x; + y = (k - 1) * graphics.height - offset_y; + + /* Does the shadow fall into this square? */ + if(x > -(graphics.width) && x < width && y > -(graphics.height) && y < height) + { + if(x >= 0) + { + graphics.shadow_start_x[p][j+k*3]= x; + graphics.shadow_offset_x[p][j+k*3] = 0; + + if(x + graphics.width > width) + graphics.shadow_width[p][j+k*3] = width - x; + else + graphics.shadow_width[p][j+k*3] = graphics.width; + } + else + { + graphics.shadow_start_x[p][j+k*3] = 0; + graphics.shadow_offset_x[p][j+k*3] = -x; + + graphics.shadow_width[p][j+k*3] = graphics.width + x; + } + + + if(y >= 0) + { + graphics.shadow_start_y[p][j+k*3]= y; + graphics.shadow_offset_y[p][j+k*3] = 0; + + if(y + graphics.height > height) + graphics.shadow_height[p][j+k*3] = height - y; + else + graphics.shadow_height[p][j+k*3] = graphics.height; + } + else + { + graphics.shadow_start_y[p][j+k*3] = 0; + graphics.shadow_offset_y[p][j+k*3] = -y; + + graphics.shadow_height[p][j+k*3] = graphics.height + y; + } + + graphics.shadow_flags[p] |= shadow_flags[j+k*3]; + } + } + } + } + } + + /* Calcuate flags for shadows */ + for(s = 0; s < graphics.shadows.length; s ++) + { + graphics.shadows[s].flag = shadow_flags[(graphics.shadows[s].x + 1) + 3 * (graphics.shadows[s].y + 1)]; + graphics.shadows[s].shadow = (1 + graphics.shadows[s].x) + 3 * (1 + graphics.shadows[s].y); + } + } + + graphics_return_after_rendering(); +} + +function graphics_return_after_rendering() +{ + document.getElementById("missing-render").style.display = "none"; + document.getElementById("missing").style.display = "none"; + document.getElementById("items").style.display = "block"; + + display_focus(); + display_level(); + menu_show(false); +} + +function screen_resize() +{ + if(level != null && (menu.state == false || menu.becoming == false)) + graphics_render(); +} + +function level_from_string(s) +{ + var level = {}; + + level.mode = MODE_CHROMA; + level.title = ""; + level.width = 0; + level.height = 0; + level.flags = 0; + + level.piece = []; + level.moving = []; + level.previous = []; + level.previousmoving = []; + level.detonator = []; + level.detonatormoving = []; + level.data = []; + + level.movers = []; + level.oldmovers = []; + level.stack = []; + + level.player = 0; + level.player_x = [0, 0]; + level.player_y = [0, 0]; + level.alive = [false, false]; + + level.teleport_x = [0, 0]; + level.teleport_y = [0, 0]; + level.view_x = [0, 0]; + level.view_y = [0, 0]; + level.view_teleport_x = [0, 0]; + level.view_teleport_y = [0, 0]; + level.switched = 0; + level.mapped = 0; + + + level.stars_caught = 0; + level.stars_exploded = 0; + level.stars_total = 0; + + level.moves = []; + level.redoable_moves = []; + + level.level = 0; + + var l = s.split("\n"); + + var i = 0; + var a; + while(i < l.length) + { + if(a = l[i].match(/^mode: (\w+)/)) + { + switch(a[1]) + { + case "chroma": + level.mode = MODE_CHROMA; + break; + case "xor": + level.mode = MODE_XOR; + break; + case "enigma": + level.mode = MODE_ENIGMA; + break; + } + } + + else if(a = l[i].match(/^title: (.*)/)) + level.title = a[1]; + + else if(a = l[i].match(/^level: (.*)/)) + level.level= parseInt(a[1]); + + else if(a = l[i].match(/^size: (\d+) (\d+)/)) + { + level.width = parseInt(a[1]); + level.height = parseInt(a[2]); + + for(var x = 0; x < level.width; x ++) + { + level.piece[x] = []; + level.moving[x] = []; + level.previous[x] = []; + level.previousmoving[x] = []; + level.detonator[x] = []; + level.detonatormoving[x] = []; + level.data[x] = []; + } + } + + else if(a = l[i].match(/^stars: (\d+) (\d+) (\d+)/)) + { + level.stars_caught = parseInt(a[1]); + level.stars_exploded = parseInt(a[2]); + level.stars_total = parseInt(a[3]); + } + + else if(a = l[i].match(/^moves: (.*)/)) + moves = parseInt(a[1]); + + else if(a = l[i].match(/^player: (.*)/)) + { + p = parseInt(a[1]); + if(p == 1 || p == 2) + level.player = p - 1; + } + + else if(l[i] == "solved: 1") + { + level.flags |= LEVELFLAG_SOLVED; + level.flags |= LEVELFLAG_EXIT; + } + + else if(l[i] == "failed: 1") + level.flags |= LEVELFLAG_FAILED; + + else if(l[i] == "switched: 1") + level.switched = 1; + + else if(a = l[i].match(/^view1: (\d+) (\d+)/)) + { + level.view_x[0] = parseInt(a[1]); + level.view_y[0] = parseInt(a[2]); + } + + else if(a = l[i].match(/^view2: (\d+) (\d+)/)) + { + level.view_x[1] = parseInt(a[1]); + level.view_y[1] = parseInt(a[2]); + } + + else if(a = l[i].match(/^viewteleport1: (\d+) (\d+) \((\d+) (\d+)\)/)) + { + level.teleport_x[0] = parseInt(a[3]); + level.teleport_y[0] = parseInt(a[4]); + level.view_teleport_x[0] = parseInt(a[1]); + level.view_teleport_y[0] = parseInt(a[2]); + } + + else if(a = l[i].match(/^viewteleport2: (\d+) (\d+) \((\d+) (\d+)\)/)) + { + level.teleport_x[1] = parseInt(a[3]); + level.teleport_y[1] = parseInt(a[4]); + level.view_teleport_x[1] = parseInt(a[1]); + level.view_teleport_y[1] = parseInt(a[2]); + } + + else if(a = l[i].match(/^mapped:/)) + { + if(l[i].includes("top_left")) + level.mapped |= MAPPED_TOP_LEFT; + if(l[i].includes("top_right")) + level.mapped |= MAPPED_TOP_RIGHT; + if(l[i].includes("bottom_left")) + level.mapped |= MAPPED_BOTTOM_LEFT; + if(l[i].includes("bottom_right")) + level.mapped |= MAPPED_BOTTOM_RIGHT; + } + + else if(l[i].match(/^data:/)) + { + level.stars_total = 0; + teleport = 0; + + for(var y = 0; y < level.height; y ++) + { + i ++; + var d = l[i].split(""); + for(var x = 0; x < level.width; x ++) + { + var p = character_to_piece(d[x]); + + switch(p) + { + case PIECE_PLAYER_ONE: + level.player_x[0] = x; + level.player_y[0] = y; + level.alive[0] = true; + break; + case PIECE_PLAYER_TWO: + level.player_x[1] = x; + level.player_y[1] = y; + level.alive[1] = true; + break; + case PIECE_STAR: + level.stars_total ++; + break; + case PIECE_TELEPORT: + if(teleport < 2) + { + level.teleport_x[teleport] = x; + level.teleport_y[teleport] = y; + teleport ++; + } + break; + } + + level.piece[x][y] = p; + level.moving[x][y] = MOVE_NONE; + level.previous[x][y] = PIECE_SPACE; + level.previousmoving[x][y] = MOVE_NONE; + level.detonator[x][y] = PIECE_SPACE; + level.detonatormoving[x][y] = MOVE_NONE; + level.data[x][y] = Math.floor(Math.random() * 65536); + } + } + + level.stars_total += level.stars_caught + level.stars_exploded; + } + + else if(l[i].match(/^movedata:/)) + { + i ++; + + while(l[i] != "") + { + for(p = 0; p < l[i].length; p ++) + { + var direction = character_to_direction(l[i][p]); + if(direction != MOVE_UNKNOWN) + { + var move = new Object; + move.direction = direction; + move.movers = []; + move.count = level.moves.length; + + level.moves.push(move); + } + } + i ++; + } + } + + else if(l[i].match(/^undodata:/)) + { + i ++; + + m = 0; + + while(l[i] != "") + { + j = 0; + while(j < l[i].length) + { + var mover = new Object; + + mover.x = parseInt(l[i][j++]) * 10 + parseInt(l[i][j++]); + j ++; + mover.y = parseInt(l[i][j++]) * 10 + parseInt(l[i][j++]); + mover.direction = character_to_direction(l[i][j++]); + mover.piece = character_to_piece(l[i][j++]); + mover.piece_previous = character_to_piece(l[i][j++]); + + c = l[i][j++]; + mover.fast = (c == "," ? 1 : 0); + + level.moves[m].movers.push(mover); + + if(c == ".") + m ++; + } + + i ++; + } + } + + i ++; + } + + return level; +} + +function level_to_string() +{ + var l; + + l = "chroma level\n\n"; + + if(level.mode == MODE_XOR) + l += "mode: xor\n\n"; + + if(level.mode == MODE_ENIGMA) + l += "mode: enigma\n\n"; + + if(level.title != null && level.title != "") + l += "title: "+level.title+"\n"; + if(level.level != null && level.level != 0) + l += "level: "+level.level+"\n"; + + l += "size: "+level.width+" "+level.height+"\n"; + + l += "player: "+(level.player + 1)+"\n"; + l += "moves: "+level.moves.length+"\n"; + l += "stars: "+level.stars_caught+" "+level.stars_exploded+" "+level.stars_total+"\n"; + + if(level.flags & LEVELFLAG_SOLVED) + { + l += "solved: 1\n"; + } + + if(level.flags & LEVELFLAG_FAILED) + l += "failed: 1\n"; + + if(level.mode == MODE_XOR) + { + if(level.switched == 1) + l += "switched: "+level.switched+"\n"; + + l += "view1: "+level.view_x[0]+" "+level.view_y[0]+"\n"; + l += "view2: "+level.view_x[1]+" "+level.view_y[1]+"\n"; + + if(level.teleport_x[0] != -1) + { + l += "viewteleport1: "+level.view_teleport_x[0]+" "+level.view_teleport_y[0]+" ("+level.teleport_x[0]+" "+level.teleport_y[0]+")\n"; + l += "viewteleport2: "+level.view_teleport_x[1]+" "+level.view_teleport_y[1]+" ("+level.teleport_x[1]+" "+level.teleport_y[1]+")\n"; + } + + if(level.mapped) + { + l += "mapped:"; + if(level.mapped & MAPPED_TOP_LEFT) + l += " top_left"; + if(level.mapped & MAPPED_TOP_RIGHT) + l += " top_right"; + if(level.mapped & MAPPED_BOTTOM_LEFT) + l += " bottom_left"; + if(level.mapped & MAPPED_BOTTOM_RIGHT) + l += " bottom_right"; + l += "\n"; + } + } + + l += "\ndata:\n"; + + for(y = 0; y < level.height; y ++) + { + for(x = 0; x < level.width; x ++) + { + l += piece_to_character(level_piece(x, y)); + } + l += "\n"; + } + l += "\n"; + + if(level.moves.length != 0) + { + l += "movedata:\n"; + + for(m = 0; m < level.moves.length; m++) + { + l += direction_to_character(level.moves[m].direction); + if(m % 78 == 77) + l += "\n"; + } + l += "\n\n"; + + l += "undodata:\n"; + + buffer = ""; + for(m = 0; m < level.moves.length; m++) + { + move = level.moves[m]; + + for(n = 0; n < move.movers.length; n ++) + { + mover = move.movers[n]; + + c = ','; + if(mover.fast == 0) + c = ';'; + if(n == move.movers.length - 1) + c = '.'; + + buffer += two(mover.x); + buffer += ":"; + buffer += two(mover.y); + buffer += direction_to_character(mover.direction); + buffer += piece_to_character(mover.piece); + buffer += piece_to_character(mover.piece_previous); + buffer += c; + + if(buffer.length > 71) + { + l += buffer+"\n"; + buffer = ""; + } + } + } + if(buffer != "") + l += buffer+"\n"; + } + + return l; + +} + +function two(v) +{ + return v < 10 ? "0" + v : v; +} + + +function character_to_piece(c) +{ + switch(c) + { + case ' ': + return PIECE_SPACE; + case "%": + return PIECE_WALL; + case '1': + return PIECE_PLAYER_ONE; + case '2': + return PIECE_PLAYER_TWO; + case '.': + return PIECE_DOTS; + case 'a': + return PIECE_ARROW_RED_LEFT; + case 'b': + return PIECE_ARROW_RED_UP; + case 'c': + return PIECE_ARROW_RED_RIGHT; + case 'd': + return PIECE_ARROW_RED_DOWN; + case 'A': + return PIECE_BOMB_RED_LEFT; + case 'B': + return PIECE_BOMB_RED_UP; + case 'C': + return PIECE_BOMB_RED_RIGHT; + case 'D': + return PIECE_BOMB_RED_DOWN; + case 'e': + return PIECE_ARROW_GREEN_LEFT; + case 'f': + return PIECE_ARROW_GREEN_UP; + case 'g': + return PIECE_ARROW_GREEN_RIGHT; + case 'h': + return PIECE_ARROW_GREEN_DOWN; + case 'E': + return PIECE_BOMB_GREEN_LEFT; + case 'F': + return PIECE_BOMB_GREEN_UP; + case 'G': + return PIECE_BOMB_GREEN_RIGHT; + case 'H': + return PIECE_BOMB_GREEN_DOWN; + case 'i': + return PIECE_ARROW_BLUE_LEFT; + case 'j': + return PIECE_ARROW_BLUE_UP; + case 'k': + return PIECE_ARROW_BLUE_RIGHT; + case 'l': + return PIECE_ARROW_BLUE_DOWN; + case 'I': + return PIECE_BOMB_BLUE_LEFT; + case 'J': + return PIECE_BOMB_BLUE_UP; + case 'K': + return PIECE_BOMB_BLUE_RIGHT; + case 'L': + return PIECE_BOMB_BLUE_DOWN; + case 'o': + return PIECE_CIRCLE; + case '*': + return PIECE_STAR; + case '/': + return PIECE_DOOR; + case '8': + return PIECE_CIRCLE_DOUBLE; + case ':': + return PIECE_DOTS_DOUBLE; + case '-': + return PIECE_DOTS_X; + case '|': + return PIECE_DOTS_Y; + case 'S': + return PIECE_SWITCH; + case 'T': + return PIECE_TELEPORT; + case 'M': + return PIECE_MAP_TOP_LEFT; + case 'm': + return PIECE_MAP_TOP_RIGHT; + case 'N': + return PIECE_MAP_BOTTOM_LEFT; + case 'n': + return PIECE_MAP_BOTTOM_RIGHT; + case '!': + return PIECE_GONE; + case 'p': + return PIECE_EXPLOSION_RED_LEFT; + case 'q': + return PIECE_EXPLOSION_RED_HORIZONTAL; + case 'r': + return PIECE_EXPLOSION_RED_RIGHT; + case 'P': + return PIECE_EXPLOSION_RED_TOP; + case 'Q': + return PIECE_EXPLOSION_RED_VERTICAL; + case 'R': + return PIECE_EXPLOSION_RED_BOTTOM; + case 'u': + return PIECE_EXPLOSION_GREEN_LEFT; + case 'v': + return PIECE_EXPLOSION_GREEN_HORIZONTAL; + case 'w': + return PIECE_EXPLOSION_GREEN_RIGHT; + case 'U': + return PIECE_EXPLOSION_GREEN_TOP; + case 'V': + return PIECE_EXPLOSION_GREEN_VERTICAL; + case 'W': + return PIECE_EXPLOSION_GREEN_BOTTOM; + case 'x': + return PIECE_EXPLOSION_BLUE_LEFT; + case 'y': + return PIECE_EXPLOSION_BLUE_HORIZONTAL; + case 'z': + return PIECE_EXPLOSION_BLUE_RIGHT; + case 'X': + return PIECE_EXPLOSION_BLUE_TOP; + case 'Y': + return PIECE_EXPLOSION_BLUE_VERTICAL; + case 'Z': + return PIECE_EXPLOSION_BLUE_BOTTOM; + default: + return PIECE_UNKNOWN; + } +} + +function piece_to_character(piece) +{ + switch(piece) + { + case PIECE_SPACE: + return ' '; + case PIECE_WALL: + return '%'; + case PIECE_PLAYER_ONE: + return '1'; + case PIECE_PLAYER_TWO: + return '2'; + case PIECE_DOTS: + return '.'; + case PIECE_ARROW_RED_LEFT: + return 'a'; + case PIECE_ARROW_RED_UP: + return 'b'; + case PIECE_ARROW_RED_RIGHT: + return 'c'; + case PIECE_ARROW_RED_DOWN: + return 'd'; + case PIECE_BOMB_RED_LEFT: + return 'A'; + case PIECE_BOMB_RED_UP: + return 'B'; + case PIECE_BOMB_RED_RIGHT: + return 'C'; + case PIECE_BOMB_RED_DOWN: + return 'D'; + case PIECE_ARROW_GREEN_LEFT: + return 'e'; + case PIECE_ARROW_GREEN_UP: + return 'f'; + case PIECE_ARROW_GREEN_RIGHT: + return 'g'; + case PIECE_ARROW_GREEN_DOWN: + return 'h'; + case PIECE_BOMB_GREEN_LEFT: + return 'E'; + case PIECE_BOMB_GREEN_UP: + return 'F'; + case PIECE_BOMB_GREEN_RIGHT: + return 'G'; + case PIECE_BOMB_GREEN_DOWN: + return 'H'; + case PIECE_ARROW_BLUE_LEFT: + return 'i'; + case PIECE_ARROW_BLUE_UP: + return 'j'; + case PIECE_ARROW_BLUE_RIGHT: + return 'k'; + case PIECE_ARROW_BLUE_DOWN: + return 'l'; + case PIECE_BOMB_BLUE_LEFT: + return 'I'; + case PIECE_BOMB_BLUE_UP: + return 'J'; + case PIECE_BOMB_BLUE_RIGHT: + return 'K'; + case PIECE_BOMB_BLUE_DOWN: + return 'L'; + case PIECE_CIRCLE: + return 'o'; + case PIECE_STAR: + return '*'; + case PIECE_DOOR: + return '/'; + case PIECE_DOTS_DOUBLE: + return ':'; + case PIECE_CIRCLE_DOUBLE: + return '8'; + case PIECE_DOTS_X: + return '-'; + case PIECE_DOTS_Y: + return '|'; + case PIECE_SWITCH: + return 'S'; + case PIECE_TELEPORT: + return 'T'; + case PIECE_MAP_TOP_LEFT: + return 'M'; + case PIECE_MAP_TOP_RIGHT: + return 'm'; + case PIECE_MAP_BOTTOM_LEFT: + return 'N'; + case PIECE_MAP_BOTTOM_RIGHT: + return 'n'; + case PIECE_GONE: + return '!'; + case PIECE_EXPLOSION_RED_LEFT: + return 'p'; + case PIECE_EXPLOSION_RED_HORIZONTAL: + return 'q'; + case PIECE_EXPLOSION_RED_RIGHT: + return 'r'; + case PIECE_EXPLOSION_RED_TOP: + return 'P'; + case PIECE_EXPLOSION_RED_VERTICAL: + return 'Q'; + case PIECE_EXPLOSION_RED_BOTTOM: + return 'R'; + case PIECE_EXPLOSION_GREEN_LEFT: + return 'u'; + case PIECE_EXPLOSION_GREEN_HORIZONTAL: + return 'v'; + case PIECE_EXPLOSION_GREEN_RIGHT: + return 'w'; + case PIECE_EXPLOSION_GREEN_TOP: + return 'U'; + case PIECE_EXPLOSION_GREEN_VERTICAL: + return 'V'; + case PIECE_EXPLOSION_GREEN_BOTTOM: + return 'W'; + case PIECE_EXPLOSION_BLUE_LEFT: + return 'x'; + case PIECE_EXPLOSION_BLUE_HORIZONTAL: + return 'y'; + case PIECE_EXPLOSION_BLUE_RIGHT: + return 'z'; + case PIECE_EXPLOSION_BLUE_TOP: + return 'X'; + case PIECE_EXPLOSION_BLUE_VERTICAL: + return 'Y'; + case PIECE_EXPLOSION_BLUE_BOTTOM: + return 'Z'; + + default: + return '?'; + } +} + +function direction_to_character(direction) +{ + switch(direction) + { + case MOVE_LEFT: + return 'l'; + case MOVE_UP: + return 'u'; + case MOVE_RIGHT: + return 'r'; + case MOVE_DOWN: + return 'd'; + case MOVE_SWAP: + return 's'; + case MOVE_SWAPPED: + return 'w'; + case MOVE_NONE: + return 'n'; + + default: + return '?'; + } +} + +function character_to_direction(c) +{ + switch(c) + { + case 'l': + return MOVE_LEFT; + case 'u': + return MOVE_UP; + case 'r': + return MOVE_RIGHT; + case 'd': + return MOVE_DOWN; + case 's': + return MOVE_SWAP; + case 'w': + return MOVE_SWAPPED; + case 'n': + return MOVE_NONE; + + default: + return MOVE_UNKNOWN; + } +} + +function explosiontype(p) +{ + switch(p) + { + case PIECE_ARROW_RED_LEFT: + case PIECE_ARROW_RED_RIGHT: + case PIECE_BOMB_RED_LEFT: + case PIECE_BOMB_RED_RIGHT: + return PIECE_EXPLOSION_NEW_RED_VERTICAL; + case PIECE_ARROW_RED_UP: + case PIECE_ARROW_RED_DOWN: + case PIECE_BOMB_RED_UP: + case PIECE_BOMB_RED_DOWN: + return PIECE_EXPLOSION_NEW_RED_HORIZONTAL; + + case PIECE_ARROW_GREEN_LEFT: + case PIECE_ARROW_GREEN_RIGHT: + case PIECE_BOMB_GREEN_LEFT: + case PIECE_BOMB_GREEN_RIGHT: + return PIECE_EXPLOSION_NEW_GREEN_VERTICAL; + case PIECE_ARROW_GREEN_UP: + case PIECE_ARROW_GREEN_DOWN: + case PIECE_BOMB_GREEN_UP: + case PIECE_BOMB_GREEN_DOWN: + return PIECE_EXPLOSION_NEW_GREEN_HORIZONTAL; + + case PIECE_ARROW_BLUE_LEFT: + case PIECE_ARROW_BLUE_RIGHT: + case PIECE_BOMB_BLUE_LEFT: + case PIECE_BOMB_BLUE_RIGHT: + return PIECE_EXPLOSION_NEW_BLUE_VERTICAL; + case PIECE_ARROW_BLUE_UP: + case PIECE_ARROW_BLUE_DOWN: + case PIECE_BOMB_BLUE_UP: + case PIECE_BOMB_BLUE_DOWN: + return PIECE_EXPLOSION_NEW_BLUE_HORIZONTAL; + + default: + /* This should never happen */ + return PIECE_GONE; + } +} + +function level_moved(move) +{ + level_addmove(move); + + level.flags |= LEVELFLAG_MOVES; + + level_storemovers(); + + display_start_update(); +} + +function level_move(move) +{ + var realmove = move; + var x, y, ok, p, px, py; + var teleport, tx, ty, td, dx, dy; + + if(level.flags & LEVELFLAG_EXIT) + return; + + if(realmove == MOVE_REDO) + { + move = level.redoable_moves[level.redoable_moves.length - 1].direction; + } + + + if(move == MOVE_SWAP) + { + if(level.alive[1 - level.player]) + { + level.player = 1 - level.player; + + /* Create new movers for the stationary swapped players to allow + the display to redraw them after the swap. */ + mover_new(level.player_x[level.player], level.player_y[level.player], MOVE_SWAP, PIECE_PLAYER_ONE + level.player, 0); + + /* Is the first player still alive? */ + if(level.alive[1 - level.player]) + mover_new(level.player_x[1 - level.player], level.player_y[1 - level.player], MOVE_SWAPPED, PIECE_PLAYER_ONE + 1 - level.player, 0); + + level_moved(realmove); + + return true; + } + else + return false; + } + + if(level.alive[level.player] == 0) + return false; + + if(level.mode == MODE_XOR && options.xor_engine) + { + if(xor_move(move)) + { + level_moved(realmove); + xor_focus(); + return true; + } + return false; + } + if(level.mode == MODE_ENIGMA && options.enigma_engine) + { + if(enigma_move(move)) + { + level_moved(realmove); + return true; + } + return false; + } + + /* Consider where we are moving to */ + x = level.player_x[level.player] + move_x[move]; + y = level.player_y[level.player] + move_y[move]; + + p = level_piece(x, y); + + ok = 0; + + /* Can we move into the piece in that direction? */ + switch(p) + { + case PIECE_DOOR: + if(level.stars_caught == level.stars_total) + { + level.flags |= LEVELFLAG_EXIT; + ok = 1; + } + break; + + case PIECE_STAR: + level.stars_caught ++; + level.flags |= LEVELFLAG_STARS; + ok = 1; + break; + + case PIECE_TELEPORT: + /* Only XOR has teleports. We force the issue so as not to break + Chroma's rotational symmetry by introducing teleport order. */ + if(level.mode != MODE_XOR) + break; + + teleport = -1; + if(x == level.teleport_x[0] && y == level.teleport_y[0]) + teleport = 0; + if(x == level.teleport_x[1] && y == level.teleport_y[1]) + teleport = 1; + + if(teleport != -1) + { + tx = level.teleport_x[1 - teleport]; + ty = level.teleport_y[1 - teleport]; + td = move; + + /* Does the other teleport still exist? */ + if(level_piece(tx, ty) == PIECE_TELEPORT) + { + ok = 0; + /* Find the first available exit from it */ + for(i = 0; i < 4; i ++) + { + dx = tx + move_x[xor_teleport_order[i]]; + dy = ty + move_y[xor_teleport_order[i]]; + if(!ok && level_piece(dx, dy) == PIECE_SPACE) + { + /* Change move to produce the effect of coming + out of the teleport */ + x = dx; y = dy; move = xor_teleport_order[i]; + ok = 1; + } + } + if(ok) + { + /* Visual effects for the player going in one teleport */ + /* Store original player move direction in cosmetic mover */ + mover_new(level.teleport_x[teleport], level.teleport_y[teleport], td, PIECE_TELEPORT, 0); + level_setprevious(level.teleport_x[teleport], level.teleport_y[teleport], PIECE_PLAYER_ONE + level.player); + level_setpreviousmoving(level.teleport_x[teleport], level.teleport_y[teleport], realmove); + /* and out of the other teleport */ + mover_new(level.teleport_x[1 - teleport], level.teleport_y[1 - teleport], MOVE_NONE, PIECE_TELEPORT, 0); + + /* Change the viewpoint to that of the other teleport */ + level.view_x[level.player] = level.view_teleport_x[1 - teleport]; + level.view_y[level.player] = level.view_teleport_y[1 - teleport]; + + } + } + } + break; + + case PIECE_SWITCH: + level.switched = 1 - level.switched; + level.flags |= LEVELFLAG_SWITCH; + ok = 1; + break; + + case PIECE_MAP_TOP_LEFT: + level.mapped |= MAPPED_TOP_LEFT; + level.flags |= LEVELFLAG_MAP; + ok = 1; + break; + + case PIECE_MAP_TOP_RIGHT: + level.mapped |= MAPPED_TOP_RIGHT; + level.flags |= LEVELFLAG_MAP; + ok = 1; + break; + + case PIECE_MAP_BOTTOM_LEFT: + level.mapped |= MAPPED_BOTTOM_LEFT; + level.flags |= LEVELFLAG_MAP; + ok = 1; + break; + + case PIECE_MAP_BOTTOM_RIGHT: + level.mapped |= MAPPED_BOTTOM_RIGHT; + level.flags |= LEVELFLAG_MAP; + ok = 1; + break; + + case PIECE_DOTS_X: + if(move == MOVE_LEFT || move == MOVE_RIGHT) + ok = 1; + break; + + case PIECE_DOTS_Y: + if(move == MOVE_UP || move == MOVE_DOWN) + ok = 1; + break; + + case PIECE_DOTS_DOUBLE: + case PIECE_DOTS: + case PIECE_SPACE: + ok = 1; + break; + } + + /* Is there a piece we can push? */ + if(!ok) + { + tx = x + move_x[move]; + ty = y + move_y[move]; + + if(canbepushed(p, level_piece(tx, ty), move, level.mode)) + { + mover_new(tx, ty, move, p, 0); + ok = 1; + } + } + + if(ok) + { + + /* Cosmetic mover for storing the player's direction in undo */ + mover_new(level.player_x[level.player], level.player_y[level.player], move, PIECE_GONE, 0); + + mover_new(x, y, move, PIECE_PLAYER_ONE + level.player, 0); + + px = level.player_x[level.player]; + py = level.player_y[level.player]; + + /* XOR protects the players move */ + if(level.mode == MODE_XOR) + { + /* Blank the player's space first to avoid upsetting undo */ + level_setpiece(px, py, PIECE_SPACE); + mover_new(px, py, (move + 1) % 4, PIECE_SPACE, 1); + } + /* Chroma lets a piece follow in the player's trail */ + else + { + /* Blank the player's space first to avoid upsetting undo */ + level_setpiece(px, py, PIECE_SPACE); + mover_consider(px, py, move % 4); + } + + level.player_x[level.player] = x; + level.player_y[level.player] = y; + + level_moved(realmove); + + if(level.mode == MODE_XOR) + xor_focus(); + + return true; + } + + return false; +} + +function mover_explode(x, y, d, p) +{ + /* Don't explode any of the edge wall */ + if(x == 0 || y == 0 || x == level.width - 1 || y == level.width - 1) + return; + + /* What have we exploded? */ + switch(level_piece(x, y)) + { + case PIECE_STAR: + level.stars_exploded ++; + level.flags |= LEVELFLAG_STARS; + break; + + case PIECE_SWITCH: + level.switched = 1 - level.switched; + level.flags |= LEVELFLAG_SWITCH; + break; + } + + mover_new(x, y, d, p, 1); +} + +function mover_new(x, y, d, piece, fast) +{ + var mover = new Object; + + /* Don't allow two movers in the same space, unless one is exploding */ + if(!isnewexplosion(piece) && level_moving(x, y) != MOVE_NONE) + return; + + var previous = level_piece(x, y); + + mover.x = x; + mover.y = y; + mover.direction = d; + mover.piece = piece; + mover.piece_previous = previous; + mover.fast = fast; + + /* Show pieces collected by players */ + if(piece == PIECE_PLAYER_ONE || piece == PIECE_PLAYER_TWO) + { + if((previous < PIECE_MOVERS_FIRST || previous > PIECE_MOVERS_LAST) + && previous != PIECE_CIRCLE + && previous != PIECE_CIRCLE_DOUBLE + && previous != PIECE_PLAYER_ONE + && previous != PIECE_PLAYER_TWO) + level_setprevious(x, y, previous); + } + + /* Show players squashed by movers */ + if(piece >= PIECE_MOVERS_FIRST && piece <= PIECE_MOVERS_LAST) + { + if(previous == PIECE_PLAYER_ONE || previous == PIECE_PLAYER_TWO) + level_setprevious(x, y, previous); + } + + /* Show pieces removed by movers or explosions */ + if(previous == PIECE_DOTS + || previous == PIECE_DOTS_DOUBLE + || previous == PIECE_DOTS_X + || previous == PIECE_DOTS_Y + || isexplosion(previous)) + level_setprevious(x, y, previous); + + /* Show exploded pieces */ + if(isnewexplosion(piece) && !isnewexplosion(previous)) + { + level_setprevious(x, y, previous); + level_setpreviousmoving(x, y, level_moving(x, y)); + } + + /* Explosions occur later */ + if(!isnewexplosion(piece) && piece != PIECE_GONE) + { + level_setpiece(x, y, piece); + level_setmoving(x, y, d); + } + + /* Maintain piece graphic */ + if(d != MOVE_NONE) + { + data = level_data(x - move_x[d], y - move_y[d]) & 0xff00; + data = (level_data(x, y) & ~0xff00) | data; + level_setdata(x, y, data); + } + + level.movers.push(mover); +} + +function mover_addtostack(x, y, move) +{ + var mover = new Object; + + mover.x = x; + mover.y = y; + mover.direction = move; + mover.piece = PIECE_SPACE; + mover.fast = 0; + + level.stack.push(mover); +} + + +function level_addmove(direction) +{ + if(direction == MOVE_REDO) + { + direction = level.redoable_moves[level.redoable_moves.length - 1].direction; + level.redoable_moves.pop(); + } + else if(level.redoable_moves.length != 0) + level.redoable_moves = []; + + var move = new Object; + move.direction = direction; + move.movers = []; + move.count = level.moves.length; + + level.moves.push(move); +} + +function level_storemovers() +{ + var previous; + + for(m = 0; m < level.movers.length; m ++) + { + /* If something is moving into an explosion, don't store it as the + previous piece for this space; it will have its own mover, and thus + will be stored elsewhere. */ + previous = level.movers[m].piece_previous; + if(isexplosion(level.movers[m].piece) && level_previousmoving(level.movers[m].x, level.movers[m].y) != MOVE_NONE) + previous = PIECE_SPACE; + + mover_newundo(level.movers[m].x, level.movers[m].y, + level.movers[m].direction, level.movers[m].piece, previous, + MOVER_STORE | (m == level.movers.length - 1 ? 0 : MOVER_FAST)); + } +} + +function level_evolve() +{ + var mover, x, y, i, d, ad, ed, ax, ay, bp, bd, filled; + + if(level.mode == MODE_XOR && options.xor_engine) + { + return xor_evolve(); + } + if(level.mode == MODE_ENIGMA && options.enigma_engine) + { + return enigma_evolve(); + } + + level.oldmovers = level.movers; + level.movers = []; + + /* Chroma's engine isn't perfect. Pieces that appear to be in continuous + motion are actually momentarily stationary at the start of every cycle. + In pathological cases, this can give rise to some counterintuitive + situations, where the outcome depends on the order of the movers. + + See levels/regression/chroma-regression.chroma for some examples. + */ + + for(m = 0; m < level.oldmovers.length; m ++) + { + mover = level.oldmovers[m]; + + level_setmoving(mover.x, mover.y, MOVE_NONE); + level_setprevious(mover.x, mover.y, PIECE_SPACE); + level_setpreviousmoving(mover.x, mover.y, MOVE_NONE); + level_setdetonator(mover.x, mover.y, PIECE_SPACE); + level_setdetonatormoving(mover.x, mover.y, MOVE_NONE); + } + + /* Make any changes to the map, if necessary */ + if(level.mode == MODE_XOR && options.xor_display) + { + for(m = 0; m < level.oldmovers.length; m ++) + { + mover = level.oldmovers[m]; + + display_map_piece(mover.x, mover.y); + } + } + + + + for(m = 0; m < level.oldmovers.length; m ++) + { + mover = level.oldmovers[m]; + + /* Remove the mover if something has already moved into its space */ + if(level_moving(mover.x, mover.y) != MOVE_NONE + /* or it isn't what it should be */ + || level_piece(mover.x, mover.y) != mover.piece + ) + mover.piece = PIECE_GONE; + + switch(mover.piece) + { + case PIECE_SPACE: + case PIECE_EXPLOSION_RED_LEFT: + case PIECE_EXPLOSION_RED_HORIZONTAL: + case PIECE_EXPLOSION_RED_RIGHT: + case PIECE_EXPLOSION_RED_TOP: + case PIECE_EXPLOSION_RED_VERTICAL: + case PIECE_EXPLOSION_RED_BOTTOM: + case PIECE_EXPLOSION_GREEN_LEFT: + case PIECE_EXPLOSION_GREEN_HORIZONTAL: + case PIECE_EXPLOSION_GREEN_RIGHT: + case PIECE_EXPLOSION_GREEN_TOP: + case PIECE_EXPLOSION_GREEN_VERTICAL: + case PIECE_EXPLOSION_GREEN_BOTTOM: + case PIECE_EXPLOSION_BLUE_LEFT: + case PIECE_EXPLOSION_BLUE_HORIZONTAL: + case PIECE_EXPLOSION_BLUE_RIGHT: + case PIECE_EXPLOSION_BLUE_TOP: + case PIECE_EXPLOSION_BLUE_VERTICAL: + case PIECE_EXPLOSION_BLUE_BOTTOM: + i = 0; + filled = 0; + + /* Consider the pieces around the space */ + for(i = 0; i < 4; i ++) + { + if(filled) + continue; + + /* Enigma has a fixed move order */ + if(level.mode == MODE_ENIGMA) + d = enigma_move_order[i]; + else + /* Chroma and XOR depend on how the space was emptied */ + d = (mover.direction + i) % 4; + + ad = (d + 2) % 4; + ax = mover.x + move_x[ad]; + ay = mover.y + move_y[ad]; + + /* Can the piece move into the space? */ + if(canfall(level_piece(ax, ay), PIECE_SPACE, d) + /* and that piece isn't already moving */ + && level_moving(ax, ay) == MOVE_NONE + ) + { + x = mover.x + move_x[d]; + y = mover.y + move_y[d]; + + /* Can the piece from the opposite direction also + move into this space? */ + if(canfall(level_piece(x, y), PIECE_SPACE, ad) + /* and that piece isn't already moving */ + && level_moving(x, y) == MOVE_NONE + /* If so, can the two explode? */ + && canexplode(level_piece(ax, ay), level_piece(x, y), d, 1, level.mode) + /* (but not for XOR and Enigma) */ + && level.mode == MODE_CHROMA + ) + { + /* If so, detonate them in the middle */ + if((level_piece(x, y) & 4) == 4) + { + /* The first piece is the bomb */ + bp = level_piece(x, y); + bd = ad; + ed = level_piece(x, y) & 3; + + level_setdetonator(mover.x, mover.y, level_piece(ax, ay)); + level_setdetonatormoving(mover.x, mover.y, d); + } + else + { + /* The second piece is the bomb */ + bp = level_piece(ax, ay); + bd = d; + ed = level_piece(ax, ay) & 3; + + level_setdetonator(mover.x, mover.y, level_piece(x, y)); + level_setdetonatormoving(mover.x, mover.y, ad); + } + + /* and consider anything following them */ + mover_consider(x, y, ad); + mover_consider(ax, ay, d); + + /* Move the bomb into the space */ + level_setpiece(mover.x, mover.y, bp); + level_setmoving(mover.x, mover.y, bd); + + /* and explode it */ + mover_explode(mover.x, mover.y, ed, explosiontype(bp)); + + /* Create the central explosion now, to prevent the + piece there being processed as a later mover. */ + level_setpiece(mover.x, mover.y, explosiontype(bp)); + explode_sides(mover.x, mover.y, bp, ed); + + filled = 1; + break; + } + + /* Otherwise, keep the piece moving */ + mover_new(mover.x, mover.y, d, level_piece(ax, ay), 1); + /* and see if anything is following in its trail */ + mover_consider(ax, ay, d); + + filled = 1; + break; + } + } + + /* If the explosion has not been filled */ + if(isexplosion(mover.piece) && filled == 0 + /* and nothing else is moving into it */ + && level_moving(mover.x, mover.y) == MOVE_NONE + ) + /* then turn it into a space */ + mover_new(mover.x, mover.y, mover.direction, PIECE_SPACE, 0); + + break; + + case PIECE_PLAYER_ONE: + case PIECE_PLAYER_TWO: + case PIECE_GONE: + /* These 'movers' are purely for cosmetic purposes */ + break; + + case PIECE_TELEPORT: + /* These 'movers' are purely for cosmetic purposes */ + break; + + default: + /* A pushed arrow still falls in its natural direction */ + if(mover.fast == 0 && mover.piece >= PIECE_MOVERS_FIRST && mover.piece <= PIECE_MOVERS_LAST) + mover.direction = mover.piece % 4; + + /* Consider the space in front of the mover */ + x = mover.x + move_x[mover.direction]; + y = mover.y + move_y[mover.direction]; + + /* Can the mover move into the space in front of it? */ + if(canmove(mover.piece, level_piece(x, y), mover.direction, mover.fast) + /* and that space doesn't already have something + moving into it */ + && (level_moving(x, y) == MOVE_NONE) + ) + { + /* If so, keep it moving */ + mover_new(x, y, mover.direction, mover.piece, 1); + /* and see if anything is following in its trail */ + mover_consider(mover.x, mover.y, mover.direction); + break; + } + + /* Can the mover explode the piece in front of it? */ + if(canexplode(mover.piece, level_piece(x, y), mover.direction, mover.fast, level.mode) + /* and the piece in front isn't moving */ + && (level_moving(x, y) == MOVE_NONE + /* or it is moving towards us */ + || (level_moving(x, y) == ((mover.direction + 2) % 4) + /* (but not for XOR or Enigma) */ + && level.mode==MODE_CHROMA)) + ) + { + bp = level_piece(x, y); + level_setdetonator(x, y, mover.piece); + level_setdetonatormoving(x, y, mover.direction); + + /* Explosion direction is bomb fall direction */ + if(bp & 4) + ed = bp & 3; + else + ed = mover.piece & 3; + + mover_explode(x, y, ed, explosiontype(bp)); + + /* Create the central explosion now, to prevent the piece + there being processed as a later mover. */ + level_setpiece(x, y, explosiontype(bp)); + + mover_consider(mover.x, mover.y, mover.direction); + + explode_sides(x, y, bp, ed); + + break; + } + + } + } + + /* Create the side explosions at the end, rather than during the previous + loop. This allows multiple explosions to occur in parallel. Centre + explosions will have already been created earlier on. */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + if(isnewexplosion(mover.piece)) + { + if(!isnewexplosion(level_piece(mover.x, mover.y))) + { + level_setprevious(mover.x, mover.y, level_piece(mover.x, mover.y)); + level_setpreviousmoving(mover.x, mover.y, level_moving(mover.x, mover.y)); + } + + /* Use PIECE_EXPLOSION_NEW to allow detection of overlapping + explosions further down. */ + level_setpiece(mover.x, mover.y, mover.piece); + level_setmoving(mover.x, mover.y, mover.direction); + + mover.piece += PIECE_EXPLOSION_FIRST - PIECE_EXPLOSION_NEW_FIRST; + } + } + + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + if(isexplosion(mover.piece)) + { + /* Remove any explosions that overlap other explosions */ + if(isexplosion(level_piece(mover.x, mover.y))) + mover.piece = PIECE_GONE; + /* Otherwise, convert new explosions into explosions proper */ + else + level_setpiece(mover.x, mover.y, mover.piece); + } + /* Remove any movers that have exploded, or aren't as they should be */ + if(level_piece(mover.x, mover.y) != mover.piece) + { + mover.piece = PIECE_GONE; + } + } + + /* Is player one still alive? */ + if(level_piece(level.player_x[0], level.player_y[0]) != PIECE_PLAYER_ONE) + { + level.flags |= LEVELFLAG_MOVES; + level.alive[0] = false; + } + + /* Is player two still alive? */ + if(level_piece(level.player_x[1], level.player_y[1]) != PIECE_PLAYER_TWO) + { + level.flags |= LEVELFLAG_MOVES; + level.alive[1] = false; + } + + if(level.alive[0] == false && level.alive[1] == false) + level.flags |= LEVELFLAG_FAILED; + + level.oldmovers = []; +} + +function mover_consider(x, y, d) +{ + var tx, ty, ad; + + /* Is there already a mover in this space? If so, don't allow another */ + if(level_moving(x, y) != MOVE_NONE) + return; + + /* Enigma doesn't consider the direction in which a space was emptied */ + if(level.mode == MODE_ENIGMA) + { + mover_new(x, y, d, PIECE_SPACE, 1); + return; + } + + if(level.mode == MODE_XOR) + { + mover_new(x, y, d, PIECE_SPACE, 1); + return; + } + + ad = (d + 2) % 4; + tx = x + move_x[ad]; + ty = y + move_y[ad]; + + /* Can a piece follow in the trail of this one? */ + if(canfall(level_piece(tx, ty), PIECE_SPACE, d)) + { + /* If it's moving already, just clear this space (1.07) */ + if(level_moving(tx, ty) != MOVE_NONE) + { + mover_new(x, y, MOVE_NONE, PIECE_SPACE, 0); + return; + } + + /* Otherwise, set it moving */ + mover_new(x, y, d, level_piece(tx, ty), 1); + /* and see if there's anything following in its trail */ + mover_consider(tx, ty, d); + return; + } + + mover_new(x, y, d, PIECE_SPACE, 1); +} + +function explode_sides(x, y, p, d) +{ + /* Chroma is subtle. This may be too subtle to have any effect in practice, + but the principle elsewhere is that things should be rotationally + symmetric, and this carries through here. */ + if(level.mode == MODE_CHROMA) + { + switch(p % 4) + { + case 0: /* left */ + mover_explode(x, y - 1, d, explosiontype(p) - 1); + mover_explode(x, y + 1, d, explosiontype(p) + 1); + break; + + case 1: /* up */ + mover_explode(x + 1, y, d, explosiontype(p) + 1); + mover_explode(x - 1, y, d, explosiontype(p) - 1); + break; + + case 2: /* right */ + mover_explode(x, y + 1, d, explosiontype(p) + 1); + mover_explode(x, y - 1, d, explosiontype(p) - 1); + break; + + case 3: /* down */ + mover_explode(x - 1, y, d, explosiontype(p) - 1); + mover_explode(x + 1, y, d, explosiontype(p) + 1); + break; + } + } + else + { + switch(p % 2) + { + case 0: /* left / right */ + mover_explode(x, y - 1, d, explosiontype(p) - 1); + mover_explode(x, y + 1, d, explosiontype(p) + 1); + break; + + case 1: /* up /down */ + mover_explode(x - 1, y, d, explosiontype(p) - 1); + mover_explode(x + 1, y, d, explosiontype(p) + 1); + break; + } + } +} + +function canfall(p, into, d) +{ + /* Determine whether a piece can start moving */ + + /* Arrows and bombs */ + if(p >= PIECE_MOVERS_FIRST && p<= PIECE_MOVERS_LAST) + { + /* can start falling in their natural direction */ + if(d == (p % 4)) + { + /* but only into empty space */ + if(into == PIECE_SPACE) + return true; + /* or into directional dots if appropriate */ + if(into == PIECE_DOTS_X && (d == MOVE_LEFT || d == MOVE_RIGHT )) + return true; + if(into == PIECE_DOTS_Y && (d == MOVE_UP || d == MOVE_DOWN )) + return true; + } + } + + return false; +} + +function canmove(p, into, d, fast) +{ + /* Determine whether a piece can continue moving */ + + /* Arrows and bombs */ + if(p >= PIECE_MOVERS_FIRST && p<= PIECE_MOVERS_LAST) + { + /* can continue moving in their natural direction */ + if(d == (p % 4)) + { + /* into empty space */ + if(into == PIECE_SPACE) + return true; + /* into dots if they're already moving */ + if(into == PIECE_DOTS && fast) + return true; + /* into directional dots if appropriate */ + if(into == PIECE_DOTS_X && (d == MOVE_LEFT || d == MOVE_RIGHT )) + return true; + if(into == PIECE_DOTS_Y && (d == MOVE_UP || d == MOVE_DOWN )) + return true; + /* through dying explosions */ + if(isexplosion(into)) + return true; + /* can kill players if already moving */ + if(into == PIECE_PLAYER_ONE && fast) + return true; + if(into == PIECE_PLAYER_TWO && fast) + return true; + } + return false; + } + + /* Circles */ + if(p == PIECE_CIRCLE) + { + /* are stopped by everything other than empty space */ + if(into == PIECE_SPACE) + return true; + /* and dying explosions */ + if(isexplosion(into)) + return true; + return false; + } + + return false; +} + +function canbepushed(p, into, d, mode) +{ + /* Determine whether a piece can be pushed by the player */ + + /* Arrows and bombs */ + if(p >= PIECE_MOVERS_FIRST && p<= PIECE_MOVERS_LAST) + { + /* can be pushed, but not against their natural direction */ + if(d != ((p + 2) % 4)) + { + /* into empty space or through dots */ + if(into == PIECE_SPACE || into == PIECE_DOTS) + return true; + /* through directional dots if appropriate */ + if(into == PIECE_DOTS_X && (d == MOVE_LEFT || d == MOVE_RIGHT)) + return true; + if(into == PIECE_DOTS_Y && (d == MOVE_UP || d == MOVE_DOWN)) + return true; + } + return false; + } + + /* Circles can be pushed in any direction */ + if(p == PIECE_CIRCLE || p == PIECE_CIRCLE_DOUBLE) + { + /* into empty space */ + if(into == PIECE_SPACE) + return true; + /* XOR won't let circles (dolls) pass through dots */ + if(mode == MODE_XOR) + return false; + /* pushed through dots */ + if(into == PIECE_DOTS) + return true; + return false; + } + + return false; +} + +function canexplode(p, i, d, fast, mode) +{ + /* Only an already moving arrow or bomb can act as a detonator */ + if(fast == 0) + return false; + + /* Arrows can detonate bombs */ + if(p >= PIECE_ARROW_RED_LEFT && p<= PIECE_ARROW_RED_DOWN && + i >= PIECE_BOMB_RED_LEFT && i<= PIECE_BOMB_RED_DOWN) + return true; + if(p >= PIECE_ARROW_GREEN_LEFT && p<= PIECE_ARROW_GREEN_DOWN && + i >= PIECE_BOMB_GREEN_LEFT && i<= PIECE_BOMB_GREEN_DOWN) + return true; + if(p >= PIECE_ARROW_BLUE_LEFT && p<= PIECE_ARROW_BLUE_DOWN && + i >= PIECE_BOMB_BLUE_LEFT && i<= PIECE_BOMB_BLUE_DOWN) + return true; + + /* Enigma requires a moving arrow to detonate a stationary bomb, and + does not permit bombs to detonate other bombs */ + if(mode == MODE_ENIGMA) + return false; + + /* Bombs can be detonated by arrows pointing towards them */ + if(p >= PIECE_BOMB_RED_LEFT && p<= PIECE_BOMB_RED_DOWN && + i == (PIECE_ARROW_RED_LEFT + ((d + 2) % 4))) + return true; + if(p >= PIECE_BOMB_GREEN_LEFT && p<= PIECE_BOMB_GREEN_DOWN && + i == (PIECE_ARROW_GREEN_LEFT + ((d + 2) % 4))) + return true; + if(p >= PIECE_BOMB_BLUE_LEFT && p<= PIECE_BOMB_BLUE_DOWN && + i == (PIECE_ARROW_BLUE_LEFT + ((d + 2) % 4))) + return true; + + /* Bombs can detonate other bombs */ + if(p >= PIECE_BOMB_RED_LEFT && p<= PIECE_BOMB_RED_DOWN && + i >= PIECE_BOMB_RED_LEFT && i<= PIECE_BOMB_RED_DOWN) + return true; + if(p >= PIECE_BOMB_GREEN_LEFT && p<= PIECE_BOMB_GREEN_DOWN && + i >= PIECE_BOMB_GREEN_LEFT && i<= PIECE_BOMB_GREEN_DOWN) + return true; + if(p >= PIECE_BOMB_BLUE_LEFT && p<= PIECE_BOMB_BLUE_DOWN && + i >= PIECE_BOMB_BLUE_LEFT && i<= PIECE_BOMB_BLUE_DOWN) + return true; + + return false; +} + +function mover_newundo(x, y, d, piece, previous, flags) +{ + var mover = new Object; + + mover.x = x; + mover.y = y; + mover.direction = d; + mover.piece = piece; + mover.piece_previous = previous; + + if(flags & MOVER_FAST) + mover.fast = 1; + else + mover.fast = 0; + + if(flags & MOVER_UNDO) + { + level_setmoving(x, y, d); + + level.movers.push(mover); + } + + if(flags & MOVER_STORE) + { + level.moves[level.moves.length - 1].movers.push(mover); + } +} + +function level_undo() +{ + var td; + var x, y, d; + var m; + var fm; + + var count = 0; + + /* Working backwards, undo any changes made to the map by movers in the + previous step. */ + for(m = level.movers.length - 1; m >= 0; m --) + { + /* Not setting SPACEs fixes a pathological case without apparently breaking anything (1.07) */ + if(level.movers[m].piece != PIECE_SPACE) + level_setpiece(level.movers[m].x, level.movers[m].y, level.movers[m].piece); + } + + /* Undo any changes to the map, if necessary */ + if(level.mode == MODE_XOR && options.xor_display) + { + for(m = level.movers.length - 1; m >= 0; m --) + { + display_map_piece(level.movers[m].x, level.movers[m].y); + } + } + + /* Is player one still alive? */ + if(level_piece(level.player_x[0], level.player_y[0]) != PIECE_PLAYER_ONE) + level.alive[0] = false; + /* Is player two still alive? */ + if(level_piece(level.player_x[1], level.player_y[1]) != PIECE_PLAYER_TWO) + level.alive[1] = false; + + /* Tidy up any movers created in the previous step */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + level_setmoving(mover.x, mover.y, MOVE_NONE); + level_setprevious(mover.x, mover.y, PIECE_SPACE); + } + level.movers = []; + + /* Can't undo at very start of level */ + if(level.moves.length == 0) + return false; + + /* If there is no previous step to undo, remove this move entirely */ + if(level.moves[level.moves.length - 1].movers.length == 0) + { + level.redoable_moves.push(level.moves.pop()); + level.flags |= LEVELFLAG_MOVES; + + return false; + } + + /* Start from the last mover for this step. */ + m = level.moves[level.moves.length - 1].movers.length - 1; + + fm = 0; + td = MOVE_NONE; + + /* Working backwards, remove these pieces from the map */ + while(m >= 0) + { + fm = m; + + mover = level.moves[level.moves.length - 1].movers[m]; + + level_setpiece(mover.x, mover.y, PIECE_SPACE); + + /* If the piece is the player, update position and status */ + if(mover.piece_previous == PIECE_PLAYER_ONE || mover.piece_previous == PIECE_PLAYER_TWO) + { + level.player_x[mover.piece_previous - PIECE_PLAYER_ONE] = mover.x; + level.player_y[mover.piece_previous - PIECE_PLAYER_ONE] = mover.y; + + if(level.mode == MODE_XOR) + { + /* If a player is being resurrected in this move, and the + other player is alive, undo the automatic swap */ + if(level.alive[mover.piece_previous - PIECE_PLAYER_ONE] == 0 && level.alive[level.player]) + { + /* Cosmetic mover to deactivate other player */ + mover_newundo(level.player_x[level.player], level.player_y[level.player], MOVE_SWAPPED, PIECE_PLAYER_ONE + level.player, PIECE_SPACE, MOVER_UNDO); + } + /* The active player is the one which moves first + (last in undo */ + level.player = mover.piece_previous - PIECE_PLAYER_ONE; + } + + level.alive[mover.piece_previous - PIECE_PLAYER_ONE] = true; + } + + /* If the piece is a teleport, store the direction of the original move + into it for later use. */ + if(mover.piece == PIECE_TELEPORT) + td = mover.direction; + + /* until we reach the first mover for this step. */ + m --; + if(m >= 0 && level.moves[level.moves.length - 1].movers[m].fast == 0) + break; + } + + /* Now, move forwards through the movers and create cosmetic effects. */ + for(m = fm; m < level.moves[level.moves.length - 1].movers.length; m ++) + { + mover = level.moves[level.moves.length - 1].movers[m]; + + d = mover.direction; + x = mover.x - move_x[d]; + y = mover.y - move_y[d]; + + if(d != MOVE_NONE && d != MOVE_SWAP && d != MOVE_SWAPPED) + d = (d + 2) % 4; + + if(isexplosion(mover.piece)) + { + /* Explosions don't move. */ + d = MOVE_NONE; + /* Show dying explosion when undoing new explosion */ + level_setprevious(mover.x, mover.y, mover.piece); + } + + /* Do we need to patch up the direction this piece is moving in? */ + /* Is it the player? */ + if((mover.piece_previous == PIECE_PLAYER_ONE || mover.piece_previous == PIECE_PLAYER_TWO) && (mover.piece == PIECE_SPACE || mover.piece == PIECE_GONE)) + { + /* If so, are they moving out of a teleport? Use original direction + of move if so. */ + if(td != MOVE_NONE) + d = (td + 2) % 4; + } + /* Otherwise, if the previous piece wasn't a move, it must have been a + static piece being eaten by a mover, and thus shouldn't move. */ + else if((mover.piece_previous < PIECE_MOVERS_FIRST || mover.piece_previous > PIECE_MOVERS_LAST) && mover.piece_previous != PIECE_CIRCLE && mover.piece_previous != PIECE_CIRCLE_DOUBLE) + d = MOVE_NONE; + + /* Plot a cosmetic mover. */ + if(level_previous(mover.x, mover.y) != PIECE_SPACE) + d = MOVE_NONE; + /* but not if there are overlapping explosions */ + if(!(mover.piece_previous >= PIECE_EXPLOSION_NEW_FIRST && mover.piece_previous <= PIECE_EXPLOSION_NEW_LAST)) + mover_newundo(mover.x, mover.y, d, mover.piece_previous, PIECE_SPACE, MOVER_UNDO); + } + + /* Remove the movers in the step we've just done */ + for(m = level.moves[level.moves.length - 1].movers.length - 1; m >= fm; m --) + { + mover = level.moves[level.moves.length - 1].movers[m]; + + /* Undo any pieces exploded or caught */ + if(mover.piece_previous == PIECE_STAR) + { + if(mover.piece == PIECE_PLAYER_ONE || mover.piece == PIECE_PLAYER_TWO) + level.stars_caught --; + else + level.stars_exploded --; + + level.flags |= LEVELFLAG_STARS; + } + if(mover.piece_previous == PIECE_SWITCH) + { + level.switched = 1 - level.switched; + level.flags |= LEVELFLAG_SWITCH; + } + if(mover.piece_previous == PIECE_MAP_TOP_LEFT) + { + level.mapped ^= MAPPED_TOP_LEFT; + level.flags |= LEVELFLAG_MAP; + } + if(mover.piece_previous == PIECE_MAP_TOP_RIGHT) + { + level.mapped ^= MAPPED_TOP_RIGHT; + level.flags |= LEVELFLAG_MAP; + } + if(mover.piece_previous == PIECE_MAP_BOTTOM_LEFT) + { + level.mapped ^= MAPPED_BOTTOM_LEFT; + level.flags |= LEVELFLAG_MAP; + } + if(mover.piece_previous == PIECE_MAP_BOTTOM_RIGHT) + { + level.mapped ^= MAPPED_BOTTOM_RIGHT; + level.flags |= LEVELFLAG_MAP; + } + + level.moves[level.moves.length - 1].movers.pop(); + } + + /* If the move was a swap, revert to the previous player */ + if(level.moves[level.moves.length - 1].direction == MOVE_SWAP) + level.player = 1 - level.player; + + /* Have we just undone failure? */ + if((level.flags & LEVELFLAG_FAILED) && (level.alive[0] == true || level.alive[1] == true)) + { + level.flags &= ~LEVELFLAG_FAILED; + level.flags |= LEVELFLAG_MOVES; + } + + /* Have we just undone success? */ + if(level.flags & (LEVELFLAG_SOLVED | LEVELFLAG_EXIT)) + { + level.flags &= ~LEVELFLAG_SOLVED; + level.flags &= ~LEVELFLAG_EXIT; + level.flags |= LEVELFLAG_STARS; + } + + if(level.mode == MODE_XOR) + xor_focus(); + + return true; +} + +function isexplosion(piece) +{ + return (piece >= PIECE_EXPLOSION_FIRST && piece <= PIECE_EXPLOSION_LAST); +} + +function isnewexplosion(piece) +{ + return (piece >= PIECE_EXPLOSION_NEW_FIRST && piece <= PIECE_EXPLOSION_NEW_LAST); +} + +function level_piece(x, y) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return PIECE_WALL; + + return level.piece[x][y]; +} + +function level_setpiece(x, y, piece) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return; + + level.piece[x][y] = piece; +} + +function level_moving(x, y) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return MOVE_NONE; + + return level.moving[x][y]; +} + +function level_setmoving(x, y, moving) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return; + + level.moving[x][y] = moving; +} + +function level_previous(x, y) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return PIECE_WALL; + + return level.previous[x][y]; +} + +function level_setprevious(x, y, previous) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return; + + level.previous[x][y] = previous; +} + +function level_previousmoving(x, y) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return MOVE_NONE; + + return level.previousmoving[x][y]; +} + +function level_setpreviousmoving(x, y, previousmoving) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return; + + level.previousmoving[x][y] = previousmoving; +} + +function level_detonator(x, y) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return PIECE_SPACE; + + return level.detonator[x][y]; +} + +function level_setdetonator(x, y, detonator) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return; + + level.detonator[x][y] = detonator; +} + +function level_detonatormoving(x, y) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return MOVE_NONE; + + return level.detonatormoving[x][y]; +} + +function level_setdetonatormoving(x, y, detonatormoving) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return; + + level.detonatormoving[x][y] = detonatormoving; +} + +function level_data(x, y) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return 0; + + return level.data[x][y]; +} + +function level_setdata(x, y, data) +{ + if(level == null || x < 0 || x >= level.width || y < 0 || y >= level.height) + return; + + level.data[x][y] = data; +} + +function level_rebevel_movers() +{ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + if(mover.piece == PIECE_WALL) + level_setpiece(mover.x, mover.y, mover.piece); + } + + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + x = mover.x; + y = mover.y; + if(mover.piece == PIECE_WALL || (isexplosion(mover.piece) && display_animation == 1)) + { + for(i = -1; i < 2; i ++) + { + for(j = - 1; j < 2; j ++) + { + bevel = display_bevelsquare(x + i, y + j); + + if(bevel != (level_data(x + i, y + j) & BEVEL_ALL)) + level_setdata(x + i, y + j, bevel | (level_data(x + i, y + j) & ~BEVEL_ALL)); + } + } + } + } +} + +function display_level() +{ + var p; + + screen.context.fillStyle = "#000000"; + screen.context.fillRect(0, 0, screen.width, screen.height); + + if(level == null) + return; + + var startx = Math.floor(- graphics.offset_x / graphics.width); + var endx = Math.ceil((screen.width - graphics.offset_x) / graphics.width); + + var starty = Math.floor(- graphics.offset_y / graphics.height); + var endy = Math.ceil((screen.height - graphics.offset_y) / graphics.height); + + if(level.mode == MODE_XOR && options.xor_display) + { + endx = startx + 8; + endy = starty + 8; + } + + if(graphics.shadows.length > 0) + { + for(var y = starty; y < endy; y ++) + { + for(var x = startx; x < endx; x ++) + { + displayshadowed_piecebase(x, y); + + p = level_piece(x, y); + if(p != PIECE_SPACE) + display_piece(p, x, y, MOVE_NONE); + } + } + } + else + { + for(var y = starty; y < endy; y ++) + { + for(var x = startx; x < endx; x ++) + { + display_piece(PIECE_SPACE, x, y, MOVE_NONE); + display_piece(level_piece(x, y), x, y, MOVE_NONE); + } + } + } + + screen.bar.context.fillStyle = "#000000"; + screen.bar.context.fillRect(0, 0, screen.bar.width, screen.bar.height * screen.bar.lines); + + if(screen.bar.lines == 1) + { + var str = level.title; + var font_size = screen.bar.height; + var ok = false; + var text; + + while(!ok) + { + screen.bar.context.font = font_size + "px " + font_name; + + text = screen.bar.context.measureText(str); + if(text.width < screen.bar.width || font_size == 1) + ok = true; + else + font_size --; + } + screen.bar.title_position = (screen.bar.width - text.width) / 2; + screen.bar.title_width = text.width; + + screen.bar.context.lineWidth = screen.bar.height / 16; + screen.bar.context.strokeStyle= "#7f7f7f"; + screen.bar.context.strokeText(str, screen.bar.title_position, screen.bar.height - screen.bar.height / 8); + + screen.bar.context.fillStyle = "#ffffff"; + screen.bar.context.fillText(str, screen.bar.title_position, screen.bar.height - screen.bar.height / 8); + } + + screen.bar.stars_width = 0; + screen.bar.moves_width = 0; + + display_moves(); + display_stars(); + + if(level.mode == MODE_XOR && options.xor_display) + display_map(); +} + +function display_movers() +{ + var m, x, y, p, pm; + var mover; + + if(graphics.shadows.length > 0) + { + displayshadowed_movers(); + return; + } + + /* First, plot spaces for all moving pieces */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m] + + display_piece(PIECE_SPACE, mover.x, mover.y, MOVE_NONE); + } + + /* Plot moving pieces */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + x = mover.x; + y = mover.y; + + if(isexplosion(mover.piece)) + { + /* Plot any piece destroyed by the explosion, or the bomb itself */ + p = level_previous(x, y); + pm = level_previousmoving(x, y); + if(p != PIECE_SPACE) + display_piece(p, x, y, pm); + + /* Plot the detonator */ + p = level_detonator(x, y); + pm = level_detonatormoving(x, y); + if(p != PIECE_SPACE) + display_piece(p, x, y, pm); + } + /* Spaces have already been covered */ + else if(mover.piece != PIECE_SPACE && mover.piece != PIECE_GONE) + { + if(display_animation < 1) + { + /* Pieces being collected, earth being eaten */ + p = level_previous(x, y); + pm = level_previousmoving(x, y); + if((p != PIECE_SPACE && !isexplosion(p) && pm == MOVE_NONE) || mover.piece == PIECE_TELEPORT) + display_piece(p, x, y, pm); + } + + display_piece(mover.piece, x, y, mover.direction); + } + } + + /* At the peak of the explosion, rebevel any walls that have been + destroyed. When undoing, rebevel any walls that have been recreated. */ + if(display_animation ==0 || display_animation == 1) + { + /* When undoing, we have to create the wall prior to rebevelling, as it + wouldn't otherwise exist until after the end of the animation. */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + if(mover.piece == PIECE_WALL) + level_setpiece(mover.x, mover.y, mover.piece); + } + + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + x = mover.x; + y = mover.y; + if(mover.piece == PIECE_WALL || (isexplosion(mover.piece) && display_animation == 1)) + { + for(i = -1; i < 2; i ++) + { + for(j = - 1; j < 2; j ++) + { + bevel = display_bevelsquare(x + i, y + j); + + if(bevel != (level_data(x + i, y + j) & BEVEL_ALL)) + { + level_setdata(x + i, y + j, bevel | (level_data(x + i, y + j) & ~BEVEL_ALL)); + + p = level_piece(x + i, y + j); + if(p == PIECE_WALL) + { + if(level.switched) + display_piece(PIECE_DARKNESS, x + i, y + j, MOVE_NONE); + else + display_piece(PIECE_WALL, x + i, y + j, MOVE_NONE); + } + else + { + if(level.switched) + display_piece(PIECE_DARKNESS, x + i, y + j, MOVE_NONE); + else + display_piece(PIECE_SPACE, x + i, y + j, MOVE_NONE); + /* Moving pieces will be replotted when they next move. */ + if(p != PIECE_SPACE && level_moving(x + i, y + j) == MOVE_NONE) + display_piece(p, x + i, y + j, MOVE_NONE); + } + } + } + } + } + } + } + + /* Plot explosions */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + x = mover.x; + y = mover.y; + + /* Plot growing explosion */ + if(isexplosion(mover.piece)) + display_piece(mover.piece + PIECE_EXPLOSION_NEW_FIRST - PIECE_EXPLOSION_FIRST, x, y, MOVE_NONE); + + /* Plot dying explosion */ + p = level_previous(x, y); + if(isexplosion(p) && display_animation < 1) + display_piece(p, x, y, MOVE_NONE); + } +} + +function display_piece(p, x, y, d) +{ + var op; + var sx, sy, sw, sh; + var dw, dh; + var xstart, xend, xpos, xsize; + var bimage = []; + var i; + var bsizex, bsizey, boffset; + + var px = x * graphics.width + graphics.offset_x; + var py = y * graphics.height + graphics.offset_y; + + if(p < PIECE_SPACE || p >= PIECE_MAX) + return; + + if(level.switched && (p == PIECE_WALL || p == PIECE_SPACE)) + p = PIECE_DARKNESS; + + op = p; + + if(d != MOVE_NONE + && p != PIECE_SPACE && !isexplosion(p) + && p != PIECE_TELEPORT + ) + { + if(d == MOVE_LEFT) + px = px + Math.floor((1 - display_animation) * graphics.width); + if(d == MOVE_RIGHT) + px = px - Math.floor((1 - display_animation) * graphics.width); + if(d == MOVE_UP) + py = py + Math.floor((1 - display_animation) * graphics.height); + if(d == MOVE_DOWN) + py = py - Math.floor((1 -display_animation) * graphics.height); + } + + + + if(isexplosion(p)) + screen.context.globalAlpha = 1 - display_animation; + else if(isnewexplosion(p)) + { + p += PIECE_EXPLOSION_FIRST - PIECE_EXPLOSION_NEW_FIRST; + screen.context.globalAlpha = display_animation; + } + else + screen.context.globalAlpha = 1; + + if(graphics.image[p] == null) + return; + + sx = 0; + sy = 0; + sw = graphics.width; + sh = graphics.height; + + if(graphics.image[p].width > graphics.width) + { + xstart = 0; + xend = graphics.image[p].width / graphics.width; + xsize = 1; + xpos = 0; + + if(graphics.image_flags[p] & GRAPHICS_BEVEL) + xend -= 4; + + if(graphics.image_flags[p] & GRAPHICS_BEVEL16) + xsize = 16; + + if(graphics.image_flags[p] & GRAPHICS_MOVER) + { + xsize = 5; + + if(d == MOVE_LEFT) + xpos += 1; + if(d == MOVE_UP) + xpos += 2; + if(d == MOVE_RIGHT) + xpos += 3; + if(d == MOVE_DOWN) + xpos += 4; + } + + if(graphics.image_flags[p] & GRAPHICS_LEVEL && level.level > 0) + { + xsize = 15; + xpos = level.level - 1; + } + + /* If we're plotting the players */ + if(p == PIECE_PLAYER_ONE || p == PIECE_PLAYER_TWO) + { + + /* and there's an image for the swapped player */ + if(xend > xstart + xsize) + { + /* then use it if the player is swapped out */ + if(level.player != (p & 1) && level.player != 2) + xpos += xsize; + } + } + + if(graphics.image_flags[p] & GRAPHICS_BEVEL16) + { + i = 15; + b = level_data(x, y) & BEVEL_ALL; + + if(b & BEVEL_U) + i -= 1; + if(b & BEVEL_R) + i -= 2; + if(b & BEVEL_D) + i -= 4; + if(b & BEVEL_L) + i -= 8; + + xpos += i; + } + + if(graphics.image_flags[p] & GRAPHICS_ANIMATE) + { + b = (xend - xstart) / xsize; + + if(!isexplosion(p)) + b = b * display_animation; + else + b = b * ((display_animation + (isnewexplosion(op) ? 0 : 1)) * 0.5); + + xpos += b * xsize; + } + else if(graphics.image_flags[p] & GRAPHICS_RANDOM) + { + b = (xend - xstart) / xsize; + + if(p == PIECE_SPACE) + b = (level_data(x, y) & 0xff) % b; + else + b = ((level_data(x, y) & 0xff00) / 0x100) % b; + + xpos += b * xsize; + } + else if(graphics.image_flags[p] & GRAPHICS_TILE) + { + b = x % ((xend - xstart) / xsize); + if(b < 0) + b += (xend - xstart) / xsize; + xpos += b * xsize; + + b = y % (graphics.image[p].height / graphics.height); + if(b < 0) + b += (graphics.image[p].height / graphics.height); + sy = b * graphics.height; + } + + sx = (xstart + xpos) * graphics.width; + } + + /* Plot piece */ + screen.context.drawImage(graphics.image[p], sx, sy, graphics.width, graphics.height, px, py, graphics.width, graphics.height); + + /* Plot bevelling */ + if(graphics.image_flags[p] & GRAPHICS_BEVEL) + { + b = level_data(x, y) & BEVEL_ALL; + + if(b != 0) + { + bsizex = graphics.width / 2; + bsizey = graphics.height / 2; + boffset = (xend - 1) * graphics.width; + + for(i = 0; i < 4; i ++) + bimage[i] = 0; + + if(b & BEVEL_L) + { + if(b & BEVEL_U) + bimage[0] = 3 * graphics.width; + else + bimage[0] = 1 * graphics.width; + + if(b & BEVEL_D) + bimage[2] = 3 * graphics.width; + else + bimage[2] = 1 * graphics.width; + } + else + { + if(b & BEVEL_U) + bimage[0] = 2 * graphics.width; + if(b & BEVEL_D) + bimage[2] = 2 * graphics.width; + } + + if(b & BEVEL_R) + { + if(b & BEVEL_U) + bimage[1] = 3 * graphics.width; + else + bimage[1] = 1 * graphics.width; + + if(b & BEVEL_D) + bimage[3] = 3 * graphics.width; + else + bimage[3] = 1 * graphics.width; + } + else + { + if(b & BEVEL_U) + bimage[1] = 2 * graphics.width; + if(b & BEVEL_D) + bimage[3] = 2 * graphics.width; + } + + if(b & BEVEL_TL) + bimage[0] = 4 * graphics.width; + if(b & BEVEL_TR) + bimage[1] = 4 * graphics.width; + if(b & BEVEL_BL) + bimage[2] = 4 * graphics.width; + if(b & BEVEL_BR) + bimage[3] = 4 * graphics.width; + + for(i = 0; i < 4; i ++) + { + if(bimage[i] != 0) + { + sx = boffset + bimage[i] + ((i & 1) ? bsizex : 0); + sy = (i & 2) ? bsizey : 0; + sw = bsizex; + sh = bsizey; + + screen.context.drawImage(graphics.image[p], sx, sy, sw, sh, px + ((i & 1) ? bsizex : 0), py + ((i & 2) ? bsizey : 0), bsizex, bsizey); + } + } + } + } + + screen.context.globalAlpha = 1; +} + +function displayshadowed_piecebase(x, y) +{ + var p; + var px, py; + var z; + var ok; + var b, bp; + var xend; + + var sx, sy, sw, sh; + var dx, dy, dw, dh; + var bsx, bsy, bsw, bsh; + var bdx, bdy, bdw, bdh; + var alpha; + + p = level_piece(x, y); + + if(level_moving(x, y) != MOVE_NONE) + { + if(display_animation >= 1) + p = PIECE_SPACE; + else + p = level_previous(x, y); + } + + if(level.switched && (p == PIECE_WALL || p == PIECE_SPACE)) + p = PIECE_DARKNESS; + + if(level.switched) + bp = PIECE_DARKNESS; + else + bp = PIECE_SPACE; + + image = graphics.image[bp]; + + px = x * graphics.width + graphics.offset_x; + py = y * graphics.height + graphics.offset_y; + + + sx = 0; + sy = 0; + sw = graphics.width; + sh = graphics.height; + + dx = px; + dy = py; + dw = graphics.width; + dh = graphics.height; + + /* Is the base tiled? */ + if(graphics.image_flags[bp] & GRAPHICS_TILE) + { + xend = image.width / graphics.width; + if(graphics.image_flags[bp] & GRAPHICS_BEVEL) + xend -= 4; + sx += graphics.width * (x % xend); + sy += graphics.height * (y % (image.height / graphics.height)); + } + + /* Plot the base */ + screen.context.globalAlpha = 1; + screen.context.drawImage(graphics.image[bp], sx, sy, sw, sh, dx, dy, dw, dh); + + /* Do we need to order the shadows prior to plotting? */ + if(graphics.flags & GRAPHICS_ZORDER) + { + graphics.shadows_sorted = []; + + for(s = 0; s < graphics.shadows.length; s ++) + { + shadow = graphics.shadows[s]; + + /* Determine which piece to consider the shadow of */ + p = level_piece(x - shadow.x, y - shadow.y); + if(level_moving(x - shadow.x, y - shadow.y) != MOVE_NONE) + { + if(display_animation >= 1) + p = PIECE_SPACE; + else + { + if(level_previousmoving(x - shadow.x, y - shadow.y) == MOVE_NONE) + p = level_previous(x - shadow.x, y - shadow.y); + else + p = PIECE_SPACE; + } + } + + if(p == PIECE_WALL && level.switched) + p = PIECE_DARKNESS; + + /* Does it have a shadow? */ + if(graphics.shadow_image[p] != null && (graphics.shadow_flags[p] & shadow.flag)) + { + z = graphics.shadow_z[p]; + shadow.z = graphics.shadow_z[p]; + shadow.p = p; + + graphics.shadows_sorted.push(shadow); + } + } + + graphics.shadows_sorted.sort(function(a, b) { return parseInt(a.z) - parseInt(b.z); }); + + } + else + { + /* Use the order specified in the graphics file */ + graphics.shadows_sorted = graphics.shadows; + } + + /* Plot shadows in order */ + for(var s = 0; s < graphics.shadows_sorted.length; s ++) + { + shadow = graphics.shadows_sorted[s]; + + /* Determine which piece to consider the shadow of */ + p = level_piece(x - shadow.x, y - shadow.y); + if(level_moving(x - shadow.x, y - shadow.y) != MOVE_NONE) + { + if(display_animation >= 1) + p = PIECE_SPACE; + else + { + if(level_previousmoving(x - shadow.x, y - shadow.y) == MOVE_NONE) + p = level_previous(x - shadow.x, y - shadow.y); + else + p = PIECE_SPACE; + } + } + /* Does it have a shadow? */ + if(graphics.shadow_image[p] != null && (graphics.shadow_flags[p] & shadow.flag)) + { + image = graphics.shadow_image[p]; + + if(isexplosion(p)) + screen.context.globalAlpha = 1 - display_animation; + else if(isnewexplosion(p)) + { + p += PIECE_EXPLOSION_FIRST - PIECE_EXPLOSION_NEW_FIRST; + screen.context.globalAlpha = display_animation; + } + else + screen.context.globalAlpha = 1; + + sx = graphics.shadow_start_x[p][shadow.shadow]; + sy = graphics.shadow_start_y[p][shadow.shadow]; + sw = graphics.shadow_width[p][shadow.shadow]; + sh = graphics.shadow_height[p][shadow.shadow]; + + dx = px + graphics.shadow_offset_x[p][shadow.shadow]; + dy = py + graphics.shadow_offset_y[p][shadow.shadow]; + dw = graphics.shadow_width[p][shadow.shadow]; + dh = graphics.shadow_height[p][shadow.shadow]; + + /* Are there multiple images? */ + if(image.width > graphics.shadow_width[p][9]) + { + /* Choose swapped player if necessary */ + if(p == PIECE_PLAYER_ONE || p == PIECE_PLAYER_TWO) + { + if(level.player != (p & 1) && level.player != 2) + sx += graphics.shadow_width[p][9]; + } + } + + /* Plot shadow */ + screen.context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh); + + /* Bevel shadow */ + if(graphics.image_flags[p] & GRAPHICS_BEVEL_SHADOW) + { + b = level_data(x - shadow.x, y - shadow.y) & BEVEL_ALL; + /* Top left quadrant */ + if(b & (BEVEL_L | BEVEL_U | BEVEL_TL)) + { + bsx = 0; + bsy = 0; + bsw = graphics.shadow_width[p][9] / 2; + bsh = graphics.shadow_height[p][9] / 2; + bdx = dx; + bdy = dy; + + ok = 1; + if(bsx < sx) + { + if(bsw > (sx - bsx)) + { + bsw -= (sx - bsx); + bdx -= bsx; + bsx = sx; + } + else + ok = 0; + } + if(bsy < sy) + { + if(bsh > (sy - bsy)) + { + bsh -= (sy - bsy); + bdy -= bsy; + bsy = sy; + } + else + ok = 0; + } + if(bdx + bsw > dx + dw) + { + if(bsw > ((bdx + bsw) - (dx + dw))) + bsw -= ((bdx + bsw) - (dx + dw)); + else + ok = 0; + } + if(bdy + bsh > dy + dh) + { + if(bsh > ((bdy + bsh) - (dy + dh))) + bsh -= ((bdy + bsh) - (dy + dh)); + else + ok = 0; + } + if(b & BEVEL_TL) + bsx += graphics.shadow_width[p][9] * 4; + else + { + if(b & BEVEL_U) + bsx += graphics.shadow_width[p][9] * 2; + if(b & BEVEL_L) + bsx += graphics.shadow_width[p][9]; + } + + if(ok) + screen.context.drawImage(image, bsx, bsy, bsw, bsh, bdx, bdy, bdw, bdh); + } + + /* Top right quadrant */ + if(b & (BEVEL_R | BEVEL_U | BEVEL_TR)) + { + bsx = graphics.shadow_width[p][9] / 2; + bsy = 0; + bsw = graphics.shadow_width[p][9] / 2; + bsh = graphics.shadow_height[p][9] / 2; + bdx = dx + graphics.width / 2; + bdy = dy; + + ok = 1; + if(bsx < sx) + { + if(bsw > (sx - bsx)) + { + bsw -= (sx - bsx); + bdx -= bsx; + bsx = sx; + } + else + ok = 0; + } + if(bsy < sy) + { + if(bsh > (sy - bsy)) + { + bsh -= (sy - bsy); + bdy -= bsy; + bsy = sy; + } + else + ok = 0; + } + if(bdx + bsw > dx + dw) + { + if(bsw > ((bdx + bsw) - (dx + dw))) + bsw -= ((bdx + bsw) - (dx + dw)); + else + ok = 0; + } + if(bdy + bsh > dy + dh) + { + if(bsh > ((bdy + bsh) - (dy + dh))) + bsh -= ((bdy + bsh) - (dy + dh)); + else + ok = 0; + } + if(b & BEVEL_TR) + bsx += graphics.shadow_width[p][9] * 4; + else + { + if(b & BEVEL_U) + bsx += graphics.shadow_width[p][9] * 2; + if(b & BEVEL_R) + bsx += graphics.shadow_width[p][9]; + } + if(ok) + screen.context.drawImage(image, bsx, bsy, bsw, bsh, bdx, bdy, bdw, bdh); + } + + /* Bottom left quadrant */ + if(b & (BEVEL_L | BEVEL_D | BEVEL_BL)) + { + bsx = 0; + bsy = graphics.shadow_height[p][9] / 2;; + bsw = graphics.shadow_width[p][9] / 2; + bsh = graphics.shadow_height[p][9] / 2; + bdx = dx; + bdy = dy + graphics.height / 2; + + ok = 1; + if(bsx < sx) + { + if(bsw > (sx - bsx)) + { + bsw -= (sx - bsx); + bdx -= bsx; + bsx = sx; + } + else + ok = 0; + } + if(bsy < sy) + { + if(bsh > (sy - bsy)) + { + bsh -= (sy - bsy); + bdy -= bsy; + bsy = sy; + } + else + ok = 0; + } + if(bdx + bsw > dx + dw) + { + if(bsw > ((bdx + bsw) - (dx + dw))) + bsw -= ((bdx + bsw) - (dx + dw)); + else + ok = 0; + } + if(bdy + bsh > dy + dh) + { + if(bsh > ((bdy + bsh) - (dy + dh))) + bsh -= ((bdy + bsh) - (dy + dh)); + else + ok = 0; + } + if(b & BEVEL_BL) + bsx += graphics.shadow_width[p][9] * 4; + else + { + if(b & BEVEL_D) + bsx += graphics.shadow_width[p][9] * 2; + if(b & BEVEL_L) + bsx += graphics.shadow_width[p][9]; + } + if(ok) + screen.context.drawImage(image, bsx, bsy, bsw, bsh, bdx, bdy, bdw, bdh); + } + + /* Bottom right quadrant */ + if(b & (BEVEL_R | BEVEL_D | BEVEL_BR)) + { + bsx = graphics.shadow_width[p][9] / 2; + bsy = graphics.shadow_height[p][9] / 2; + bsw = graphics.shadow_width[p][9] / 2; + bsh = graphics.shadow_height[p][9] / 2; + bdx = dx + graphics.width / 2; + bdy = dy + graphics.height / 2; + + ok = 1; + if(bsx < sx) + { + if(bsw > (sx - bsx)) + { + bsw -= (sx - bsx); + bdx -= bsx; + bsx = sx; + } + else + ok = 0; + } + if(bsy < sy) + { + if(bsh > (sy - bsy)) + { + bsh -= (sy - bsy); + bdy -= bsy; + bsy = sy; + } + else + ok = 0; + } + if(bdx + bsw > dx + dw) + { + if(bsw > ((bdx + bsw) - (dx + dw))) + bsw -= ((bdx + bsw) - (dx + dw)); + else + ok = 0; + } + if(bdy + bsh > dy + dh) + { + if(bsh > ((bdy + bsh) - (dy + dh))) + bsh -= ((bdy + bsh) - (dy + dh)); + else + ok = 0; + } + if(b & BEVEL_BR) + bsx += graphics.shadow_width[p][9] * 4; + else + { + if(b & BEVEL_D) + bsx += graphics.shadow_width[p][9] * 2; + if(b & BEVEL_R) + bsx += graphics.shadow_width[p][9]; + } + if(ok) + screen.context.drawImage(image, bsx, bsy, bsw, bsh, bdx, bdy, bdw, bdh); + } + } + } + } + + screen.context.globalAlpha = 1; +} + +function displayshadowed_movers() +{ + var x, y, p, pm; + var i, j; + var d; + var bevel; + var bevelold; + var sx, sy, sw, sh; + var dx, dy, dw, dh; + var mover; + + p = PIECE_SPACE; + + /* Stage one: plot base for pieces that need rebevelling */ + if(display_animation == 0 || display_animation == 1) + { + /* When undoing, we have to create the wall prior to rebevelling, as it + wouldn't otherwise exist until after the end of the animation. */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + if(mover.piece == PIECE_WALL) + level_setpiece(mover.x, mover.y, mover.piece); + } + + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + x = mover.x; + y = mover.y; + if(mover.piece == PIECE_WALL || + (isexplosion(mover.piece) && display_animation == 1)) + { + for(s = 0; s < graphics.shadows.length; s ++) + { + shadow = graphics.shadows[s]; + bevel = display_bevelsquare(x + shadow.x, y + shadow.y); + bevelold = (level_data(x + shadow.x, y + shadow.y) & BEVEL_ALL); + /* Because this happens only once per move cycle, we + are lazy and don't bother to count whether this base + has already been plotted */ + if(bevel != bevelold); + displayshadowed_piecebase(mover.x + shadow.x, mover.y + shadow.y); + } + } + } + } + + /* Stage two: plot shadows for stationary squares affected by movers */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + if(mover.piece != PIECE_GONE) + { + /* This is overkill, but it's easier just to plot everything that + could be affected than to calculate what is actually affected. + */ + + for(s = 0; s < graphics.shadows.length; s ++) + { + shadow = graphics.shadows[s]; + if(displayshadowed_count(mover.x + shadow.x, mover.y + shadow.y, 1) == 0) + displayshadowed_piecebase(mover.x + shadow.x, mover.y + shadow.y); + } + if(displayshadowed_count(mover.x, mover.y, 1) == 0) + displayshadowed_piecebase(mover.x, mover.y); + } + + } + /* then reset the counts */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + if(mover.piece != PIECE_GONE) + { + for(s = 0; s < graphics.shadows.length; s ++) + { + shadow = graphics.shadows[s]; + + displayshadowed_count(mover.x + shadow.x, mover.y + shadow.y, -1); + } + displayshadowed_count(mover.x, mover.y, -1); + } + } + + /* Stage three: plot shadows for movers */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + d = mover.direction; + x = mover.x; + y = mover.y; + + if(isexplosion(mover.piece)) + { + /* If the previous piece, that is, the piece destroyed in the + explosion, is stationary, we don't need to plot a shadow for it, + as that is handled in stage one. If it is moving, however, it + needs a moving shadow, which we do have to plot here. */ + p = level_previous(x, y); + pm = level_previousmoving(x, y); + if(p != PIECE_SPACE && pm != MOVE_NONE) + displayshadowed_pieceshadow(p, x, y, pm); + + /* Plot shadow for the detonator */ + p = level_detonator(x, y); + pm = level_detonatormoving(x, y); + if(p != PIECE_SPACE) + displayshadowed_pieceshadow(p, x, y, pm); + + } + /* Spaces and walls were handled in stage one */ + else if(mover.piece != PIECE_SPACE && mover.piece != PIECE_WALL && mover.piece != PIECE_GONE) + { + /* We don't need to plot the shadow for the previous piece + as that is handled in stage one */ + + /* Plot shadow for mover */ + if(mover.piece == PIECE_TELEPORT) + d = MOVE_NONE; + + displayshadowed_pieceshadow(mover.piece, mover.x, mover.y, d); + } + } + + /* Stage four: plot shadows for explosions */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + x = mover.x; + y = mover.y; + /* Plot growing explosion */ + if(isexplosion(mover.piece)) + displayshadowed_pieceshadow(mover.piece + PIECE_EXPLOSION_NEW_FIRST - PIECE_EXPLOSION_FIRST, x, y, MOVE_NONE); + + /* Plot dying explosion */ + p = level_previous(x, y); + if(isexplosion(p) && display_animation < 1) + displayshadowed_pieceshadow(p, x, y, MOVE_NONE); + } + + /* Stage five: plot pieces for stationary squares affected by movers. + We need to be careful not to plot the same piece twice, so we keep + count and only plot on the first occurrence. */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + for(s = 0; s < graphics.shadows.length; s ++) + { + shadow = graphics.shadows[s]; + if(displayshadowed_count(mover.x + shadow.x, mover.y + shadow.y, 1) == 0) + { + p = level_piece(mover.x + shadow.x, mover.y + shadow.y); + pm = level_moving(mover.x + shadow.x, mover.y + shadow.y); + if(p != PIECE_SPACE && p != PIECE_GONE && pm == MOVE_NONE) + display_piece(p, mover.x + shadow.x, mover.y + shadow.y, MOVE_NONE); + } + } + } + /* then reset the counts */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + for(s = 0; s < graphics.shadows.length; s ++) + { + shadow = graphics.shadows[s]; + displayshadowed_count(mover.x + shadow.x, mover.y + shadow.y, -1); + } + } + + /* Stage six: plot pieces for movers */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + d = mover.direction; + x = mover.x; + y = mover.y; + + if(isexplosion(mover.piece)) + { + /* Plot any piece destroyed by the explosion, or the bomb itself */ + p = level_previous(x, y); + pm = level_previousmoving(x, y); + if(p != PIECE_SPACE) + display_piece(p, x, y, pm); + + /* Plot the detonator */ + p = level_detonator(x, y); + pm = level_detonatormoving(x, y); + if(p != PIECE_SPACE) + display_piece(p, x, y, pm); + + } + /* Spaces were handled in stage one */ + else if(mover.piece != PIECE_SPACE && mover.piece != PIECE_GONE) + { + if(display_animation < 1) + { + /* Pieces being collected, earth being eaten */ + p = level_previous(x, y); + pm = level_previousmoving(x, y); + if((p != PIECE_SPACE && !isexplosion(p) && pm == MOVE_NONE) || mover.piece == PIECE_TELEPORT) + display_piece(p, x, y, pm); + } + + /* Plot the piece itself */ + if(mover.piece == PIECE_TELEPORT) + d = MOVE_NONE; + + display_piece(mover.piece, mover.x, mover.y, d); + } + pmover = mover.next; + } + + /* Stage seven: plot pieces that need rebevelling */ + if(display_animation == 0 || display_animation == 1) + { + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + x = mover.x; + y = mover.y; + if(mover.piece == PIECE_WALL || + (isexplosion(mover.piece) && display_animation == 1)) + { + for(i = -1; i < 2; i ++) + { + for(j = - 1; j < 2; j ++) + { + bevel = display_bevelsquare(x + i, y + j); + bevelold = (level_data(x + i, y + j) & BEVEL_ALL); + if(bevel != bevelold); + { + /* Here we are not lazy, to avoid issues with + transparent graphics being plotted twice */ + if(displayshadowed_count(mover.x + i, mover.y + j, 1) == 0) + { + level_setdata(x + i, y + j, bevel | (level_data(x + i, y + j) & ~BEVEL_ALL)); + p = level_piece(x + i, y + j); + if(p == PIECE_WALL) + display_piece(p, mover.x + i, mover.y + j, MOVE_NONE); + level_setdata(x + i, y + j, bevelold | (level_data(x + i, y + j) & ~BEVEL_ALL)); + } + } + } + } + } + } + /* and reset counts */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + x = mover.x; + y = mover.y; + if(mover.piece == PIECE_WALL || + (isexplosion(mover.piece) && display_animation == 1)) + { + for(i = -1; i < 2; i ++) + { + for(j = - 1; j < 2; j ++) + { + bevel = display_bevelsquare(x + i, y + j); + bevelold = (level_data(x + i, y + j) & BEVEL_ALL); + if(bevel != bevelold); + displayshadowed_count(mover.x + i, mover.y + j, -1); + } + } + } + } + } + + + /* Stage eight: plot pieces for explosions */ + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + x = mover.x; + y = mover.y; + /* Plot growing explosion */ + if(isexplosion(mover.piece)) + display_piece(mover.piece + PIECE_EXPLOSION_NEW_FIRST - PIECE_EXPLOSION_FIRST, x, y, MOVE_NONE); + + /* Plot dying explosion */ + p = level_previous(x, y); + if(isexplosion(p) && display_animation < 1) + display_piece(p, x, y, MOVE_NONE); + } + + /* Stage nine: rebevel pieces that need rebevelling */ + if(display_animation == 0 || display_animation == 1) + { + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + x = mover.x; + y = mover.y; + if(mover.piece == PIECE_WALL || (isexplosion(mover.piece) && display_animation == 1)) + { + for(i = -1; i < 2; i ++) + { + for(j = - 1; j < 2; j ++) + { + bevel = display_bevelsquare(x + i, y + j); + bevelold = (level_data(x + i, y + j) & BEVEL_ALL); + if(bevel != bevelold); + { + /* Again, we are lazy and do not keep count of + whether this square has already been rebevelled. */ + level_setdata(x + i, y + j, bevel | (level_data(x + i, y + j) & ~BEVEL_ALL)); + } + } + } + } + } + } +} + +function displayshadowed_count(x, y, delta) +{ + var d = level_data(x, y); + level_setdata(x, y, d + (delta * SHADOW_BASE)); + + return d & (0x7f * SHADOW_BASE); +} + +function displayshadowed_pieceshadow(p, x, y, d) +{ + var px, py; + var image; + var sx, sy, sw, sh; + var dx, dy, dw, dh; + + if(isexplosion(p)) + screen.context.globalAlpha = 1 - display_animation; + else if(isnewexplosion(p)) + { + p += PIECE_EXPLOSION_FIRST - PIECE_EXPLOSION_NEW_FIRST; + screen.context.globalAlpha = display_animation; + } + else + screen.context.globalAlpha = 1; + + image = graphics.shadow_image[p]; + if(image == null) + return; + + px = x * graphics.width + graphics.offset_x; + py = y * graphics.height + graphics.offset_y; + + if(d == MOVE_LEFT) + px = px + Math.floor((1 - display_animation) * graphics.width); + if(d == MOVE_RIGHT) + px = px - Math.floor((1 - display_animation) * graphics.width); + if(d == MOVE_UP) + py = py + Math.floor((1 - display_animation) * graphics.height); + if(d == MOVE_DOWN) + py = py - Math.floor((1 -display_animation) * graphics.height); + + + sx = 0; + sy = 0; + sw = graphics.shadow_width[p][9]; + sh = graphics.shadow_height[p][9]; + + dx = px + graphics.shadow_offset_x[p][9]; + dy = py + graphics.shadow_offset_y[p][9]; + dw = sw; + dh = sh; + + if(image.width > graphics.shadow_width[p][9]) + { + if(p == PIECE_PLAYER_ONE || p == PIECE_PLAYER_TWO) + { + if(level.player != (p & 1)) + sx = graphics.shadow_width[p][9]; + } + } + + /* Plot piece */ + screen.context.drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh); + + screen.context.globalAlpha = 1; +} + +function display_start_update() +{ + graphics.time_start = Date.now(); + + display_animation = 0; + display_movers(); + + window.requestAnimationFrame(display_update); +} + +function display_update() +{ + var t = Date.now(); + + /* Calculate what the delay should be, defaulting to the Move Speed. */ + var delay = options.move_delay; + + if(level_replay != null) + delay = options.replay_delay; + else + { + for(m = 0; m < level.movers.length; m ++) + { + mover = level.movers[m]; + + /* Use the Player Speed if the player is still moving */ + if(mover.piece == PIECE_PLAYER_ONE || mover.piece == PIECE_PLAYER_TWO) + delay = options.player_delay; + /* unless there's a piece following in their trail */ + else if(mover.piece != PIECE_SPACE && mover.fast == 1) + delay = options.move_delay; + } + + /* If we're undoing, use the Undo Speed */ + if(level.flags & LEVELFLAG_UNDO) + delay = options.undo_delay; + } + + /* If SHIFT is pressed, speed things up. */ + if(graphics.shift) + delay = delay / 10; + /* If CTRL is pressed, slow things down. */ + if(graphics.ctrl) + delay = delay * 4; + + /* If the delay has changed, preserve our position in the animation */ + if(delay != options.previous_delay) + { + if(options.previous_delay != 0) + graphics.time_start = t - (((t - graphics.time_start) * delay) / options.previous_delay); + options.previous_delay = delay; + } + + if(t < graphics.time_start + delay) + display_animation = (t - graphics.time_start) / delay; + else + display_animation = 1; + + if(level.flags & LEVELFLAG_SWITCH) + { + display_level(); + level.flags &= ~LEVELFLAG_SWITCH; + } + + display_movers(); + + if(display_animation != 1) + window.requestAnimationFrame(display_update); + else + { + if(level.flags & LEVELFLAG_STARS || level.flags & LEVELFLAG_EXIT) + { + display_stars(); + level.flags &= ~LEVELFLAG_STARS; + } + + if(level.flags & LEVELFLAG_MAP) + { + display_map(); + level.flags &= ~LEVELFLAG_MAP; + } + + if(level.flags & LEVELFLAG_MOVES) + { + display_moves(); + level.flags &= ~LEVELFLAG_MOVES; + } + + if(level.flags & LEVELFLAG_EXIT) + { + level.flags |= LEVELFLAG_SOLVED; + } + + if(!(level.flags & LEVELFLAG_UNDO)) + { + level_evolve(); + level_storemovers(); + + if(display_focus()) + display_level(); + + if(level.movers.length > 0) + display_start_update(); + else + { + if(level_replay != null) + consider_replay_move(); + else + consider_mouse_move(); + } + } + else + { + if(level_undo()) + { + level.flags |= LEVELFLAG_UNDO; + } + else + level.flags &= ~LEVELFLAG_UNDO; + + if(level_replay != null) + consider_replay_move(); + else + consider_mouse_move(); + + if(display_focus()) + display_level(); + + display_start_update(); + + if(level_replay != null) + consider_replay_move(); + } + + } +} + +function display_bevelsquare(x, y) +{ + var bevel = 0; + + bevel = 0; + + if(level_piece(x, y) == PIECE_WALL) + { + if(level_piece(x - 1, y) != PIECE_WALL) + bevel |= BEVEL_L; + if(level_piece(x + 1, y) != PIECE_WALL) + bevel |= BEVEL_R; + if(level_piece(x, y - 1) != PIECE_WALL) + bevel |= BEVEL_U; + if(level_piece(x, y + 1) != PIECE_WALL) + bevel |= BEVEL_D; + + if(((bevel & (BEVEL_L | BEVEL_U)) == 0) && level_piece(x - 1, y - 1) != PIECE_WALL) + bevel |= BEVEL_TL; + if(((bevel & (BEVEL_R | BEVEL_U)) == 0) && level_piece(x + 1, y - 1) != PIECE_WALL) + bevel |= BEVEL_TR; + if(((bevel & (BEVEL_L | BEVEL_D)) == 0) && level_piece(x - 1, y + 1) != PIECE_WALL) + bevel |= BEVEL_BL; + if(((bevel & (BEVEL_R | BEVEL_D)) == 0) && level_piece(x + 1, y + 1) != PIECE_WALL) + bevel |= BEVEL_BR; + } + else + { + if(level_piece(x - 1, y) == PIECE_WALL) + bevel |= BEVEL_L; + if(level_piece(x + 1, y) == PIECE_WALL) + bevel |= BEVEL_R; + if(level_piece(x, y - 1) == PIECE_WALL) + bevel |= BEVEL_U; + if(level_piece(x, y + 1) == PIECE_WALL) + bevel |= BEVEL_D; + + if(((bevel & (BEVEL_L | BEVEL_U)) == 0) && level_piece(x - 1, y - 1) == PIECE_WALL) + bevel |= BEVEL_TL; + if(((bevel & (BEVEL_R | BEVEL_U)) == 0) && level_piece(x + 1, y - 1) == PIECE_WALL) + bevel |= BEVEL_TR; + if(((bevel & (BEVEL_L | BEVEL_D)) == 0) && level_piece(x - 1, y + 1) == PIECE_WALL) + bevel |= BEVEL_BL; + if(((bevel & (BEVEL_R | BEVEL_D)) == 0) && level_piece(x + 1, y + 1) == PIECE_WALL) + bevel |= BEVEL_BR; + } + + return bevel; +} + +function display_bevellevel() +{ + var bevel; + var x, y; + + for(x = 0; x < level.width; x ++) + { + for(y = 0; y < level.height; y ++) + { + bevel = level_data(x, y) & ~BEVEL_ALL; + bevel = bevel | display_bevelsquare(x, y); + level_setdata(x, y, bevel); + } + } +} + +function display_moves() +{ + var str; + var line_offset; + var x; + + if(screen.bar.lines == 1) + line_offset = 0; + else + line_offset = 1 * screen.bar.height; + + if(level_replay != null) + { + if(level_replay.flags & LEVELFLAG_PAUSED) + str = "\u25a0"; + else if(level_replay.flags & LEVELFLAG_UNDO) + str = "\u25c2"; + else + str = "\u25b8"; + + str += " "+level.moves.length + "/" + level_replay.moves.length; + } + else if(level.flags & LEVELFLAG_FAILED) + str = "failed"; + else if(level.redoable_moves.length != 0) + str = level.moves.length + "/" + (level.moves.length + level.redoable_moves.length); + else + str = level.moves.length; + + str = " " + str + " "; + + screen.bar.context.font = screen.bar.height + "px " + font_name; + + var text = screen.bar.context.measureText(str); + if(screen.bar.move_width < text.width) + screen.bar.move_width = text.width; + + if(screen.bar.lines == 1) + x = screen.bar.width - graphics.small_width - screen.bar.move_width; + else + x = 0; + + screen.bar.context.fillStyle = "#000000"; + screen.bar.context.fillRect(x, line_offset, screen.bar.move_width + graphics.small_width, screen.bar.height); + + screen.bar.move_width = text.width; + + if(screen.bar.lines == 1) + x = screen.bar.width - graphics.small_width - text.width; + else + x = graphics.small_width; + + screen.bar.context.lineWidth = screen.bar.height / 16; + screen.bar.context.strokeStyle= "#0080ff"; + screen.bar.context.strokeText(str, x, line_offset + screen.bar.height - screen.bar.height / 8); + + screen.bar.context.fillStyle = "#66b3ff"; + screen.bar.context.fillText(str, x, line_offset + screen.bar.height - screen.bar.height / 8); + + var sx = 0; + /* If there is a second small image, use it for a dead player */ + if(!level.alive[level.player] && graphics.small_image[PIECE_PLAYER_ONE + level.player].width > graphics.small_width) + sx = graphics.small_width; + if(graphics.image_flags[PIECE_PLAYER_ONE + level.player] & GRAPHICS_LEVEL && level.level > 0) + sx = graphics.small_width * (level.level - 1); + + if(screen.bar.lines == 1) + x = screen.bar.width - graphics.small_width; + else + x = 0; + + if(graphics.small_image[PIECE_PLAYER_ONE + level.player] != null) + screen.bar.context.drawImage(graphics.small_image[PIECE_PLAYER_ONE + level.player], sx, 0, graphics.small_width, graphics.small_height, x, line_offset + (screen.bar.height / 2) - (graphics.small_height / 2), graphics.small_width, graphics.small_height); + +} + +function display_stars() +{ + var str; + var line_offset; + + if(screen.bar.lines == 1) + line_offset = 0; + else + line_offset = 0 * screen.bar.height; + + if(level.flags & LEVELFLAG_EXIT) + str = "solved"; + else if(level.stars_exploded != 0) + str = level.stars_exploded + " lost"; + else + str = level.stars_caught + "/" + level.stars_total; + + str = " " + str + " "; + + screen.bar.context.font = screen.bar.height + "px " + font_name; + + var text = screen.bar.context.measureText(str); + if(screen.bar.stars_width < text.width) + screen.bar.stars_width = text.width; + + screen.bar.context.fillStyle = "#000000"; + screen.bar.context.fillRect(0, line_offset, graphics.small_width + screen.bar.stars_width, screen.bar.height); + + screen.bar.stars_width = text.width; + + screen.bar.context.lineWidth = screen.bar.height / 16; + screen.bar.context.strokeStyle= "#ffa000"; + screen.bar.context.strokeText(str, graphics.small_width, line_offset + screen.bar.height - screen.bar.height / 8); + + screen.bar.context.fillStyle = "#ffff33"; + screen.bar.context.fillText(str, graphics.small_width, line_offset + screen.bar.height - screen.bar.height / 8); + + var p = PIECE_STAR; + + if(level.flags & LEVELFLAG_EXIT && !(level.flags & LEVELFLAG_FAILED) && graphics.small_image[PIECE_DOOR] != null) + p = PIECE_DOOR; + + var sx = 0; + if(graphics.image_flags[p] & GRAPHICS_LEVEL && level.level > 0) + sx = graphics.small_width * (level.level - 1); + + if(graphics.small_image[p] != null) + screen.bar.context.drawImage(graphics.small_image[p], sx, 0, graphics.small_width, graphics.small_height, 0, line_offset + (screen.bar.height / 2) - (graphics.small_height / 2), graphics.small_width, graphics.small_height) + +} + +function display_focus() +{ + if(level == null) + return; + + if(level.mode == MODE_XOR && options.xor_display) + { + ox = graphics.offset_x; + oy = graphics.offset_y; + + graphics.offset_x = 0; + graphics.offset_y = 0; + + graphics.offset_x -= level.view_x[level.player] * graphics.width; + graphics.offset_y -= level.view_y[level.player] * graphics.height; + + if(graphics.offset_x != ox || graphics.offset_y != oy) + return 1; + else + return 0; + } + + px = level.player_x[level.player] * graphics.width; + py = level.player_y[level.player] * graphics.height; + ox = graphics.offset_x; + oy = graphics.offset_y; + + display_border_x = graphics.width * 3; + display_border_y = graphics.height * 3; + + for(var i = 1; i < 4; i ++) + { + if(graphics.width * i < screen.width / 2) + display_border_x = graphics.width * i; + if(graphics.height * i < screen.height / 2) + display_border_y = graphics.height * i; + } + + maxx = (level.width * graphics.width - screen.width); + maxy = (level.height * graphics.height - screen.height); + + if((level.width - 1) * graphics.width < screen.width) + { + graphics.offset_x = (screen.width - (level.width * graphics.width)) / 2; + } + else + { + if(px < -(graphics.offset_x - display_border_x)) + graphics.offset_x = -(px - display_border_x); + if(px >= -(graphics.offset_x - screen.width + display_border_x + graphics.width)) + graphics.offset_x = -(px - screen.width + display_border_x + graphics.width); + + if(graphics.offset_x > 0) + graphics.offset_x = 0; + if(graphics.offset_x < -maxx) + graphics.offset_x = -maxx; + + } + + if((level.height - 1) * graphics.height < screen.height) + { + graphics.offset_y = (screen.height - (level.height * graphics.height)) / 2; + } + else + { + if(py < -(graphics.offset_y - display_border_y)) + graphics.offset_y = -(py - display_border_y); + if(py >= -(graphics.offset_y - screen.height + display_border_y + graphics.height)) + graphics.offset_y = -(py - screen.height + display_border_y + graphics.height); + + if(graphics.offset_y > 0) + graphics.offset_y = 0; + if(graphics.offset_y < -maxy) + graphics.offset_y = -maxy; + } + + graphics.offset_x = Math.floor(graphics.offset_x); + graphics.offset_y = Math.floor(graphics.offset_y); + + if(graphics.offset_x != ox || graphics.offset_y != oy) + return 1; + else + return 0; +} + +function display_map() +{ + graphics.map_colours = []; + + for(var x = 0; x < level.width; x ++) + { + for(var y = 0; y < level.height; y ++) + { + display_map_piece(x, y); + } + } +} + +function display_map_piece(x, y) +{ + var c = "#ffffff"; + var p = PIECE_SPACE; + + var ok = false; + + if(x < level.width / 2 && y < level.width / 2 && level.mapped & MAPPED_TOP_LEFT) + ok = true; + if(x >= level.width / 2 && y < level.width / 2 && level.mapped & MAPPED_TOP_RIGHT) + ok = true; + if(x < level.width / 2 && y >= level.width / 2 && level.mapped & MAPPED_BOTTOM_LEFT) + ok = true; + if(x >= level.width / 2 && y >= level.width / 2 && level.mapped & MAPPED_BOTTOM_RIGHT) + ok = true; + + if(ok) + { + p = level_piece(x, y); + + if(p != PIECE_WALL && p != PIECE_STAR && p != PIECE_DOOR) + p = PIECE_SPACE; + } + + if(graphics.map_colours[p] == null) + { + var context = graphics.image[p].getContext("2d"); + var r = 0; + var g = 0; + var b = 0; + var a = 1; + for(var i = 0; i < 24; i += 1) + { + for(var j = 0; j < 24; j += 1) + { + var px = (i + 0.5) * graphics.width / 24; + var py = (j + 0.5) * graphics.height / 24; + + if(graphics.image_flags[p] & GRAPHICS_LEVEL && level.level > 0) + px += (level.level - 1) * graphics.width; + var data = context.getImageData(Math.floor(px), Math.floor(py), 1, 1).data; + + r += data[0]; + g += data[1]; + b += data[2]; + a += data[3]; + } + } + colour = "#" + (Math.floor((r/a)*16).toString(16)) + (Math.floor((g/a)*16).toString(16)) + (Math.floor((b/a)*16).toString(16)); + graphics.map_colours[p] = colour; + } + + screen.map.context.fillStyle = graphics.map_colours[p]; + screen.map.context.fillRect(x * screen.map.pixel_width, y * screen.map.pixel_height, screen.map.pixel_width, screen.map.pixel_height); +} + +function main_menu() +{ + level = null; + level_replay = null; + + menu_new(""); + + var sets = levels.dom.getElementsByTagName("set"); + + + menu_section("Instructions"); + menu_new_entry("H", "How to Play", null, null, null, instructions_menu, null); + + menu_section("Chroma"); + + var other = false; + + for(var s = 0; s < sets.length; s ++) + { + if(sets[s].getAttribute("type") != "chroma" && other == false) + { + menu_section("Other Games"); + other = true; + } + + if(sets[s].getAttribute("hidden") == null || options.show_hidden) + menu_new_entry(sets[s].getAttribute("key"), sets[s].getAttribute("title"), null, null, sets[s].getAttribute("subtitle"), level_set_menu, s); + + } + + /* Are there saved positions? */ + var ok = false; + for(var i = 0; i < localStorage.length; i ++) + { + if(a = localStorage.key(i).match(/^save-(\w+)/)) + { + ok = true; + break; + } + } + + if(ok) + { + menu_section("Saved Positions"); + + menu_new_entry("S", "Saved Positions", null, null, null, saved_positions_menu, ""); + } + + menu_section("Preferences"); + + menu_new_entry("P", "Preferences", null, null, null, preferences_menu, null); + + menu_show(true); + +} + +function level_set_menu() +{ + var sets = levels.dom.getElementsByTagName("set"); + var set = sets[this.dataset.data]; + var ok; + + menu_new("Choose a Level"); + + menu_new_entry("Q", "Return to previous menu", null, null, null, main_menu, null); + menu_new_spacer(); + + var levs = set.getElementsByTagName("level"); + + for(var l = 0; l < levs.length; l ++) + { + ok = true; + if(levs[l].getAttribute("broken") != null) + { + ok = false; + if(levs[l].getAttribute("broken") == "yes" && !options.xor_fix) + ok = true; + if(levs[l].getAttribute("broken") == "no" && options.xor_fix) + ok = true; + } + if(ok) + menu_new_entry(levs[l].getAttribute("key"), levs[l].getAttribute("title"), null, null, null, play_level, levs[l].childNodes[0].nodeValue); + } + + menu_show(true); +} + +function play_level() +{ + level = level_from_string(this.dataset.data); + + revert = new Object; + revert.data = this.dataset.data; + revert.moves = level.moves.length; + + display_bevellevel(); + graphics_render(); +} + +function game_menu() +{ + menu_new("Game Options"); + + menu_new_entry("Q", "Return to Level", null, null, null, game_return, null); + menu_new_entry("A", "Abort Level and Return to Main Menu", null, null, null, main_menu, null); + menu_new_entry("V", "Revert to Original Position", level.moves.length == revert.moves ? "(only after changes)" : "", null, null, level.moves.length == revert.moves ? null : revert_level, null); + menu_new_spacer(); + menu_new_entry("L", "Load Position", null, null, null, load_position, null); + menu_new_entry("S", "Save Position", level.movers.length != 0 ? "(not while pieces in motion)" : options.storage ? "" : "(in Private Browsing mode, saved positions will be lost when the browser is closed - use Preferences / Export to save them to a file)", null, null, level.movers.length != 0 ? null : save_position, null); + menu_new_spacer(); + + if(level_replay == null) + menu_new_entry("R", "Replay Saved Position", level.moves.length != 0 ? "(only at start of level)" : "", null, null, level.moves.length != 0 ? null : load_replay_position, null); + else + menu_new_entry("T", "Stop Replaying Position", null, null, null, stop_replay, null); + + menu_new_spacer(); + menu_new_entry("P", "Preferences", null, null, null, preferences_menu, null); + + menu_show(true); +} + +function revert_level() +{ + level = level_from_string(revert.data); + display_bevellevel(); + + graphics_render(); +} + +function instructions_menu() +{ + menu_new("How to Play") + + menu_new_entry("Q", "Return to previous menu", null, null, null, quit_instructions_menu, null); + + document.getElementById("instructions").style.display = "block"; +} + +function quit_instructions_menu() +{ + document.getElementById("instructions").style.display = "none"; + main_menu(); +} + +function preferences_menu() +{ + menu_new("Preferences") + + if(level != null) + menu_new_entry("Q", "Return to Level", null, null, null, quit_preferences_menu, null); + else + menu_new_entry("Q", "Return to Main Menu", null, null, null, quit_preferences_menu, null); + + menu_new_spacer(); + + menu_new_select("K", "Show On-screen Keypad", "show_keypad", options.keypad, "no", "yes"); + + menu_section("Graphics Scheme"); + + var item = document.createElement("div"); + item.className = "item-options"; + item.id = "sets"; + + for(var s=0; s < graphics_sets.length; s ++) + { + var option = document.createElement("div"); + option.className = "option has-key four"; + + if(graphics_sets[s].set != "xor") + { + if(graphics_sets[s].set == options.graphics) + option.classList.add("selected"); + } + else + { + if(options.graphics_xor) + option.classList.add("selected"); + option.classList.add("other"); + option.id = "xor"; + } + item.appendChild(option); + + var div = document.createElement("div"); + div.className = "key"; + div.textContent = graphics_sets[s].key; + option.appendChild(div); + + var t = document.createTextNode(graphics_sets[s].title); + option.appendChild(t); + + var div = document.createElement("img"); + div.src = graphics_sets[s].preview; + option.appendChild(div); + + if(graphics_sets[s].set == "xor") + { + var t = document.createTextNode("for XOR levels"); + option.appendChild(t); + } + + option.dataset.data = graphics_sets[s].set; + option.dataset.key = graphics_sets[s].key; + option.onclick = set_graphics_set; + + } + + document.getElementById("items").appendChild(item); + + menu_section("Graphics Size"); + + var item = document.createElement("div"); + item.className = "item-options"; + item.id = "sizes"; + + for(var s=0; s < graphics_sizes.length; s ++) + { + var option = document.createElement("div"); + option.className = "option has-key three"; + if(graphics_sizes[s].size == options.graphics_size) + option.classList.add("selected"); + item.appendChild(option); + + var div = document.createElement("div"); + div.className = "key"; + div.textContent = graphics_sizes[s].key; + option.appendChild(div); + + var t = document.createTextNode(graphics_sizes[s].title); + option.appendChild(t); + + + if(graphics_sizes[s].size == -1) + { + t = document.createElement("input"); + t.type = "number"; + t.value = options.graphics_custom_size; + t.id = "custom-number"; + option.appendChild(t); + option.id = "custom"; + + option.onclick = custom_graphics_size; + } + else + option.onclick = set_graphics_size; + + option.dataset.data = graphics_sizes[s].size; + option.dataset.key = graphics_sizes[s].key; + } + + document.getElementById("items").appendChild(item); + + menu_section("Speeds"); + + menu_slider("P", "Player Speed", "player", options.player_delay); + menu_slider("V", "Move Speed", "move", options.move_delay); + menu_slider("U", "Undo Speed", "undo", options.undo_delay); + menu_slider("R", "Replay Speed", "replay", options.replay_delay); + + if(options.others) + { + menu_section("Other Game Options"); + + menu_new_select("L", "XOR Display", "xor_display", options.xor_display, "full", "partial"); + menu_new_select("O", "XOR Engine", "xor_engine", options.xor_engine, "approximate", "exact"); + menu_new_select("B", "XOR Procyon Levels", "xor_fix", options.xor_fix, "broken", "fixed"); + + menu_new_spacer(); + + menu_new_select("E", "Enigma Engine", "enigma_engine", options.enigma_engine, "approximate", "exact"); + } + + menu_section("Save and Restore"); + + menu_new_entry("S", "Save Preferences", null, options.storage ? "" : "(in Private Browsing mode, preferences will be lost when the browser is closed - use Export to save them to a file)", null, save_preferences, null); + + menu_new_entry("I", "Import and Export Preferences and Saved Positions", null, null, null, import_export_menu, null); + + menu_new_entry("D", "Restore Defaults", null, null, null, restore_default_preferences, null); + + menu_show(true); +} + +function menu_section(title) +{ + var heading = document.createElement("h2"); + heading.textContent = title; + document.getElementById("items").appendChild(heading); +} + +function menu_slider(key, title, prefix, value) +{ + var item = document.createElement("div"); + item.className = "item has-key"; + + var div = document.createElement("div"); + div.className = "key"; + div.textContent = key; + item.appendChild(div); + item.dataset.key = key; + item.onclick = clicked_slider; + + var inner = document.createElement("div"); + inner.className = "item-slider"; + + var t = document.createElement("div"); + t.className = "title"; + t.textContent = title; + inner.appendChild(t); + + var slider = document.createElement("input"); + slider.type = "range"; + slider.className = "slider"; + slider.id = prefix+"-slider"; + slider.min = 0; + slider.max = 140; + slider.value = number_to_slider(value); + slider.onchange = slider_change; + slider.oninput = slider_change; + inner.appendChild(slider); + + var number = document.createElement("input"); + number.type= "number"; + number.className = "number"; + number.id = prefix+"-number"; + number.min = 0; + number.max = 10000; + number.value = value; + number.onchange = number_change; + inner.appendChild(number); + + var div = document.createElement("div"); + div.className = "clear"; + inner.appendChild(div); + + item.appendChild(inner); + + document.getElementById("items").appendChild(item); +} + +function clicked_slider() +{ + this.getElementsByTagName("input")[0].focus(); +} + +function slider_change() +{ + id = this.id; + id = id.replace("slider", "number"); + + document.getElementById(id).value = slider_to_number(this.value); +} + +function slider_to_number(s) +{ + var p = s % 35; + var t = Math.floor(s/35); + + return slider_positions[p] * Math.pow(10, t); +} + +function number_to_slider(n) +{ + var t = 0; + var p = 0; + + while(n >= 10) + { + n = n /10; + t ++; + } + + for(var i = 0; i < 35; i ++) + { + if(n >= slider_positions[i]) + p = i; + } + + return t * 35 + p; +} + +function number_change() +{ + id = this.id; + id = id.replace("number", "slider"); + + document.getElementById(id).value = number_to_slider(this.value); +} + +function menu_new_select(key, title, prefix, value, no, yes) +{ + var item = document.createElement("div"); + item.className = "item has-key"; + + var div = document.createElement("div"); + div.className = "key"; + div.textContent = key; + item.appendChild(div); + item.dataset.key = key; + item.onclick = clicked_select; + + var inner = document.createElement("div"); + inner.className = "item-text"; + + var t = document.createTextNode(title); + inner.appendChild(t); + + var select = document.createElement("select"); + select.id = prefix; + var option = document.createElement("option"); + option.textContent = no; + option.value = 0; + option.selected = (value == false); + select.appendChild(option); + + var option = document.createElement("option"); + option.textContent = yes; + option.value = 1; + option.selected = (value == true); + select.appendChild(option); + + inner.appendChild(select); + + item.appendChild(inner); + + document.getElementById("items").appendChild(item); +} + +function clicked_select() +{ + this.getElementsByTagName("select")[0].focus(); +} + +function set_graphics_set() +{ + if(this.dataset.data != "xor") + options.graphics = this.dataset.data; + else + options.graphics_xor = !options.graphics_xor; + + var opts = document.getElementById("sets").getElementsByClassName("option"); + for(o = 0; o < opts.length; o ++) + { + if(opts[o].dataset.data == options.graphics) + opts[o].classList.add("selected"); + else + opts[o].classList.remove("selected"); + } + + var x = document.getElementById("xor"); + if(options.graphics_xor) + x.classList.add("selected"); + else + x.classList.remove("selected"); +} + +function set_graphics_size() +{ + options.graphics_size = parseInt(this.dataset.data); + + var opts = document.getElementById("sizes").getElementsByClassName("option"); + for(o = 0; o < opts.length; o ++) + { + if(opts[o].dataset.data == options.graphics_size) + opts[o].classList.add("selected"); + else + opts[o].classList.remove("selected"); + } +} + +function custom_graphics_size() +{ + var opts = document.getElementById("sizes").getElementsByClassName("selected"); + for(o = 0; o < opts.length; o ++) + opts[o].classList.remove("selected"); + + document.getElementById("custom").classList.add("selected"); + document.getElementById("custom-number").focus(); + + options.graphics_size = -1; +} + +function quit_preferences_menu() +{ + gather_preferences(); + + if(level != null) + game_return(); + else + main_menu(); +} + +function gather_preferences() +{ + options.player_delay = parseFloat(document.getElementById("player-number").value); + options.move_delay = parseFloat(document.getElementById("move-number").value); + options.undo_delay = parseFloat(document.getElementById("undo-number").value); + options.replay_delay = parseFloat(document.getElementById("replay-number").value); + + if(options.others) + { + if(document.getElementById("xor_fix").value == "1") + options.xor_fix = true; + else + options.xor_fix = false; + + if(document.getElementById("xor_display").value == "1") + options.xor_display = true; + else + options.xor_display = false; + + if(document.getElementById("xor_engine").value == "1") + options.xor_engine = true; + else + options.xor_engine = false; + + if(document.getElementById("enigma_engine").value == "1") + options.enigma_engine = true; + else + options.enigma_engine = false; + } + + if(document.getElementById("show_keypad").value == "1") + options.keypad = true; + else + options.keypad = false; + + toggle_keypad(options.keypad); + + var size = parseInt(document.getElementById("custom-number").value); + if(size > 0 && size <= 512) + options.graphics_custom_size = size; +} + +function save_preferences() +{ + gather_preferences(); + push_preferences(); + + if(level != null) + game_return(); + else + main_menu(); +} + +function push_preferences() +{ + try + { + localStorage.setItem("options.player_delay", options.player_delay); + localStorage.setItem("options.undo_delay", options.undo_delay); + localStorage.setItem("options.move_delay", options.move_delay); + localStorage.setItem("options.replay_delay", options.replay_delay); + localStorage.setItem("options.graphics", options.graphics); + localStorage.setItem("options.graphics_size", options.graphics_size); + localStorage.setItem("options.graphics_custom_size", options.graphics_custom_size); + localStorage.setItem("options.graphics_xor", options.graphics_xor); + localStorage.setItem("options.xor_fix", options.xor_fix); + localStorage.setItem("options.xor_display", options.xor_display); + localStorage.setItem("options.xor_engine", options.xor_engine); + localStorage.setItem("options.enigma_engine", options.enigma_engine); + localStorage.setItem("options.keypad", options.keypad); + } + catch(e) + { + alert("Unable to save preferences: "+e.message); + } +} + +function default_preferences() +{ + options.player_delay = 100; + options.undo_delay = 100; + options.move_delay = 100; + options.replay_delay = 100; + options.graphics = "zen"; + options.graphics_size = 0; + if(window.innerWidth < 768) + options.graphics_size = 24; + options.graphics_custom_size = 192; + options.graphics_xor = true; + options.xor_fix = true; + options.xor_display = true; + options.xor_engine = true; + options.enigma_engine = true; + options.keypad = false; +} + +function load_preferences() +{ + try + { + if(localStorage.getItem("options.player_delay") != null) + options.player_delay = parseInt(localStorage.getItem("options.player_delay")); + if(localStorage.getItem("options.undo_delay") != null) + options.undo_delay = parseInt(localStorage.getItem("options.undo_delay")); + if(localStorage.getItem("options.move_delay") != null) + options.move_delay = parseInt(localStorage.getItem("options.move_delay")); + if(localStorage.getItem("options.replay_delay") != null) + options.replay_delay = parseInt(localStorage.getItem("options.replay_delay")); + + if(localStorage.getItem("options.graphics") != null) + { + if(localStorage.getItem("options.graphics") == "zen" || + localStorage.getItem("options.graphics") == "marble" || + localStorage.getItem("options.graphics") == "neon" || + localStorage.getItem("options.graphics") == "xor") + options.graphics = localStorage.getItem("options.graphics"); + } + + if(localStorage.getItem("options.graphics_size") != null) + options.graphics_size = parseInt(localStorage.getItem("options.graphics_size")); + if(localStorage.getItem("options.graphics_custom_size") != null) + options.graphics_custom_size = parseInt(localStorage.getItem("options.graphics_custom_size")); + + if(localStorage.getItem("options.graphics_xor") == "false") + options.graphics_xor = false; + if(localStorage.getItem("options.graphics_xor") == "true") + options.graphics_xor = true; + + if(localStorage.getItem("options.xor_fix") == "false") + options.xor_fix = false; + if(localStorage.getItem("options.xor_fix") == "true") + options.xor_fix = true; + + if(localStorage.getItem("options.xor_display") == "false") + options.xor_display = false; + if(localStorage.getItem("options.xor_display") == "true") + options.xor_display = true; + + if(localStorage.getItem("options.xor_engine") == "false") + options.xor_engine = false; + if(localStorage.getItem("options.xor_engine") == "true") + options.xor_engine = true; + + if(localStorage.getItem("options.enigma_engine") == "false") + options.enigma_engine = false; + if(localStorage.getItem("options.enigma_engine") == "true") + options.enigma_engine = true; + + if(localStorage.getItem("options.keypad") == "false") + options.keypad = false; + if(localStorage.getItem("options.keypad") == "true") + options.keypad = true; + } + catch(e) + { + alert("Unable to load preferences: "+e.message); + } +} + +function restore_default_preferences() +{ + default_preferences(); + toggle_keypad(options.keypad); + preferences_menu(); +} + +function game_return() +{ + graphics_render(); +} + +function menu_keydown(e) +{ + var key = e.key; + + if(key == "Escape") + key = "Q"; + + key = key.toUpperCase(); + + if(document.activeElement.tagName == "INPUT" && key >= "0" && key <= "9") + { + return true; + } + + if(e.ctrlKey) + return true; + + var items = document.getElementsByClassName("has-key"); + for(i = 0; i < items.length; i ++) + { + if(items[i].dataset.key == key) + { + items[i].click(); + return false; + } + } +} + +function menu_show(show) +{ + document.onkeydown = null; + document.onkeyup = null; + document.onmousedown = null; + document.onmouseup = null; + document.ontouchstart = null; + document.ontouchend = null; + document.onclick = null; + + menu.becoming = show; + + if(show != menu.state) + { + if(show) + { + document.getElementById("menu-icon").style.display = "none"; + document.getElementById("menu-icon").style.opacity = 0; + + + document.getElementById("menu").style.display = "block"; + + + setTimeout(function() { menu_shown(true); }, 100); + } + else + { + document.getElementById("screen").style.display = "block"; + document.getElementById("bar").style.display = "block"; + if(level != null && level.mode == MODE_XOR && options.xor_display) + document.getElementById("map").style.display = "block"; + + + document.getElementById("keypad").style.display = "block"; + + document.getElementById("menu-icon").onclick = game_menu; + + document.getElementById("menu").style.position = "fixed"; + + document.getElementById("menu").style.right = "-100%"; + document.getElementById("menu").style.top= "-100%"; + + setTimeout(function() { menu_shown(false); }, 1000); + } + } + else + menu_shown(show); +} + +function menu_shown(show) +{ + + if(menu.state != show) + { + if(show) + { + setTimeout(menu_make_absolute, 1000); + document.getElementById("menu").style.right = "0"; + document.getElementById("menu").style.top= "0"; + } + else + { + document.getElementById("menu").style.display = "none"; + document.getElementById("menu-icon").style.display = "block"; + document.getElementById("menu-icon").style.opacity = 0; + + setTimeout(function() { document.getElementById("menu-icon").style.opacity = 1; }, 50); + } + } + + if(show) + { + document.onkeydown = menu_keydown; + document.onkeyup = null; + document.onmousedown = null; + document.onmouseup = null; + document.ontouchstart = null; + document.ontouchend = null; + document.onclick = null; + } + else + { + document.onkeydown = game_keydown; + document.onkeyup = game_keyup; + document.onmousedown = function(e) { return game_mousedown(e, false) }; + document.onmouseup = function(e) { return game_mouseup(e, false) }; + document.ontouchstart = function(e) { if(e.changedTouches.length > 0) return game_mousedown(e.changedTouches[0], true); }; + document.ontouchend = function(e) { if(e.changedTouches.length > 0) return game_mouseup(e.changedTouches[0], true); }; + document.onclick = game_click; + } + + menu.state = show; +} + + +function menu_make_absolute() +{ + if(menu.becoming == true) + { + document.getElementById("screen").style.display = "none"; + document.getElementById("bar").style.display = "none"; + document.getElementById("map").style.display = "none"; + document.getElementById("keypad").style.display = "none"; + document.getElementById("menu").style.position = "absolute"; + } +} + +function menu_new(title) +{ + menu.keys = []; + menu.key = 1; + document.getElementById("items").innerHTML = ""; + + if(title != "") + { + var heading = document.createElement("h1"); + heading.textContent = title; + document.getElementById("items").appendChild(heading); + document.getElementById("logo").classList.remove("big"); + } + else + document.getElementById("logo").classList.add("big"); + + window.scrollTo(0, 0); +} + +function menu_new_entry(key, text1, text2, text3, text4, onclick, data) +{ + var item = document.createElement("div"); + if(onclick != null) + item.className = "item has-key"; + else + item.className = "item grey"; + + if(key != null) + item.dataset.key = key.toUpperCase(); + else + { + key = menu.key.toString(36); + key = key.toUpperCase(); + menu.key ++; + + item.dataset.key = key; + } + + menu.keys[item.dataset.key] = true; + + var div = document.createElement("div"); + div.className = "key"; + div.textContent = key; + item.appendChild(div); + + var div = document.createElement("div"); + div.className = "item-text"; + item.appendChild(div); + + if(text1 != null) + { + var tdiv = document.createElement("div"); + tdiv.id = "text1"; + tdiv.className = "item-left"; + tdiv.textContent = text1; + div.appendChild(tdiv); + } + + if(text2 != null) + { + var tdiv = document.createElement("div"); + tdiv.id = "text2"; + tdiv.className = "item-right"; + tdiv.textContent = text2; + div.appendChild(tdiv); + } + + if(text1 != null || text2 != null) + { + var tdiv = document.createElement("div"); + tdiv.className = "clear"; + div.appendChild(tdiv); + } + + if(text3 != null) + { + var tdiv = document.createElement("div"); + tdiv.id = "text3"; + tdiv.className = "item-left"; + tdiv.textContent = text3; + div.appendChild(tdiv); + } + + if(text4 != null) + { + var tdiv = document.createElement("div"); + tdiv.id = "text4"; + tdiv.className = "item-right"; + tdiv.textContent = text4; + div.appendChild(tdiv); + } + + if(text3 != null || text4 != null) + { + var tdiv = document.createElement("div"); + tdiv.className = "clear"; + div.appendChild(tdiv); + } + + if(data != null) + item.dataset.data = data; + + if(onclick != null) + item.onclick = onclick; + + document.getElementById("items").appendChild(item); + + return item; +} + +function menu_new_spacer() +{ + var item = document.createElement("div"); + item.className = "spacer"; + + document.getElementById("items").appendChild(item); +} + +function save_position() +{ + var str = level_to_string(level); + var time = Date.now().toString(16); + + var summary; + + if(level.flags & LEVELFLAG_FAILED) + summary = "failed"; + else if(level.flags & LEVELFLAG_SOLVED) + summary = "solved"; + else + summary = level.stars_caught+"/"+level.stars_exploded+"/"+level.stars_total; + + summary += " "+level.moves.length+" "+level.title; + + try + { + localStorage.setItem("save-"+time, summary); + localStorage.setItem("data-"+time, str); + } + catch(e) + { + alert("Unable to save position: "+e.message); + return; + } + + if(localStorage.getItem("save-"+time) != summary || localStorage.getItem("data-"+time, str) != str) + { + alert("Unable to save position."); + return; + } + + revert = new Object; + revert.data = this.dataset.data; + revert.moves = level.moves.length; + + game_return(); +} + + +function load_position() +{ + saved_positions(level.title, "", false, false); +} + +function load_replay_position() +{ + saved_positions(level.title, "", false, true); +} + +function saved_positions_menu() +{ + saved_positions("", this.dataset.data, false, false); +} + +function saved_positions(limit, oldlimit, deleting, replay) +{ + var a; + var positions = []; + var limited = 0; + + if(replay) + menu_new("Replay Saved Position"); + else if(deleting) + menu_new("Delete Saved Positions"); + else + menu_new("Load Position"); + + var return_function = main_menu; + if(limit != "") + return_function = game_menu; + if(oldlimit != "") + return_function = load_position; + + menu_new_entry("Q", "Return to previous menu", null, null, null, return_function, null); + if(deleting == false && replay == false) + menu_new_entry("Delete", "Delete positions", null, null, null, delete_positions, limit); + menu_new_spacer(); + + for(var i = 0; i < localStorage.length; i ++) + { + if(a = localStorage.key(i).match(/^save-(\w+)/)) + positions.push(a[1]); + } + + positions.sort(function(a, b) { return b > a; }); + + var action; + if(replay) + action = load_replay; + else if(deleting) + action = delete_position; + else + action = play_level; + + for(var i = 0; i < positions.length; i ++) + { + var s = localStorage.getItem("save-"+positions[i]); + var stars = ""; + var moves = ""; + var title = ""; + var date = ""; + + if(a = s.match(/^(\S+) (\S+) (.*)/)) + { + stars = a[1]; + moves = a[2] + " move" + (a[2] == 1 ? "" : "s"); + title = a[3]; + + if(a = stars.match(/^(\d+)\/(\d+)\/(\d+)/)) + { + if(a[2] != 0) + stars = a[2] + " lost"; + else + stars = a[1] + "/" + a[3]; + } + + d = new Date(parseInt(positions[i], 16)); + date = d.toString(); + + date = days[d.getDay()]+" "+months[d.getMonth()]+" "+d.getDate()+" "+d.getHours()+":"+two(d.getMinutes())+":"+two(d.getSeconds())+" "+d.getFullYear(); + + if(limit == "" || title == limit) + menu_new_entry(null, title, stars, date, moves, action, deleting ? positions[i] : localStorage.getItem("data-"+positions[i])); + else + limited ++; + } + + } + + if(limited != 0 && deleting == false && replay == false) + { + menu_new_spacer(); + menu_new_entry("+", "Show positions for other levels", "("+limited+" other"+(limited == 1 ? "" : "s")+")", null, null, saved_positions_menu, title); + } + + menu_show(true); +} + +function delete_positions() +{ + saved_positions(this.dataset.data, level != null ? level.title : "", true, false); +} + +function delete_position() +{ + var p = this.dataset.data; + + var i = document.querySelectorAll("[data-data=\""+p+"\"]"); + if(i.length > 0) + i[0].parentElement.removeChild(i[0]); + + localStorage.removeItem("save-"+p); + localStorage.removeItem("data-"+p); +} + +function load_replay() +{ + level_replay = level_from_string(this.dataset.data); + consider_replay_move(); + display_moves(); + game_return(); +} + +function stop_replay() +{ + level_replay = null; + display_moves(); + game_return(); +} + +function consider_replay_move() +{ + var move; + + display_moves(); + + if(level.movers.length == 0 && !(level.flags & LEVELFLAG_UNDO)) + { + if(!(level_replay.flags & LEVELFLAG_PAUSED)) + { + if(level_replay.flags & LEVELFLAG_UNDO) + { + if(level_undo()) + { + level.flags |= LEVELFLAG_UNDO; + display_start_update(); + } + else + level.flags &= ~LEVELFLAG_UNDO; + } + else + { + move = level_replay.moves[level.moves.length].direction; + level_move(move); + } + } + } +} + +function import_export_menu(really) +{ + if(really != true) + gather_preferences(); + + menu_new("Import and Export Preferences and Saved Positions"); + + menu_new_entry("Q", "Return to previous menu", null, null, null, preferences_menu, null); + + menu_new_spacer(); + + menu_new_entry("E", "Export Preferences and Saved Positions to file", null, null, null, really == true ? null : export_data, null); + + var item = menu_new_entry("I", "Import Preferences and Saved Positions from file", null, null, null, really == true ? null : import_click, null); + + if(really != true) + { + var upload = document.createElement("input"); + upload.type= "file"; + div = item.getElementsByTagName("div")[3]; + div.appendChild(upload); + div.style.display = "none"; + upload.addEventListener("change", import_data); + } + + menu_new_spacer(); + + if(really == true) + menu_new_entry("Y", "Really Delete Preferences and Saved Positions", null, "(cannot be undone)", null, clear_data, null); + else + menu_new_entry("D", "Delete Preferences and Saved Positions", null, null, null, confirm_clear_data, null); + + menu_show(true); +} + +function confirm_clear_data() +{ + import_export_menu(true); +} + +function clear_data() +{ + localStorage.clear(); + alert("Preferences and Saved Positions deleted"); + + main_menu(); +} + +function export_data() +{ + push_preferences(); + + var l = {}; + for(var i = 0; i < localStorage.length; i ++) + { + l[localStorage.key(i)] = localStorage.getItem(localStorage.key(i)); + } + + var data = JSON.stringify(l); + var filename = "chroma.json"; + + var blob = new Blob([data], {type: "application/octet-stream;"}); + if(window.navigator.msSaveOrOpenBlob) + { + window.navigator.msSaveBlob(blob, filename); + } + else + { + var e = window.document.createElement("a"); + e.href = window.URL.createObjectURL(blob); + e.download = filename; + document.body.appendChild(e); + e.click(); + document.body.removeChild(e); + } +} + +function import_click() +{ + this.getElementsByTagName("input")[0].click(); +} + +function import_data() +{ + if(this.files.length == 1) + { + var reader = new FileReader(); + reader.onload = import_data_stage_two; + reader.readAsText(this.files[0]); + } +} + +function import_data_stage_two() +{ + localStorage.clear(); + + var positions = 0; + + try + { + var l = JSON.parse(this.result); + for(var i in l) + { + if(l.hasOwnProperty(i)) + { + localStorage.setItem(i, l[i]); + if(i.substr(0,5) == "save-") + positions ++; + } + } + } + catch(e) + { + alert("Unable to import data: " + e.message); + return; + } + + alert("Preferences and "+positions+" saved position"+(positions == 1 ? "" : "s")+" successfully imported"); + + options.storage = true; + + load_preferences(); + preferences_menu(); +} + +function game_keydown(e) +{ + var move = MOVE_NONE; + + if(e.key == "Shift") + graphics.shift = true; + if(e.key == "Control") + graphics.ctrl = true; + + if(e.key == "Escape" || e.key == "Q" || e.key == "q") + { + game_menu(); + return; + } + else if(e.key == "Tab") + { + display_level(); + } + else if(e.key == "ArrowUp" || e.keyCode == 104) + move = MOVE_UP; + else if(e.key == "ArrowDown" || e.keyCode == 98) + move = MOVE_DOWN; + else if(e.key == "ArrowLeft" || e.keyCode == 100) + move = MOVE_LEFT; + else if(e.key == "ArrowRight" || e.keyCode == 102) + move = MOVE_RIGHT; + else if(e.key == " " || e.key == "Enter" || e.key == "Return") + move = MOVE_SWAP; + else if(e.key == "Delete" || e.keyCode == 109) + move = MOVE_UNDO; + else if (e.key == "Insert" || e.keyCode == 107) + move = MOVE_REDO; + else + return true; + + if(move != MOVE_NONE) + make_move(move); + + return false; +} + +function game_keyup(e) +{ + if(e.key == "Shift") + graphics.shift = false; + if(e.key == "Control") + graphics.ctrl = false; +} + +function game_mouseup(e, touch) +{ + if(e.target != null) + { + if(e.target.classList.contains("key") || e.target.id == "bar") + { + mouse_move = MOVE_NONE; + } + } + + if(!keypad.classList.contains("transition")) + keypad.classList.add("transition"); + + if(touch) + document.ontouchmove = null; + else + document.onmousemove = null; +} + +function game_mousedown(e, touch) +{ + if(mouse_recent_event) + return false; + + mouse_recent_event = true; + setTimeout(function() { mouse_recent_event = false; }, 500); + + if(e.target != null) + { + if(e.target.classList.contains("key")) + { + if(e.target.id == "up") + mouse_move = MOVE_UP; + else if(e.target.id == "down") + mouse_move = MOVE_DOWN; + else if(e.target.id == "left") + mouse_move = MOVE_LEFT; + else if(e.target.id == "right") + mouse_move = MOVE_RIGHT; + else if(e.target.id == "swap") + mouse_move = MOVE_SWAP; + else if(e.target.id == "undo") + mouse_move = MOVE_UNDO; + else if(e.target.id == "redo") + mouse_move = MOVE_REDO; + + if(mouse_move != MOVE_NONE); + consider_mouse_move(); + + return false; + } + else if(e.target.id == "drag") + { + var keypad = document.getElementById("keypad"); + keypad.dataset.startX = e.clientX - keypad.offsetLeft; + keypad.dataset.startY = e.clientY - keypad.offsetTop; + keypad.classList.remove("transition"); + + if(touch) + document.ontouchmove = function(e) { if(e.changedTouches.length > 0) return drag_keypad(e.changedTouches[0], true) }; + else + document.onmousemove = function(e) { return drag_keypad(e, false) }; + + return false; + } + else if(e.target.id == "toggle") + { + options.keypad = !options.keypad; + toggle_keypad(options.keypad); + + return false; + } + else if(e.target.id == "screen") + { + var scr = document.getElementById("screen"); + scr.dataset.startX = e.clientX - graphics.offset_x; + scr.dataset.startY = e.clientY - graphics.offset_y; + + if(touch) + document.ontouchmove = function(e) { if(e.changedTouches.length > 0) return drag_screen(e.changedTouches[0], true) }; + else + document.onmousemove = function(e) { return drag_screen(e, false) }; + + return false; + } + else if(e.target.id == "bar") + { + if((screen.bar.lines == 1 && e.clientX > screen.bar.width - graphics.small_width - screen.bar.move_width) || + (screen.bar.lines != 1 && e.clientY > screen.height - screen.bar.height)) + { + mouse_move = MOVE_UNDO; + consider_mouse_move(); + } + } + } +} + +function game_click(e) +{ + var x = Math.floor((e.clientX - graphics.offset_x - screen.offset_x) / graphics.width); + var y = Math.floor((e.clientY - graphics.offset_y - screen.offset_y) / graphics.height); + + if(!mouse_recent_event) + return; + + if(level.alive[1 - level.player] && x == level.player_x[1 - level.player] && y == level.player_y[1 - level.player]) + { + mouse_move = MOVE_SWAP; + mouse_target = true; + consider_mouse_move(); + return false; + } + if(level.alive[level.player]) + { + if(x == level.player_x[level.player] && y != level.player_y[level.player]) + { + mouse_target = true; + mouse_target_x = x; + mouse_target_y = y; + + if(y < level.player_y[level.player]) + mouse_move = MOVE_UP; + else + mouse_move = MOVE_DOWN; + + consider_mouse_move(); + return false; + } + if(x != level.player_x[level.player] && y == level.player_y[level.player]) + { + mouse_target = true; + mouse_target_x = x; + mouse_target_y = y; + + if(x < level.player_x[level.player]) + mouse_move = MOVE_LEFT; + else + mouse_move = MOVE_RIGHT; + + consider_mouse_move(); + return false; + } + } +} + +function toggle_keypad(state) +{ + var keypad = document.getElementById("keypad"); + + if(state) + { + keypad.style.top = keypad.dataset.top; + keypad.style.left = keypad.dataset.left; + keypad.classList.remove("minimised"); + document.getElementById("toggle").innerHTML = "◤"; + } + else + { + keypad.dataset.top = keypad.style.top; + keypad.dataset.left = keypad.style.left; + keypad.classList.add("minimised"); + keypad.style.top = null; + keypad.style.left = null; + document.getElementById("toggle").innerHTML = "◢"; + } +} + +function consider_mouse_move() +{ + if(mouse_move != MOVE_NONE) + { + var move = make_move(mouse_move); + if(mouse_target) + { + if(mouse_move == MOVE_SWAP) + mouse_target = false; + else + { + mouse_target = move; + if(level.player_x[level.player] == mouse_target_x && level.player_y[level.player] == mouse_target_y) + mouse_target = false; + } + if(mouse_target == false) + mouse_move = MOVE_NONE; + } + } +} + +function make_move(move) +{ + if(level_replay != null) + { + if(move == MOVE_UP || move == MOVE_DOWN || move == MOVE_SWAP) + { + level_replay.flags |= LEVELFLAG_PAUSED; + } + else if(move == MOVE_LEFT || move == MOVE_UNDO) + { + level_replay.flags |= LEVELFLAG_UNDO; + level_replay.flags &= ~LEVELFLAG_PAUSED; + } + else if(move == MOVE_RIGHT || move == MOVE_REDO) + { + level_replay.flags &= ~LEVELFLAG_UNDO; + level_replay.flags &= ~LEVELFLAG_PAUSED; + } + + consider_replay_move(); + return; + } + + if(level.movers.length != 0 || level.flags & LEVELFLAG_UNDO) + return; + + if(move == MOVE_UNDO) + { + if(level_undo()) + { + level.flags |= LEVELFLAG_UNDO; + display_start_update(); + } + else + level.flags &= ~LEVELFLAG_UNDO; + } + else if(move == MOVE_REDO) + { + if(level.redoable_moves.length != 0) + level_move(MOVE_REDO) + } + else if(move != MOVE_NONE) + { + return level_move(move); + } +} + +function drag_keypad(e) +{ + var keypad = document.getElementById("keypad"); + + keypad.style.left = (e.clientX - keypad.dataset.startX) + "px"; + keypad.style.top = (e.clientY - keypad.dataset.startY) + "px"; + + return false; +} + +function drag_screen(e) +{ + var scr = document.getElementById("screen"); + + var ox = graphics.offset_x; + var oy = graphics.offset_y; + + if(level == null) + return; + + if(level.mode == MODE_XOR && options.xor_display) + return; + + if((level.width - 1) * graphics.width > screen.width) + { + graphics.offset_x = (e.clientX - scr.dataset.startX); + if(graphics.offset_x > 0) + graphics.offset_x = 0; + if(graphics.offset_x < -graphics.width * level.width + screen.width) + graphics.offset_x = -graphics.width * level.width + screen.width; + } + if((level.height - 1) * graphics.height > screen.height) + { + graphics.offset_y = (e.clientY - scr.dataset.startY); + if(graphics.offset_y > 0) + graphics.offset_y = 0; + if(graphics.offset_y < -graphics.height * level.height + screen.height) + graphics.offset_y = -graphics.height * level.height + screen.height; + } + + if(graphics.offset_x != ox || graphics.offset_y != oy) + display_level(); + + return false; + +} + +function enigma_move(move) +{ + var px, py; + var dx, dy; + var p; + var into; + + if(!level.alive[level.player]) + return false; + if(move == MOVE_SWAP) + return false; + + px = level.player_x[level.player]; + py = level.player_y[level.player]; + + dx = px + move_x[move]; + dy = py + move_y[move]; + + /* Can we make the move? */ + p = level_piece(dx, dy); + switch(p) + { + /* Pieces that can be collected */ + case PIECE_SPACE: + case PIECE_DOTS: + case PIECE_DOTS_DOUBLE: + break; + case PIECE_STAR: + level.stars_caught ++; + level.flags |= LEVELFLAG_STARS; + break; + case PIECE_DOOR: + if(level.stars_caught == level.stars_total) + level.flags |= LEVELFLAG_EXIT; + else + return false; + break; + /* Pieces that can be pushed */ + case PIECE_ARROW_RED_LEFT: + case PIECE_ARROW_RED_RIGHT: + case PIECE_ARROW_RED_UP: + case PIECE_ARROW_RED_DOWN: + case PIECE_BOMB_RED_LEFT: + case PIECE_BOMB_RED_RIGHT: + case PIECE_BOMB_RED_UP: + case PIECE_BOMB_RED_DOWN: + /* Can't push against gravity */ + if(((level_piece(dx, dy) + 2) % 4) == move) + return false; + /* fallthrough */ + case PIECE_CIRCLE: + case PIECE_CIRCLE_DOUBLE: + /* Can't push into other pieces */ + into = level_piece(dx + move_x[move], dy + move_y[move]); + if(into != PIECE_SPACE && into != PIECE_DOTS) + return false; + mover_new(dx + move_x[move], dy + move_y[move], move, p, 0); + break; + + /* Can't move */ + default: + return false; + } + + mover_new(dx, dy, move, PIECE_PLAYER_ONE + level.player, 0); + mover_new(px, py, move, PIECE_SPACE, 0); + level_setmoving(px, py, MOVE_NONE); + level.player_x[level.player] = dx; + level.player_y[level.player] = dy; + mover_addtostack(px, py, move); + + return true; + +} + +function enigma_evolve() +{ + var into; + + var d; + var i, p, ep; + + var px, py; + var dx, dy; + + var ok; + + ok = false; + while(!ok) + { + /* Examine the stack, and generate movers from it */ + for(m = 0; m < level.stack.length; m ++) + { + mover = level.stack[m]; + /* Can anything fall into this space? */ + for(i = 0; i < 4; i ++) + { + d = enigma_move_order[i]; + px = mover.x - move_x[d]; + py = mover.y - move_y[d]; + p = level_piece(px, py); + if(p >= PIECE_ARROW_RED_LEFT && p <= PIECE_BOMB_RED_DOWN && (p % 4 == d)) + { + if(level_moving(px, py) == MOVE_NONE) + { + mover_new(px, py, d, p, 1); + i = 4; + } + } + } + } + level.stack = []; + + level.oldmovers = level.movers; + level.movers = []; + + /* Examine the movers, adding new movers to a separate list */ + for(m = 0 ; m < level.oldmovers.length; m ++) + { + mover = level.oldmovers[m]; + + level_setmoving(mover.x, mover.y, MOVE_NONE); + level_setprevious(mover.x, mover.y, PIECE_SPACE); + level_setpreviousmoving(mover.x, mover.y, MOVE_NONE); + level_setdetonator(mover.x, mover.y, PIECE_SPACE); + level_setdetonatormoving(mover.x, mover.y, MOVE_NONE); + + p = mover.piece; + if(p == PIECE_EXPLOSION_RED_HORIZONTAL || p == PIECE_EXPLOSION_RED_VERTICAL) + { + mover_new(mover.x, mover.y, MOVE_NONE, PIECE_SPACE, 0); + mover_addtostack(mover.x, mover.y, MOVE_NONE); + if(p == PIECE_EXPLOSION_RED_HORIZONTAL) + { + if(mover.x - 1 > 0) + { + mover_new(mover.x - 1, mover.y, MOVE_NONE, PIECE_SPACE, 0); + mover_addtostack(mover.x - 1, mover.y, MOVE_NONE); + } + if(mover.x + 1 < level.width - 1) + { + mover_new(mover.x + 1, mover.y, MOVE_NONE, PIECE_SPACE, 0); + mover_addtostack(mover.x + 1, mover.y, MOVE_NONE); + } + } + else + { + if(mover.y - 1 > 0) + { + mover_new(mover.x, mover.y - 1, MOVE_NONE, PIECE_SPACE, 0); + mover_addtostack(mover.x, mover.y - 1, MOVE_NONE); + } + if(mover.y + 1 < level.height - 1) + { + mover_new(mover.x, mover.y + 1, MOVE_NONE, PIECE_SPACE, 0); + mover_addtostack(mover.x, mover.y + 1, MOVE_NONE); + } + } + } + if((p >= PIECE_ARROW_RED_LEFT && p <= PIECE_BOMB_RED_DOWN) || p == PIECE_CIRCLE) + { + if(p == PIECE_CIRCLE) + d = mover.direction; + else + d = p % 4; + dx = mover.x + move_x[d]; + dy = mover.y + move_y[d]; + + into = level_piece(dx, dy); + /* Can it detonate something? */ + if(p >= PIECE_ARROW_RED_LEFT && p <= PIECE_ARROW_RED_DOWN && into >= PIECE_BOMB_RED_LEFT && into <= PIECE_BOMB_RED_DOWN && mover.fast && level_moving(dx, dy) == MOVE_NONE) + { + /* Add the central explosion to the stack */ + mover_new(mover.x, mover.y, d, PIECE_SPACE, 0); + level_setprevious(dx, dy, into); + level_setdetonator(dx, dy, p); + level_setdetonatormoving(dx, dy, d); + mover_addtostack(mover.x, mover.y, MOVE_NONE); + + /* Generate cosmetic side explosions */ + if(into % 2) + { + if(dx - 1 > 0) + { + ep = level_piece(dx - 1, dy); + if(ep == PIECE_STAR) + { + level.stars_exploded ++; + level.flags |= LEVELFLAG_STARS; + } + level_setmoving(dx - 1, dy, MOVE_NONE); + mover_new(dx - 1, dy, level_moving(dx - 1, dy), PIECE_EXPLOSION_RED_LEFT, 1); + level_setprevious(dx - 1, dy, ep); + } + if(dx + 1 < level.width - 1) + { + ep = level_piece(dx + 1, dy); + if(ep == PIECE_STAR) + { + level.stars_exploded ++; + level.flags |= LEVELFLAG_STARS; + } + level_setmoving(dx + 1, dy, MOVE_NONE); + mover_new(dx + 1, dy, level_moving(dx + 1, dy), PIECE_EXPLOSION_RED_RIGHT, 0); + level_setprevious(dx + 1, dy, ep); + } + mover_new(dx, dy, MOVE_NONE, PIECE_EXPLOSION_RED_HORIZONTAL, 0); + } + else + { + if(dy - 1 > 0) + { + ep = level_piece(dx, dy - 1); + if(ep == PIECE_STAR) + { + level.stars_exploded ++; + level.flags |= LEVELFLAG_STARS; + } + level_setmoving(dx, dy - 1, MOVE_NONE); + mover_new(dx, dy - 1, level_moving(dx, dy - 1), PIECE_EXPLOSION_RED_TOP, 0); + level_setprevious(dx, dy - 1, ep); + } + if(dy + 1 < level.height - 1) + { + ep = level_piece(dx, dy + 1); + if(ep == PIECE_STAR) + { + level.stars_exploded ++; + level.flags |= LEVELFLAG_STARS; + } + level_setmoving(dx, dy + 1, MOVE_NONE); + mover_new(dx, dy + 1, level_moving(dx, dy + 1), PIECE_EXPLOSION_RED_BOTTOM, 0); + level_setprevious(dx, dy + 1, ep); + } + mover_new(dx, dy, MOVE_NONE, PIECE_EXPLOSION_RED_VERTICAL, 0); + } + } + /* Can it keep moving? */ + else if(into == PIECE_SPACE || ((into == PIECE_DOTS || into == PIECE_PLAYER_ONE) && p != PIECE_CIRCLE && mover.fast == 1)) + { + mover_new(dx, dy, d, p, 1); + mover_new(mover.x, mover.y, d, PIECE_SPACE, 0); + level_setmoving(mover.x, mover.y, MOVE_NONE); + mover_addtostack(mover.x, mover.y, MOVE_NONE); + } + } + } + + if(level.movers.length != 0 || level.stack.length == 0) + ok = true; + } + + /* Is player one still alive? */ + if(level_piece(level.player_x[0], level.player_y[0]) != PIECE_PLAYER_ONE) + level.alive[0] = 0; +} + +function xor_considerdownmover(x, y) +{ + var p = level_piece(x, y - 1); + if(p == PIECE_XOR_FISH || p == PIECE_XOR_H_BOMB) + mover_addtostack(x, y - 1, 0); +} + +function xor_considerleftmover(x, y) +{ + var p = level_piece(x + 1, y); + if(p == PIECE_XOR_CHICKEN || p == PIECE_XOR_V_BOMB) + mover_addtostack(x + 1, y, 0); +} + +function xor_teleport(px, py, dx, dy, move) +{ + var teleport; + var tx, ty; + var moveout = MOVE_NONE; + + teleport = -1; + if(px == level.teleport_x[0] && py == level.teleport_y[0]) + teleport = 0; + if(px == level.teleport_x[1] && py == level.teleport_y[1]) + teleport = 1; + if(teleport == -1) + return [false, dx, dy, move]; + + tx = level.teleport_x[1 - teleport]; + ty = level.teleport_y[1 - teleport]; + + /* If the other teleport has been destroyed, turn this one into a wall */ + if(level_piece(tx, ty) != PIECE_TELEPORT) + { + mover_new(level.teleport_x[teleport], level.teleport_y[teleport], MOVE_NONE, PIECE_WALL, 0); + return [false, dx, dy, move]; + } + + if(level_piece(tx + 1, ty) == PIECE_SPACE) + { + dx = tx + 1; + dy = ty; + moveout = MOVE_RIGHT; + } + else if(level_piece(tx, ty - 1) == PIECE_SPACE) + { + dx = tx; + dy = ty - 1; + moveout = MOVE_UP; + } + else if(level_piece(tx - 1, ty) == PIECE_SPACE) + { + dx = tx - 1; + dy = ty; + moveout = MOVE_LEFT; + } + else if(level_piece(tx, ty + 1) == PIECE_SPACE) + { + dx = tx; + dy = ty + 1; + moveout = MOVE_DOWN; + } + + if(moveout != MOVE_NONE) + { + /* Visual effects for the player moving in to the teleport */ + /* Store original player move direction in cosmetic mover */ + mover_new(px, py, move, PIECE_TELEPORT, 0); + level_setprevious(px, py, PIECE_PLAYER_ONE + level.player); + level_setpreviousmoving(px, py, move); + + /* Visual effects for the player moving out of the teleport */ + mover_new(tx, ty, MOVE_NONE, PIECE_TELEPORT, 0); + + /* Change move to produce the effect of coming out of the teleport */ + move = moveout; + + level.view_x[level.player] = level.view_teleport_x[1 - teleport]; + level.view_y[level.player] = level.view_teleport_y[1 - teleport]; + + return [true, dx, dy, move]; + } + + return [false, dx, dy, move]; +} + +function xor_explode(x, y, type, previous) +{ + var p = level_piece(x, y); + + if(p == PIECE_SWITCH) + { + level.switched = 1 - level.switched; + level.flags |= LEVELFLAG_SWITCH; + } + if(p == PIECE_XOR_MASK) + { + level.stars_exploded ++; + level.flags |= LEVELFLAG_STARS; + } + + /* Don't explode edge walls */ + if(x == 0 || y == 0 || x == level.width - 1 || y == level.height - 1) + return; + + if(previous != MOVE_NONE) + { + mover_new(x, y, previous, PIECE_GONE, 0); + level_setpiece(x, y, PIECE_SPACE); + } + mover_new(x, y, MOVE_NONE, type, 0); + if(previous == MOVE_NONE) + level_setprevious(x, y, p); +} + +function xor_move(move) +{ + var p; + var px, py; + var dx, dy; + var ox, oy; + var into; + var bp; + + if(!level.alive[level.player]) + return false + + px = level.player_x[level.player]; + py = level.player_y[level.player]; + + if(move == MOVE_LEFT) + { + dx = px - 1; + dy = py; + + ox = px - 2; + oy = py; + + p = level_piece(dx, dy); + if(p == PIECE_WALL || p == PIECE_XOR_MAGUS || p == PIECE_XOR_QUESTOR) + return false; + if(p == PIECE_DOOR) + { + if(level.stars_caught == level.stars_total) + level.flags |= LEVELFLAG_EXIT; + else + return false; + } + if(p == PIECE_XOR_WAVES || p == PIECE_XOR_CHICKEN || p == PIECE_XOR_V_BOMB) + return false; + if(p == PIECE_XOR_FISH || p == PIECE_XOR_H_BOMB) + { + into = level_piece(ox, oy); + if(into == PIECE_SPACE || into == PIECE_XOR_DOTS) + { + mover_new(ox, oy, MOVE_LEFT, p, 0); + bp = level_piece(ox, oy + 1); + if(bp == PIECE_SPACE || bp == PIECE_XOR_WAVES) + mover_addtostack(ox, oy, 0); + } + else + return false; + } + if(p == PIECE_TELEPORT) + { + var a = xor_teleport(px - 1, py, dx, dy, move); + if(!a[0]) + return false; + dx = a[1]; dy = a[2]; move = a[3]; + } + if(p == PIECE_XOR_MASK) + { + level.stars_caught ++; + level.flags |= LEVELFLAG_STARS; + } + if(p == PIECE_SWITCH) + { + level.switched = 1 - level.switched; + level.flags |= LEVELFLAG_SWITCH; + } + if(p == PIECE_MAP_TOP_LEFT) + { + level.mapped |= MAPPED_TOP_LEFT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_TOP_RIGHT) + { + level.mapped |= MAPPED_TOP_RIGHT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_BOTTOM_LEFT) + { + level.mapped |= MAPPED_BOTTOM_LEFT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_BOTTOM_RIGHT) + { + level.mapped |= MAPPED_BOTTOM_RIGHT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_XOR_DOLL) + { + into = level_piece(ox, oy); + if(into == PIECE_SPACE) + { + mover_new(ox, oy, MOVE_LEFT, p, 0); + if(level_piece(ox - 1, oy) == PIECE_SPACE) + mover_addtostack(ox, oy, MOVE_LEFT); + } + else + return false; + } + + level.player_x[level.player] = dx; + level.player_y[level.player] = dy; + + mover_new(dx, dy, move, PIECE_XOR_MAGUS + level.player, 0); + mover_new(px, py, move, PIECE_SPACE, 0); + + if(level.flags & LEVELFLAG_EXIT) + return true; + + xor_considerdownmover(px, py); + xor_considerleftmover(px, py); + + return true; + } + + if(move == MOVE_RIGHT) + { + dx = px + 1; + dy = py; + + ox = px + 2; + oy = py; + + p = level_piece(dx, dy); + if(p == PIECE_WALL || p == PIECE_XOR_MAGUS || p == PIECE_XOR_QUESTOR) + return false; + if(p == PIECE_DOOR) + { + if(level.stars_caught == level.stars_total) + level.flags |= LEVELFLAG_EXIT; + else + return false; + } + if(p == PIECE_XOR_WAVES || p == PIECE_XOR_CHICKEN || p == PIECE_XOR_V_BOMB) + return false; + if(p == PIECE_XOR_FISH || p == PIECE_XOR_H_BOMB) + { + into = level_piece(ox, oy); + if(into == PIECE_SPACE || into == PIECE_XOR_DOTS) + { + mover_new(ox, oy, MOVE_RIGHT, p, 0); + bp = level_piece(ox, oy + 1); + if(bp == PIECE_SPACE || bp == PIECE_XOR_WAVES) + mover_addtostack(ox, oy, 0); + } + else + return false; + } + if(p == PIECE_TELEPORT) + { + var a = xor_teleport(px + 1, py, dx, dy, move); + if(!a[0]) + return false; + dx = a[1]; dy = a[2]; move = a[3]; + } + if(p == PIECE_XOR_MASK) + { + level.stars_caught ++; + level.flags |= LEVELFLAG_STARS; + } + if(p == PIECE_SWITCH) + { + level.switched = 1 - level.switched; + level.flags |= LEVELFLAG_SWITCH; + } + if(p == PIECE_MAP_TOP_LEFT) + { + level.mapped |= MAPPED_TOP_LEFT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_TOP_RIGHT) + { + level.mapped |= MAPPED_TOP_RIGHT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_BOTTOM_LEFT) + { + level.mapped |= MAPPED_BOTTOM_LEFT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_BOTTOM_RIGHT) + { + level.mapped |= MAPPED_BOTTOM_RIGHT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_XOR_DOLL) + { + into = level_piece(ox, oy); + if(into == PIECE_SPACE) + { + mover_new(ox, oy, MOVE_RIGHT, p, 0); + if(level_piece(ox + 1, oy) == PIECE_SPACE) + mover_addtostack(ox, oy, MOVE_RIGHT); + } + else + return false + } + + level.player_x[level.player] = dx; + level.player_y[level.player] = dy; + + mover_new(dx, dy, move, PIECE_XOR_MAGUS + level.player, 0); + mover_new(px, py, move, PIECE_SPACE, 0); + + if(level.flags & LEVELFLAG_EXIT) + return true; + + xor_considerdownmover(px, py); + + return true; + } + + if(move == MOVE_UP) + { + dx = px; + dy = py - 1; + + ox = px; + oy = py - 2; + + p = level_piece(dx, dy); + if(p == PIECE_WALL || p == PIECE_XOR_MAGUS || p == PIECE_XOR_QUESTOR) + return false; + if(p == PIECE_DOOR) + { + if(level.stars_caught == level.stars_total) + level.flags |= LEVELFLAG_EXIT; + else + return false; + } + if(p == PIECE_XOR_DOTS || p == PIECE_XOR_FISH || p == PIECE_XOR_H_BOMB) + return false; + if(p == PIECE_XOR_CHICKEN || p == PIECE_XOR_V_BOMB) + { + into = level_piece(ox, oy); + if(into == PIECE_SPACE || into == PIECE_XOR_WAVES) + { + mover_new(ox, oy, MOVE_UP, p, 0); + bp = level_piece(ox - 1, oy); + if(bp == PIECE_SPACE || bp == PIECE_XOR_DOTS) + mover_addtostack(ox, oy, 0); + } + else + return false; + } + if(p == PIECE_TELEPORT) + { + var a = xor_teleport(px, py - 1, dx, dy, move); + if(!a[0]) + return false; + dx = a[1]; dy = a[2]; move = a[3]; + } + if(p == PIECE_XOR_MASK) + { + level.stars_caught ++; + level.flags |= LEVELFLAG_STARS; + } + if(p == PIECE_SWITCH) + { + level.switched = 1 - level.switched; + level.flags |= LEVELFLAG_SWITCH; + } + if(p == PIECE_MAP_TOP_LEFT) + { + level.mapped |= MAPPED_TOP_LEFT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_TOP_RIGHT) + { + level.mapped |= MAPPED_TOP_RIGHT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_BOTTOM_LEFT) + { + level.mapped |= MAPPED_BOTTOM_LEFT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_BOTTOM_RIGHT) + { + level.mapped |= MAPPED_BOTTOM_RIGHT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_XOR_DOLL) + { + into = level_piece(ox, oy); + if(into == PIECE_SPACE) + { + mover_new(ox, oy, MOVE_UP, p, 0); + if(level_piece(ox, oy - 1) == PIECE_SPACE) + mover_addtostack(ox, oy, MOVE_UP); + } + else + return false + } + + level.player_x[level.player] = dx; + level.player_y[level.player] = dy; + + mover_new(dx, dy, move, PIECE_XOR_MAGUS + level.player, 0); + mover_new(px, py, move, PIECE_SPACE, 0); + + if(level.flags & LEVELFLAG_EXIT) + return true; + + xor_considerleftmover(px, py); + + return true; + } + + if(move == MOVE_DOWN) + { + dx = px; + dy = py + 1; + + ox = px; + oy = py + 2; + + p = level_piece(dx, dy); + if(p == PIECE_WALL || p == PIECE_XOR_MAGUS || p == PIECE_XOR_QUESTOR) + return false; + if(p == PIECE_DOOR) + { + if(level.stars_caught == level.stars_total) + level.flags |= LEVELFLAG_EXIT; + else + return false; + } + if(p == PIECE_XOR_DOTS || p == PIECE_XOR_FISH || p == PIECE_XOR_H_BOMB) + return false; + if(p == PIECE_XOR_CHICKEN || p == PIECE_XOR_V_BOMB) + { + into = level_piece(ox, oy); + if(into == PIECE_SPACE || into == PIECE_XOR_WAVES) + { + mover_new(ox, oy, MOVE_DOWN, p, 0); + bp = level_piece(ox - 1, oy); + if(bp == PIECE_SPACE || bp == PIECE_XOR_DOTS) + mover_addtostack(ox, oy, 0); + } + else + return false; + } + if(p == PIECE_TELEPORT) + { + var a = xor_teleport(px, py + 1, dx, dy, move); + if(!a[0]) + return false; + dx = a[1]; dy = a[2]; move = a[3]; + } + if(p == PIECE_XOR_MASK) + { + level.stars_caught ++; + level.flags |= LEVELFLAG_STARS; + } + if(p == PIECE_SWITCH) + { + level.switched = 1 - level.switched; + level.flags |= LEVELFLAG_SWITCH; + } + if(p == PIECE_MAP_TOP_LEFT) + { + level.mapped |= MAPPED_TOP_LEFT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_TOP_RIGHT) + { + level.mapped |= MAPPED_TOP_RIGHT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_BOTTOM_LEFT) + { + level.mapped |= MAPPED_BOTTOM_LEFT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_MAP_BOTTOM_RIGHT) + { + level.mapped |= MAPPED_BOTTOM_RIGHT; + level.flags |= LEVELFLAG_MAP; + } + if(p == PIECE_XOR_DOLL) + { + into = level_piece(ox, oy); + if(into == PIECE_SPACE) + { + mover_new(ox, oy, MOVE_DOWN, p, 0); + if(level_piece(ox, oy + 1) == PIECE_SPACE) + mover_addtostack(ox, oy, MOVE_DOWN); + } + else + return false; + } + + level.player_x[level.player] = dx; + level.player_y[level.player] = dy; + + mover_new(dx, dy, move, PIECE_XOR_MAGUS + level.player, 0); + mover_new(px, py, move, PIECE_SPACE, 0); + + if(level.flags & LEVELFLAG_EXIT) + return true; + + xor_considerleftmover(px, py); + xor_considerdownmover(px, py); + + return true; + } + + return false; +} + +function xor_evolve() +{ + var mp; + var into; + var np; + + var d; + + var px, py; + + level.oldmovers = level.movers; + level.movers = []; + + for(m = 0; m < level.oldmovers.length; m ++) + { + mover = level.oldmovers[m]; + + if(isexplosion(mover.piece)) + mover_new(mover.x, mover.y, MOVE_NONE, PIECE_SPACE, 0); + + level_setmoving(mover.x, mover.y, MOVE_NONE); + level_setprevious(mover.x, mover.y, PIECE_SPACE); + level_setpreviousmoving(mover.x, mover.y, MOVE_NONE); + level_setdetonator(mover.x, mover.y, PIECE_SPACE); + level_setdetonatormoving(mover.x, mover.y, MOVE_NONE); + + if(isexplosion(mover.piece)) + level_setprevious(mover.x, mover.y, mover.piece); + + /* Update the map */ + display_map_piece(mover.x, mover.y); + } + + while(level.movers.length == 0 && level.stack.length != 0) + { + mover = level.stack[0]; + + px = mover.x; + py = mover.y; + + mp = level_piece(px, py); + + if(mp == PIECE_XOR_FISH || mp == PIECE_XOR_H_BOMB) + { + into = level_piece(px, py + 1); + if(into == PIECE_SPACE || into == PIECE_XOR_WAVES || into == PIECE_XOR_MAGUS || into == PIECE_XOR_QUESTOR) + { + xor_considerdownmover(px, py); + xor_considerleftmover(px, py); + + np = level_piece(px, py + 2); + if(np == PIECE_SPACE || np == PIECE_XOR_WAVES || np == PIECE_XOR_MAGUS || np == PIECE_XOR_QUESTOR || np == PIECE_XOR_V_BOMB || np == PIECE_XOR_H_BOMB) + mover_addtostack(px, py + 1, MOVE_NONE); + + mover_new(px, py + 1, MOVE_DOWN, mp, 0); + mover_new(px, py, MOVE_DOWN, PIECE_SPACE, 0); + + } + if(into == PIECE_XOR_H_BOMB) + { + /* BBC XOR does *not* considerleftmover(px, py) */ + xor_considerdownmover(px, py); + xor_considerdownmover(px - 1, py + 1); + xor_considerdownmover(px + 1, py + 1); + xor_considerleftmover(px + 1, py + 1); + + mover_new(px, py, MOVE_DOWN, PIECE_SPACE, 0); + level_setdetonator(px, py + 1, mp); + level_setdetonatormoving(px, py + 1, MOVE_DOWN); + + xor_explode(px - 1, py + 1, PIECE_EXPLOSION_RED_LEFT, MOVE_NONE); + xor_explode(px, py + 1, PIECE_EXPLOSION_RED_HORIZONTAL, MOVE_NONE); + xor_explode(px + 1, py + 1, PIECE_EXPLOSION_RED_RIGHT, MOVE_NONE); + } + if(into == PIECE_XOR_V_BOMB) + { + xor_considerdownmover(px, py); + xor_considerleftmover(px, py); + xor_considerleftmover(px, py + 1); + xor_considerleftmover(px, py + 2); + + level_setdetonator(px, py + 1, mp); + level_setdetonatormoving(px, py + 1, MOVE_DOWN); + + xor_explode(px, py + 0, PIECE_EXPLOSION_RED_TOP, MOVE_DOWN); + xor_explode(px, py + 1, PIECE_EXPLOSION_RED_VERTICAL, MOVE_NONE); + xor_explode(px, py + 2, PIECE_EXPLOSION_RED_BOTTOM, MOVE_NONE); + } + } + + if(mp == PIECE_XOR_CHICKEN || mp == PIECE_XOR_V_BOMB) + { + into = level_piece(px - 1, py); + if(into == PIECE_SPACE || into == PIECE_XOR_DOTS || into == PIECE_XOR_MAGUS || into == PIECE_XOR_QUESTOR) + { + xor_considerleftmover(px, py); + xor_considerdownmover(px, py); + + np = level_piece(px - 2, py); + if(np == PIECE_SPACE || np == PIECE_XOR_DOTS || np == PIECE_XOR_MAGUS || np == PIECE_XOR_QUESTOR || np == PIECE_XOR_V_BOMB || np == PIECE_XOR_H_BOMB) + mover_addtostack(px - 1, py, MOVE_NONE); + + mover_new(px - 1, py, MOVE_LEFT, mp, 0); + mover_new(px, py, MOVE_LEFT, PIECE_SPACE, 0); + + } + if(into == PIECE_XOR_H_BOMB) + { + xor_considerleftmover(px, py); + xor_considerdownmover(px, py); + xor_considerdownmover(px - 1, py); + xor_considerdownmover(px - 2, py); + + level_setdetonator(px - 1, py, mp); + level_setdetonatormoving(px - 1, py, MOVE_LEFT); + + xor_explode(px - 2, py, PIECE_EXPLOSION_RED_LEFT, MOVE_NONE); + xor_explode(px - 1, py, PIECE_EXPLOSION_RED_HORIZONTAL, MOVE_NONE); + xor_explode(px, py, PIECE_EXPLOSION_RED_RIGHT, MOVE_LEFT); + } + if(into == PIECE_XOR_V_BOMB) + { + xor_considerleftmover(px, py); + xor_considerdownmover(px, py); + xor_considerleftmover(px - 1, py + 1); + xor_considerleftmover(px - 1, py - 1); + xor_considerdownmover(px - 1, py - 1); + + mover_new(px, py, MOVE_LEFT, PIECE_SPACE, 0); + level_setdetonator(px - 1, py, mp); + level_setdetonatormoving(px - 1, py, MOVE_LEFT); + + xor_explode(px - 1, py - 1, PIECE_EXPLOSION_RED_TOP, MOVE_NONE); + xor_explode(px - 1, py, PIECE_EXPLOSION_RED_VERTICAL, MOVE_NONE); + xor_explode(px - 1, py + 1, PIECE_EXPLOSION_RED_BOTTOM, MOVE_NONE); + } + } + + if(mp == PIECE_XOR_DOLL) + { + d = mover.direction; + + into = level_piece(px + move_x[d], py + move_y[d]); + if(into == PIECE_SPACE) + { + np = level_piece(px + 2 * move_x[d], py + 2 * move_y[d]); + if(np == PIECE_SPACE) + mover_addtostack(px + move_x[d], py + move_y[d], d); + + mover_new(px + move_x[d], py + move_y[d], d, PIECE_XOR_DOLL, 0); + mover_new(px, py, d, PIECE_SPACE, 0); + } + } + + level.stack.shift(); + } + + /* Is player one still alive? */ + if(level_piece(level.player_x[0], level.player_y[0]) != PIECE_PLAYER_ONE) + level.alive[0] = false; + + /* Is player two still alive? */ + if(level_piece(level.player_x[1], level.player_y[1]) != PIECE_PLAYER_TWO) + level.alive[1] = false; + + /* If a player has died, swap to the other player at the end of the move */ + if(level.alive[level.player] == 0 && level.stack.length == 0) + { + if(level.alive[1 - level.player]) + { + level.player = 1 - level.player; + + /* Cosmetic mover for the newly swapped in player */ + mover_new(level.player_x[level.player], level.player_y[level.player], MOVE_SWAP, PIECE_PLAYER_ONE + level.player, 0); + } + + /* Force a check for whether a redraw is needed */ + return true; + } + + return false; +} + +function xor_focus() +{ + if(level.player_x[level.player] <= level.view_x[level.player]) + level.view_x[level.player] = level.player_x[level.player] - 1; + if(level.player_x[level.player] >= level.view_x[level.player] + 7) + level.view_x[level.player] = level.player_x[level.player] - 6; + if(level.player_y[level.player] <= level.view_y[level.player]) + level.view_y[level.player] = level.player_y[level.player] - 1; + if(level.player_y[level.player] >= level.view_y[level.player] + 7) + level.view_y[level.player] = level.player_y[level.player] - 6; +} + diff --git a/browser/chroma-style.css b/browser/chroma-style.css new file mode 100644 index 0000000..9751fb5 --- /dev/null +++ b/browser/chroma-style.css @@ -0,0 +1,522 @@ +// stroke fill +// {0xcc, 0xcc, 0xcc}, {0x7f, 0x7f, 0x7f}, /* 0 */ +// {0xff, 0x99, 0x99}, {0xff, 0x00, 0x00}, /* 1 */ +// {0x99, 0xff, 0x99}, {0x00, 0xcc, 0x00}, /* 2 */ +// {0xff, 0xff, 0x33}, {0xff, 0xa0, 0x00}, /* 3 */ +// {0x99, 0x99, 0xff}, {0x00, 0x00, 0xff}, /* 4 */ +// {0xcc, 0x99, 0xff}, {0x80, 0x00, 0xff}, /* 5 */ +// {0x66, 0xb3, 0xff}, {0x00, 0x80, 0xff}, /* 6 */ +// {0xff, 0xff, 0xff}, {0x7f, 0x7f, 0x7f}, /* 7 */ +// +///* light */ - use for background blocsk +// {0xee, 0xee, 0xee}, {0x7f, 0x7f, 0x7f}, /* 0 */ +// {0xff, 0xcc, 0xcc}, {0xff, 0x00, 0x00}, /* 1 */ +// {0xcc, 0xff, 0xcc}, {0x00, 0xcc, 0x00}, /* 2 */ +// {0xff, 0xff, 0x99}, {0xff, 0xa0, 0x00}, /* 3 */ +// {0xcc, 0xcc, 0xff}, {0x00, 0x00, 0xff}, /* 4 */ +// {0xe6, 0xcc, 0xff}, {0x80, 0x00, 0xff}, /* 5 */ +// {0xb3, 0xd9, 0xff}, {0x00, 0x80, 0xff}, /* 6 */ +// {0xff, 0xff, 0xff}, {0x7f, 0x7f, 0x7f}, /* 7 */ +// +///* bold */ +// {0xaa, 0xaa, 0xaa}, {0x7f, 0x7f, 0x7f}, /* 0 */ +// {0xff, 0x5c, 0x5c}, {0xff, 0x00, 0x00}, /* 1 */ +// {0x5c, 0xff, 0x5c}, {0x00, 0xcc, 0x00}, /* 2 */ +// {0xff, 0xc0, 0x00}, {0xff, 0xa0, 0x00}, /* 3 */ +// {0x5c, 0x5c, 0xff}, {0x00, 0x00, 0xff}, /* 4 */ +// {0xae, 0x5c, 0xff}, {0x80, 0x00, 0xff}, /* 5 */ +// {0x29, 0x94, 0xff}, {0x00, 0x80, 0xff}, /* 6 */ +// {0xff, 0xff, 0xff}, {0x00, 0x00, 0x00} /* 7 white, black outline */ + + +body +{ +margin: 0px; +background: #000000; +font-family: sans-serif; +font-size: 3vw; +} + +.black, div.item.grey div.key, div.item.grey div.item-text, div.menu h1, div.menu h2 +{ +color: #7f7f7f; +-webkit-text-fill-color: #cccccc; +-webkit-text-stroke-width: 0.03em; +-webkit-text-stroke-color: #7f7f7f; +text-fill-color: #cccccc; +text-stroke-width: 0.03em; +text-stroke-color: #7f7f7f; +} + +.red +{ +color: ##ff0000; +-webkit-text-fill-color: #ff9999; +-webkit-text-stroke-width: 0.03em; +-webkit-text-stroke-color: #ff0000; +text-fill-color: #ff9999; +text-stroke-width: 0.3em; +text-stroke-color: #ff0000; +} + +.green +{ +color: #00cc00; +-webkit-text-fill-color: #99ff99; +-webkit-text-stroke-width: 0.03em; +-webkit-text-stroke-color: #00cc00; +text-fill-color: #99ff99; +text-stroke-width: 0.03em; +text-stroke-color: #00cc00; +} + +.yellow +{ +color: #ffa000; +-webkit-text-fill-color: #ffff33; +-webkit-text-stroke-width: 0.03em; +-webkit-text-stroke-color: #ffa000; +text-fill-color: #ffff33; +text-stroke-width: 0.03em; +text-stroke-color: #ffa000; +} + +.blue, div.item, div.item-options, div.instructions p +{ +color: #0000ff; +-webkit-text-fill-color: #9999ff; +-webkit-text-stroke-width: 0.03em; +-webkit-text-stroke-color: #0000ff; +text-fill-color: #9999ff; +text-stroke-width: 0.03em; +text-stroke-color: #0000ff; +} + +.magenta +{ +color: #8000ff; +-webkit-text-fill-color: #cc99ff; +-webkit-text-stroke-width: 0.03em; +-webkit-text-stroke-color: #8000ff; +text-fill-color: #cc99ff; +text-stroke-width: 0.03em; +text-stroke-color: #8000ff; +} + +.cyan, div.item-options div.option.selected +{ +color: #0080ff; +-webkit-text-fill-color: #66b3ff; +-webkit-text-stroke-width: 0.03em; +-webkit-text-stroke-color: #0080ff; +text-fill-color: #66b3ff; +text-stroke-width: 0.03em; +text-stroke-color: #0080ff; +} + +.black-background, div.item.grey div.key, div.item.grey div.item-text +{ +background: #eeeeee; +border: 0.06em solid #7f7f7f; +} + +.blue-background, div.item div.key, div.item div.item-text, div.item-options div.option, div.item-slider +{ +background:#ccccff; +border:0.06em solid #0000ff; +} + +.cyan-background, div.item-options div.option.selected +{ +background: #b3d9ff; +border: 0.06em solid #0080ff; +} + +div.menu +{ +position: absolute; +top: 0px; +right: 0px; +opacity: 1; +background: #ffffff; +width: 100%; +min-height: 100%; +transition: width 1s ease, height 1s ease, opacity 1s ease, top 1s ease, right 1s ease; +} + +div.menu h1 +{ +font-size: 100%; +text-align: center; +margin-top: 1em; +margin-bottom: 1em; +} + +div.menu h2 +{ +font-size: 100%; +margin-top: 1em; +margin-bottom: 0.25em; +margin-left: 1em; +margin-right: 1em; +} + +div.menu div.logo +{ +margin: auto; +text-align: center; +font-size: 125%; +margin-top: 0.5em; +margin-bottom: -0.5em; +} + +div.menu div.logo.big +{ +font-size: 500%; +margin-top: 0em; +margin-bottom: -0.125em; +} + +div.spacer { +height: 1em; +} + +div.items { +padding-bottom: 0.5em; +} + +div.item { +margin-top: 0.06em; +cursor: pointer; +width: 100%; +} + +div.item div.key { +float: left; +width: 1.5em; +text-align: center; +padding-top: 0.25em; +padding-bottom: 0.25em; +margin-left: 1em; +margin-right: 0.06em; +overflow: hidden; + +} + +div.item-text { +overflow: auto; +text-align: left; +padding-top: 0.25em; +padding-bottom: 0.25em; +padding-left: 0.5em; +padding-right: 0.25em; +margin-left: 2em; +margin-right: 1em; + +} + +div.item-text select { +float: right; +} + +div.item-options +{ +display: flex; +flex-direction: row; +flex-wrap: wrap; +justify-content: space-between; + +margin-left: 1em; +margin-right: 0.94em; + +cursor: pointer; + +} + +div.item-options div.option +{ +flex-grow: 1; +position: relative; + +margin-right: 0.06em; +margin-top: 0.06em; +padding: 0.25em; +} + +div.item-options div.option.four +{ +flex: 1 0 0; +width: 0%; +} + +div.item-options div.option.three +{ +width: 25%; +} + +div.item-options div.option div.key +{ + +display: inline-block; +width: 1.5em; +text-align: center; + +padding-top: 0.25em; +padding-bottom: 0.25em; + +margin-left: -0.25em; +margin-top: -0.25em; +margin-bottom: 0.25em; +margin-right: 0.5em; + +background:#ccccff; +border-right: 0.06em solid #0000ff; +border-bottom: 0.06em solid #0000ff; +} + +div.item-options div.option.selected div.key +{ +background: #b3d9ff; +border-right: 0.06em solid #0080ff; +border-bottom: 0.06em solid #0080ff; +} + +div.item-options div.option img +{ +width: 100%; +display: block; +} + +div.item-options div.option input +{ +float: right; +width: 3em; +height: 1em; +font-size: 100%; +} + +div.item-slider +{ +margin-left: 1em; +margin-right: 1em; +margin-top: 0.06em; +padding-left: 2em; +padding-right: 0.25em; +padding-bottom: 0.25em; +} + +div.item-slider input.slider +{ +display: block; +float: left; +width: calc(100% - 6em); +height: 1em; +} + +div.item select +{ +font-size: 100%; +} + +div.item input +{ +font-size: 100%; +} + +div.item-slider input.number +{ +float: right; +font-size: 100%; +width: 3em; +height: 1em; +} + +div.item-slider div.title +{ +text-align: left; +padding-top: 0.25em; +padding-bottom: 0.25em; +} + +div.item-left { +float: left; +} + +div.item-right { +float: right; +} + + +div.clear { +clear: both; +} + + +div.instructions p +{ +margin-left: 1em; +margin-right: 1em; +} + + + + + + + + + + + + + + + + + + + + +div#menu-icon { +display: none; +position: fixed; +top: 0px; +right: 0px; +background: #ffffff; +cursor: pointer; +transition: opacity 1s ease; +opacity: 1; +} + + + + +div.keypad +{ +position: fixed; +top: 0px; +left: 0px; +display: table; +background: #ffffff; +width: auto; +border: 1px solid black; +font-size: 16px; +} + +div.keypad.transition +{ +transition: top 1s ease, left 1s ease; +} + +div.keypad.minimised +{ +top: -125px; +left: -125px; +} + +div.keypad div.row +{ +display: table-row; +width: auto; +} + +div.keypad div.row div.cell +{ +display: table-cell; +height: 50px; +width: 50px; +text-align: center; +vertical-align: middle; +cursor: pointer; +border: 2px solid #ffffff; + +} + +div.keypad div.row div.cell div.key +{ +display: table-cell; +height: 50px; +width: 50px; +text-align: center; +vertical-align: middle; +cursor: pointer; +top: 0px; +left: 0px; +} + +div.keypad div.row div.cell div.key.cyan +{ +background:#b3d9ff; +border:2px solid #0080ff; +} + +div.keypad div.row div.cell div.key.blue +{ +background:#ccccff; +border:2px solid #0000ff; +} + +div.keypad div.row div.cell div.toggle +{ +display: table-cell; +height: 50px; +width: 50px; +text-align: right; +vertical-align: bottom; +cursor: pointer; +} + +div.keypad div.row div.cell div.drag +{ +display: table-cell; +height: 50px; +width: 50px; +text-align: left; +vertical-align: bottom; +cursor: pointer; +} + + + + + +@media (max-width: 480px) +{ + body + { + font-size: 14.4px; + } + + div.item div.key, div.item-options div.option div.key + { + display: none; + } + + div.item div.item-text, div.menu h2, div.item-options, div.item-slider, div.instructions p + { + margin-left: 0em; + margin-right: 0em; + } + + div.item-slider + { + padding-left: 0.5em; + } + + div#menu-icon + { + font-size: 200%; + } + + div.item, div.slider + { + margin-top: 1px; + } + + div.item-options div.option + { + margin-top: 1px; + margin-right: 1px; + } +} + diff --git a/browser/chroma.html b/browser/chroma.html new file mode 100644 index 0000000..e4904e0 --- /dev/null +++ b/browser/chroma.html @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/graphics-marble.svg b/browser/graphics-marble.svg new file mode 100644 index 0000000..2e1a30f --- /dev/null +++ b/browser/graphics-marble.svg @@ -0,0 +1,687 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/graphics-marble.xml b/browser/graphics-marble.xml new file mode 100644 index 0000000..f5a8a75 --- /dev/null +++ b/browser/graphics-marble.xml @@ -0,0 +1,309 @@ + + + + +Chroma Marble + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/graphics-neon.svg b/browser/graphics-neon.svg new file mode 100644 index 0000000..2d60f3d --- /dev/null +++ b/browser/graphics-neon.svg @@ -0,0 +1,1300 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/graphics-neon.xml b/browser/graphics-neon.xml new file mode 100644 index 0000000..b8fd0fb --- /dev/null +++ b/browser/graphics-neon.xml @@ -0,0 +1,310 @@ + + +Chroma Neon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/graphics-xor.png b/browser/graphics-xor.png new file mode 100644 index 0000000..248b1b2 Binary files /dev/null and b/browser/graphics-xor.png differ diff --git a/browser/graphics-xor.xml b/browser/graphics-xor.xml new file mode 100644 index 0000000..a7ef79d --- /dev/null +++ b/browser/graphics-xor.xml @@ -0,0 +1,113 @@ + + +XOR + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/graphics-zen.svg b/browser/graphics-zen.svg new file mode 100644 index 0000000..b517ae3 --- /dev/null +++ b/browser/graphics-zen.svg @@ -0,0 +1,203 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/graphics-zen.xml b/browser/graphics-zen.xml new file mode 100644 index 0000000..eb00c66 --- /dev/null +++ b/browser/graphics-zen.xml @@ -0,0 +1,251 @@ + + +Chroma Zen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/levels.xml b/browser/levels.xml new file mode 100644 index 0000000..212f078 --- /dev/null +++ b/browser/levels.xml @@ -0,0 +1,831 @@ + + + + +chroma level + +title: chroma 1.01 : invitation +level: 1 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%lll%h %ll%% d%* . % *.* * % +%*l*%* h%*ll%dd%/%j * .bb*%%f%%% +%%l%% *% ll *d *%j% b %f. % +% * h % .. %%d%%%% %%%%* %ff*% +% % % *.%%%%d%d.%. . %*%b %fff% +%l l% %hh%d d%%f*f*.% %% %%%%% +%.l.% % %h*%d . %.%fff% * %* *% +% .*% %* .*% %f * % j%%% . % +%%%%%% %%h %*%% % *%%%% *..% b.% +%* *%d d%. % %*f%* jjj b% +%hhh%* *%%%%%%l%%%%% %%%%%%%%%%% +%*hh% 1 l l*.%***% * %.* %. *% +% ..%*d %l. l %...%.* b . f f% +% %%%%% %.%*%. %fff% b % *b%f *% +% %%%%%% % %%%%% .f% +% llll% %h hhh % %%% % b b f % +% ***.% %* .h*h%*..j*%%%.%%%%%%% +%%%%%%% % * . .%jjjjj% * %* *% +%ddd%d % %%%%%%%%%%%% . 2 %j j% +%.d*%* % %ddd % .f.f*f* * * % +%*. *% ...*%%*f ff%f%f% j % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 1.02 : illustration +level: 2 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% h *%*l% %*%c* %*g* *%*% +% .* he% .il % 2 % gf f g. % +% * *e%%%* .i % c% *% f % +% % .ee% % % b b%g.% g*% *% +% %%%%.%%% %%%%%%% *%gf %gf% +%* da%%% *i%%%%% . f f % +% da%d%% %%h% * %%k.%%%%% %%% +%* d * %*/*%cb%kkj*% % +% * %% %% h %b%bb%*%j %* cc*% % +%%% %% %eee%%%%%%%%%%% b% % +%*%%% li% *%g*.* . %*. cb *%%% +% *i %%%%% f % %%b %b % +% %%%%%%%%l l%%%%f%% %%%%%% % % +% h %d. %li.i% %%% k* %g. . % +% *e%*aa%* % % %% * % * f % +%1 % %% % %c. *%k*j. %fgg*% +%% %% %%% h % b%%%%%% %%%b%%% +% % h*e%% %%%%g.*% % c. % +% da%li% h*e % .*. %g.*% %c. *% +%*a %. % *e %%j.j %% f %%c* %% +% d%* % jk. f %cb *% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 1.03 : elaboration +level: 3 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%hgg*%g.%ll % %*a % h % +%gf g. .. *ee% ba *aa 1*ee% +% %% %%k* %gg* *d b b% % f % +% d %j .i% %c. cb %%%%%% +% d %% %%%%%%%%%%%%%% %d%*d% +%cc*aa% . *a d% *.l%*/*%d*% +% b %kj % .%cd *%kk.j*%b% %. % +% b %*%*%*a% d b% j %%% .% +% %% %%%%%%%%%*ccb%%%*% *he %*b% +%.eg.% l li%d%%%%%%h%%%% *fe%b*% +% fe%k* . %*. *a%h*h%* gf %%%% +%*% * *% .%%. .%% *%% %li% +%%% %%% . %%. % %k*% +%dc. % ji%c* .*%g. .e%cda% 2% +%cb *%*%*%%%%%b% * * % d %% %%% +%%%%%%%%%%%*c.%%%%% %%% b % % +%**% * %**%% d %*%* *%%%%%g. *% +%ggg. .eee%c.* %i%k. % hf% +%ff ff%% % . . li % gf% +% . . ..a%%j%*j% kl ..e% +%g* f*f *e%cb %%kj *. % f *% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 1.04 : detonation +level: 4 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% G*% *% %l%gF.*e% .*i*i*i% +% Gf.% gF%c*%*/*%%%%% % . % +%* %B% F % D %j% .*AA%%%%%%%J*% +%%%%*%%%%% b %*%d * % %%%% +%1d% Hl%%%%%% %c* . %LLL*i% % +% .%g* .%%k*. % b %...% %g.% +%*D% b *K% . *%%%H%%%%** %*%. % +%%%%%%%%%%* J j%* . *e%%%%%E*Ee% +%*Ee%l %%%%%%%% d % % +% %*cC*% h %g.* G% * %%%%%% +%g* % %%%gG* . %%%%%*% k. % +% f %L %*% H*% l %%%C.A%kK.*% +%%%%%%%%h%%%%%%%% l *% * % kK.% +% .%.*%.% d% . %%%%%%% % +%Cdb%Jl% %c*A.aD%%K.%* %%%%%% +% d %*.%H% .*%*K%%% *a%G*.E% +% * %j %%%%%%%%%%% *%*% b %d *% +% . % L% . *%%%%%%%%%%%%%%% +%%%%%%%%%%f%g* G% l %h h %I *i% +%*%*%L l %gGf%gg%% L %* H % % +%f%D%* *i%*gf .*%*.k% * %*D 2% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 1.05 : complication +level: 5 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% %B 2 D% %l% %d l % +%.Iaei%Fc*iH% l d %.e *Aa %*1* % +% %J L% .h. % * %H .e% +%%%%%%%%%%%%% * % %%%.%%%%%% +% l h d %*l*%%A%K%%I %*%L% h d% +% . . . %ji%%%%%%%%%%%% %%% . .% +%* %%%%l *%*%* *% d % K% +%%%%%%%E%GA%h %%%b dj% l % % +% %%% %d % l % * % k* % +% dlh % * %.*Aa % hA% % C% +%*... f % % . %KCK%%%%%% +%.EEe % b.i%*%%%%% %%%%%%%%% *% +%%%%%%% %I%* D%%% %c* *% Dj% +%c* *%%%%%%%%E . *.ei%%%% % gD% +%%%%%%% d%c.*%* B% b *%D% % *% +%*l%L %*a%%h%%%%%%%%% %%* %% %% +% .%* . *% H %H %k*i% +%%%%D %e %% %d% H .I %* L % % +%c*%. % *%k% . * % * %DDH% +%%/%* %.i% %%A% .AA%HDL%%...% +%g*%H j % *%L %fbja%***% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 1.06 : transportation +level: 6 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% *e% .% *% *%*% %B *% .*h % +% /J *i f% %.% %go o % *o% +% *a% .% %% % % % o % +% %%% %oooo% oa% . G%o* % +% k*% *a % % % %%% % +%%%%%%%%%%%%%%%%%% %%% * %*%%% % +%Dk. *L % % *a %h%%%%%%%. *% +%* % o %%% % *% o %oa%% +% %c.* %G%%%%% % o *% +%*.go %* %%% %kL o %% %% +%B o%f %cc. %%% % % +%%%%%%%A%%%%%% oo Da% . *i%ooo% +% % % o %*% % 1 % +% o Hoo o g% * %%%%%%%%%% %% +% % * %%%f %* .e% * % +% g* %%%%b%%%%K%%%%%%%c.C*% %%%% +% *%%% . %* *% %%% l % +%%%%%%d%% *% .o. %e . % +% . % o % o*o *%% c% +% o 2 *% . o % .o. % di%* % +% D% j %* *%*ie%%f * % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 1.07 : collaboration +level: 7 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% J%*%*%B F%*% d %h*% +% C. %%%%% * * % o . %%%% +% jC. % % % % % %%%. K.*% +% h * % b %k%B % +%%%%%%%%f %%%%f%%%%%% . *%%%%% +%* .a.a%i1% *. lli%*%H %%%%% Da% +%%%* B % %kjj .*%% %%%%* %* *%% +% %*G%%%%%%%% % .%f %% +%*%%g* %%%% * %c. l c. . o % +% %% % .ji% *%%cc%h %% +%oo % %cc* % jkj%* D * %. *%% +% %% %% j %%%%%%%%%%%%%%%%% Ba% +%*%% %%j % k.* Fa%lll % %%% +%%%g.%.e%%%% g. %*%kD. % %h% +%A% *b* %2 % %k% . *a%*/*% +% %%%%%%%*i%.a *% % L% %j% % +% %J j b %%%%%%%%%%%%%% +%%* d %%%%%%%%%%% l % * C% +%gb h *a F %* oa % f h% +%%% L %% * . %%%. % b * *% +%*% . *i f %*%L g* H% j % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 1.08 : preparation +level: 8 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*% .a% d . %*j %k* *% +% * % h o % D*f % o %%%%% D .% +% be% .e% *%2.%%%%e %IEA% H. % +%%* % c* % D* % *a% % D* % +%*f % . *%%%% % %%%%% *%% . % +% ja% j %%%% %d*e% b %% %%% +%%%%%%%%%* d oooo %hl f %K.Il% +% . . . . .% o o %la % j %j k*% +%* . . . . o o %*1 %%%%%%%%%% +%A%%%%%%%%%% oooo %c. % f % +%%% %e% % d * k% +%l%c*c*c*C*%%%%%%%%%%%%%% % % % +%.% %e%*%* D%*a% . .% g% +% %* *%%%%%%%% g. .%%/%% o % +%I%G.E%d% J % . % *a% d % +%%%%*%%. k.K% c. .Ho%%%%%%%%%C% +% J %*% %* %%%* b% +% g. %%%%% *%%%%%%%d%% L H D %% +% % dh% j%he%D .%H . . .*a% +% k* C%dahe c%gh%* %* . . . %% +% b %* . * . %L%F . *% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 1.09 : application +level: 9 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% c* %h le%* % *e*%. *%*a% +% h c*%. d %b . da gco %/%% +%K. % . % %biEe%* B .%*e% +% * %E* %%%.%%%%%%%% F %%%%%%% +%. .*%kc. l% % d%%%%% % +%*i G% %l*% % H * . % D2d % +%%%%%%%%%%.%% % % % %aei% G* *E% +%I h C% . %l%1 .i %l % +%* . *% *%%%%%%%%%G%* %*% % +%% cie %* . % %%%%%%%%%% +%l*af %f % %%%%%%% B .ab % +%G%%%%%% * %%% Lh %E o.e kh % +% %C* *A% *. % * K*% +% * % %%% . b% d %%%%% %%%%%%% +% % %%f%%%%gg. %H*l% ha*% +% o . . d%L% %%%* .e.%%% o %% +% . . .*%%%g.Ha% *% %*%. % +%C%%%%% %%ka k*%%%%%%%%%% %***% +%%% *% %%Ik* .II% d %GGG% +% g.c. D %%%%% %%%% . *Aa%%%%% +%* j % f* *%*% *a *%*D %*%k*i% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + + +chroma level + +title: chroma 2.01 : inauguration +level: 1 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%h h l%l d% ld% *.f.* %.*...*.% +%. *d*%*h *%h.*%*bj. j %fbfjfbf% +%* l. % d %.d % ..b.f %.j.2.j.% +% d.h %.*..%l*.%* fjfb.% % +% . ..% hd.h %%%%%%%j%%%%% %%% +%*l l .. * % .b *%*% +%%%%%%%%%%%%%%d%.fj %%%%%%%%b% % +%*dhdh%l.d%dh .%*.f %*.f..*%j % +%l.d.l%*h*%ldl % b% %.j.b.j%f% % +%dhldh%h.l%h.h%%% % %f.j...%bj.% +%l.h.d%.d.%d%. */*% %.b.f.b%f%f% +%. . . * * %%%f%.%%%%%j%%%% % +%%%%% % %%%% %%d%j% b f.% +% d1%h d %l *%%%%%%%%%f% b% +%l.h.l%.l..%.%l %* *%*%*%j%* *j% +%*d.h.% h. %h%. %...%.%.%f%j.f.% +%h.l.*%*.*d%l%d %jfb.f.j.b% . % +%%%%%%% %%%%d%h % j.b. *%*b* % +%* l d h . %.* .j.f j%f.j*% +%dhlhd%.%% %*%% %bj *. *b%j*bf% +%...*.% %* *%*f f jf%bjfj% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.02 : manipulation +level: 2 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% f %* .% *g. %* h %.* l% +%g* b %jcg. f%cj *% d la %hlae% +% *j %gk.j .% kb% . *.e%dh%*% +%c*j. * %fb j *f%%h%i *aiea% +%%%%%%%%%%%2%%%g%%% . . .i% +%%c*% k.* *% .*%*%%%%%%%%%%%% +%gj.* g*.% fkb% kb% l ha% hd*% +%* . j%c.f % f%%% . *i % .le% +%%%%%j% %%% %%%.%%*d %.%%e% *a % +%gc* % f %* f*% . *% +%kf % %*g.k. c.%1%%%%%%%% %%%% +%ck. .%j b*j%k. % *%h d d.i% +%* *j%%%%%%%%%%%%%aie%*ah l.e % +% . b . .% *a * . % l .a *% +%g.% % % j.b%ahle%%%% %%*%%%%%%% +%j c* *% gbf%*dea% l %d hi de*% +%c.k.%j% bj*% . *.e *a%..a *h % +%g*.f%%%%%%%%%%l%% %% %l .e l.% +% k. %k* %d%* . %.* %% d.% +% .g.%c. .%*/*% * lea%%%d% *i% +%* b j *.f% .ai*%* . *e*% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.03 : edification +level: 3 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*d *k* d . . % d h %gl% +% hide% .. hajgj % g..* *i %la% +%gl kb% g. * *%%%*% ck. . % +% * *%cl k%%%l%%%* .e.a% *% +%%%.%%% .*ha% .le%%%% %%%%%%%%% +% gj*%* *fi %gc.. %* l *%h *l*% +% %*%%%d%%%%%%* %*% .d. %c. . % +%c* .lh l*%kd.% % kc*ai *...e% +% . .b.d .h%jg.* % % .b1 %kfb % +% f j *.* .%c. % %.%* j *%%%%%%% +%%% %%% %%%%* %%% %%% %%%h*.*a% +%*f.l*%.i*%*kg*% c. %.a. * k. % +%k.b.g%.e %l% %cf..i% fj% ..bh% +%.a2c. %b*/*%.a%* f *%cjb%lb .% +%e.d.i%%%j% %%%%%%%j * . *e*% +%*j.h*%*%%%%%%%%*l h %%%%%%%%% % +%%% %%% . l %.. *e%*h* d % +%lc.h %%%je .*.%f j %%.b k.*hi% +%*e l. %aj d %*a%.*%cl .f .*f% +% .a% * .e..*i .ib % . * l .a% +%*%.* %.% b *a% .e% b .d % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.04 : disintegration +level: 4 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% l *%*%kK* *%F* h .B D*% +% Kl %%% L . kK*%%% . %A.c.C% +% .Ll %k. j jiK%*%.%g%E% b2d % +%%%.L * %*j %%%*h % %A.a.C% +%*% .*j %%%%%K.i * %f. %*%*B D.% +%%%%%%% %* %%K.ij*%%% %%%%%%% % +%*.e gG*% h %%L.i %*% . % +%.egG...%%.E %%%%%%%% L l % +% 1* %* g. % HG..e% K*I k*i % +%...Aac.% .e % h % J j %% +%*Aa c.*%*% % . .eG*e%. .% +% %%%%%%%E%%%%% * %%%%%%%k*.*i%% +% h %fee%h%*g. g* %%j%j%%% +%%. .*eE%%%*/*%%%%%%%%%%%%%%%%*% +%%h %*%f% g. %*%*%g*F.e% K% +% .*e. %%%%%%%%%%%% % * %.i*% +%*H G%A* d% h.eF. %. j% +% %%%%%%%%% *cC*%d% % F %j % +% %*%*%*.Aa B*% H * % +%%kLi %%%%%b .Aa%b %%%g.H.e%*Ji% +%K*. *L% * %*%*H*eF%Ji % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.05 : triplication +level: 5 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% l l %*% 1 %*% d %* H d % +%k. . %%% l d %%% % % %l% . D % +% J gd % .h. % . . %. f .I% +%%% G*% % D.L %C% %e% % c.* %%% +%*% D %h% .H. % . . % %*% +%%%%%%%%.% . % % % % %*g*%%%%% +% %.g.E% %%%*%%% j F %kb %d%l% +% *j % %*%%%%%%%%%%%%%*/*% +% %a%%% %%%%%%%%* c* J%*g.e % % +%*LHD % %* .a% d % %*%%% %%% % +% ... % %% %% .i %%%%% % % % % +%%jfb %a% %* h L%c. . . .*% +% % % . k. .%*f L %%% +%C.*.a%%%*%%C.a lg.E%%%lc*. .*% +%%%%%%%*% %%*%k*%*%%*%. F Bi% +%l%*%*%%%.%%%%%%%%%%%%%*.i j % +%*d %lg.E D %ch*%E%%%%%%%%%% +% l.Di%*d L . %%%%% h % +%he . % . k. *% * * .AI.IA2% +%*. %%% c. *.e%%%%% f % +% g*E%*% b*%kF*%*g.E G.e*% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.06 : orchestration +level: 6 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*a h. %*% %J %DH d .*% +%bo oi.a%%%DgoE %%Dd.i .*% o .% +%*l .I.%cC. b %*.. %b% o % +% . % %%% goG%%%.1 oe% +%%%%%%%%% l .Ii%*. %*%*. % +%* j G% GoeJ%%%%%k.o %%%%%A% +% o % %*%*% L%*%*. la% +%A o %% %%%%%%%%%%%%%%%. . % +% 2 o % . *% h %d% % . % +% l o %c.%%oL %co.i%*/*% . % +% f %k*e% .*% *Da%j% o % +%%%%%%%%%%%A%%%%%%%%%%%%%% b .I% +%*% .o. %%h* l* .*% h *% +% %.o o.%*. .*.*. .*% .a%%%%%%% +%. o o o *b%%%% %%*%g*E% +%%%.o o.%%%%%%%%%G%% % d*l % +%*% .o. % .* .d.L o o % .o. % +%%%%%%%%% .o %%%% o o % o o % +% h *A%c* h .a*% o o %. o .% +% o.o.i%% o . %%% o o %I%.%C% +% b %D* %*% o o %f*f*f% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.07 : augmentation +level: 7 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*%*% D %*Ad %.%1 % 2%* %F%*% +%%%%%goH%%%k*L%*% l o d %co%%%%% +% %* .%.% %%a% D L %kK. . % +%C*A%%%%%*%* *%.% . . % . .% +% . % H % %%%%%%% * * % fDd j% +% b % . .*% . %% %%% %% c* j% +% b % h %a%%% %G.ehG.e%%%%%%C% +%G.E% *. % * .% %h% % l % +% * % %J% %%o B %%%%%%%%a . %.% +% f % b *%c. j %. Ha% *%K% +%%%%%%%%%%%%%%%%% * *ae%%%%%%%%% +% * %J%*l %*f . Fa% d % *.% +% d % C.a%H%.%%% %%%%%.K.%o%b% +% . h %%f %%L% *a% %. *% * * % +% D . H%% .%%/%% % o %.k.%%%%% +% . B .*% %%J%c* .L% .% f %G.e% +% o .f%%oe%F%%%%%D%kK*%%%%%kBa% +% L f % . %. % .* % l*% .i% +%k% l %c* %j . %%B%%% %h.a% b % +% % . *.i *%H b o J % . . %%b%% +%*b*%* %g*.%*e c*%%*%*%kL* *% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.08 : conflagration +level: 8 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*B.D.B*% l .*%*Bla* % H*%. L .% +%A.C.B.C% * .%%kgc. % *A% L1 % +%.A.b.D.%%%e. % d %c. %KK*II% +%C.a2c.A* o * .% .*.E%.o % J % +%.B.d.C.%%%*EE %* *%f *%. J .% +%A.D.A.C% f %fLe%%%%%%%%%%%%% +%*D.B.D*%*II%%l%%%*%E%*%I%*a *% +%%%%*%%%%%%%%*.*a%%%. D%%%cgoeG% +% % % %h h%BH %% h* . %. D .% +%kL%oii*%gH*%B. %c.j *% %%%%%%% +% * *. j% . % .%%% . . .*.*% +% k* %% .a% %%J% %%% f h% +%%%%%%%%%%%%I* %*i% j*%*%*D .a% +%. J .%*%d*%%%%%%%%%%%%% %%%%%%% +% g*i %%%.h%*.ae * c* .% * *i% +% B %* .%% %oC% L%h %f%I.i/%% +%h H % .i %*h% % .di %b%% *i% +%* %%% %d.k. %I * %%% d.%%% +%FD %E % %%* j h l%el % +%%L.*. la %%% g* %%%* *%dhae % +%*%b%f*a D*%D%H. %H%.aH%*.* L% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.09 : restoration +level: 9 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*h.aL% *i l k* % H %d* .%*%*d% +% * k.% H l H %gKoi%kh B%%%je% +% *% de%%%gD % .a%*. *%* % +%g.* % * . . * % D *%%% o % *% +%jc. *%. % % .%*D%%%* J B% +%%%%%%%%%%% %%%%%%%%*%%%.a H.%%% +%d .J%*%*%.*2 1E %%%G%b Jj%*% +%k. .C% %f%c%DDDD% . %f*%%%%%% +%Ag. %o%%% %....% L %%%% *d % +%* b * * .%*.%****% *a%*%* % % +%%% H .%%%%%%%%%%%% f %%%% H.e% +%*%* .ab%dl%*%C*.*A% . % *%%%% % +%.%%%%%%%kd%%%%kFi%%%%%% %%ck* % +%*a*% % *%c*%% . d .*%I%gkb. % +%.o .e* . %. .fcJ %%%%%%%%% +%b. %k* %%C%c.i%C%%%%%%%*% l . % +%I*.%% *%.% * %c* %D%.% d b % +%%%%%E c.%%% . %%%e%*jI%L* o f % +% %d%*cl %*%%*E%* .% .*%.% * J % +%*/*% L.%%%A .ai%*ji%*% j % +%j% %D . b*%D %L * %Bj.% h . f % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.10 : perturbation +level: 10 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%c*1D%*.* h % .*a % . %hd le% +%%%%%%%%g*%*% % .%*% %D%.%*. . % +%. %g. J %gk. C*A %%%%%%% +% K* K% *i%* .%.%B% % .a%*% +% .fEk*%a.Ad %%%c*% . %o* %%% +%c*f j% * *%.%*%%%%%% %%%%l*%C% +% .2 %*%%%%%%gG.%c.%c* *a%*b %.% +%%%%*%j%Gg. g* %%%%%. .%%%%%%G% +% *%%%E%.*g. j *%*B*%B*B% %*%%% +%co% %%% f * b% %.% F %ih *C% +% %%l%%%%%f% bf% f % %. % +% . *i%kg.B%C.ja.%G% J % %%K% % +% * .a%.a %* be %*% j % D% b % +% .F %glGkD . % %%%%% *% .*% +%.f l %jg*.%.%%%%%*k.%L % *G% +%f . %%%%b%*/*% %%%%%%%K*%ej.% +%I%%%%%% %%%b%j%ld c.G*% B%k*b% +%ch%*D %%%Laa*gj %%%%%%%% +%.i%c. . g*%he f K.% . .*a% +% .Ee *i .o d %H% *i%%B.f. % +%* %* J f . %*%D* j %* b f % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.11 : bifurcation +level: 11 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%l%H d . %* h%% h h .%D *% +%*%. . B j %. L lk.*a. B%*g. %% +% o D%%* % *. * % *aK% +%g. * %b%%% b*H Ge %L.i *% +% .* .aG%%%%%%%%%%%%%%%%%%%%%% +%a j %%%k%G. . %l %%%* . K*% +% .%I%%%*%%%* f%%B.a%h ga%%% +%k.f% %h%%% B. g. . G%. . g.A% +%d%%%*/*%k% . % b %%* %% +%*%cgbA %%%. b. %%% %%%%%. . Hi% +%%%%% G.eh%f. % d C%*f f o%% +%*B %%* %l% * *a%ck*e *%%A.a % +% .*d%b*%d% B f % g.* H%*%%%%*% +% bFK%%gb.%l% %%%%%%%%%%%%%*.%%% +%* .e % %.% .i *%h%d%* l .% +%.a * % %%g. Fiaei%..fl C% +% . .K%c% %%%%%% %%H% %% *a % +% c.f %L% % *% . %. % +% d * %%% %%B% * .e%BL *i% +%.I%H% .j D%oh%c* o %D%%%.2.I% +%*%j*f C. .% *%I%H*e bi%1%f b% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +chroma level + +title: chroma 2.12 : culmination +level: 12 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%***e%*% .%d%d%* Ji% % +%CCC%%H%kk* * %*/*% %I*i% *a.e% +%b .% .% d. J % %.% d %% % +%% %II%%cDFae % % %%% o.e%.k.*% +% %* .f j % l . *E% b % +%k. *% %k. *%%% h.j %%%*a % +%c. %%%%%%%%%%f%*% HcC* .%* b % +% K. o%B %%%%%%%%%l%%%F%%%%% +% *. *.e *%.d %kkd%%% % +% b *k% H %% o %***% *a% +%%%%%%%%%%%.e* % L %%%%% d % +%i % %%*k. dI% *.l % +% * .* d %....d%j . jA%* * % +%. l *a%jjbf*%%%%%%%%%% k*ee% +% %% h %%%%%%%%%* D%A%BK% dF % +% g% .AA% l% 2ec.B%%%%%%%% 1L%% +% * % * o % * %*. .a % +% % %%ji% h Lci% H K%f%. % % +% l %%%% %%%.% . *% D %%% *e % +%K. o%g*k. .%J% * %%%*i *%%%%%% +%j % %.L b .I%*% .iae%*% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + diff --git a/browser/preview-marble.svg b/browser/preview-marble.svg new file mode 100644 index 0000000..e8d6d5c --- /dev/null +++ b/browser/preview-marble.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/preview-neon.svg b/browser/preview-neon.svg new file mode 100644 index 0000000..491794c --- /dev/null +++ b/browser/preview-neon.svg @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/browser/preview-xor.svg b/browser/preview-xor.svg new file mode 100644 index 0000000..1c2c240 --- /dev/null +++ b/browser/preview-xor.svg @@ -0,0 +1,17 @@ + + + + +image/svg+xml + + + + + + + + + + + + diff --git a/browser/preview-zen.svg b/browser/preview-zen.svg new file mode 100644 index 0000000..960ada9 --- /dev/null +++ b/browser/preview-zen.svg @@ -0,0 +1,30 @@ + + + + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/chroma.h b/chroma.h new file mode 100644 index 0000000..96c8333 --- /dev/null +++ b/chroma.h @@ -0,0 +1,30 @@ +/* + chroma.h + + Copyright (C) 2010-2019 Amf + + 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 XOR_COMPATIBILITY +#define ENIGMA_COMPATIBILITY + +#define DEBUG_MENU 1 +#define DEBUG_ORDER 2 +#define DEBUG_SPEED 4 +#define DEBUG_MOVERS 8 +#define DEBUG_HIDDEN 16 + diff --git a/chroma.nsi b/chroma.nsi new file mode 100755 index 0000000..aeeb9c2 --- /dev/null +++ b/chroma.nsi @@ -0,0 +1,2723 @@ +; Script generated by the HM NIS Edit Script Wizard. + +; HM NIS Edit Wizard helper defines +!define PRODUCT_NAME "Chroma" +!define PRODUCT_VERSION "1.16" +!define PRODUCT_PUBLISHER "Amf" +!define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\chroma.exe" +!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" +!define PRODUCT_UNINST_ROOT_KEY "HKLM" + +; MUI 1.67 compatible ------ +!include "MUI.nsh" + +; MUI Settings +!define MUI_ABORTWARNING +!define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico" +!define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" + +; Welcome page +!insertmacro MUI_PAGE_WELCOME +; License page +;!insertmacro MUI_PAGE_LICENSE "..\..\..\..\path\to\licence\YourSoftwareLicence.txt" +; Directory page +!insertmacro MUI_PAGE_DIRECTORY +; Instfiles page +!insertmacro MUI_PAGE_INSTFILES +; Finish page +!insertmacro MUI_PAGE_FINISH + +; Uninstaller pages +!insertmacro MUI_UNPAGE_INSTFILES + +; Language files +!insertmacro MUI_LANGUAGE "English" + +; MUI end ------ + +Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" +OutFile "chroma-setup.exe" +InstallDir "$PROGRAMFILES\Chroma" +InstallDirRegKey HKLM "${PRODUCT_DIR_REGKEY}" "" +ShowInstDetails show +ShowUnInstDetails show + +Section "MainSection" SEC01 + SetOutPath "$INSTDIR" + SetOverwrite try + File "chroma.exe" + File "chroma-curses.exe" + File "COPYING" + File "README" + CreateDirectory "$SMPROGRAMS\Chroma" + CreateShortCut "$SMPROGRAMS\Chroma\Chroma.lnk" "$INSTDIR\chroma.exe" + CreateShortCut "$SMPROGRAMS\Chroma\Chroma Curses.lnk" "$INSTDIR\chroma-curses.exe" + CreateShortCut "$DESKTOP\Chroma.lnk" "$INSTDIR\chroma.exe" + SetOutPath "$INSTDIR\colours" + File "colours\chroma-enhanced.chroma" + File "colours\chroma-enigma.chroma" + File "colours\chroma-monochrome.chroma" + File "colours\chroma-reverse.chroma" + File "colours\chroma-standard.chroma" + File "colours\fallback.chroma" + SetOutPath "$INSTDIR\help" + File "help\README" + SetOutPath "$INSTDIR\graphics\chroma-marble" + File "graphics\chroma-marble\16_arrow_blue_down.png" + File "graphics\chroma-marble\16_arrow_blue_left.png" + File "graphics\chroma-marble\16_arrow_blue_right.png" + File "graphics\chroma-marble\16_arrow_blue_up.png" + File "graphics\chroma-marble\16_arrow_green_down.png" + File "graphics\chroma-marble\16_arrow_green_left.png" + File "graphics\chroma-marble\16_arrow_green_right.png" + File "graphics\chroma-marble\16_arrow_green_up.png" + File "graphics\chroma-marble\16_arrow_red_down.png" + File "graphics\chroma-marble\16_arrow_red_left.png" + File "graphics\chroma-marble\16_arrow_red_right.png" + File "graphics\chroma-marble\16_arrow_red_up.png" + File "graphics\chroma-marble\16_arrow_shadow_down.png" + File "graphics\chroma-marble\16_arrow_shadow_left.png" + File "graphics\chroma-marble\16_arrow_shadow_right.png" + File "graphics\chroma-marble\16_arrow_shadow_up.png" + File "graphics\chroma-marble\16_bomb_blue_down.png" + File "graphics\chroma-marble\16_bomb_blue_left.png" + File "graphics\chroma-marble\16_bomb_blue_right.png" + File "graphics\chroma-marble\16_bomb_blue_up.png" + File "graphics\chroma-marble\16_bomb_green_down.png" + File "graphics\chroma-marble\16_bomb_green_left.png" + File "graphics\chroma-marble\16_bomb_green_right.png" + File "graphics\chroma-marble\16_bomb_green_up.png" + File "graphics\chroma-marble\16_bomb_red_down.png" + File "graphics\chroma-marble\16_bomb_red_left.png" + File "graphics\chroma-marble\16_bomb_red_right.png" + File "graphics\chroma-marble\16_bomb_red_up.png" + File "graphics\chroma-marble\16_bomb_shadow_down.png" + File "graphics\chroma-marble\16_bomb_shadow_left.png" + File "graphics\chroma-marble\16_bomb_shadow_right.png" + File "graphics\chroma-marble\16_bomb_shadow_up.png" + File "graphics\chroma-marble\16_circle.png" + File "graphics\chroma-marble\16_circle_double.png" + File "graphics\chroma-marble\16_circle_double_shadow.png" + File "graphics\chroma-marble\16_circle_shadow.png" + File "graphics\chroma-marble\16_door.png" + File "graphics\chroma-marble\16_door_shadow.png" + File "graphics\chroma-marble\16_dots.png" + File "graphics\chroma-marble\16_dots_double.png" + File "graphics\chroma-marble\16_dots_double_shadow.png" + File "graphics\chroma-marble\16_dots_shadow.png" + File "graphics\chroma-marble\16_dots_x.png" + File "graphics\chroma-marble\16_dots_x_shadow.png" + File "graphics\chroma-marble\16_dots_y.png" + File "graphics\chroma-marble\16_dots_y_shadow.png" + File "graphics\chroma-marble\16_map_bottom_left.png" + File "graphics\chroma-marble\16_map_bottom_right.png" + File "graphics\chroma-marble\16_map_shadow.png" + File "graphics\chroma-marble\16_map_top_left.png" + File "graphics\chroma-marble\16_map_top_right.png" + File "graphics\chroma-marble\16_player_one.png" + File "graphics\chroma-marble\16_player_one_swapped.png" + File "graphics\chroma-marble\16_player_shadow.png" + File "graphics\chroma-marble\16_player_two.png" + File "graphics\chroma-marble\16_player_two_swapped.png" + File "graphics\chroma-marble\16_space.png" + File "graphics\chroma-marble\16_star.png" + File "graphics\chroma-marble\16_star_shadow.png" + File "graphics\chroma-marble\16_switch.png" + File "graphics\chroma-marble\16_switch_shadow.png" + File "graphics\chroma-marble\16_teleport.png" + File "graphics\chroma-marble\16_teleport_shadow.png" + File "graphics\chroma-marble\16_wall.png" + File "graphics\chroma-marble\16_wall_inside.png" + File "graphics\chroma-marble\16_wall_inside_shadow.png" + File "graphics\chroma-marble\16_wall_outside.png" + File "graphics\chroma-marble\16_wall_outside_shadow.png" + File "graphics\chroma-marble\16_wall_x.png" + File "graphics\chroma-marble\16_wall_x_shadow.png" + File "graphics\chroma-marble\16_wall_y.png" + File "graphics\chroma-marble\16_wall_y_shadow.png" + File "graphics\chroma-marble\20_arrow_blue_down.png" + File "graphics\chroma-marble\20_arrow_blue_left.png" + File "graphics\chroma-marble\20_arrow_blue_right.png" + File "graphics\chroma-marble\20_arrow_blue_up.png" + File "graphics\chroma-marble\20_arrow_green_down.png" + File "graphics\chroma-marble\20_arrow_green_left.png" + File "graphics\chroma-marble\20_arrow_green_right.png" + File "graphics\chroma-marble\20_arrow_green_up.png" + File "graphics\chroma-marble\20_arrow_red_down.png" + File "graphics\chroma-marble\20_arrow_red_left.png" + File "graphics\chroma-marble\20_arrow_red_right.png" + File "graphics\chroma-marble\20_arrow_red_up.png" + File "graphics\chroma-marble\20_arrow_shadow_down.png" + File "graphics\chroma-marble\20_arrow_shadow_left.png" + File "graphics\chroma-marble\20_arrow_shadow_right.png" + File "graphics\chroma-marble\20_arrow_shadow_up.png" + File "graphics\chroma-marble\20_bomb_blue_down.png" + File "graphics\chroma-marble\20_bomb_blue_left.png" + File "graphics\chroma-marble\20_bomb_blue_right.png" + File "graphics\chroma-marble\20_bomb_blue_up.png" + File "graphics\chroma-marble\20_bomb_green_down.png" + File "graphics\chroma-marble\20_bomb_green_left.png" + File "graphics\chroma-marble\20_bomb_green_right.png" + File "graphics\chroma-marble\20_bomb_green_up.png" + File "graphics\chroma-marble\20_bomb_red_down.png" + File "graphics\chroma-marble\20_bomb_red_left.png" + File "graphics\chroma-marble\20_bomb_red_right.png" + File "graphics\chroma-marble\20_bomb_red_up.png" + File "graphics\chroma-marble\20_bomb_shadow_down.png" + File "graphics\chroma-marble\20_bomb_shadow_left.png" + File "graphics\chroma-marble\20_bomb_shadow_right.png" + File "graphics\chroma-marble\20_bomb_shadow_up.png" + File "graphics\chroma-marble\20_circle.png" + File "graphics\chroma-marble\20_circle_double.png" + File "graphics\chroma-marble\20_circle_double_shadow.png" + File "graphics\chroma-marble\20_circle_shadow.png" + File "graphics\chroma-marble\20_door.png" + File "graphics\chroma-marble\20_door_shadow.png" + File "graphics\chroma-marble\20_dots.png" + File "graphics\chroma-marble\20_dots_double.png" + File "graphics\chroma-marble\20_dots_double_shadow.png" + File "graphics\chroma-marble\20_dots_shadow.png" + File "graphics\chroma-marble\20_dots_x.png" + File "graphics\chroma-marble\20_dots_x_shadow.png" + File "graphics\chroma-marble\20_dots_y.png" + File "graphics\chroma-marble\20_dots_y_shadow.png" + File "graphics\chroma-marble\20_map_bottom_left.png" + File "graphics\chroma-marble\20_map_bottom_right.png" + File "graphics\chroma-marble\20_map_shadow.png" + File "graphics\chroma-marble\20_map_top_left.png" + File "graphics\chroma-marble\20_map_top_right.png" + File "graphics\chroma-marble\20_player_one.png" + File "graphics\chroma-marble\20_player_one_swapped.png" + File "graphics\chroma-marble\20_player_shadow.png" + File "graphics\chroma-marble\20_player_two.png" + File "graphics\chroma-marble\20_player_two_swapped.png" + File "graphics\chroma-marble\20_space.png" + File "graphics\chroma-marble\20_star.png" + File "graphics\chroma-marble\20_star_shadow.png" + File "graphics\chroma-marble\20_switch.png" + File "graphics\chroma-marble\20_switch_shadow.png" + File "graphics\chroma-marble\20_teleport.png" + File "graphics\chroma-marble\20_teleport_shadow.png" + File "graphics\chroma-marble\20_wall.png" + File "graphics\chroma-marble\20_wall_inside.png" + File "graphics\chroma-marble\20_wall_inside_shadow.png" + File "graphics\chroma-marble\20_wall_outside.png" + File "graphics\chroma-marble\20_wall_outside_shadow.png" + File "graphics\chroma-marble\20_wall_x.png" + File "graphics\chroma-marble\20_wall_x_shadow.png" + File "graphics\chroma-marble\20_wall_y.png" + File "graphics\chroma-marble\20_wall_y_shadow.png" + File "graphics\chroma-marble\24_arrow_blue_down.png" + File "graphics\chroma-marble\24_arrow_blue_left.png" + File "graphics\chroma-marble\24_arrow_blue_right.png" + File "graphics\chroma-marble\24_arrow_blue_up.png" + File "graphics\chroma-marble\24_arrow_green_down.png" + File "graphics\chroma-marble\24_arrow_green_left.png" + File "graphics\chroma-marble\24_arrow_green_right.png" + File "graphics\chroma-marble\24_arrow_green_up.png" + File "graphics\chroma-marble\24_arrow_red_down.png" + File "graphics\chroma-marble\24_arrow_red_left.png" + File "graphics\chroma-marble\24_arrow_red_right.png" + File "graphics\chroma-marble\24_arrow_red_up.png" + File "graphics\chroma-marble\24_arrow_shadow_down.png" + File "graphics\chroma-marble\24_arrow_shadow_left.png" + File "graphics\chroma-marble\24_arrow_shadow_right.png" + File "graphics\chroma-marble\24_arrow_shadow_up.png" + File "graphics\chroma-marble\24_bomb_blue_down.png" + File "graphics\chroma-marble\24_bomb_blue_left.png" + File "graphics\chroma-marble\24_bomb_blue_right.png" + File "graphics\chroma-marble\24_bomb_blue_up.png" + File "graphics\chroma-marble\24_bomb_green_down.png" + File "graphics\chroma-marble\24_bomb_green_left.png" + File "graphics\chroma-marble\24_bomb_green_right.png" + File "graphics\chroma-marble\24_bomb_green_up.png" + File "graphics\chroma-marble\24_bomb_red_down.png" + File "graphics\chroma-marble\24_bomb_red_left.png" + File "graphics\chroma-marble\24_bomb_red_right.png" + File "graphics\chroma-marble\24_bomb_red_up.png" + File "graphics\chroma-marble\24_bomb_shadow_down.png" + File "graphics\chroma-marble\24_bomb_shadow_left.png" + File "graphics\chroma-marble\24_bomb_shadow_right.png" + File "graphics\chroma-marble\24_bomb_shadow_up.png" + File "graphics\chroma-marble\24_circle.png" + File "graphics\chroma-marble\24_circle_double.png" + File "graphics\chroma-marble\24_circle_double_shadow.png" + File "graphics\chroma-marble\24_circle_shadow.png" + File "graphics\chroma-marble\24_door.png" + File "graphics\chroma-marble\24_door_shadow.png" + File "graphics\chroma-marble\24_dots.png" + File "graphics\chroma-marble\24_dots_double.png" + File "graphics\chroma-marble\24_dots_double_shadow.png" + File "graphics\chroma-marble\24_dots_shadow.png" + File "graphics\chroma-marble\24_dots_x.png" + File "graphics\chroma-marble\24_dots_x_shadow.png" + File "graphics\chroma-marble\24_dots_y.png" + File "graphics\chroma-marble\24_dots_y_shadow.png" + File "graphics\chroma-marble\24_map_bottom_left.png" + File "graphics\chroma-marble\24_map_bottom_right.png" + File "graphics\chroma-marble\24_map_shadow.png" + File "graphics\chroma-marble\24_map_top_left.png" + File "graphics\chroma-marble\24_map_top_right.png" + File "graphics\chroma-marble\24_player_one.png" + File "graphics\chroma-marble\24_player_one_swapped.png" + File "graphics\chroma-marble\24_player_shadow.png" + File "graphics\chroma-marble\24_player_two.png" + File "graphics\chroma-marble\24_player_two_swapped.png" + File "graphics\chroma-marble\24_space.png" + File "graphics\chroma-marble\24_star.png" + File "graphics\chroma-marble\24_star_shadow.png" + File "graphics\chroma-marble\24_switch.png" + File "graphics\chroma-marble\24_switch_shadow.png" + File "graphics\chroma-marble\24_teleport.png" + File "graphics\chroma-marble\24_teleport_shadow.png" + File "graphics\chroma-marble\24_wall.png" + File "graphics\chroma-marble\24_wall_inside.png" + File "graphics\chroma-marble\24_wall_inside_shadow.png" + File "graphics\chroma-marble\24_wall_outside.png" + File "graphics\chroma-marble\24_wall_outside_shadow.png" + File "graphics\chroma-marble\24_wall_x.png" + File "graphics\chroma-marble\24_wall_x_shadow.png" + File "graphics\chroma-marble\24_wall_y.png" + File "graphics\chroma-marble\24_wall_y_shadow.png" + File "graphics\chroma-marble\32_arrow_blue_down.png" + File "graphics\chroma-marble\32_arrow_blue_left.png" + File "graphics\chroma-marble\32_arrow_blue_right.png" + File "graphics\chroma-marble\32_arrow_blue_up.png" + File "graphics\chroma-marble\32_arrow_green_down.png" + File "graphics\chroma-marble\32_arrow_green_left.png" + File "graphics\chroma-marble\32_arrow_green_right.png" + File "graphics\chroma-marble\32_arrow_green_up.png" + File "graphics\chroma-marble\32_arrow_red_down.png" + File "graphics\chroma-marble\32_arrow_red_left.png" + File "graphics\chroma-marble\32_arrow_red_right.png" + File "graphics\chroma-marble\32_arrow_red_up.png" + File "graphics\chroma-marble\32_arrow_shadow_down.png" + File "graphics\chroma-marble\32_arrow_shadow_left.png" + File "graphics\chroma-marble\32_arrow_shadow_right.png" + File "graphics\chroma-marble\32_arrow_shadow_up.png" + File "graphics\chroma-marble\32_bomb_blue_down.png" + File "graphics\chroma-marble\32_bomb_blue_left.png" + File "graphics\chroma-marble\32_bomb_blue_right.png" + File "graphics\chroma-marble\32_bomb_blue_up.png" + File "graphics\chroma-marble\32_bomb_green_down.png" + File "graphics\chroma-marble\32_bomb_green_left.png" + File "graphics\chroma-marble\32_bomb_green_right.png" + File "graphics\chroma-marble\32_bomb_green_up.png" + File "graphics\chroma-marble\32_bomb_red_down.png" + File "graphics\chroma-marble\32_bomb_red_left.png" + File "graphics\chroma-marble\32_bomb_red_right.png" + File "graphics\chroma-marble\32_bomb_red_up.png" + File "graphics\chroma-marble\32_bomb_shadow_down.png" + File "graphics\chroma-marble\32_bomb_shadow_left.png" + File "graphics\chroma-marble\32_bomb_shadow_right.png" + File "graphics\chroma-marble\32_bomb_shadow_up.png" + File "graphics\chroma-marble\32_circle.png" + File "graphics\chroma-marble\32_circle_double.png" + File "graphics\chroma-marble\32_circle_double_shadow.png" + File "graphics\chroma-marble\32_circle_shadow.png" + File "graphics\chroma-marble\32_door.png" + File "graphics\chroma-marble\32_door_shadow.png" + File "graphics\chroma-marble\32_dots.png" + File "graphics\chroma-marble\32_dots_double.png" + File "graphics\chroma-marble\32_dots_double_shadow.png" + File "graphics\chroma-marble\32_dots_shadow.png" + File "graphics\chroma-marble\32_dots_x.png" + File "graphics\chroma-marble\32_dots_x_shadow.png" + File "graphics\chroma-marble\32_dots_y.png" + File "graphics\chroma-marble\32_dots_y_shadow.png" + File "graphics\chroma-marble\32_map_bottom_left.png" + File "graphics\chroma-marble\32_map_bottom_right.png" + File "graphics\chroma-marble\32_map_shadow.png" + File "graphics\chroma-marble\32_map_top_left.png" + File "graphics\chroma-marble\32_map_top_right.png" + File "graphics\chroma-marble\32_player_one.png" + File "graphics\chroma-marble\32_player_one_swapped.png" + File "graphics\chroma-marble\32_player_shadow.png" + File "graphics\chroma-marble\32_player_two.png" + File "graphics\chroma-marble\32_player_two_swapped.png" + File "graphics\chroma-marble\32_space.png" + File "graphics\chroma-marble\32_star.png" + File "graphics\chroma-marble\32_star_shadow.png" + File "graphics\chroma-marble\32_switch.png" + File "graphics\chroma-marble\32_switch_shadow.png" + File "graphics\chroma-marble\32_teleport.png" + File "graphics\chroma-marble\32_teleport_shadow.png" + File "graphics\chroma-marble\32_wall.png" + File "graphics\chroma-marble\32_wall_inside.png" + File "graphics\chroma-marble\32_wall_inside_shadow.png" + File "graphics\chroma-marble\32_wall_outside.png" + File "graphics\chroma-marble\32_wall_outside_shadow.png" + File "graphics\chroma-marble\32_wall_x.png" + File "graphics\chroma-marble\32_wall_x_shadow.png" + File "graphics\chroma-marble\32_wall_y.png" + File "graphics\chroma-marble\32_wall_y_shadow.png" + File "graphics\chroma-marble\40_arrow_blue_down.png" + File "graphics\chroma-marble\40_arrow_blue_left.png" + File "graphics\chroma-marble\40_arrow_blue_right.png" + File "graphics\chroma-marble\40_arrow_blue_up.png" + File "graphics\chroma-marble\40_arrow_green_down.png" + File "graphics\chroma-marble\40_arrow_green_left.png" + File "graphics\chroma-marble\40_arrow_green_right.png" + File "graphics\chroma-marble\40_arrow_green_up.png" + File "graphics\chroma-marble\40_arrow_red_down.png" + File "graphics\chroma-marble\40_arrow_red_left.png" + File "graphics\chroma-marble\40_arrow_red_right.png" + File "graphics\chroma-marble\40_arrow_red_up.png" + File "graphics\chroma-marble\40_arrow_shadow_down.png" + File "graphics\chroma-marble\40_arrow_shadow_left.png" + File "graphics\chroma-marble\40_arrow_shadow_right.png" + File "graphics\chroma-marble\40_arrow_shadow_up.png" + File "graphics\chroma-marble\40_bomb_blue_down.png" + File "graphics\chroma-marble\40_bomb_blue_left.png" + File "graphics\chroma-marble\40_bomb_blue_right.png" + File "graphics\chroma-marble\40_bomb_blue_up.png" + File "graphics\chroma-marble\40_bomb_green_down.png" + File "graphics\chroma-marble\40_bomb_green_left.png" + File "graphics\chroma-marble\40_bomb_green_right.png" + File "graphics\chroma-marble\40_bomb_green_up.png" + File "graphics\chroma-marble\40_bomb_red_down.png" + File "graphics\chroma-marble\40_bomb_red_left.png" + File "graphics\chroma-marble\40_bomb_red_right.png" + File "graphics\chroma-marble\40_bomb_red_up.png" + File "graphics\chroma-marble\40_bomb_shadow_down.png" + File "graphics\chroma-marble\40_bomb_shadow_left.png" + File "graphics\chroma-marble\40_bomb_shadow_right.png" + File "graphics\chroma-marble\40_bomb_shadow_up.png" + File "graphics\chroma-marble\40_circle.png" + File "graphics\chroma-marble\40_circle_double.png" + File "graphics\chroma-marble\40_circle_double_shadow.png" + File "graphics\chroma-marble\40_circle_shadow.png" + File "graphics\chroma-marble\40_door.png" + File "graphics\chroma-marble\40_door_shadow.png" + File "graphics\chroma-marble\40_dots.png" + File "graphics\chroma-marble\40_dots_double.png" + File "graphics\chroma-marble\40_dots_double_shadow.png" + File "graphics\chroma-marble\40_dots_shadow.png" + File "graphics\chroma-marble\40_dots_x.png" + File "graphics\chroma-marble\40_dots_x_shadow.png" + File "graphics\chroma-marble\40_dots_y.png" + File "graphics\chroma-marble\40_dots_y_shadow.png" + File "graphics\chroma-marble\40_map_bottom_left.png" + File "graphics\chroma-marble\40_map_bottom_right.png" + File "graphics\chroma-marble\40_map_shadow.png" + File "graphics\chroma-marble\40_map_top_left.png" + File "graphics\chroma-marble\40_map_top_right.png" + File "graphics\chroma-marble\40_player_one.png" + File "graphics\chroma-marble\40_player_one_swapped.png" + File "graphics\chroma-marble\40_player_shadow.png" + File "graphics\chroma-marble\40_player_two.png" + File "graphics\chroma-marble\40_player_two_swapped.png" + File "graphics\chroma-marble\40_space.png" + File "graphics\chroma-marble\40_star.png" + File "graphics\chroma-marble\40_star_shadow.png" + File "graphics\chroma-marble\40_switch.png" + File "graphics\chroma-marble\40_switch_shadow.png" + File "graphics\chroma-marble\40_teleport.png" + File "graphics\chroma-marble\40_teleport_shadow.png" + File "graphics\chroma-marble\40_wall.png" + File "graphics\chroma-marble\40_wall_inside.png" + File "graphics\chroma-marble\40_wall_inside_shadow.png" + File "graphics\chroma-marble\40_wall_outside.png" + File "graphics\chroma-marble\40_wall_outside_shadow.png" + File "graphics\chroma-marble\40_wall_x.png" + File "graphics\chroma-marble\40_wall_x_shadow.png" + File "graphics\chroma-marble\40_wall_y.png" + File "graphics\chroma-marble\40_wall_y_shadow.png" + File "graphics\chroma-marble\64_arrow_blue_down.png" + File "graphics\chroma-marble\64_arrow_blue_left.png" + File "graphics\chroma-marble\64_arrow_blue_right.png" + File "graphics\chroma-marble\64_arrow_blue_up.png" + File "graphics\chroma-marble\64_arrow_green_down.png" + File "graphics\chroma-marble\64_arrow_green_left.png" + File "graphics\chroma-marble\64_arrow_green_right.png" + File "graphics\chroma-marble\64_arrow_green_up.png" + File "graphics\chroma-marble\64_arrow_red_down.png" + File "graphics\chroma-marble\64_arrow_red_left.png" + File "graphics\chroma-marble\64_arrow_red_right.png" + File "graphics\chroma-marble\64_arrow_red_up.png" + File "graphics\chroma-marble\64_arrow_shadow_down.png" + File "graphics\chroma-marble\64_arrow_shadow_left.png" + File "graphics\chroma-marble\64_arrow_shadow_right.png" + File "graphics\chroma-marble\64_arrow_shadow_up.png" + File "graphics\chroma-marble\64_bomb_blue_down.png" + File "graphics\chroma-marble\64_bomb_blue_left.png" + File "graphics\chroma-marble\64_bomb_blue_right.png" + File "graphics\chroma-marble\64_bomb_blue_up.png" + File "graphics\chroma-marble\64_bomb_green_down.png" + File "graphics\chroma-marble\64_bomb_green_left.png" + File "graphics\chroma-marble\64_bomb_green_right.png" + File "graphics\chroma-marble\64_bomb_green_up.png" + File "graphics\chroma-marble\64_bomb_red_down.png" + File "graphics\chroma-marble\64_bomb_red_left.png" + File "graphics\chroma-marble\64_bomb_red_right.png" + File "graphics\chroma-marble\64_bomb_red_up.png" + File "graphics\chroma-marble\64_bomb_shadow_down.png" + File "graphics\chroma-marble\64_bomb_shadow_left.png" + File "graphics\chroma-marble\64_bomb_shadow_right.png" + File "graphics\chroma-marble\64_bomb_shadow_up.png" + File "graphics\chroma-marble\64_circle.png" + File "graphics\chroma-marble\64_circle_double.png" + File "graphics\chroma-marble\64_circle_double_shadow.png" + File "graphics\chroma-marble\64_circle_shadow.png" + File "graphics\chroma-marble\64_door.png" + File "graphics\chroma-marble\64_door_shadow.png" + File "graphics\chroma-marble\64_dots.png" + File "graphics\chroma-marble\64_dots_double.png" + File "graphics\chroma-marble\64_dots_double_shadow.png" + File "graphics\chroma-marble\64_dots_shadow.png" + File "graphics\chroma-marble\64_dots_x.png" + File "graphics\chroma-marble\64_dots_x_shadow.png" + File "graphics\chroma-marble\64_dots_y.png" + File "graphics\chroma-marble\64_dots_y_shadow.png" + File "graphics\chroma-marble\64_map_bottom_left.png" + File "graphics\chroma-marble\64_map_bottom_right.png" + File "graphics\chroma-marble\64_map_shadow.png" + File "graphics\chroma-marble\64_map_top_left.png" + File "graphics\chroma-marble\64_map_top_right.png" + File "graphics\chroma-marble\64_player_one.png" + File "graphics\chroma-marble\64_player_one_swapped.png" + File "graphics\chroma-marble\64_player_shadow.png" + File "graphics\chroma-marble\64_player_two.png" + File "graphics\chroma-marble\64_player_two_swapped.png" + File "graphics\chroma-marble\64_space.png" + File "graphics\chroma-marble\64_star.png" + File "graphics\chroma-marble\64_star_shadow.png" + File "graphics\chroma-marble\64_switch.png" + File "graphics\chroma-marble\64_switch_shadow.png" + File "graphics\chroma-marble\64_teleport.png" + File "graphics\chroma-marble\64_teleport_shadow.png" + File "graphics\chroma-marble\64_wall.png" + File "graphics\chroma-marble\64_wall_inside.png" + File "graphics\chroma-marble\64_wall_inside_shadow.png" + File "graphics\chroma-marble\64_wall_outside.png" + File "graphics\chroma-marble\64_wall_outside_shadow.png" + File "graphics\chroma-marble\64_wall_x.png" + File "graphics\chroma-marble\64_wall_x_shadow.png" + File "graphics\chroma-marble\64_wall_y.png" + File "graphics\chroma-marble\64_wall_y_shadow.png" + SetOutPath "$INSTDIR\graphics" + File "graphics\chroma-marble.chroma" + SetOutPath "$INSTDIR\graphics\chroma-neon" + File "graphics\chroma-neon\16_arrow_blue_down.png" + File "graphics\chroma-neon\16_arrow_blue_down_shadow.png" + File "graphics\chroma-neon\16_arrow_blue_left.png" + File "graphics\chroma-neon\16_arrow_blue_left_shadow.png" + File "graphics\chroma-neon\16_arrow_blue_right.png" + File "graphics\chroma-neon\16_arrow_blue_right_shadow.png" + File "graphics\chroma-neon\16_arrow_blue_up.png" + File "graphics\chroma-neon\16_arrow_blue_up_shadow.png" + File "graphics\chroma-neon\16_arrow_green_down.png" + File "graphics\chroma-neon\16_arrow_green_down_shadow.png" + File "graphics\chroma-neon\16_arrow_green_left.png" + File "graphics\chroma-neon\16_arrow_green_left_shadow.png" + File "graphics\chroma-neon\16_arrow_green_right.png" + File "graphics\chroma-neon\16_arrow_green_right_shadow.png" + File "graphics\chroma-neon\16_arrow_green_up.png" + File "graphics\chroma-neon\16_arrow_green_up_shadow.png" + File "graphics\chroma-neon\16_arrow_red_down.png" + File "graphics\chroma-neon\16_arrow_red_down_shadow.png" + File "graphics\chroma-neon\16_arrow_red_left.png" + File "graphics\chroma-neon\16_arrow_red_left_shadow.png" + File "graphics\chroma-neon\16_arrow_red_right.png" + File "graphics\chroma-neon\16_arrow_red_right_shadow.png" + File "graphics\chroma-neon\16_arrow_red_up.png" + File "graphics\chroma-neon\16_arrow_red_up_shadow.png" + File "graphics\chroma-neon\16_bomb_blue_down.png" + File "graphics\chroma-neon\16_bomb_blue_down_shadow.png" + File "graphics\chroma-neon\16_bomb_blue_left.png" + File "graphics\chroma-neon\16_bomb_blue_left_shadow.png" + File "graphics\chroma-neon\16_bomb_blue_right.png" + File "graphics\chroma-neon\16_bomb_blue_right_shadow.png" + File "graphics\chroma-neon\16_bomb_blue_up.png" + File "graphics\chroma-neon\16_bomb_blue_up_shadow.png" + File "graphics\chroma-neon\16_bomb_green_down.png" + File "graphics\chroma-neon\16_bomb_green_down_shadow.png" + File "graphics\chroma-neon\16_bomb_green_left.png" + File "graphics\chroma-neon\16_bomb_green_left_shadow.png" + File "graphics\chroma-neon\16_bomb_green_right.png" + File "graphics\chroma-neon\16_bomb_green_right_shadow.png" + File "graphics\chroma-neon\16_bomb_green_up.png" + File "graphics\chroma-neon\16_bomb_green_up_shadow.png" + File "graphics\chroma-neon\16_bomb_red_down.png" + File "graphics\chroma-neon\16_bomb_red_down_shadow.png" + File "graphics\chroma-neon\16_bomb_red_left.png" + File "graphics\chroma-neon\16_bomb_red_left_shadow.png" + File "graphics\chroma-neon\16_bomb_red_right.png" + File "graphics\chroma-neon\16_bomb_red_right_shadow.png" + File "graphics\chroma-neon\16_bomb_red_up.png" + File "graphics\chroma-neon\16_bomb_red_up_shadow.png" + File "graphics\chroma-neon\16_circle.png" + File "graphics\chroma-neon\16_circle_double.png" + File "graphics\chroma-neon\16_circle_double_shadow.png" + File "graphics\chroma-neon\16_circle_shadow.png" + File "graphics\chroma-neon\16_door.png" + File "graphics\chroma-neon\16_door_shadow.png" + File "graphics\chroma-neon\16_dots.png" + File "graphics\chroma-neon\16_dots_double.png" + File "graphics\chroma-neon\16_dots_double_shadow.png" + File "graphics\chroma-neon\16_dots_shadow.png" + File "graphics\chroma-neon\16_dots_x.png" + File "graphics\chroma-neon\16_dots_x_shadow.png" + File "graphics\chroma-neon\16_dots_y.png" + File "graphics\chroma-neon\16_dots_y_shadow.png" + File "graphics\chroma-neon\16_map_bottom_left.png" + File "graphics\chroma-neon\16_map_bottom_left_shadow.png" + File "graphics\chroma-neon\16_map_bottom_right.png" + File "graphics\chroma-neon\16_map_bottom_right_shadow.png" + File "graphics\chroma-neon\16_map_top_left.png" + File "graphics\chroma-neon\16_map_top_left_shadow.png" + File "graphics\chroma-neon\16_map_top_right.png" + File "graphics\chroma-neon\16_map_top_right_shadow.png" + File "graphics\chroma-neon\16_player_one.png" + File "graphics\chroma-neon\16_player_one_shadow.png" + File "graphics\chroma-neon\16_player_one_swapped.png" + File "graphics\chroma-neon\16_player_one_swapped_shadow.png" + File "graphics\chroma-neon\16_player_two.png" + File "graphics\chroma-neon\16_player_two_shadow.png" + File "graphics\chroma-neon\16_player_two_swapped.png" + File "graphics\chroma-neon\16_player_two_swapped_shadow.png" + File "graphics\chroma-neon\16_star.png" + File "graphics\chroma-neon\16_star_shadow.png" + File "graphics\chroma-neon\16_switch.png" + File "graphics\chroma-neon\16_switch_shadow.png" + File "graphics\chroma-neon\16_teleport.png" + File "graphics\chroma-neon\16_teleport_shadow.png" + File "graphics\chroma-neon\16_wall.png" + File "graphics\chroma-neon\16_wall_inside.png" + File "graphics\chroma-neon\16_wall_outside.png" + File "graphics\chroma-neon\16_wall_shadow.png" + File "graphics\chroma-neon\16_wall_x.png" + File "graphics\chroma-neon\16_wall_y.png" + File "graphics\chroma-neon\20_arrow_blue_down.png" + File "graphics\chroma-neon\20_arrow_blue_down_shadow.png" + File "graphics\chroma-neon\20_arrow_blue_left.png" + File "graphics\chroma-neon\20_arrow_blue_left_shadow.png" + File "graphics\chroma-neon\20_arrow_blue_right.png" + File "graphics\chroma-neon\20_arrow_blue_right_shadow.png" + File "graphics\chroma-neon\20_arrow_blue_up.png" + File "graphics\chroma-neon\20_arrow_blue_up_shadow.png" + File "graphics\chroma-neon\20_arrow_green_down.png" + File "graphics\chroma-neon\20_arrow_green_down_shadow.png" + File "graphics\chroma-neon\20_arrow_green_left.png" + File "graphics\chroma-neon\20_arrow_green_left_shadow.png" + File "graphics\chroma-neon\20_arrow_green_right.png" + File "graphics\chroma-neon\20_arrow_green_right_shadow.png" + File "graphics\chroma-neon\20_arrow_green_up.png" + File "graphics\chroma-neon\20_arrow_green_up_shadow.png" + File "graphics\chroma-neon\20_arrow_red_down.png" + File "graphics\chroma-neon\20_arrow_red_down_shadow.png" + File "graphics\chroma-neon\20_arrow_red_left.png" + File "graphics\chroma-neon\20_arrow_red_left_shadow.png" + File "graphics\chroma-neon\20_arrow_red_right.png" + File "graphics\chroma-neon\20_arrow_red_right_shadow.png" + File "graphics\chroma-neon\20_arrow_red_up.png" + File "graphics\chroma-neon\20_arrow_red_up_shadow.png" + File "graphics\chroma-neon\20_bomb_blue_down.png" + File "graphics\chroma-neon\20_bomb_blue_down_shadow.png" + File "graphics\chroma-neon\20_bomb_blue_left.png" + File "graphics\chroma-neon\20_bomb_blue_left_shadow.png" + File "graphics\chroma-neon\20_bomb_blue_right.png" + File "graphics\chroma-neon\20_bomb_blue_right_shadow.png" + File "graphics\chroma-neon\20_bomb_blue_up.png" + File "graphics\chroma-neon\20_bomb_blue_up_shadow.png" + File "graphics\chroma-neon\20_bomb_green_down.png" + File "graphics\chroma-neon\20_bomb_green_down_shadow.png" + File "graphics\chroma-neon\20_bomb_green_left.png" + File "graphics\chroma-neon\20_bomb_green_left_shadow.png" + File "graphics\chroma-neon\20_bomb_green_right.png" + File "graphics\chroma-neon\20_bomb_green_right_shadow.png" + File "graphics\chroma-neon\20_bomb_green_up.png" + File "graphics\chroma-neon\20_bomb_green_up_shadow.png" + File "graphics\chroma-neon\20_bomb_red_down.png" + File "graphics\chroma-neon\20_bomb_red_down_shadow.png" + File "graphics\chroma-neon\20_bomb_red_left.png" + File "graphics\chroma-neon\20_bomb_red_left_shadow.png" + File "graphics\chroma-neon\20_bomb_red_right.png" + File "graphics\chroma-neon\20_bomb_red_right_shadow.png" + File "graphics\chroma-neon\20_bomb_red_up.png" + File "graphics\chroma-neon\20_bomb_red_up_shadow.png" + File "graphics\chroma-neon\20_circle.png" + File "graphics\chroma-neon\20_circle_double.png" + File "graphics\chroma-neon\20_circle_double_shadow.png" + File "graphics\chroma-neon\20_circle_shadow.png" + File "graphics\chroma-neon\20_door.png" + File "graphics\chroma-neon\20_door_shadow.png" + File "graphics\chroma-neon\20_dots.png" + File "graphics\chroma-neon\20_dots_double.png" + File "graphics\chroma-neon\20_dots_double_shadow.png" + File "graphics\chroma-neon\20_dots_shadow.png" + File "graphics\chroma-neon\20_dots_x.png" + File "graphics\chroma-neon\20_dots_x_shadow.png" + File "graphics\chroma-neon\20_dots_y.png" + File "graphics\chroma-neon\20_dots_y_shadow.png" + File "graphics\chroma-neon\20_map_bottom_left.png" + File "graphics\chroma-neon\20_map_bottom_left_shadow.png" + File "graphics\chroma-neon\20_map_bottom_right.png" + File "graphics\chroma-neon\20_map_bottom_right_shadow.png" + File "graphics\chroma-neon\20_map_top_left.png" + File "graphics\chroma-neon\20_map_top_left_shadow.png" + File "graphics\chroma-neon\20_map_top_right.png" + File "graphics\chroma-neon\20_map_top_right_shadow.png" + File "graphics\chroma-neon\20_player_one.png" + File "graphics\chroma-neon\20_player_one_shadow.png" + File "graphics\chroma-neon\20_player_one_swapped.png" + File "graphics\chroma-neon\20_player_one_swapped_shadow.png" + File "graphics\chroma-neon\20_player_two.png" + File "graphics\chroma-neon\20_player_two_shadow.png" + File "graphics\chroma-neon\20_player_two_swapped.png" + File "graphics\chroma-neon\20_player_two_swapped_shadow.png" + File "graphics\chroma-neon\20_star.png" + File "graphics\chroma-neon\20_star_shadow.png" + File "graphics\chroma-neon\20_switch.png" + File "graphics\chroma-neon\20_switch_shadow.png" + File "graphics\chroma-neon\20_teleport.png" + File "graphics\chroma-neon\20_teleport_shadow.png" + File "graphics\chroma-neon\20_wall.png" + File "graphics\chroma-neon\20_wall_inside.png" + File "graphics\chroma-neon\20_wall_outside.png" + File "graphics\chroma-neon\20_wall_shadow.png" + File "graphics\chroma-neon\20_wall_x.png" + File "graphics\chroma-neon\20_wall_y.png" + File "graphics\chroma-neon\24_arrow_blue_down.png" + File "graphics\chroma-neon\24_arrow_blue_down_shadow.png" + File "graphics\chroma-neon\24_arrow_blue_left.png" + File "graphics\chroma-neon\24_arrow_blue_left_shadow.png" + File "graphics\chroma-neon\24_arrow_blue_right.png" + File "graphics\chroma-neon\24_arrow_blue_right_shadow.png" + File "graphics\chroma-neon\24_arrow_blue_up.png" + File "graphics\chroma-neon\24_arrow_blue_up_shadow.png" + File "graphics\chroma-neon\24_arrow_green_down.png" + File "graphics\chroma-neon\24_arrow_green_down_shadow.png" + File "graphics\chroma-neon\24_arrow_green_left.png" + File "graphics\chroma-neon\24_arrow_green_left_shadow.png" + File "graphics\chroma-neon\24_arrow_green_right.png" + File "graphics\chroma-neon\24_arrow_green_right_shadow.png" + File "graphics\chroma-neon\24_arrow_green_up.png" + File "graphics\chroma-neon\24_arrow_green_up_shadow.png" + File "graphics\chroma-neon\24_arrow_red_down.png" + File "graphics\chroma-neon\24_arrow_red_down_shadow.png" + File "graphics\chroma-neon\24_arrow_red_left.png" + File "graphics\chroma-neon\24_arrow_red_left_shadow.png" + File "graphics\chroma-neon\24_arrow_red_right.png" + File "graphics\chroma-neon\24_arrow_red_right_shadow.png" + File "graphics\chroma-neon\24_arrow_red_up.png" + File "graphics\chroma-neon\24_arrow_red_up_shadow.png" + File "graphics\chroma-neon\24_bomb_blue_down.png" + File "graphics\chroma-neon\24_bomb_blue_down_shadow.png" + File "graphics\chroma-neon\24_bomb_blue_left.png" + File "graphics\chroma-neon\24_bomb_blue_left_shadow.png" + File "graphics\chroma-neon\24_bomb_blue_right.png" + File "graphics\chroma-neon\24_bomb_blue_right_shadow.png" + File "graphics\chroma-neon\24_bomb_blue_up.png" + File "graphics\chroma-neon\24_bomb_blue_up_shadow.png" + File "graphics\chroma-neon\24_bomb_green_down.png" + File "graphics\chroma-neon\24_bomb_green_down_shadow.png" + File "graphics\chroma-neon\24_bomb_green_left.png" + File "graphics\chroma-neon\24_bomb_green_left_shadow.png" + File "graphics\chroma-neon\24_bomb_green_right.png" + File "graphics\chroma-neon\24_bomb_green_right_shadow.png" + File "graphics\chroma-neon\24_bomb_green_up.png" + File "graphics\chroma-neon\24_bomb_green_up_shadow.png" + File "graphics\chroma-neon\24_bomb_red_down.png" + File "graphics\chroma-neon\24_bomb_red_down_shadow.png" + File "graphics\chroma-neon\24_bomb_red_left.png" + File "graphics\chroma-neon\24_bomb_red_left_shadow.png" + File "graphics\chroma-neon\24_bomb_red_right.png" + File "graphics\chroma-neon\24_bomb_red_right_shadow.png" + File "graphics\chroma-neon\24_bomb_red_up.png" + File "graphics\chroma-neon\24_bomb_red_up_shadow.png" + File "graphics\chroma-neon\24_circle.png" + File "graphics\chroma-neon\24_circle_double.png" + File "graphics\chroma-neon\24_circle_double_shadow.png" + File "graphics\chroma-neon\24_circle_shadow.png" + File "graphics\chroma-neon\24_door.png" + File "graphics\chroma-neon\24_door_shadow.png" + File "graphics\chroma-neon\24_dots.png" + File "graphics\chroma-neon\24_dots_double.png" + File "graphics\chroma-neon\24_dots_double_shadow.png" + File "graphics\chroma-neon\24_dots_shadow.png" + File "graphics\chroma-neon\24_dots_x.png" + File "graphics\chroma-neon\24_dots_x_shadow.png" + File "graphics\chroma-neon\24_dots_y.png" + File "graphics\chroma-neon\24_dots_y_shadow.png" + File "graphics\chroma-neon\24_map_bottom_left.png" + File "graphics\chroma-neon\24_map_bottom_left_shadow.png" + File "graphics\chroma-neon\24_map_bottom_right.png" + File "graphics\chroma-neon\24_map_bottom_right_shadow.png" + File "graphics\chroma-neon\24_map_top_left.png" + File "graphics\chroma-neon\24_map_top_left_shadow.png" + File "graphics\chroma-neon\24_map_top_right.png" + File "graphics\chroma-neon\24_map_top_right_shadow.png" + File "graphics\chroma-neon\24_player_one.png" + File "graphics\chroma-neon\24_player_one_shadow.png" + File "graphics\chroma-neon\24_player_one_swapped.png" + File "graphics\chroma-neon\24_player_one_swapped_shadow.png" + File "graphics\chroma-neon\24_player_two.png" + File "graphics\chroma-neon\24_player_two_shadow.png" + File "graphics\chroma-neon\24_player_two_swapped.png" + File "graphics\chroma-neon\24_player_two_swapped_shadow.png" + File "graphics\chroma-neon\24_star.png" + File "graphics\chroma-neon\24_star_shadow.png" + File "graphics\chroma-neon\24_switch.png" + File "graphics\chroma-neon\24_switch_shadow.png" + File "graphics\chroma-neon\24_teleport.png" + File "graphics\chroma-neon\24_teleport_shadow.png" + File "graphics\chroma-neon\24_wall.png" + File "graphics\chroma-neon\24_wall_inside.png" + File "graphics\chroma-neon\24_wall_outside.png" + File "graphics\chroma-neon\24_wall_shadow.png" + File "graphics\chroma-neon\24_wall_x.png" + File "graphics\chroma-neon\24_wall_y.png" + File "graphics\chroma-neon\32_arrow_blue_down.png" + File "graphics\chroma-neon\32_arrow_blue_down_shadow.png" + File "graphics\chroma-neon\32_arrow_blue_left.png" + File "graphics\chroma-neon\32_arrow_blue_left_shadow.png" + File "graphics\chroma-neon\32_arrow_blue_right.png" + File "graphics\chroma-neon\32_arrow_blue_right_shadow.png" + File "graphics\chroma-neon\32_arrow_blue_up.png" + File "graphics\chroma-neon\32_arrow_blue_up_shadow.png" + File "graphics\chroma-neon\32_arrow_green_down.png" + File "graphics\chroma-neon\32_arrow_green_down_shadow.png" + File "graphics\chroma-neon\32_arrow_green_left.png" + File "graphics\chroma-neon\32_arrow_green_left_shadow.png" + File "graphics\chroma-neon\32_arrow_green_right.png" + File "graphics\chroma-neon\32_arrow_green_right_shadow.png" + File "graphics\chroma-neon\32_arrow_green_up.png" + File "graphics\chroma-neon\32_arrow_green_up_shadow.png" + File "graphics\chroma-neon\32_arrow_red_down.png" + File "graphics\chroma-neon\32_arrow_red_down_shadow.png" + File "graphics\chroma-neon\32_arrow_red_left.png" + File "graphics\chroma-neon\32_arrow_red_left_shadow.png" + File "graphics\chroma-neon\32_arrow_red_right.png" + File "graphics\chroma-neon\32_arrow_red_right_shadow.png" + File "graphics\chroma-neon\32_arrow_red_up.png" + File "graphics\chroma-neon\32_arrow_red_up_shadow.png" + File "graphics\chroma-neon\32_bomb_blue_down.png" + File "graphics\chroma-neon\32_bomb_blue_down_shadow.png" + File "graphics\chroma-neon\32_bomb_blue_left.png" + File "graphics\chroma-neon\32_bomb_blue_left_shadow.png" + File "graphics\chroma-neon\32_bomb_blue_right.png" + File "graphics\chroma-neon\32_bomb_blue_right_shadow.png" + File "graphics\chroma-neon\32_bomb_blue_up.png" + File "graphics\chroma-neon\32_bomb_blue_up_shadow.png" + File "graphics\chroma-neon\32_bomb_green_down.png" + File "graphics\chroma-neon\32_bomb_green_down_shadow.png" + File "graphics\chroma-neon\32_bomb_green_left.png" + File "graphics\chroma-neon\32_bomb_green_left_shadow.png" + File "graphics\chroma-neon\32_bomb_green_right.png" + File "graphics\chroma-neon\32_bomb_green_right_shadow.png" + File "graphics\chroma-neon\32_bomb_green_up.png" + File "graphics\chroma-neon\32_bomb_green_up_shadow.png" + File "graphics\chroma-neon\32_bomb_red_down.png" + File "graphics\chroma-neon\32_bomb_red_down_shadow.png" + File "graphics\chroma-neon\32_bomb_red_left.png" + File "graphics\chroma-neon\32_bomb_red_left_shadow.png" + File "graphics\chroma-neon\32_bomb_red_right.png" + File "graphics\chroma-neon\32_bomb_red_right_shadow.png" + File "graphics\chroma-neon\32_bomb_red_up.png" + File "graphics\chroma-neon\32_bomb_red_up_shadow.png" + File "graphics\chroma-neon\32_circle.png" + File "graphics\chroma-neon\32_circle_double.png" + File "graphics\chroma-neon\32_circle_double_shadow.png" + File "graphics\chroma-neon\32_circle_shadow.png" + File "graphics\chroma-neon\32_door.png" + File "graphics\chroma-neon\32_door_shadow.png" + File "graphics\chroma-neon\32_dots.png" + File "graphics\chroma-neon\32_dots_double.png" + File "graphics\chroma-neon\32_dots_double_shadow.png" + File "graphics\chroma-neon\32_dots_shadow.png" + File "graphics\chroma-neon\32_dots_x.png" + File "graphics\chroma-neon\32_dots_x_shadow.png" + File "graphics\chroma-neon\32_dots_y.png" + File "graphics\chroma-neon\32_dots_y_shadow.png" + File "graphics\chroma-neon\32_map_bottom_left.png" + File "graphics\chroma-neon\32_map_bottom_left_shadow.png" + File "graphics\chroma-neon\32_map_bottom_right.png" + File "graphics\chroma-neon\32_map_bottom_right_shadow.png" + File "graphics\chroma-neon\32_map_top_left.png" + File "graphics\chroma-neon\32_map_top_left_shadow.png" + File "graphics\chroma-neon\32_map_top_right.png" + File "graphics\chroma-neon\32_map_top_right_shadow.png" + File "graphics\chroma-neon\32_player_one.png" + File "graphics\chroma-neon\32_player_one_shadow.png" + File "graphics\chroma-neon\32_player_one_swapped.png" + File "graphics\chroma-neon\32_player_one_swapped_shadow.png" + File "graphics\chroma-neon\32_player_two.png" + File "graphics\chroma-neon\32_player_two_shadow.png" + File "graphics\chroma-neon\32_player_two_swapped.png" + File "graphics\chroma-neon\32_player_two_swapped_shadow.png" + File "graphics\chroma-neon\32_star.png" + File "graphics\chroma-neon\32_star_shadow.png" + File "graphics\chroma-neon\32_switch.png" + File "graphics\chroma-neon\32_switch_shadow.png" + File "graphics\chroma-neon\32_teleport.png" + File "graphics\chroma-neon\32_teleport_shadow.png" + File "graphics\chroma-neon\32_wall.png" + File "graphics\chroma-neon\32_wall_inside.png" + File "graphics\chroma-neon\32_wall_outside.png" + File "graphics\chroma-neon\32_wall_shadow.png" + File "graphics\chroma-neon\32_wall_x.png" + File "graphics\chroma-neon\32_wall_y.png" + File "graphics\chroma-neon\40_arrow_blue_down.png" + File "graphics\chroma-neon\40_arrow_blue_down_shadow.png" + File "graphics\chroma-neon\40_arrow_blue_left.png" + File "graphics\chroma-neon\40_arrow_blue_left_shadow.png" + File "graphics\chroma-neon\40_arrow_blue_right.png" + File "graphics\chroma-neon\40_arrow_blue_right_shadow.png" + File "graphics\chroma-neon\40_arrow_blue_up.png" + File "graphics\chroma-neon\40_arrow_blue_up_shadow.png" + File "graphics\chroma-neon\40_arrow_green_down.png" + File "graphics\chroma-neon\40_arrow_green_down_shadow.png" + File "graphics\chroma-neon\40_arrow_green_left.png" + File "graphics\chroma-neon\40_arrow_green_left_shadow.png" + File "graphics\chroma-neon\40_arrow_green_right.png" + File "graphics\chroma-neon\40_arrow_green_right_shadow.png" + File "graphics\chroma-neon\40_arrow_green_up.png" + File "graphics\chroma-neon\40_arrow_green_up_shadow.png" + File "graphics\chroma-neon\40_arrow_red_down.png" + File "graphics\chroma-neon\40_arrow_red_down_shadow.png" + File "graphics\chroma-neon\40_arrow_red_left.png" + File "graphics\chroma-neon\40_arrow_red_left_shadow.png" + File "graphics\chroma-neon\40_arrow_red_right.png" + File "graphics\chroma-neon\40_arrow_red_right_shadow.png" + File "graphics\chroma-neon\40_arrow_red_up.png" + File "graphics\chroma-neon\40_arrow_red_up_shadow.png" + File "graphics\chroma-neon\40_bomb_blue_down.png" + File "graphics\chroma-neon\40_bomb_blue_down_shadow.png" + File "graphics\chroma-neon\40_bomb_blue_left.png" + File "graphics\chroma-neon\40_bomb_blue_left_shadow.png" + File "graphics\chroma-neon\40_bomb_blue_right.png" + File "graphics\chroma-neon\40_bomb_blue_right_shadow.png" + File "graphics\chroma-neon\40_bomb_blue_up.png" + File "graphics\chroma-neon\40_bomb_blue_up_shadow.png" + File "graphics\chroma-neon\40_bomb_green_down.png" + File "graphics\chroma-neon\40_bomb_green_down_shadow.png" + File "graphics\chroma-neon\40_bomb_green_left.png" + File "graphics\chroma-neon\40_bomb_green_left_shadow.png" + File "graphics\chroma-neon\40_bomb_green_right.png" + File "graphics\chroma-neon\40_bomb_green_right_shadow.png" + File "graphics\chroma-neon\40_bomb_green_up.png" + File "graphics\chroma-neon\40_bomb_green_up_shadow.png" + File "graphics\chroma-neon\40_bomb_red_down.png" + File "graphics\chroma-neon\40_bomb_red_down_shadow.png" + File "graphics\chroma-neon\40_bomb_red_left.png" + File "graphics\chroma-neon\40_bomb_red_left_shadow.png" + File "graphics\chroma-neon\40_bomb_red_right.png" + File "graphics\chroma-neon\40_bomb_red_right_shadow.png" + File "graphics\chroma-neon\40_bomb_red_up.png" + File "graphics\chroma-neon\40_bomb_red_up_shadow.png" + File "graphics\chroma-neon\40_circle.png" + File "graphics\chroma-neon\40_circle_double.png" + File "graphics\chroma-neon\40_circle_double_shadow.png" + File "graphics\chroma-neon\40_circle_shadow.png" + File "graphics\chroma-neon\40_door.png" + File "graphics\chroma-neon\40_door_shadow.png" + File "graphics\chroma-neon\40_dots.png" + File "graphics\chroma-neon\40_dots_double.png" + File "graphics\chroma-neon\40_dots_double_shadow.png" + File "graphics\chroma-neon\40_dots_shadow.png" + File "graphics\chroma-neon\40_dots_x.png" + File "graphics\chroma-neon\40_dots_x_shadow.png" + File "graphics\chroma-neon\40_dots_y.png" + File "graphics\chroma-neon\40_dots_y_shadow.png" + File "graphics\chroma-neon\40_map_bottom_left.png" + File "graphics\chroma-neon\40_map_bottom_left_shadow.png" + File "graphics\chroma-neon\40_map_bottom_right.png" + File "graphics\chroma-neon\40_map_bottom_right_shadow.png" + File "graphics\chroma-neon\40_map_top_left.png" + File "graphics\chroma-neon\40_map_top_left_shadow.png" + File "graphics\chroma-neon\40_map_top_right.png" + File "graphics\chroma-neon\40_map_top_right_shadow.png" + File "graphics\chroma-neon\40_player_one.png" + File "graphics\chroma-neon\40_player_one_shadow.png" + File "graphics\chroma-neon\40_player_one_swapped.png" + File "graphics\chroma-neon\40_player_one_swapped_shadow.png" + File "graphics\chroma-neon\40_player_two.png" + File "graphics\chroma-neon\40_player_two_shadow.png" + File "graphics\chroma-neon\40_player_two_swapped.png" + File "graphics\chroma-neon\40_player_two_swapped_shadow.png" + File "graphics\chroma-neon\40_star.png" + File "graphics\chroma-neon\40_star_shadow.png" + File "graphics\chroma-neon\40_switch.png" + File "graphics\chroma-neon\40_switch_shadow.png" + File "graphics\chroma-neon\40_teleport.png" + File "graphics\chroma-neon\40_teleport_shadow.png" + File "graphics\chroma-neon\40_wall.png" + File "graphics\chroma-neon\40_wall_inside.png" + File "graphics\chroma-neon\40_wall_outside.png" + File "graphics\chroma-neon\40_wall_shadow.png" + File "graphics\chroma-neon\40_wall_x.png" + File "graphics\chroma-neon\40_wall_y.png" + File "graphics\chroma-neon\64_arrow_blue_down.png" + File "graphics\chroma-neon\64_arrow_blue_down_shadow.png" + File "graphics\chroma-neon\64_arrow_blue_left.png" + File "graphics\chroma-neon\64_arrow_blue_left_shadow.png" + File "graphics\chroma-neon\64_arrow_blue_right.png" + File "graphics\chroma-neon\64_arrow_blue_right_shadow.png" + File "graphics\chroma-neon\64_arrow_blue_up.png" + File "graphics\chroma-neon\64_arrow_blue_up_shadow.png" + File "graphics\chroma-neon\64_arrow_green_down.png" + File "graphics\chroma-neon\64_arrow_green_down_shadow.png" + File "graphics\chroma-neon\64_arrow_green_left.png" + File "graphics\chroma-neon\64_arrow_green_left_shadow.png" + File "graphics\chroma-neon\64_arrow_green_right.png" + File "graphics\chroma-neon\64_arrow_green_right_shadow.png" + File "graphics\chroma-neon\64_arrow_green_up.png" + File "graphics\chroma-neon\64_arrow_green_up_shadow.png" + File "graphics\chroma-neon\64_arrow_red_down.png" + File "graphics\chroma-neon\64_arrow_red_down_shadow.png" + File "graphics\chroma-neon\64_arrow_red_left.png" + File "graphics\chroma-neon\64_arrow_red_left_shadow.png" + File "graphics\chroma-neon\64_arrow_red_right.png" + File "graphics\chroma-neon\64_arrow_red_right_shadow.png" + File "graphics\chroma-neon\64_arrow_red_up.png" + File "graphics\chroma-neon\64_arrow_red_up_shadow.png" + File "graphics\chroma-neon\64_bomb_blue_down.png" + File "graphics\chroma-neon\64_bomb_blue_down_shadow.png" + File "graphics\chroma-neon\64_bomb_blue_left.png" + File "graphics\chroma-neon\64_bomb_blue_left_shadow.png" + File "graphics\chroma-neon\64_bomb_blue_right.png" + File "graphics\chroma-neon\64_bomb_blue_right_shadow.png" + File "graphics\chroma-neon\64_bomb_blue_up.png" + File "graphics\chroma-neon\64_bomb_blue_up_shadow.png" + File "graphics\chroma-neon\64_bomb_green_down.png" + File "graphics\chroma-neon\64_bomb_green_down_shadow.png" + File "graphics\chroma-neon\64_bomb_green_left.png" + File "graphics\chroma-neon\64_bomb_green_left_shadow.png" + File "graphics\chroma-neon\64_bomb_green_right.png" + File "graphics\chroma-neon\64_bomb_green_right_shadow.png" + File "graphics\chroma-neon\64_bomb_green_up.png" + File "graphics\chroma-neon\64_bomb_green_up_shadow.png" + File "graphics\chroma-neon\64_bomb_red_down.png" + File "graphics\chroma-neon\64_bomb_red_down_shadow.png" + File "graphics\chroma-neon\64_bomb_red_left.png" + File "graphics\chroma-neon\64_bomb_red_left_shadow.png" + File "graphics\chroma-neon\64_bomb_red_right.png" + File "graphics\chroma-neon\64_bomb_red_right_shadow.png" + File "graphics\chroma-neon\64_bomb_red_up.png" + File "graphics\chroma-neon\64_bomb_red_up_shadow.png" + File "graphics\chroma-neon\64_circle.png" + File "graphics\chroma-neon\64_circle_double.png" + File "graphics\chroma-neon\64_circle_double_shadow.png" + File "graphics\chroma-neon\64_circle_shadow.png" + File "graphics\chroma-neon\64_door.png" + File "graphics\chroma-neon\64_door_shadow.png" + File "graphics\chroma-neon\64_dots.png" + File "graphics\chroma-neon\64_dots_double.png" + File "graphics\chroma-neon\64_dots_double_shadow.png" + File "graphics\chroma-neon\64_dots_shadow.png" + File "graphics\chroma-neon\64_dots_x.png" + File "graphics\chroma-neon\64_dots_x_shadow.png" + File "graphics\chroma-neon\64_dots_y.png" + File "graphics\chroma-neon\64_dots_y_shadow.png" + File "graphics\chroma-neon\64_map_bottom_left.png" + File "graphics\chroma-neon\64_map_bottom_left_shadow.png" + File "graphics\chroma-neon\64_map_bottom_right.png" + File "graphics\chroma-neon\64_map_bottom_right_shadow.png" + File "graphics\chroma-neon\64_map_top_left.png" + File "graphics\chroma-neon\64_map_top_left_shadow.png" + File "graphics\chroma-neon\64_map_top_right.png" + File "graphics\chroma-neon\64_map_top_right_shadow.png" + File "graphics\chroma-neon\64_player_one.png" + File "graphics\chroma-neon\64_player_one_shadow.png" + File "graphics\chroma-neon\64_player_one_swapped.png" + File "graphics\chroma-neon\64_player_one_swapped_shadow.png" + File "graphics\chroma-neon\64_player_two.png" + File "graphics\chroma-neon\64_player_two_shadow.png" + File "graphics\chroma-neon\64_player_two_swapped.png" + File "graphics\chroma-neon\64_player_two_swapped_shadow.png" + File "graphics\chroma-neon\64_star.png" + File "graphics\chroma-neon\64_star_shadow.png" + File "graphics\chroma-neon\64_switch.png" + File "graphics\chroma-neon\64_switch_shadow.png" + File "graphics\chroma-neon\64_teleport.png" + File "graphics\chroma-neon\64_teleport_shadow.png" + File "graphics\chroma-neon\64_wall.png" + File "graphics\chroma-neon\64_wall_inside.png" + File "graphics\chroma-neon\64_wall_outside.png" + File "graphics\chroma-neon\64_wall_shadow.png" + File "graphics\chroma-neon\64_wall_x.png" + File "graphics\chroma-neon\64_wall_y.png" + SetOutPath "$INSTDIR\graphics" + File "graphics\chroma-neon.chroma" + SetOutPath "$INSTDIR\graphics\chroma-zen" + File "graphics\chroma-zen\16_arrow_blue_down.png" + File "graphics\chroma-zen\16_arrow_blue_left.png" + File "graphics\chroma-zen\16_arrow_blue_right.png" + File "graphics\chroma-zen\16_arrow_blue_up.png" + File "graphics\chroma-zen\16_arrow_green_down.png" + File "graphics\chroma-zen\16_arrow_green_left.png" + File "graphics\chroma-zen\16_arrow_green_right.png" + File "graphics\chroma-zen\16_arrow_green_up.png" + File "graphics\chroma-zen\16_arrow_red_down.png" + File "graphics\chroma-zen\16_arrow_red_left.png" + File "graphics\chroma-zen\16_arrow_red_right.png" + File "graphics\chroma-zen\16_arrow_red_up.png" + File "graphics\chroma-zen\16_bomb_blue_down.png" + File "graphics\chroma-zen\16_bomb_blue_left.png" + File "graphics\chroma-zen\16_bomb_blue_right.png" + File "graphics\chroma-zen\16_bomb_blue_up.png" + File "graphics\chroma-zen\16_bomb_green_down.png" + File "graphics\chroma-zen\16_bomb_green_left.png" + File "graphics\chroma-zen\16_bomb_green_right.png" + File "graphics\chroma-zen\16_bomb_green_up.png" + File "graphics\chroma-zen\16_bomb_red_down.png" + File "graphics\chroma-zen\16_bomb_red_left.png" + File "graphics\chroma-zen\16_bomb_red_right.png" + File "graphics\chroma-zen\16_bomb_red_up.png" + File "graphics\chroma-zen\16_circle.png" + File "graphics\chroma-zen\16_circle_double.png" + File "graphics\chroma-zen\16_door.png" + File "graphics\chroma-zen\16_dots.png" + File "graphics\chroma-zen\16_dots_double.png" + File "graphics\chroma-zen\16_dots_x.png" + File "graphics\chroma-zen\16_dots_y.png" + File "graphics\chroma-zen\16_map_bottom_left.png" + File "graphics\chroma-zen\16_map_bottom_right.png" + File "graphics\chroma-zen\16_map_top_left.png" + File "graphics\chroma-zen\16_map_top_right.png" + File "graphics\chroma-zen\16_player_one.png" + File "graphics\chroma-zen\16_player_one_swapped.png" + File "graphics\chroma-zen\16_player_two.png" + File "graphics\chroma-zen\16_player_two_swapped.png" + File "graphics\chroma-zen\16_star.png" + File "graphics\chroma-zen\16_switch.png" + File "graphics\chroma-zen\16_teleport.png" + File "graphics\chroma-zen\16_wall_inside.png" + File "graphics\chroma-zen\16_wall_outside.png" + File "graphics\chroma-zen\16_wall_x.png" + File "graphics\chroma-zen\16_wall_y.png" + File "graphics\chroma-zen\20_arrow_blue_down.png" + File "graphics\chroma-zen\20_arrow_blue_left.png" + File "graphics\chroma-zen\20_arrow_blue_right.png" + File "graphics\chroma-zen\20_arrow_blue_up.png" + File "graphics\chroma-zen\20_arrow_green_down.png" + File "graphics\chroma-zen\20_arrow_green_left.png" + File "graphics\chroma-zen\20_arrow_green_right.png" + File "graphics\chroma-zen\20_arrow_green_up.png" + File "graphics\chroma-zen\20_arrow_red_down.png" + File "graphics\chroma-zen\20_arrow_red_left.png" + File "graphics\chroma-zen\20_arrow_red_right.png" + File "graphics\chroma-zen\20_arrow_red_up.png" + File "graphics\chroma-zen\20_bomb_blue_down.png" + File "graphics\chroma-zen\20_bomb_blue_left.png" + File "graphics\chroma-zen\20_bomb_blue_right.png" + File "graphics\chroma-zen\20_bomb_blue_up.png" + File "graphics\chroma-zen\20_bomb_green_down.png" + File "graphics\chroma-zen\20_bomb_green_left.png" + File "graphics\chroma-zen\20_bomb_green_right.png" + File "graphics\chroma-zen\20_bomb_green_up.png" + File "graphics\chroma-zen\20_bomb_red_down.png" + File "graphics\chroma-zen\20_bomb_red_left.png" + File "graphics\chroma-zen\20_bomb_red_right.png" + File "graphics\chroma-zen\20_bomb_red_up.png" + File "graphics\chroma-zen\20_circle.png" + File "graphics\chroma-zen\20_circle_double.png" + File "graphics\chroma-zen\20_door.png" + File "graphics\chroma-zen\20_dots.png" + File "graphics\chroma-zen\20_dots_double.png" + File "graphics\chroma-zen\20_dots_x.png" + File "graphics\chroma-zen\20_dots_y.png" + File "graphics\chroma-zen\20_map_bottom_left.png" + File "graphics\chroma-zen\20_map_bottom_right.png" + File "graphics\chroma-zen\20_map_top_left.png" + File "graphics\chroma-zen\20_map_top_right.png" + File "graphics\chroma-zen\20_player_one.png" + File "graphics\chroma-zen\20_player_one_swapped.png" + File "graphics\chroma-zen\20_player_two.png" + File "graphics\chroma-zen\20_player_two_swapped.png" + File "graphics\chroma-zen\20_star.png" + File "graphics\chroma-zen\20_switch.png" + File "graphics\chroma-zen\20_teleport.png" + File "graphics\chroma-zen\20_wall_inside.png" + File "graphics\chroma-zen\20_wall_outside.png" + File "graphics\chroma-zen\20_wall_x.png" + File "graphics\chroma-zen\20_wall_y.png" + File "graphics\chroma-zen\24_arrow_blue_down.png" + File "graphics\chroma-zen\24_arrow_blue_left.png" + File "graphics\chroma-zen\24_arrow_blue_right.png" + File "graphics\chroma-zen\24_arrow_blue_up.png" + File "graphics\chroma-zen\24_arrow_green_down.png" + File "graphics\chroma-zen\24_arrow_green_left.png" + File "graphics\chroma-zen\24_arrow_green_right.png" + File "graphics\chroma-zen\24_arrow_green_up.png" + File "graphics\chroma-zen\24_arrow_red_down.png" + File "graphics\chroma-zen\24_arrow_red_left.png" + File "graphics\chroma-zen\24_arrow_red_right.png" + File "graphics\chroma-zen\24_arrow_red_up.png" + File "graphics\chroma-zen\24_bomb_blue_down.png" + File "graphics\chroma-zen\24_bomb_blue_left.png" + File "graphics\chroma-zen\24_bomb_blue_right.png" + File "graphics\chroma-zen\24_bomb_blue_up.png" + File "graphics\chroma-zen\24_bomb_green_down.png" + File "graphics\chroma-zen\24_bomb_green_left.png" + File "graphics\chroma-zen\24_bomb_green_right.png" + File "graphics\chroma-zen\24_bomb_green_up.png" + File "graphics\chroma-zen\24_bomb_red_down.png" + File "graphics\chroma-zen\24_bomb_red_left.png" + File "graphics\chroma-zen\24_bomb_red_right.png" + File "graphics\chroma-zen\24_bomb_red_up.png" + File "graphics\chroma-zen\24_circle.png" + File "graphics\chroma-zen\24_circle_double.png" + File "graphics\chroma-zen\24_door.png" + File "graphics\chroma-zen\24_dots.png" + File "graphics\chroma-zen\24_dots_double.png" + File "graphics\chroma-zen\24_dots_x.png" + File "graphics\chroma-zen\24_dots_y.png" + File "graphics\chroma-zen\24_map_bottom_left.png" + File "graphics\chroma-zen\24_map_bottom_right.png" + File "graphics\chroma-zen\24_map_top_left.png" + File "graphics\chroma-zen\24_map_top_right.png" + File "graphics\chroma-zen\24_player_one.png" + File "graphics\chroma-zen\24_player_one_swapped.png" + File "graphics\chroma-zen\24_player_two.png" + File "graphics\chroma-zen\24_player_two_swapped.png" + File "graphics\chroma-zen\24_star.png" + File "graphics\chroma-zen\24_switch.png" + File "graphics\chroma-zen\24_teleport.png" + File "graphics\chroma-zen\24_wall_inside.png" + File "graphics\chroma-zen\24_wall_outside.png" + File "graphics\chroma-zen\24_wall_x.png" + File "graphics\chroma-zen\24_wall_y.png" + File "graphics\chroma-zen\32_arrow_blue_down.png" + File "graphics\chroma-zen\32_arrow_blue_left.png" + File "graphics\chroma-zen\32_arrow_blue_right.png" + File "graphics\chroma-zen\32_arrow_blue_up.png" + File "graphics\chroma-zen\32_arrow_green_down.png" + File "graphics\chroma-zen\32_arrow_green_left.png" + File "graphics\chroma-zen\32_arrow_green_right.png" + File "graphics\chroma-zen\32_arrow_green_up.png" + File "graphics\chroma-zen\32_arrow_red_down.png" + File "graphics\chroma-zen\32_arrow_red_left.png" + File "graphics\chroma-zen\32_arrow_red_right.png" + File "graphics\chroma-zen\32_arrow_red_up.png" + File "graphics\chroma-zen\32_bomb_blue_down.png" + File "graphics\chroma-zen\32_bomb_blue_left.png" + File "graphics\chroma-zen\32_bomb_blue_right.png" + File "graphics\chroma-zen\32_bomb_blue_up.png" + File "graphics\chroma-zen\32_bomb_green_down.png" + File "graphics\chroma-zen\32_bomb_green_left.png" + File "graphics\chroma-zen\32_bomb_green_right.png" + File "graphics\chroma-zen\32_bomb_green_up.png" + File "graphics\chroma-zen\32_bomb_red_down.png" + File "graphics\chroma-zen\32_bomb_red_left.png" + File "graphics\chroma-zen\32_bomb_red_right.png" + File "graphics\chroma-zen\32_bomb_red_up.png" + File "graphics\chroma-zen\32_circle.png" + File "graphics\chroma-zen\32_circle_double.png" + File "graphics\chroma-zen\32_door.png" + File "graphics\chroma-zen\32_dots.png" + File "graphics\chroma-zen\32_dots_double.png" + File "graphics\chroma-zen\32_dots_x.png" + File "graphics\chroma-zen\32_dots_y.png" + File "graphics\chroma-zen\32_map_bottom_left.png" + File "graphics\chroma-zen\32_map_bottom_right.png" + File "graphics\chroma-zen\32_map_top_left.png" + File "graphics\chroma-zen\32_map_top_right.png" + File "graphics\chroma-zen\32_player_one.png" + File "graphics\chroma-zen\32_player_one_swapped.png" + File "graphics\chroma-zen\32_player_two.png" + File "graphics\chroma-zen\32_player_two_swapped.png" + File "graphics\chroma-zen\32_star.png" + File "graphics\chroma-zen\32_switch.png" + File "graphics\chroma-zen\32_teleport.png" + File "graphics\chroma-zen\32_wall_inside.png" + File "graphics\chroma-zen\32_wall_outside.png" + File "graphics\chroma-zen\32_wall_x.png" + File "graphics\chroma-zen\32_wall_y.png" + File "graphics\chroma-zen\40_arrow_blue_down.png" + File "graphics\chroma-zen\40_arrow_blue_left.png" + File "graphics\chroma-zen\40_arrow_blue_right.png" + File "graphics\chroma-zen\40_arrow_blue_up.png" + File "graphics\chroma-zen\40_arrow_green_down.png" + File "graphics\chroma-zen\40_arrow_green_left.png" + File "graphics\chroma-zen\40_arrow_green_right.png" + File "graphics\chroma-zen\40_arrow_green_up.png" + File "graphics\chroma-zen\40_arrow_red_down.png" + File "graphics\chroma-zen\40_arrow_red_left.png" + File "graphics\chroma-zen\40_arrow_red_right.png" + File "graphics\chroma-zen\40_arrow_red_up.png" + File "graphics\chroma-zen\40_bomb_blue_down.png" + File "graphics\chroma-zen\40_bomb_blue_left.png" + File "graphics\chroma-zen\40_bomb_blue_right.png" + File "graphics\chroma-zen\40_bomb_blue_up.png" + File "graphics\chroma-zen\40_bomb_green_down.png" + File "graphics\chroma-zen\40_bomb_green_left.png" + File "graphics\chroma-zen\40_bomb_green_right.png" + File "graphics\chroma-zen\40_bomb_green_up.png" + File "graphics\chroma-zen\40_bomb_red_down.png" + File "graphics\chroma-zen\40_bomb_red_left.png" + File "graphics\chroma-zen\40_bomb_red_right.png" + File "graphics\chroma-zen\40_bomb_red_up.png" + File "graphics\chroma-zen\40_circle.png" + File "graphics\chroma-zen\40_circle_double.png" + File "graphics\chroma-zen\40_door.png" + File "graphics\chroma-zen\40_dots.png" + File "graphics\chroma-zen\40_dots_double.png" + File "graphics\chroma-zen\40_dots_x.png" + File "graphics\chroma-zen\40_dots_y.png" + File "graphics\chroma-zen\40_map_bottom_left.png" + File "graphics\chroma-zen\40_map_bottom_right.png" + File "graphics\chroma-zen\40_map_top_left.png" + File "graphics\chroma-zen\40_map_top_right.png" + File "graphics\chroma-zen\40_player_one.png" + File "graphics\chroma-zen\40_player_one_swapped.png" + File "graphics\chroma-zen\40_player_two.png" + File "graphics\chroma-zen\40_player_two_swapped.png" + File "graphics\chroma-zen\40_star.png" + File "graphics\chroma-zen\40_switch.png" + File "graphics\chroma-zen\40_teleport.png" + File "graphics\chroma-zen\40_wall_inside.png" + File "graphics\chroma-zen\40_wall_outside.png" + File "graphics\chroma-zen\40_wall_x.png" + File "graphics\chroma-zen\40_wall_y.png" + File "graphics\chroma-zen\64_arrow_blue_down.png" + File "graphics\chroma-zen\64_arrow_blue_left.png" + File "graphics\chroma-zen\64_arrow_blue_right.png" + File "graphics\chroma-zen\64_arrow_blue_up.png" + File "graphics\chroma-zen\64_arrow_green_down.png" + File "graphics\chroma-zen\64_arrow_green_left.png" + File "graphics\chroma-zen\64_arrow_green_right.png" + File "graphics\chroma-zen\64_arrow_green_up.png" + File "graphics\chroma-zen\64_arrow_red_down.png" + File "graphics\chroma-zen\64_arrow_red_left.png" + File "graphics\chroma-zen\64_arrow_red_right.png" + File "graphics\chroma-zen\64_arrow_red_up.png" + File "graphics\chroma-zen\64_bomb_blue_down.png" + File "graphics\chroma-zen\64_bomb_blue_left.png" + File "graphics\chroma-zen\64_bomb_blue_right.png" + File "graphics\chroma-zen\64_bomb_blue_up.png" + File "graphics\chroma-zen\64_bomb_green_down.png" + File "graphics\chroma-zen\64_bomb_green_left.png" + File "graphics\chroma-zen\64_bomb_green_right.png" + File "graphics\chroma-zen\64_bomb_green_up.png" + File "graphics\chroma-zen\64_bomb_red_down.png" + File "graphics\chroma-zen\64_bomb_red_left.png" + File "graphics\chroma-zen\64_bomb_red_right.png" + File "graphics\chroma-zen\64_bomb_red_up.png" + File "graphics\chroma-zen\64_circle.png" + File "graphics\chroma-zen\64_circle_double.png" + File "graphics\chroma-zen\64_door.png" + File "graphics\chroma-zen\64_dots.png" + File "graphics\chroma-zen\64_dots_double.png" + File "graphics\chroma-zen\64_dots_x.png" + File "graphics\chroma-zen\64_dots_y.png" + File "graphics\chroma-zen\64_map_bottom_left.png" + File "graphics\chroma-zen\64_map_bottom_right.png" + File "graphics\chroma-zen\64_map_top_left.png" + File "graphics\chroma-zen\64_map_top_right.png" + File "graphics\chroma-zen\64_player_one.png" + File "graphics\chroma-zen\64_player_one_swapped.png" + File "graphics\chroma-zen\64_player_two.png" + File "graphics\chroma-zen\64_player_two_swapped.png" + File "graphics\chroma-zen\64_star.png" + File "graphics\chroma-zen\64_switch.png" + File "graphics\chroma-zen\64_teleport.png" + File "graphics\chroma-zen\64_wall_inside.png" + File "graphics\chroma-zen\64_wall_outside.png" + File "graphics\chroma-zen\64_wall_x.png" + File "graphics\chroma-zen\64_wall_y.png" + SetOutPath "$INSTDIR\graphics" + File "graphics\chroma-zen.chroma" + File "graphics\curses.chroma" + File "graphics\fallback.chroma" + File "graphics\font.txt" + File "graphics\font.ttf" + File "graphics\icon.png" + SetOutPath "$INSTDIR" + File "jpeg.dll" + SetOutPath "$INSTDIR\levels\chroma-1" + File "levels\chroma-1\chroma-1-01.chroma" + File "levels\chroma-1\chroma-1-02.chroma" + File "levels\chroma-1\chroma-1-03.chroma" + File "levels\chroma-1\chroma-1-04.chroma" + File "levels\chroma-1\chroma-1-05.chroma" + File "levels\chroma-1\chroma-1-06.chroma" + File "levels\chroma-1\chroma-1-07.chroma" + File "levels\chroma-1\chroma-1-08.chroma" + File "levels\chroma-1\chroma-1-09.chroma" + File "levels\chroma-1\set.chroma" + SetOutPath "$INSTDIR\levels\chroma-2" + File "levels\chroma-2\chroma-2-01.chroma" + File "levels\chroma-2\chroma-2-02.chroma" + File "levels\chroma-2\chroma-2-03.chroma" + File "levels\chroma-2\chroma-2-04.chroma" + File "levels\chroma-2\chroma-2-05.chroma" + File "levels\chroma-2\chroma-2-06.chroma" + File "levels\chroma-2\chroma-2-07.chroma" + File "levels\chroma-2\chroma-2-08.chroma" + File "levels\chroma-2\chroma-2-09.chroma" + File "levels\chroma-2\chroma-2-10.chroma" + File "levels\chroma-2\chroma-2-11.chroma" + File "levels\chroma-2\chroma-2-12.chroma" + File "levels\chroma-2\set.chroma" + SetOutPath "$INSTDIR\levels\regression" + File "levels\regression\chroma-pieces.chroma" + File "levels\regression\chroma-regression.chroma" + File "levels\regression\enigma-regression.chroma" + File "levels\regression\set.chroma" + File "levels\regression\xor-regression.chroma" + SetOutPath "$INSTDIR" + File "libfreetype-6.dll" + File "libintl.dll" + File "libpng1.dll" + File "SDL.dll" + File "SDL_image.dll" + File "zlib.dll" + File "zlib1.dll" +SectionEnd + +Section -AdditionalIcons + CreateShortCut "$SMPROGRAMS\Chroma\Uninstall.lnk" "$INSTDIR\uninst.exe" +SectionEnd + +Section -Post + WriteUninstaller "$INSTDIR\uninst.exe" + WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\chroma.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\chroma.exe" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" + WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" +SectionEnd + + +Function un.onUninstSuccess + HideWindow + MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer." +FunctionEnd + +Function un.onInit + MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2 + Abort +FunctionEnd + +Section Uninstall + Delete "$INSTDIR\uninst.exe" + Delete "$INSTDIR\zlib1.dll" + Delete "$INSTDIR\zlib.dll" + Delete "$INSTDIR\SDL_image.dll" + Delete "$INSTDIR\SDL.dll" + Delete "$INSTDIR\libpng1.dll" + Delete "$INSTDIR\libintl.dll" + Delete "$INSTDIR\libfreetype-6.dll" + Delete "$INSTDIR\levels\regression\xor-regression.chroma" + Delete "$INSTDIR\levels\regression\set.chroma" + Delete "$INSTDIR\levels\regression\enigma-regression.chroma" + Delete "$INSTDIR\levels\regression\chroma-regression.chroma" + Delete "$INSTDIR\levels\regression\chroma-pieces.chroma" + Delete "$INSTDIR\levels\chroma-2\set.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-12.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-11.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-10.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-09.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-08.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-07.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-06.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-05.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-04.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-03.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-02.chroma" + Delete "$INSTDIR\levels\chroma-2\chroma-2-01.chroma" + Delete "$INSTDIR\levels\chroma-1\set.chroma" + Delete "$INSTDIR\levels\chroma-1\chroma-1-09.chroma" + Delete "$INSTDIR\levels\chroma-1\chroma-1-08.chroma" + Delete "$INSTDIR\levels\chroma-1\chroma-1-07.chroma" + Delete "$INSTDIR\levels\chroma-1\chroma-1-06.chroma" + Delete "$INSTDIR\levels\chroma-1\chroma-1-05.chroma" + Delete "$INSTDIR\levels\chroma-1\chroma-1-04.chroma" + Delete "$INSTDIR\levels\chroma-1\chroma-1-03.chroma" + Delete "$INSTDIR\levels\chroma-1\chroma-1-02.chroma" + Delete "$INSTDIR\levels\chroma-1\chroma-1-01.chroma" + Delete "$INSTDIR\jpeg.dll" + Delete "$INSTDIR\graphics\icon.png" + Delete "$INSTDIR\graphics\font.txt" + Delete "$INSTDIR\graphics\font.ttf" + Delete "$INSTDIR\graphics\fallback.chroma" + Delete "$INSTDIR\graphics\curses.chroma" + Delete "$INSTDIR\graphics\chroma-zen.chroma" + Delete "$INSTDIR\graphics\chroma-zen\64_wall_y.png" + Delete "$INSTDIR\graphics\chroma-zen\64_wall_x.png" + Delete "$INSTDIR\graphics\chroma-zen\64_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-zen\64_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-zen\64_teleport.png" + Delete "$INSTDIR\graphics\chroma-zen\64_switch.png" + Delete "$INSTDIR\graphics\chroma-zen\64_star.png" + Delete "$INSTDIR\graphics\chroma-zen\64_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\64_player_two.png" + Delete "$INSTDIR\graphics\chroma-zen\64_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\64_player_one.png" + Delete "$INSTDIR\graphics\chroma-zen\64_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-zen\64_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-zen\64_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-zen\64_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-zen\64_dots_y.png" + Delete "$INSTDIR\graphics\chroma-zen\64_dots_x.png" + Delete "$INSTDIR\graphics\chroma-zen\64_dots_double.png" + Delete "$INSTDIR\graphics\chroma-zen\64_dots.png" + Delete "$INSTDIR\graphics\chroma-zen\64_door.png" + Delete "$INSTDIR\graphics\chroma-zen\64_circle_double.png" + Delete "$INSTDIR\graphics\chroma-zen\64_circle.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\64_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\64_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\40_wall_y.png" + Delete "$INSTDIR\graphics\chroma-zen\40_wall_x.png" + Delete "$INSTDIR\graphics\chroma-zen\40_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-zen\40_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-zen\40_teleport.png" + Delete "$INSTDIR\graphics\chroma-zen\40_switch.png" + Delete "$INSTDIR\graphics\chroma-zen\40_star.png" + Delete "$INSTDIR\graphics\chroma-zen\40_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\40_player_two.png" + Delete "$INSTDIR\graphics\chroma-zen\40_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\40_player_one.png" + Delete "$INSTDIR\graphics\chroma-zen\40_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-zen\40_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-zen\40_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-zen\40_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-zen\40_dots_y.png" + Delete "$INSTDIR\graphics\chroma-zen\40_dots_x.png" + Delete "$INSTDIR\graphics\chroma-zen\40_dots_double.png" + Delete "$INSTDIR\graphics\chroma-zen\40_dots.png" + Delete "$INSTDIR\graphics\chroma-zen\40_door.png" + Delete "$INSTDIR\graphics\chroma-zen\40_circle_double.png" + Delete "$INSTDIR\graphics\chroma-zen\40_circle.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\40_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\40_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\32_wall_y.png" + Delete "$INSTDIR\graphics\chroma-zen\32_wall_x.png" + Delete "$INSTDIR\graphics\chroma-zen\32_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-zen\32_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-zen\32_teleport.png" + Delete "$INSTDIR\graphics\chroma-zen\32_switch.png" + Delete "$INSTDIR\graphics\chroma-zen\32_star.png" + Delete "$INSTDIR\graphics\chroma-zen\32_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\32_player_two.png" + Delete "$INSTDIR\graphics\chroma-zen\32_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\32_player_one.png" + Delete "$INSTDIR\graphics\chroma-zen\32_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-zen\32_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-zen\32_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-zen\32_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-zen\32_dots_y.png" + Delete "$INSTDIR\graphics\chroma-zen\32_dots_x.png" + Delete "$INSTDIR\graphics\chroma-zen\32_dots_double.png" + Delete "$INSTDIR\graphics\chroma-zen\32_dots.png" + Delete "$INSTDIR\graphics\chroma-zen\32_door.png" + Delete "$INSTDIR\graphics\chroma-zen\32_circle_double.png" + Delete "$INSTDIR\graphics\chroma-zen\32_circle.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\32_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\32_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\24_wall_y.png" + Delete "$INSTDIR\graphics\chroma-zen\24_wall_x.png" + Delete "$INSTDIR\graphics\chroma-zen\24_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-zen\24_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-zen\24_teleport.png" + Delete "$INSTDIR\graphics\chroma-zen\24_switch.png" + Delete "$INSTDIR\graphics\chroma-zen\24_star.png" + Delete "$INSTDIR\graphics\chroma-zen\24_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\24_player_two.png" + Delete "$INSTDIR\graphics\chroma-zen\24_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\24_player_one.png" + Delete "$INSTDIR\graphics\chroma-zen\24_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-zen\24_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-zen\24_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-zen\24_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-zen\24_dots_y.png" + Delete "$INSTDIR\graphics\chroma-zen\24_dots_x.png" + Delete "$INSTDIR\graphics\chroma-zen\24_dots_double.png" + Delete "$INSTDIR\graphics\chroma-zen\24_dots.png" + Delete "$INSTDIR\graphics\chroma-zen\24_door.png" + Delete "$INSTDIR\graphics\chroma-zen\24_circle_double.png" + Delete "$INSTDIR\graphics\chroma-zen\24_circle.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\24_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\24_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\20_wall_y.png" + Delete "$INSTDIR\graphics\chroma-zen\20_wall_x.png" + Delete "$INSTDIR\graphics\chroma-zen\20_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-zen\20_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-zen\20_teleport.png" + Delete "$INSTDIR\graphics\chroma-zen\20_switch.png" + Delete "$INSTDIR\graphics\chroma-zen\20_star.png" + Delete "$INSTDIR\graphics\chroma-zen\20_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\20_player_two.png" + Delete "$INSTDIR\graphics\chroma-zen\20_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\20_player_one.png" + Delete "$INSTDIR\graphics\chroma-zen\20_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-zen\20_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-zen\20_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-zen\20_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-zen\20_dots_y.png" + Delete "$INSTDIR\graphics\chroma-zen\20_dots_x.png" + Delete "$INSTDIR\graphics\chroma-zen\20_dots_double.png" + Delete "$INSTDIR\graphics\chroma-zen\20_dots.png" + Delete "$INSTDIR\graphics\chroma-zen\20_door.png" + Delete "$INSTDIR\graphics\chroma-zen\20_circle_double.png" + Delete "$INSTDIR\graphics\chroma-zen\20_circle.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\20_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\20_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\16_wall_y.png" + Delete "$INSTDIR\graphics\chroma-zen\16_wall_x.png" + Delete "$INSTDIR\graphics\chroma-zen\16_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-zen\16_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-zen\16_teleport.png" + Delete "$INSTDIR\graphics\chroma-zen\16_switch.png" + Delete "$INSTDIR\graphics\chroma-zen\16_star.png" + Delete "$INSTDIR\graphics\chroma-zen\16_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\16_player_two.png" + Delete "$INSTDIR\graphics\chroma-zen\16_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-zen\16_player_one.png" + Delete "$INSTDIR\graphics\chroma-zen\16_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-zen\16_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-zen\16_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-zen\16_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-zen\16_dots_y.png" + Delete "$INSTDIR\graphics\chroma-zen\16_dots_x.png" + Delete "$INSTDIR\graphics\chroma-zen\16_dots_double.png" + Delete "$INSTDIR\graphics\chroma-zen\16_dots.png" + Delete "$INSTDIR\graphics\chroma-zen\16_door.png" + Delete "$INSTDIR\graphics\chroma-zen\16_circle_double.png" + Delete "$INSTDIR\graphics\chroma-zen\16_circle.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\16_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-zen\16_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon.chroma" + Delete "$INSTDIR\graphics\chroma-neon\64_wall_y.png" + Delete "$INSTDIR\graphics\chroma-neon\64_wall_x.png" + Delete "$INSTDIR\graphics\chroma-neon\64_wall_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-neon\64_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-neon\64_wall.png" + Delete "$INSTDIR\graphics\chroma-neon\64_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_teleport.png" + Delete "$INSTDIR\graphics\chroma-neon\64_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_switch.png" + Delete "$INSTDIR\graphics\chroma-neon\64_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_star.png" + Delete "$INSTDIR\graphics\chroma-neon\64_player_two_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\64_player_two_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_player_two.png" + Delete "$INSTDIR\graphics\chroma-neon\64_player_one_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\64_player_one_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_player_one.png" + Delete "$INSTDIR\graphics\chroma-neon\64_map_top_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-neon\64_map_top_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-neon\64_map_bottom_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-neon\64_map_bottom_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-neon\64_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_dots_y.png" + Delete "$INSTDIR\graphics\chroma-neon\64_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_dots_x.png" + Delete "$INSTDIR\graphics\chroma-neon\64_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_dots_double.png" + Delete "$INSTDIR\graphics\chroma-neon\64_dots.png" + Delete "$INSTDIR\graphics\chroma-neon\64_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_door.png" + Delete "$INSTDIR\graphics\chroma-neon\64_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_circle_double.png" + Delete "$INSTDIR\graphics\chroma-neon\64_circle.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\64_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\40_wall_y.png" + Delete "$INSTDIR\graphics\chroma-neon\40_wall_x.png" + Delete "$INSTDIR\graphics\chroma-neon\40_wall_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-neon\40_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-neon\40_wall.png" + Delete "$INSTDIR\graphics\chroma-neon\40_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_teleport.png" + Delete "$INSTDIR\graphics\chroma-neon\40_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_switch.png" + Delete "$INSTDIR\graphics\chroma-neon\40_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_star.png" + Delete "$INSTDIR\graphics\chroma-neon\40_player_two_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\40_player_two_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_player_two.png" + Delete "$INSTDIR\graphics\chroma-neon\40_player_one_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\40_player_one_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_player_one.png" + Delete "$INSTDIR\graphics\chroma-neon\40_map_top_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-neon\40_map_top_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-neon\40_map_bottom_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-neon\40_map_bottom_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-neon\40_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_dots_y.png" + Delete "$INSTDIR\graphics\chroma-neon\40_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_dots_x.png" + Delete "$INSTDIR\graphics\chroma-neon\40_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_dots_double.png" + Delete "$INSTDIR\graphics\chroma-neon\40_dots.png" + Delete "$INSTDIR\graphics\chroma-neon\40_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_door.png" + Delete "$INSTDIR\graphics\chroma-neon\40_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_circle_double.png" + Delete "$INSTDIR\graphics\chroma-neon\40_circle.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\40_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\32_wall_y.png" + Delete "$INSTDIR\graphics\chroma-neon\32_wall_x.png" + Delete "$INSTDIR\graphics\chroma-neon\32_wall_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-neon\32_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-neon\32_wall.png" + Delete "$INSTDIR\graphics\chroma-neon\32_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_teleport.png" + Delete "$INSTDIR\graphics\chroma-neon\32_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_switch.png" + Delete "$INSTDIR\graphics\chroma-neon\32_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_star.png" + Delete "$INSTDIR\graphics\chroma-neon\32_player_two_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\32_player_two_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_player_two.png" + Delete "$INSTDIR\graphics\chroma-neon\32_player_one_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\32_player_one_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_player_one.png" + Delete "$INSTDIR\graphics\chroma-neon\32_map_top_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-neon\32_map_top_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-neon\32_map_bottom_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-neon\32_map_bottom_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-neon\32_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_dots_y.png" + Delete "$INSTDIR\graphics\chroma-neon\32_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_dots_x.png" + Delete "$INSTDIR\graphics\chroma-neon\32_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_dots_double.png" + Delete "$INSTDIR\graphics\chroma-neon\32_dots.png" + Delete "$INSTDIR\graphics\chroma-neon\32_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_door.png" + Delete "$INSTDIR\graphics\chroma-neon\32_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_circle_double.png" + Delete "$INSTDIR\graphics\chroma-neon\32_circle.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\32_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\24_wall_y.png" + Delete "$INSTDIR\graphics\chroma-neon\24_wall_x.png" + Delete "$INSTDIR\graphics\chroma-neon\24_wall_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-neon\24_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-neon\24_wall.png" + Delete "$INSTDIR\graphics\chroma-neon\24_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_teleport.png" + Delete "$INSTDIR\graphics\chroma-neon\24_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_switch.png" + Delete "$INSTDIR\graphics\chroma-neon\24_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_star.png" + Delete "$INSTDIR\graphics\chroma-neon\24_player_two_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\24_player_two_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_player_two.png" + Delete "$INSTDIR\graphics\chroma-neon\24_player_one_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\24_player_one_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_player_one.png" + Delete "$INSTDIR\graphics\chroma-neon\24_map_top_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-neon\24_map_top_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-neon\24_map_bottom_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-neon\24_map_bottom_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-neon\24_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_dots_y.png" + Delete "$INSTDIR\graphics\chroma-neon\24_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_dots_x.png" + Delete "$INSTDIR\graphics\chroma-neon\24_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_dots_double.png" + Delete "$INSTDIR\graphics\chroma-neon\24_dots.png" + Delete "$INSTDIR\graphics\chroma-neon\24_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_door.png" + Delete "$INSTDIR\graphics\chroma-neon\24_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_circle_double.png" + Delete "$INSTDIR\graphics\chroma-neon\24_circle.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\24_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\20_wall_y.png" + Delete "$INSTDIR\graphics\chroma-neon\20_wall_x.png" + Delete "$INSTDIR\graphics\chroma-neon\20_wall_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-neon\20_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-neon\20_wall.png" + Delete "$INSTDIR\graphics\chroma-neon\20_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_teleport.png" + Delete "$INSTDIR\graphics\chroma-neon\20_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_switch.png" + Delete "$INSTDIR\graphics\chroma-neon\20_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_star.png" + Delete "$INSTDIR\graphics\chroma-neon\20_player_two_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\20_player_two_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_player_two.png" + Delete "$INSTDIR\graphics\chroma-neon\20_player_one_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\20_player_one_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_player_one.png" + Delete "$INSTDIR\graphics\chroma-neon\20_map_top_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-neon\20_map_top_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-neon\20_map_bottom_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-neon\20_map_bottom_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-neon\20_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_dots_y.png" + Delete "$INSTDIR\graphics\chroma-neon\20_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_dots_x.png" + Delete "$INSTDIR\graphics\chroma-neon\20_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_dots_double.png" + Delete "$INSTDIR\graphics\chroma-neon\20_dots.png" + Delete "$INSTDIR\graphics\chroma-neon\20_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_door.png" + Delete "$INSTDIR\graphics\chroma-neon\20_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_circle_double.png" + Delete "$INSTDIR\graphics\chroma-neon\20_circle.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\20_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\16_wall_y.png" + Delete "$INSTDIR\graphics\chroma-neon\16_wall_x.png" + Delete "$INSTDIR\graphics\chroma-neon\16_wall_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-neon\16_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-neon\16_wall.png" + Delete "$INSTDIR\graphics\chroma-neon\16_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_teleport.png" + Delete "$INSTDIR\graphics\chroma-neon\16_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_switch.png" + Delete "$INSTDIR\graphics\chroma-neon\16_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_star.png" + Delete "$INSTDIR\graphics\chroma-neon\16_player_two_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\16_player_two_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_player_two.png" + Delete "$INSTDIR\graphics\chroma-neon\16_player_one_swapped_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-neon\16_player_one_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_player_one.png" + Delete "$INSTDIR\graphics\chroma-neon\16_map_top_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-neon\16_map_top_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-neon\16_map_bottom_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-neon\16_map_bottom_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-neon\16_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_dots_y.png" + Delete "$INSTDIR\graphics\chroma-neon\16_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_dots_x.png" + Delete "$INSTDIR\graphics\chroma-neon\16_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_dots_double.png" + Delete "$INSTDIR\graphics\chroma-neon\16_dots.png" + Delete "$INSTDIR\graphics\chroma-neon\16_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_door.png" + Delete "$INSTDIR\graphics\chroma-neon\16_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_circle_double.png" + Delete "$INSTDIR\graphics\chroma-neon\16_circle.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_red_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_red_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_red_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_red_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_green_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_green_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_green_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_green_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_blue_up_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_blue_right_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_blue_left_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_blue_down_shadow.png" + Delete "$INSTDIR\graphics\chroma-neon\16_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble.chroma" + Delete "$INSTDIR\graphics\chroma-marble\64_wall_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_wall_y.png" + Delete "$INSTDIR\graphics\chroma-marble\64_wall_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_wall_x.png" + Delete "$INSTDIR\graphics\chroma-marble\64_wall_outside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-marble\64_wall_inside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-marble\64_wall.png" + Delete "$INSTDIR\graphics\chroma-marble\64_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_teleport.png" + Delete "$INSTDIR\graphics\chroma-marble\64_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_switch.png" + Delete "$INSTDIR\graphics\chroma-marble\64_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_star.png" + Delete "$INSTDIR\graphics\chroma-marble\64_space.png" + Delete "$INSTDIR\graphics\chroma-marble\64_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\64_player_two.png" + Delete "$INSTDIR\graphics\chroma-marble\64_player_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\64_player_one.png" + Delete "$INSTDIR\graphics\chroma-marble\64_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-marble\64_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-marble\64_map_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-marble\64_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-marble\64_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_dots_y.png" + Delete "$INSTDIR\graphics\chroma-marble\64_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_dots_x.png" + Delete "$INSTDIR\graphics\chroma-marble\64_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_dots_double.png" + Delete "$INSTDIR\graphics\chroma-marble\64_dots.png" + Delete "$INSTDIR\graphics\chroma-marble\64_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_door.png" + Delete "$INSTDIR\graphics\chroma-marble\64_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\64_circle_double.png" + Delete "$INSTDIR\graphics\chroma-marble\64_circle.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\64_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\64_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\40_wall_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_wall_y.png" + Delete "$INSTDIR\graphics\chroma-marble\40_wall_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_wall_x.png" + Delete "$INSTDIR\graphics\chroma-marble\40_wall_outside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-marble\40_wall_inside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-marble\40_wall.png" + Delete "$INSTDIR\graphics\chroma-marble\40_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_teleport.png" + Delete "$INSTDIR\graphics\chroma-marble\40_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_switch.png" + Delete "$INSTDIR\graphics\chroma-marble\40_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_star.png" + Delete "$INSTDIR\graphics\chroma-marble\40_space.png" + Delete "$INSTDIR\graphics\chroma-marble\40_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\40_player_two.png" + Delete "$INSTDIR\graphics\chroma-marble\40_player_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\40_player_one.png" + Delete "$INSTDIR\graphics\chroma-marble\40_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-marble\40_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-marble\40_map_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-marble\40_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-marble\40_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_dots_y.png" + Delete "$INSTDIR\graphics\chroma-marble\40_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_dots_x.png" + Delete "$INSTDIR\graphics\chroma-marble\40_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_dots_double.png" + Delete "$INSTDIR\graphics\chroma-marble\40_dots.png" + Delete "$INSTDIR\graphics\chroma-marble\40_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_door.png" + Delete "$INSTDIR\graphics\chroma-marble\40_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\40_circle_double.png" + Delete "$INSTDIR\graphics\chroma-marble\40_circle.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\40_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\40_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\32_wall_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_wall_y.png" + Delete "$INSTDIR\graphics\chroma-marble\32_wall_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_wall_x.png" + Delete "$INSTDIR\graphics\chroma-marble\32_wall_outside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-marble\32_wall_inside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-marble\32_wall.png" + Delete "$INSTDIR\graphics\chroma-marble\32_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_teleport.png" + Delete "$INSTDIR\graphics\chroma-marble\32_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_switch.png" + Delete "$INSTDIR\graphics\chroma-marble\32_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_star.png" + Delete "$INSTDIR\graphics\chroma-marble\32_space.png" + Delete "$INSTDIR\graphics\chroma-marble\32_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\32_player_two.png" + Delete "$INSTDIR\graphics\chroma-marble\32_player_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\32_player_one.png" + Delete "$INSTDIR\graphics\chroma-marble\32_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-marble\32_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-marble\32_map_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-marble\32_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-marble\32_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_dots_y.png" + Delete "$INSTDIR\graphics\chroma-marble\32_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_dots_x.png" + Delete "$INSTDIR\graphics\chroma-marble\32_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_dots_double.png" + Delete "$INSTDIR\graphics\chroma-marble\32_dots.png" + Delete "$INSTDIR\graphics\chroma-marble\32_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_door.png" + Delete "$INSTDIR\graphics\chroma-marble\32_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\32_circle_double.png" + Delete "$INSTDIR\graphics\chroma-marble\32_circle.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\32_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\32_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\24_wall_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_wall_y.png" + Delete "$INSTDIR\graphics\chroma-marble\24_wall_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_wall_x.png" + Delete "$INSTDIR\graphics\chroma-marble\24_wall_outside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-marble\24_wall_inside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-marble\24_wall.png" + Delete "$INSTDIR\graphics\chroma-marble\24_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_teleport.png" + Delete "$INSTDIR\graphics\chroma-marble\24_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_switch.png" + Delete "$INSTDIR\graphics\chroma-marble\24_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_star.png" + Delete "$INSTDIR\graphics\chroma-marble\24_space.png" + Delete "$INSTDIR\graphics\chroma-marble\24_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\24_player_two.png" + Delete "$INSTDIR\graphics\chroma-marble\24_player_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\24_player_one.png" + Delete "$INSTDIR\graphics\chroma-marble\24_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-marble\24_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-marble\24_map_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-marble\24_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-marble\24_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_dots_y.png" + Delete "$INSTDIR\graphics\chroma-marble\24_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_dots_x.png" + Delete "$INSTDIR\graphics\chroma-marble\24_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_dots_double.png" + Delete "$INSTDIR\graphics\chroma-marble\24_dots.png" + Delete "$INSTDIR\graphics\chroma-marble\24_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_door.png" + Delete "$INSTDIR\graphics\chroma-marble\24_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\24_circle_double.png" + Delete "$INSTDIR\graphics\chroma-marble\24_circle.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\24_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\24_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\20_wall_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_wall_y.png" + Delete "$INSTDIR\graphics\chroma-marble\20_wall_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_wall_x.png" + Delete "$INSTDIR\graphics\chroma-marble\20_wall_outside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-marble\20_wall_inside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-marble\20_wall.png" + Delete "$INSTDIR\graphics\chroma-marble\20_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_teleport.png" + Delete "$INSTDIR\graphics\chroma-marble\20_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_switch.png" + Delete "$INSTDIR\graphics\chroma-marble\20_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_star.png" + Delete "$INSTDIR\graphics\chroma-marble\20_space.png" + Delete "$INSTDIR\graphics\chroma-marble\20_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\20_player_two.png" + Delete "$INSTDIR\graphics\chroma-marble\20_player_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\20_player_one.png" + Delete "$INSTDIR\graphics\chroma-marble\20_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-marble\20_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-marble\20_map_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-marble\20_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-marble\20_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_dots_y.png" + Delete "$INSTDIR\graphics\chroma-marble\20_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_dots_x.png" + Delete "$INSTDIR\graphics\chroma-marble\20_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_dots_double.png" + Delete "$INSTDIR\graphics\chroma-marble\20_dots.png" + Delete "$INSTDIR\graphics\chroma-marble\20_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_door.png" + Delete "$INSTDIR\graphics\chroma-marble\20_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\20_circle_double.png" + Delete "$INSTDIR\graphics\chroma-marble\20_circle.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\20_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\20_arrow_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\16_wall_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_wall_y.png" + Delete "$INSTDIR\graphics\chroma-marble\16_wall_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_wall_x.png" + Delete "$INSTDIR\graphics\chroma-marble\16_wall_outside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_wall_outside.png" + Delete "$INSTDIR\graphics\chroma-marble\16_wall_inside_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_wall_inside.png" + Delete "$INSTDIR\graphics\chroma-marble\16_wall.png" + Delete "$INSTDIR\graphics\chroma-marble\16_teleport_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_teleport.png" + Delete "$INSTDIR\graphics\chroma-marble\16_switch_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_switch.png" + Delete "$INSTDIR\graphics\chroma-marble\16_star_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_star.png" + Delete "$INSTDIR\graphics\chroma-marble\16_space.png" + Delete "$INSTDIR\graphics\chroma-marble\16_player_two_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\16_player_two.png" + Delete "$INSTDIR\graphics\chroma-marble\16_player_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_player_one_swapped.png" + Delete "$INSTDIR\graphics\chroma-marble\16_player_one.png" + Delete "$INSTDIR\graphics\chroma-marble\16_map_top_right.png" + Delete "$INSTDIR\graphics\chroma-marble\16_map_top_left.png" + Delete "$INSTDIR\graphics\chroma-marble\16_map_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_map_bottom_right.png" + Delete "$INSTDIR\graphics\chroma-marble\16_map_bottom_left.png" + Delete "$INSTDIR\graphics\chroma-marble\16_dots_y_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_dots_y.png" + Delete "$INSTDIR\graphics\chroma-marble\16_dots_x_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_dots_x.png" + Delete "$INSTDIR\graphics\chroma-marble\16_dots_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_dots_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_dots_double.png" + Delete "$INSTDIR\graphics\chroma-marble\16_dots.png" + Delete "$INSTDIR\graphics\chroma-marble\16_door_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_door.png" + Delete "$INSTDIR\graphics\chroma-marble\16_circle_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_circle_double_shadow.png" + Delete "$INSTDIR\graphics\chroma-marble\16_circle_double.png" + Delete "$INSTDIR\graphics\chroma-marble\16_circle.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\16_bomb_blue_down.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_shadow_up.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_shadow_right.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_shadow_left.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_shadow_down.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_red_up.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_red_right.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_red_left.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_red_down.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_green_up.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_green_right.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_green_left.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_green_down.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_blue_up.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_blue_right.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_blue_left.png" + Delete "$INSTDIR\graphics\chroma-marble\16_arrow_blue_down.png" + Delete "$INSTDIR\help\README" + Delete "$INSTDIR\colours\fallback.chroma" + Delete "$INSTDIR\colours\chroma-standard.chroma" + Delete "$INSTDIR\colours\chroma-reverse.chroma" + Delete "$INSTDIR\colours\chroma-monochrome.chroma" + Delete "$INSTDIR\colours\chroma-enigma.chroma" + Delete "$INSTDIR\colours\chroma-enhanced.chroma" + Delete "$INSTDIR\README" + Delete "$INSTDIR\COPYING" + Delete "$INSTDIR\chroma.exe" + Delete "$INSTDIR\chroma-curses.exe" + + Delete "$SMPROGRAMS\Chroma\Uninstall.lnk" + Delete "$DESKTOP\Chroma.lnk" + Delete "$SMPROGRAMS\Chroma\Chroma.lnk" + Delete "$SMPROGRAMS\Chroma\Chroma Curses.lnk" + + RMDir "$SMPROGRAMS\Chroma" + RMDir "$INSTDIR\levels\regression" + RMDir "$INSTDIR\levels\chroma-2" + RMDir "$INSTDIR\levels\chroma-1" + RMDir "$INSTDIR\levels" + RMDir "$INSTDIR\graphics\resources" + RMDir "$INSTDIR\graphics\chroma-zen" + RMDir "$INSTDIR\graphics\chroma-neon" + RMDir "$INSTDIR\graphics\chroma-marble" + RMDir "$INSTDIR\graphics" + RMDir "$INSTDIR\help" + RMDir "$INSTDIR\colours" + RMDir "$INSTDIR" + + DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" + DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" + SetAutoClose true +SectionEnd diff --git a/colours.c b/colours.c new file mode 100644 index 0000000..12d6be0 --- /dev/null +++ b/colours.c @@ -0,0 +1,408 @@ +/* + colours.c + + Copyright (C) 2010-2019 Amf + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chroma.h" +#include "level.h" +#include "util.h" +#include "colours.h" +#include "menu.h" +#include "xmlparser.h" + +struct colours* pdisplaycolours = NULL; + +extern char options_colours[]; +extern int options_debug; +extern char *piece_name[]; + +void colours_init() +{ + char filename[FILENAME_MAX]; + char directory[FILENAME_MAX]; + + if(pdisplaycolours != NULL) + colours_delete(pdisplaycolours); + + pdisplaycolours = colours_load(options_colours, 0); + + if(pdisplaycolours == NULL) + { + /* Revert to default */ + getfilename("colours", directory, 0, LOCATION_SYSTEM); + sprintf(filename, "%s%s%s", directory, "/", COLOURS_DEFAULT); + pdisplaycolours = colours_load(filename, 0); + + /* If we can't even load the default, use an emergency scheme */ + if(pdisplaycolours == NULL) + pdisplaycolours = colours_load(NULL, 0); + } +} + +struct colours* colours_load(char *filename, int partial) +{ + struct colours* pcolours; + struct parser* pparser = NULL; + int state; + int piece; + int i; + int foreground, background, bold, reverse; + char character; + char *text; + int colour; + + if(filename != NULL) + { + if(!isfile(filename)) + return NULL; + + pparser = parser_new(filename); + if(pparser == NULL) + return NULL; + } + + pcolours = (struct colours*)malloc(sizeof(struct colours)); + pcolours->title = NULL; + if(pcolours == NULL) + return NULL; + + /* Sensible defaults */ + if(!partial) + { + for(i = 0; i < PIECE_MAX; i ++) + { + pcolours->character[i] = piecetochar(i); + pcolours->foreground[i] = -1; + pcolours->background[i] = -1; + pcolours->bold[i] = 0; + pcolours->reverse[i] = 0; + } + } + + /* Emergency default colour scheme */ + if(filename == NULL) + return pcolours; + + /* Parse XML file */ + /* + + + title + + + + + + */ + + enum{ + COLOURSPARSER_BAD, /* End of bad file */ + COLOURSPARSER_END, /* End of good file */ + COLOURSPARSER_OUTSIDE, /* Outside */ + COLOURSPARSER_CHROMA, /* Inside */ + COLOURSPARSER_PIECES /* Inside */ + }; + + state = COLOURSPARSER_OUTSIDE; + piece = PIECE_UNKNOWN; + foreground = 7; background = 0; bold = 0; reverse = 0; character = ' '; + + while(state != COLOURSPARSER_BAD && state != COLOURSPARSER_END) + { + switch(parser_parse(pparser)) + { + case PARSER_END: + if(state == COLOURSPARSER_OUTSIDE) + state = COLOURSPARSER_BAD; + else + state = COLOURSPARSER_END; + break; + + case PARSER_ELEMENT_START: + switch(state) + { + case COLOURSPARSER_CHROMA: + if(parser_match(pparser, 0, "pieces")) + state = COLOURSPARSER_PIECES; + break; + + case COLOURSPARSER_PIECES: + if(parser_match(pparser, 0, "piece")) + { + piece = PIECE_UNKNOWN; + foreground = 7; background = -1; + bold = 0; reverse = 0; + character = ' '; + } + break; + + default: + break; + } + break; + + case PARSER_ELEMENT_END: + switch(state) + { + case COLOURSPARSER_CHROMA: /* If we're only partially loading the file, end parsing at */ + if(parser_match(pparser, 0, "head")) + { + if(partial) + state = COLOURSPARSER_END; + } + break; + + case COLOURSPARSER_PIECES: + if(parser_match(pparser, 0, "pieces")) + state = COLOURSPARSER_CHROMA; + if(parser_match(pparser, 0, "piece")) + { + if(piece != PIECE_UNKNOWN) + { + pcolours->character[piece] = character; + pcolours->foreground[piece] = foreground; + pcolours->background[piece] = background; + pcolours->bold[piece] = bold; + pcolours->reverse[piece] = reverse; + } + } + break; + + default: + break; + } + + break; + + case PARSER_CONTENT: + switch(state) + { + case COLOURSPARSER_CHROMA: + if(parser_match(pparser, 1, "title")) + { + pcolours->title = malloc(strlen(parser_text(pparser, 0)) + 1); + if(pcolours->title == NULL) + fatal(gettext("Out of memory in colours_load()")); + strcpy(pcolours->title, parser_text(pparser, 0)); + } + + break; + + default: + break; + } + break; + + case PARSER_ATTRIBUTE: + switch(state) + { + case COLOURSPARSER_OUTSIDE: if(parser_match(pparser, 2, "chroma") && parser_match(pparser, 1, "type")) + { + if(parser_match(pparser, 0, "colours") || parser_match(pparser, 0, "colors")) + state = COLOURSPARSER_CHROMA; + } + break; + + case COLOURSPARSER_CHROMA: + if(parser_match(pparser, 2, "chroma") && parser_match(pparser, 1, "hidden")) + { + if(parser_match(pparser, 0, "yes")) + { + if(partial && !(options_debug & DEBUG_HIDDEN)) + state = COLOURSPARSER_BAD; + } + } + if(parser_match(pparser, 2, "title") && parser_match(pparser, 1, "translate")) + { + if(parser_match(pparser, 0, "yes")) + pcolours->flags |= COLOURS_TRANSLATE; + } + break; + + case COLOURSPARSER_PIECES: + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "name")) + { + for(i = 0; i < PIECE_UNKNOWN; i ++) + { + if(strcasecmp(parser_text(pparser, 0), piece_name[i]) == 0) + piece = i; + } + } + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "character")) + { + text = parser_text(pparser, 0); + if(text[0] != 0) + character = text[0]; + } + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "bold")) + { + bold = 0; + if(strcmp(parser_text(pparser, 0), "yes") == 0) + bold = 1; + } + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "reverse")) + { + reverse = 0; + if(strcmp(parser_text(pparser, 0), "yes") == 0) + reverse = 1; + } + if(parser_match(pparser, 2, "piece") && (parser_match(pparser, 1, "background") || parser_match(pparser, 1, "foreground"))) + { + colour = -1; + if(strcmp(parser_text(pparser, 0), "black") == 0) + colour = 0; + if(strcmp(parser_text(pparser, 0), "red") == 0) + colour = 1; + if(strcmp(parser_text(pparser, 0), "green") == 0) + colour = 2; + if(strcmp(parser_text(pparser, 0), "yellow") == 0) + colour = 3; + if(strcmp(parser_text(pparser, 0), "blue") == 0) + colour = 4; + if(strcmp(parser_text(pparser, 0), "magenta") == 0) + colour = 5; + if(strcmp(parser_text(pparser, 0), "cyan") == 0) + colour = 6; + if(strcmp(parser_text(pparser, 0), "white") == 0) + colour = 7; + + if(parser_match(pparser, 1, "background")) + background = colour; + if(parser_match(pparser, 1, "foreground") && colour != -1) + foreground = colour; + } + break; + + default: + break; + } + break; + + case PARSER_ERROR: + default: + break; + } + } + + parser_delete(pparser); + + if(state == COLOURSPARSER_BAD) + { + colours_delete(pcolours); + return NULL; + } + + return pcolours; +} + +void colours_delete(struct colours* pcolours) +{ + if(pcolours->title != NULL) + free(pcolours->title); + + free(pcolours); +} + +struct menu* colours_menu() +{ + DIR *pdir; + struct dirent *dentry; + struct menu* pmenu; + struct menuentry* pentry; + char directory[FILENAME_MAX]; + char filename[FILENAME_MAX]; + struct colours* pcolours; + int location; + + pmenu = menu_new(gettext("Colour Schemes")); + + menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + menuentry_new(pmenu, gettext("Current colour scheme:"), 0, MENU_NOTE); + + if(pdisplaycolours == NULL) + menuentry_new(pmenu, gettext("** NONE **"), 0, MENU_NOTE | MENU_RIGHT); + else if(pdisplaycolours->title == NULL) + menuentry_new(pmenu, gettext("[untitled colours]"), 0, MENU_NOTE | MENU_RIGHT); + else if(pdisplaycolours->flags & COLOURS_TRANSLATE) + menuentry_new(pmenu, gettext(pdisplaycolours->title), 0, MENU_NOTE | MENU_RIGHT); + else + menuentry_new(pmenu, pdisplaycolours->title, 0, MENU_NOTE | MENU_RIGHT); + /* Global, then user */ + for(location = 1; location >= 0; location --) + { + getfilename("colours", directory, 0, location); + + pdir = opendir(directory); + if(pdir == NULL) + continue; + + while((dentry = readdir(pdir)) != NULL) + { + if(strcmp(dentry->d_name, ".") == 0) + continue; + if(strcmp(dentry->d_name, "..") == 0) + continue; + + sprintf(filename, "%s%s%s", directory, "/", dentry->d_name); + + if(isfile(filename) && strlen(filename) > 7 && strcmp(filename + strlen(filename) - 7, ".chroma") == 0) + { + pcolours = colours_load(filename, 1); + if(pcolours != NULL) + { + if(pcolours->title == NULL) + pentry = menuentry_newwithvalue(pmenu, gettext("[untitled colours]"), 0, MENU_SORT, filename); + else if(pcolours->flags & COLOURS_TRANSLATE) + pentry = menuentry_newwithvalue(pmenu, gettext(pcolours->title), 0, MENU_SORT, filename); + else + pentry = menuentry_newwithvalue(pmenu, pcolours->title, 0, MENU_SORT, filename); + colours_delete(pcolours); + + if(strcmp(options_colours, filename) == 0) + pmenu->entry_selected = pentry; + } + } + } + + closedir(pdir); + + menu_unsort(pmenu); + + if(location == 1) + menuentry_new(pmenu, "", 0, MENU_SPACE); + } + + menu_assignletters(pmenu); + + return pmenu; +} diff --git a/colours.h b/colours.h new file mode 100644 index 0000000..3b1c1f5 --- /dev/null +++ b/colours.h @@ -0,0 +1,42 @@ +/* + colours.h + + Copyright (C) 2010-2019 Amf + + 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 COLOURS_DEFAULT "chroma-standard.chroma" + +#define COLOURS_TRANSLATE 1 + +struct colours +{ + char *title; + + char character[PIECE_MAX]; + int foreground[PIECE_MAX]; + int background[PIECE_MAX]; + int bold[PIECE_MAX]; + int reverse[PIECE_MAX]; + int flags; +}; + +void colours_init(); +struct colours* colours_load(char *filename, int partial); +void colours_delete(struct colours*); +struct menu* colours_menu(); + + diff --git a/colours/chroma-enhanced.chroma b/colours/chroma-enhanced.chroma new file mode 100644 index 0000000..ea91105 --- /dev/null +++ b/colours/chroma-enhanced.chroma @@ -0,0 +1,77 @@ + + + +Chroma Curses Enhanced + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/colours/chroma-enigma.chroma b/colours/chroma-enigma.chroma new file mode 100644 index 0000000..2c53f2c --- /dev/null +++ b/colours/chroma-enigma.chroma @@ -0,0 +1,77 @@ + + + +Chroma Curses Enigma + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/colours/chroma-monochrome.chroma b/colours/chroma-monochrome.chroma new file mode 100644 index 0000000..125a77d --- /dev/null +++ b/colours/chroma-monochrome.chroma @@ -0,0 +1,77 @@ + + + +Chroma Curses Monochrome + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/colours/chroma-reverse.chroma b/colours/chroma-reverse.chroma new file mode 100644 index 0000000..459e11c --- /dev/null +++ b/colours/chroma-reverse.chroma @@ -0,0 +1,77 @@ + + + +Chroma Curses Reverse + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/colours/chroma-standard.chroma b/colours/chroma-standard.chroma new file mode 100644 index 0000000..717ee8c --- /dev/null +++ b/colours/chroma-standard.chroma @@ -0,0 +1,77 @@ + + + +Chroma Curses Standard + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/colours/fallback.chroma b/colours/fallback.chroma new file mode 100644 index 0000000..68cbe51 --- /dev/null +++ b/colours/fallback.chroma @@ -0,0 +1,6 @@ + + diff --git a/configure b/configure new file mode 100755 index 0000000..df47484 --- /dev/null +++ b/configure @@ -0,0 +1,4298 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= +PACKAGE_URL= + +ac_unique_file="main.c" +ac_subst_vars='LTLIBOBJS +LIBOBJS +TARGETSINSTALL +TARGETSCLEAN +TARGETS +CURSES +PKG_CONFIG +FREETYPE_CONFIG +SDLCONFIG +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +OBJEXT +EXEEXT +ac_ct_CC +CPPFLAGS +LDFLAGS +CFLAGS +CC +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_sdl +enable_curses +with_freetype_prefix +with_freetype_exec_prefix +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root [DATAROOTDIR/doc/PACKAGE] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-sdl build SDL chroma + --enable-curses build curses chroma + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-freetype-prefix=PFX Prefix where FREETYPE is installed (optional) + --with-freetype-exec-prefix=PFX Exec prefix where FREETYPE is installed (optional) + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +configure +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# Check whether --enable-sdl was given. +if test "${enable_sdl+set}" = set; then : + enableval=$enable_sdl; with_sdl=$enableval +else + with_sdl=yes +fi + + +# Check whether --enable-curses was given. +if test "${enable_curses+set}" = set; then : + enableval=$enable_curses; with_curses=$enableval +else + with_curses=yes +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + fi +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl.exe + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl.exe +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$ac_cv_prog_cc_g" >&6; } +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +struct stat; +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} + +/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has + function prototypes and stuff, but not '\xHH' hex character constants. + These don't provoke an error unfortunately, instead are silently treated + as 'x'. The following induces an error, until -std is added to get + proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an + array size at least. It's necessary to write '\x00'==0 to get something + that's true only with -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1]; + +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +if test "$with_sdl" = "yes"; then + # Extract the first word of "sdl-config", so it can be a program name with args. +set dummy sdl-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_SDLCONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $SDLCONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_SDLCONFIG="$SDLCONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_SDLCONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_SDLCONFIG" && ac_cv_path_SDLCONFIG="no" + ;; +esac +fi +SDLCONFIG=$ac_cv_path_SDLCONFIG +if test -n "$SDLCONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SDLCONFIG" >&5 +$as_echo "$SDLCONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$SDLCONFIG" = "no"; then + as_fn_error $? "*** Unable to find sdl-config" "$LINENO" 5 + else + CFLAGS="$CFLAGS "`sdl-config --cflags` + LDFLAGS="$LDFLAGS "`sdl-config --libs` + fi +fi + +if test "$with_sdl" = "yes"; then + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for IMG_LoadPNG_RW in -lSDL_image" >&5 +$as_echo_n "checking for IMG_LoadPNG_RW in -lSDL_image... " >&6; } +if ${ac_cv_lib_SDL_image_IMG_LoadPNG_RW+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lSDL_image $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char IMG_LoadPNG_RW (); +int +main () +{ +return IMG_LoadPNG_RW (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_SDL_image_IMG_LoadPNG_RW=yes +else + ac_cv_lib_SDL_image_IMG_LoadPNG_RW=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_SDL_image_IMG_LoadPNG_RW" >&5 +$as_echo "$ac_cv_lib_SDL_image_IMG_LoadPNG_RW" >&6; } +if test "x$ac_cv_lib_SDL_image_IMG_LoadPNG_RW" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSDL_IMAGE 1 +_ACEOF + + LIBS="-lSDL_image $LIBS" + +fi + + if test "$ac_cv_lib_SDL_image_IMG_LoadPNG_RW" != "yes"; then + as_fn_error $? "*** Unable to find SDL_image library with PNG support" "$LINENO" 5 + fi +fi + +if test "$with_sdl" = "yes"; then + +# Check whether --with-freetype-prefix was given. +if test "${with_freetype_prefix+set}" = set; then : + withval=$with_freetype_prefix; freetype_prefix="$withval" +else + freetype_prefix="" +fi + + +# Check whether --with-freetype-exec-prefix was given. +if test "${with_freetype_exec_prefix+set}" = set; then : + withval=$with_freetype_exec_prefix; freetype_exec_prefix="$withval" +else + freetype_exec_prefix="" +fi + + if test x$freetype_exec_prefix != x ; then + freetype_args="$freetype_args --exec-prefix=$freetype_exec_prefix" + if test x${FREETYPE_CONFIG+set} != xset ; then + FREETYPE_CONFIG=$freetype_exec_prefix/bin/freetype-config + fi + fi + if test x$freetype_prefix != x ; then + freetype_args="$freetype_args --prefix=$freetype_prefix" + if test x${FREETYPE_CONFIG+set} != xset ; then + FREETYPE_CONFIG=$freetype_prefix/bin/freetype-config + fi + fi + # Extract the first word of "freetype-config", so it can be a program name with args. +set dummy freetype-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_FREETYPE_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $FREETYPE_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_FREETYPE_CONFIG="$FREETYPE_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_FREETYPE_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_FREETYPE_CONFIG" && ac_cv_path_FREETYPE_CONFIG="no" + ;; +esac +fi +FREETYPE_CONFIG=$ac_cv_path_FREETYPE_CONFIG +if test -n "$FREETYPE_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_CONFIG" >&5 +$as_echo "$FREETYPE_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + no_freetype="" + if test "$FREETYPE_CONFIG" = "no" ; then + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path_PKG_CONFIG" && ac_cv_path_PKG_CONFIG="no" + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "$PKG_CONFIG" = "no" ; then + as_fn_error $? "*** Unable to find FreeType2 library (http://www.freetype.org/)" "$LINENO" 5 + else + CFLAGS="$CFLAGS `$PKG_CONFIG freetype2 --cflags`" + LIBS="$LIBS `$PKG_CONFIG freetype2 --libs`" + fi + else + CFLAGS="$CFLAGS `$FREETYPE_CONFIG $freetypeconf_args --cflags`" + LIBS="$LIBS `$FREETYPE_CONFIG $freetypeconf_args --libs`" + fi +fi + +if test "$with_curses" = "yes"; then + CURSES="ncurses" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for initscr in -lncurses" >&5 +$as_echo_n "checking for initscr in -lncurses... " >&6; } +if ${ac_cv_lib_ncurses_initscr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lncurses $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char initscr (); +int +main () +{ +return initscr (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_ncurses_initscr=yes +else + ac_cv_lib_ncurses_initscr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ncurses_initscr" >&5 +$as_echo "$ac_cv_lib_ncurses_initscr" >&6; } +if test "x$ac_cv_lib_ncurses_initscr" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBNCURSES 1 +_ACEOF + + LIBS="-lncurses $LIBS" + +fi + + if test "$ac_cv_lib_ncurses_initscr" != "yes"; then + CURSES="curses" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for initscr in -lcurses" >&5 +$as_echo_n "checking for initscr in -lcurses... " >&6; } +if ${ac_cv_lib_curses_initscr+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lcurses $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char initscr (); +int +main () +{ +return initscr (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_curses_initscr=yes +else + ac_cv_lib_curses_initscr=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_curses_initscr" >&5 +$as_echo "$ac_cv_lib_curses_initscr" >&6; } +if test "x$ac_cv_lib_curses_initscr" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBCURSES 1 +_ACEOF + + LIBS="-lcurses $LIBS" + +fi + + if test "$ac_cv_lib_curses_initscr" != "yes"; then + CURSES="" + fi + fi + if test "$CURSES" = ""; then + as_fn_error $? "*** Unable to find curses / ncurses library" "$LINENO" 5 + fi +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gettext" >&5 +$as_echo_n "checking for library containing gettext... " >&6; } +if ${ac_cv_search_gettext+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gettext (); +int +main () +{ +return gettext (); + ; + return 0; +} +_ACEOF +for ac_lib in '' intl; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_gettext=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_gettext+:} false; then : + break +fi +done +if ${ac_cv_search_gettext+:} false; then : + +else + ac_cv_search_gettext=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gettext" >&5 +$as_echo "$ac_cv_search_gettext" >&6; } +ac_res=$ac_cv_search_gettext +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +TARGETS="" +TARGETSCLEAN="" +TARGETSINSTALL="" +if test "$with_sdl" = "yes"; then +TARGETS="$TARGETS chroma-sdl" +TARGETSCLEAN="$TARGETSCLEAN clean-sdl"; +TARGETSINSTALL="$TARGETSINSTALL install-sdl"; +fi +if test "$with_curses" = "yes"; then +TARGETS="$TARGETS chroma-curses" +TARGETSCLEAN="$TARGETSCLEAN clean-curses"; +TARGETSINSTALL="$TARGETSINSTALL install-curses"; +fi +if test "$TARGETS" = ""; then +as_fn_error $? "*** Nothing to build - specify either --enable-sdl and/or --enable-curses" "$LINENO" 5 +fi + + + + + +ac_config_files="$ac_config_files Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# Transform confdefs.h into DEFS. +# Protect against shell expansion while executing Makefile rules. +# Protect against Makefile macro expansion. +# +# If the first sed substitution is executed (which looks for macros that +# take arguments), then branch to the quote section. Otherwise, +# look for a macro that doesn't take arguments. +ac_script=' +:mline +/\\$/{ + N + s,\\\n,, + b mline +} +t clear +:clear +s/^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*([^)]*)\)[ ]*\(.*\)/-D\1=\2/g +t quote +s/^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)/-D\1=\2/g +t quote +b any +:quote +s/[ `~#$^&*(){}\\|;'\''"<>?]/\\&/g +s/\[/\\&/g +s/\]/\\&/g +s/\$/$$/g +H +:any +${ + g + s/^\n// + s/\n/ /g + p +} +' +DEFS=`sed -n "$ac_script" confdefs.h` + + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by $as_me, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + +Configuration files: +$config_files + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h | --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + + +eval set X " :F $CONFIG_FILES " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..68c5fa4 --- /dev/null +++ b/configure.ac @@ -0,0 +1,113 @@ +dnl Process this file with autoconf to produce a configure script. +AC_INIT(main.c) + +AC_ARG_ENABLE(sdl, + [ --enable-sdl build SDL chroma], + [with_sdl=$enableval], + [with_sdl=yes], +) + +AC_ARG_ENABLE(curses, + [ --enable-curses build curses chroma], + [with_curses=$enableval], + [with_curses=yes], +) + +dnl Check for programs +AC_PROG_CC +AC_PROG_INSTALL + +dnl Check for SDL +if test "$with_sdl" = "yes"; then + AC_PATH_PROG(SDLCONFIG, sdl-config, no) + if test "$SDLCONFIG" = "no"; then + AC_MSG_ERROR([*** Unable to find sdl-config]) + else + CFLAGS="$CFLAGS "`sdl-config --cflags` + LDFLAGS="$LDFLAGS "`sdl-config --libs` + fi +fi + +dnl Check for SDL_image library +if test "$with_sdl" = "yes"; then + AC_CHECK_LIB(SDL_image, IMG_LoadPNG_RW) + if test "$ac_cv_lib_SDL_image_IMG_LoadPNG_RW" != "yes"; then + AC_MSG_ERROR([*** Unable to find SDL_image library with PNG support]) + fi +fi + +dnl Check for the FreeType 2 library +if test "$with_sdl" = "yes"; then + AC_ARG_WITH(freetype-prefix,[ --with-freetype-prefix=PFX Prefix where FREETYPE is installed (optional)], freetype_prefix="$withval", freetype_prefix="") + AC_ARG_WITH(freetype-exec-prefix,[ --with-freetype-exec-prefix=PFX Exec prefix where FREETYPE is installed (optional)], freetype_exec_prefix="$withval", freetype_exec_prefix="") + if test x$freetype_exec_prefix != x ; then + freetype_args="$freetype_args --exec-prefix=$freetype_exec_prefix" + if test x${FREETYPE_CONFIG+set} != xset ; then + FREETYPE_CONFIG=$freetype_exec_prefix/bin/freetype-config + fi + fi + if test x$freetype_prefix != x ; then + freetype_args="$freetype_args --prefix=$freetype_prefix" + if test x${FREETYPE_CONFIG+set} != xset ; then + FREETYPE_CONFIG=$freetype_prefix/bin/freetype-config + fi + fi + AC_PATH_PROG(FREETYPE_CONFIG, freetype-config, no) + no_freetype="" + if test "$FREETYPE_CONFIG" = "no" ; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + if test "$PKG_CONFIG" = "no" ; then + AC_MSG_ERROR([*** Unable to find FreeType2 library (http://www.freetype.org/)]) + else + CFLAGS="$CFLAGS `$PKG_CONFIG freetype2 --cflags`" + LIBS="$LIBS `$PKG_CONFIG freetype2 --libs`" + fi + else + CFLAGS="$CFLAGS `$FREETYPE_CONFIG $freetypeconf_args --cflags`" + LIBS="$LIBS `$FREETYPE_CONFIG $freetypeconf_args --libs`" + fi +fi + +dnl Check for curses library +if test "$with_curses" = "yes"; then + CURSES="ncurses" + AC_CHECK_LIB(ncurses, initscr) + if test "$ac_cv_lib_ncurses_initscr" != "yes"; then + CURSES="curses" + AC_CHECK_LIB(curses, initscr) + if test "$ac_cv_lib_curses_initscr" != "yes"; then + CURSES="" + fi + fi + if test "$CURSES" = ""; then + AC_MSG_ERROR([*** Unable to find curses / ncurses library]) + fi +fi + +dnl Check for gettext library +AC_SEARCH_LIBS(gettext, intl) + +dnl Determine targets to build +TARGETS="" +TARGETSCLEAN="" +TARGETSINSTALL="" +if test "$with_sdl" = "yes"; then +TARGETS="$TARGETS chroma-sdl" +TARGETSCLEAN="$TARGETSCLEAN clean-sdl"; +TARGETSINSTALL="$TARGETSINSTALL install-sdl"; +fi +if test "$with_curses" = "yes"; then +TARGETS="$TARGETS chroma-curses" +TARGETSCLEAN="$TARGETSCLEAN clean-curses"; +TARGETSINSTALL="$TARGETSINSTALL install-curses"; +fi +if test "$TARGETS" = ""; then +AC_MSG_ERROR([*** Nothing to build - specify either --enable-sdl and/or --enable-curses]) +fi + +AC_SUBST(CURSES) +AC_SUBST(TARGETS) +AC_SUBST(TARGETSCLEAN) +AC_SUBST(TARGETSINSTALL) +AC_OUTPUT(Makefile) + diff --git a/cursesdisplay.c b/cursesdisplay.c new file mode 100644 index 0000000..1c694ad --- /dev/null +++ b/cursesdisplay.c @@ -0,0 +1,1872 @@ +/* + cursesdisplay.c + + Copyright (C) 2010-2019 Amf + + 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 +#include +#include +#include + +#ifdef CHROMA_CURSES_HEADER +#include CHROMA_CURSES_HEADER +#else +#ifdef __WIN32__ +#include +#else +#include +#endif +#endif + +#include "chroma.h" +#include "menu.h" +#include "level.h" +#include "display.h" +#include "colours.h" +#include "actions.h" +#include "util.h" +#include "xmlparser.h" + +char options_colours[FILENAME_MAX] = COLOURS_DEFAULT; +int options_curses_delay = 1; +int options_curses_replay_delay = 1; +int options_debug = 0; +#ifdef XOR_COMPATIBILITY +int options_xor_options = 0; +int options_xor_mode = 1; +int options_xor_display = 0; +#endif +#ifdef ENIGMA_COMPATIBILITY +int options_enigma_options = 0; +int options_enigma_mode = 1; +#endif + + +extern struct colours* pdisplaycolours; +extern int *editor_piece_maps[]; +extern char *action_name[]; +extern char *action_shortname[]; + +/* Translation table for colours. + This is necessary as some versions of curses interchange red and blue. + */ +short colourtrans[] = {COLOR_BLACK, COLOR_RED, COLOR_GREEN, COLOR_YELLOW, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_WHITE}; + +int dp_attr[256], dp_col[256]; +char dp_char[256]; + +int actions[KEY_MAX]; + +int display_size_x, display_size_y; +int display_offset_x, display_offset_y; +int display_focus_x, display_focus_y; +int display_start_x, display_start_y; +int display_end_x, display_end_y; +int display_border = 7; + +void display_piece(struct level* plevel, int piece); + +int display_colourpairs = 0; +short display_cpfore[64]; +short display_cpback[64]; + +short colourpair_red; +short colourpair_green; +short colourpair_yellow; +short colourpair_blue; +short colourpair_cyan; +short colourpair_magenta; +short colourpair_cyan; +short colourpair_white; +short colourpair_menu; +short colourpair_menugrey; + +char *display_keyname(int i); +void display_addkeytomenu(struct menu* pmenu, int action, char *text); +void display_keys(); +void display_debug(); +void display_initcolours(); + +void display_options_othergames(); + +short display_newcolourpair(short foreground, short background) +{ + short i; + + for(i = 1; i <= display_colourpairs; i ++) + { + if(foreground == display_cpfore[i] && background == display_cpback[i]) + return i; + } + display_colourpairs ++; + display_cpfore[display_colourpairs] = foreground; + display_cpback[display_colourpairs] = background; + + init_pair(display_colourpairs, foreground, background); + + return display_colourpairs; +} + +void display_init() +{ + setlocale(LC_CTYPE, ""); + atexit(display_quit); + initscr(); + raw(); + noecho(); + keypad(stdscr, TRUE); + curs_set(0); + start_color(); + + getmaxyx(stdscr, display_size_y, display_size_x); + + colourpair_red = display_newcolourpair(COLOR_RED, COLOR_BLACK); + colourpair_green = display_newcolourpair(COLOR_GREEN, COLOR_BLACK); + colourpair_yellow = display_newcolourpair(COLOR_YELLOW, COLOR_BLACK); + colourpair_blue = display_newcolourpair(COLOR_BLUE, COLOR_BLACK); + colourpair_magenta = display_newcolourpair(COLOR_MAGENTA, COLOR_BLACK); + colourpair_cyan = display_newcolourpair(COLOR_CYAN, COLOR_BLACK); + colourpair_white = display_newcolourpair(COLOR_WHITE, COLOR_BLACK); + colourpair_menu = display_newcolourpair(COLOR_CYAN, COLOR_BLUE); + colourpair_menugrey = display_newcolourpair(COLOR_CYAN, COLOR_BLACK); + + display_options_load(); + colours_init(); + display_initcolours(); +} + +void display_initcolours() +{ + int i; + short fg, bg; + +#ifdef PDCURSES + short tg; +#endif + + for(i = 0; i < PIECE_MAX; i ++) + { + fg = pdisplaycolours->foreground[i]; + if(fg < 0 || fg > 7) + fg = 7; + + bg = pdisplaycolours->background[i]; + if(bg < 0 || bg > 7) + bg = 0; + +#ifdef PDCURSES + /* PDCurses doesn't handle reverse colours well; we swap them manually */ + if(pdisplaycolours->reverse[i]) + { + tg = fg; fg = bg; bg = tg; + } +#endif + + dp_attr[i] = COLOR_PAIR(display_newcolourpair(colourtrans[fg], colourtrans[bg])); + + if(pdisplaycolours->bold[i]) + dp_attr[i] |= A_BOLD; + +#ifndef PDCURSES + if(pdisplaycolours->reverse[i]) + dp_attr[i] |= A_REVERSE; +#endif + } + +} + +void display_quit() +{ + clear(); + refresh(); + endwin(); +} + +void display_hide() +{ + clear(); + refresh(); + getch(); +} + +void display_piece(struct level* plevel, int piece) +{ + int p; + + if(piece < 0 || piece >= PIECE_MAX) + return; + + /* Use the colours of PIECE_PLAYER_ONE for the active player, + and the colours of PIECE_PLAYER_TWO for the inactive one. */ + p = piece; + if(p == PIECE_PLAYER_ONE || p == PIECE_PLAYER_TWO) + { + if(plevel->player != 2) + { + if(plevel->player != (p & 1)) + p = PIECE_PLAYER_TWO; + else + p = PIECE_PLAYER_ONE; + } + else + p = PIECE_PLAYER_ONE; + } + + addch(pdisplaycolours->character[piece] | dp_attr[p]); +} + +void display_moves(struct level* plevel, struct level* plevelreplay) +{ + static int length = 0; + int i; + char buffer[256]; + int moves, moves2; + + moves = 0; + if(plevel->move_current != NULL) + { + /* If move_current->mover_first == NULL, we've actually undone all of + the current move, and are just about to move back to the previous + one; we treat it as the previous one for counting purposes */ + if(plevel->move_current->mover_first != NULL) + moves = plevel->move_current->count; + else + moves = plevel->move_current->count - 1; + } + + moves2 = -1; + if(plevelreplay != NULL) + { + moves2 = 0; + if(plevelreplay->move_last != NULL) + moves2 = plevelreplay->move_last->count; + } + /* Similarly, move_current->mover_first == NULL complicates things here */ + else if(plevel->move_current != plevel->move_last + || (plevel->move_current != NULL && plevel->move_current->mover_first == NULL)) + { + if(plevel->move_last != NULL) + moves2 = plevel->move_last->count; + } + + if(moves2 != -1) + sprintf(buffer, "%s%d/%d", + plevel->flags & LEVELFLAG_PAUSED ? gettext("paused ") : + plevelreplay != NULL ? gettext("replay ") : "", + moves, moves2); + else + sprintf(buffer, "%s%d", + plevel->flags & LEVELFLAG_PAUSED ? gettext("paused ") : "", + moves); + + if(plevel->flags & LEVELFLAG_FAILED) + sprintf(buffer, gettext("failed")); + + attron(COLOR_PAIR(colourpair_cyan)); + + /* Blank previous display only if necessary */ + if(utf8strlen(buffer) < length) + { + for(i = 0; i < length; i ++) + mvprintw(display_size_y - 1, display_size_x - 2 - length + i, " "); + } + + length = utf8strlen(buffer); + + mvprintw(display_size_y - 1, display_size_x - utf8strlen(buffer) - 2, "%s", buffer); + attroff(COLOR_PAIR(colourpair_cyan)); + + move(display_size_y - 1, display_size_x - 1); + display_piece(plevel, PIECE_PLAYER_ONE + plevel->player); + refresh(); +} + +void display_stars(struct level* plevel) +{ + static int length = 0; + char buffer[256]; + int i; + + sprintf(buffer, "%d/%d", plevel->stars_caught, plevel->stars_total); + + if(plevel->stars_exploded != 0) + sprintf(buffer, gettext("%d lost"), plevel->stars_exploded); + + if(plevel->flags & LEVELFLAG_SOLVED && !(plevel->flags & LEVELFLAG_FAILED)) + sprintf(buffer, gettext("solved")); + + attron(COLOR_PAIR(colourpair_yellow)); + + /* Blank previous display only if necessary */ + if(utf8strlen(buffer) < length) + { + for(i = 0; i < length; i ++) + mvprintw(display_size_y - 1, i + 2, " "); + } + + length = utf8strlen(buffer); + + mvprintw(display_size_y - 1, 2, "%s", buffer); + attroff(COLOR_PAIR(colourpair_yellow)); + + move(display_size_y - 1, 0); + display_piece(plevel, PIECE_STAR); +} + +int display_focus(struct level* plevel) +{ + int px, py; + int ox, oy; +#ifdef XOR_COMPATIBILITY + int redraw; +#endif + + getmaxyx(stdscr, display_size_y, display_size_x); + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR && options_xor_display) + { + if(display_start_x != plevel->view_x[plevel->player] || display_start_y != plevel->view_y[plevel->player]) + redraw = 1; + else + redraw = 0; + + display_start_x = plevel->view_x[plevel->player]; + display_start_y = plevel->view_y[plevel->player]; + display_end_x = display_start_x + 8; + display_end_y = display_start_y + 8; + + return redraw; + } +#endif + + ox = display_start_x; + oy = display_start_y; + px = plevel->player_x[plevel->player]; + py = plevel->player_y[plevel->player]; + + if(plevel->size_x < display_size_x) + { + display_start_x = 0; + display_end_x = plevel->size_x; + } + else + { + if(px < display_start_x + display_border) + display_start_x = px - display_border; + if(px >= display_start_x + display_size_x - display_border) + display_start_x = px - display_size_x + display_border; + if(display_start_x < 0) + display_start_x = 0; + if(display_start_x + display_size_x > plevel->size_x) + display_start_x = plevel->size_x - display_size_x; + display_end_x = display_start_x + display_size_x; + + } + if(plevel->size_y < display_size_y - 1) + { + display_start_y = 0; + display_end_y = plevel->size_y; + } + else + { + if(py < display_start_y + display_border) + display_start_y = py - display_border; + if(py >= display_start_y + display_size_y - 1 - display_border) + display_start_y = py - display_size_y + 1 + display_border; + if(display_start_y < 0) + display_start_y = 0; + if(display_start_y + display_size_y - 1 > plevel->size_y) + display_start_y = plevel->size_y - display_size_y + 1; + display_end_y = display_start_y + display_size_y - 1; + + } + + if(ox != display_start_x || oy != display_start_y) + return 1; + else + return 0; +} + +void display_level(struct level* plevel) +{ + int x, y; + int p; + + clear(); + + getmaxyx(stdscr, display_size_y, display_size_x); + + if(display_start_x < 0) + display_start_x = 0; + if(display_start_y < 0) + display_start_y = 0; + + if(display_end_x > plevel->size_x) + display_end_x = plevel->size_x; + if(display_end_y > plevel->size_y) + display_end_y = plevel->size_y; + + display_offset_x = (display_size_x - (display_end_x - display_start_x))/2; + display_offset_y = (display_size_y - (display_end_y - display_start_y))/2; + + for(y = display_start_y; y < display_end_y; y++) + { + move(y + display_offset_y - display_start_y, display_offset_x); + for(x = display_start_x; x < display_end_x; x++) + { + p = level_piece(plevel, x, y); +#ifdef XOR_COMPATIBILITY + if(plevel->switched && (p == PIECE_SPACE || p == PIECE_WALL)) + p = PIECE_DARKNESS; +#endif + display_piece(plevel, p); + } + } +} + +void display_play(struct level* plevel, struct level* plevelreplay) +{ + int key; + int quit; + struct mover* pmover; + int redraw; + int x, y; + int p; + int playermove; + int delay; + int fast; + int pass; + int c; + short cp; + char font_logo_colours[] = "1326454646644"; + char buffer[256]; + + quit = 0; + redraw = 1; + fast = 0; + + while(!quit) + { + redraw += display_focus(plevel); + + if(redraw) + { + display_level(plevel); + + if(plevel->title != NULL) + { + y = display_size_y - 1; + x = (display_size_x - utf8strlen(plevel->title) - (plevel->flags & LEVELFLAG_TESTING ? utf8strlen(gettext("testing: ")) : 0) ) / 2; + if(x < 0) + x = 0; + move(y, x); + + if(plevel->flags & LEVELFLAG_TESTING) + { + attron(COLOR_PAIR(colourpair_cyan)); + printw(gettext("testing: ")); + attroff(COLOR_PAIR(colourpair_cyan)); + } + if((strncmp(gettext(plevel->title), "chroma", 6) == 0)) + { + strcpy(buffer, gettext(plevel->title)); + + for(x = 0; x < strlen(buffer); x ++) + { + cp = colourpair_white; + if(x < strlen(font_logo_colours)) + c = font_logo_colours[x] - '0'; + else + { + printw(buffer + x); + x = strlen(buffer); + break; + } + switch(c) + { + case 1: + cp = colourpair_red; + break; + case 2: + cp = colourpair_green; + break; + case 3: + cp = colourpair_yellow; + break; + case 4: + cp = colourpair_blue; + break; + case 5: + cp = colourpair_magenta; + break; + case 6: + cp = colourpair_cyan; + break; + default: + cp = colourpair_white; + break; + } + addch((*(buffer + x)) | COLOR_PAIR(cp)); + } + } + else + printw("%s", plevel->title); + } + + display_moves(plevel, plevelreplay); + display_stars(plevel); + + refresh(); + curs_set(0); + redraw = 0; + } + + /* If there are movers, plot and then evolve them */ + if(plevel->mover_first != NULL && !(plevel->flags & LEVELFLAG_PAUSED)) + { + /* Plot movers in two passes - first spaces, then non-spaces. + This is counter-intuitive, but makes undoing the player work. */ + for(pass = 0; pass < 2; pass ++) + { + pmover = plevel->mover_first; + while(pmover != NULL) + { + if((pass == 0 && pmover->piece != PIECE_SPACE) || + (pass == 1 && pmover->piece == PIECE_SPACE)) + { + pmover = pmover->next; + continue; + } + x = pmover->x; + y = pmover->y;; + if(x >= display_start_x && x < display_end_x && y>= display_start_y && y < display_end_y) + { + move(display_offset_y - display_start_y + y, display_offset_x - display_start_x + x); + p = pmover->piece; + #ifdef XOR_COMPATIBILITY + if(plevel->switched && (p == PIECE_SPACE || p == PIECE_WALL)) + p = PIECE_DARKNESS; + #endif + if(p != PIECE_GONE) + display_piece(plevel, p); + } + pmover = pmover->next; + } + } + + /* Debug movers */ + if(options_debug & DEBUG_ORDER) + { + /* Display the movers */ + pmover = plevel->mover_first; + y = 0; + while(pmover != NULL && y < display_size_y - 1) + { + if(pmover->piece != PIECE_GONE) + { + move(y ++, 0); + display_piece(plevel, pmover->piece); + printw(" %2d,%2d ", pmover->x, pmover->y); + + } + pmover = pmover->next; + } + while(y < display_size_y - 1) + mvprintw(y++, 0, " "); + + /* Display the stack if our game engine uses it */ + if(0 + #ifdef XOR_COMPATIBILITY + || (plevel->mode == MODE_XOR && options_xor_mode) + #endif + #ifdef ENIGMA_COMPATIBILITY + || (plevel->mode == MODE_ENIGMA && options_enigma_mode) + #endif + ) + { + pmover = plevel->stack_first; + y = 0; + while(pmover != NULL && y < display_size_y - 1) + { + if(pmover->piece != PIECE_GONE) + { + move(y ++, display_size_x - 8); + display_piece(plevel, pmover->piece); + printw(" %2d,%2d ", pmover->x, pmover->y); + + } + pmover = pmover->next; + } + while(y < display_size_y - 1) + mvprintw(y++, display_size_x - 8, " "); + } + } + + refresh(); + + /* Evolve movers */ + if(!(plevel->flags & LEVELFLAG_UNDO)) + { + if(level_evolve(plevel)) + redraw += display_focus(plevel); + level_storemovers(plevel); + } + else + { + if(level_undo(plevel)) + plevel->flags |= LEVELFLAG_UNDO; + else + plevel->flags &= ~LEVELFLAG_UNDO; + } + } + + /* Determine which delay to use */ + delay = options_curses_delay; + if(plevelreplay != NULL) + { + if(plevel->mover_first == NULL && plevelreplay->move_current != NULL) + delay = options_curses_replay_delay; + + if(fast) + delay = 0; + + if(plevelreplay->flags & LEVELFLAG_UNDO) + { + if(plevel->move_current == NULL && plevel->mover_first == NULL) + { + if(options_curses_replay_delay != 0) + delay = options_curses_replay_delay; + else + delay = 1; + } + } + else + { + if(plevel->mover_first == NULL && plevelreplay->move_current == NULL) + delay = -1; + } + } + else + { + if(fast) + delay = 0; + + if(plevel->mover_first == NULL) + { + delay = -1; + fast = 0; + } + } + + if(delay > 0) + halfdelay(delay); + + if(delay != 0) + { + key = getch(); + if(key < 0 || key >= KEY_MAX) + key = 0; + if(key >= 'a' && key <='z') + key -= 32; + } + else + key = 0; + + if(delay > 0) + cbreak(); + + playermove = MOVE_NONE; + + switch(actions[key]) + { + case ACTION_REDRAW: + redraw = 1; + break; + + case ACTION_HIDE: + display_hide(); + redraw = 1; + break; + + case ACTION_QUIT: + quit = 1; + break; + + case ACTION_FAST: + fast = 1 - fast; + break; + + case ACTION_LEFT: + if(plevelreplay != NULL) + { + plevelreplay->flags |= LEVELFLAG_UNDO; + plevelreplay->flags &= ~LEVELFLAG_PAUSED; + } + else + playermove = MOVE_LEFT; + break; + + case ACTION_RIGHT: + if(plevelreplay != NULL) + { + plevelreplay->flags &= ~LEVELFLAG_UNDO; + plevelreplay->flags &= ~LEVELFLAG_PAUSED; + } + else + playermove = MOVE_RIGHT; + break; + + case ACTION_UP: + if(plevelreplay != NULL) + plevelreplay->flags |= LEVELFLAG_PAUSED; + else + playermove = MOVE_UP; + break; + + case ACTION_DOWN: + if(plevelreplay != NULL) + plevelreplay->flags |= LEVELFLAG_PAUSED; + else + playermove = MOVE_DOWN; + break; + + case ACTION_PAUSE: + if(plevelreplay != NULL) + { + if(plevelreplay->flags & LEVELFLAG_PAUSED) + plevelreplay->flags &= ~LEVELFLAG_PAUSED; + else + plevelreplay->flags |= LEVELFLAG_PAUSED; + } + else if(plevel->mover_first != NULL) + { + if(plevel->flags & LEVELFLAG_PAUSED) + plevel->flags &= ~LEVELFLAG_PAUSED; + else + plevel->flags |= LEVELFLAG_PAUSED; + plevel->flags |= LEVELFLAG_MOVES; + } + break; + + case ACTION_SWAP: + if(plevelreplay == NULL) + playermove = MOVE_SWAP; + break; + + case ACTION_UNDO: + if(plevelreplay == NULL) + { + if(plevel->mover_first == NULL && !(plevel->flags & LEVELFLAG_UNDO)) + { + if(level_undo(plevel)) + plevel->flags |= LEVELFLAG_UNDO; + else + plevel->flags &= ~LEVELFLAG_UNDO; + playermove = MOVE_NONE; + } + } + break; + + case ACTION_REDO: + playermove = MOVE_REDO; + break; + + default: + break; + } + + /* Are we replaying the level? */ + if(plevelreplay != NULL) + { + /* Is it time for another move? */ + if(plevel->mover_first == NULL && !(plevelreplay->flags & LEVELFLAG_PAUSED)) + { + /* Moving backwards through replay */ + if(plevelreplay->flags & LEVELFLAG_UNDO) + { + if(level_undo(plevel)) + { + plevel->flags |= LEVELFLAG_UNDO; + if(plevelreplay->move_current != NULL) + plevelreplay->move_current = plevelreplay->move_current->previous; + else + plevelreplay->move_current = plevelreplay->move_last; + } + else + plevel->flags &= ~LEVELFLAG_UNDO; + } + /* Moving forwards through replay */ + else + { + if(plevelreplay->move_current != NULL) + { + playermove = plevelreplay->move_current->direction; + plevelreplay->move_current = plevelreplay->move_current->next; + } + } + } + } + + /* Can't move if we've failed or solved the level */ + if(plevel->flags & (LEVELFLAG_FAILED | LEVELFLAG_SOLVED)) + playermove = MOVE_NONE; + + /* If we can move, make the move */ + if(playermove != MOVE_NONE && plevel->mover_first == NULL) + level_move(plevel, playermove); + + /* Display things changed by the move */ + if(plevel->flags & LEVELFLAG_MOVES) + { + display_moves(plevel, plevelreplay); + plevel->flags ^= LEVELFLAG_MOVES; + } + + if(plevel->flags & LEVELFLAG_STARS) + { + display_stars(plevel); + plevel->flags ^= LEVELFLAG_STARS; + } + + if(plevel->flags & LEVELFLAG_SWITCH) + { + redraw = 1; + plevel->flags ^= LEVELFLAG_SWITCH; + } + + #ifdef XOR_COMPATIBILITY + if(plevel->flags & LEVELFLAG_MAP) + { + /* No sensible way to handle this in curses */ + plevel->flags ^= LEVELFLAG_MAP; + } + #endif + + if(!(plevel->flags & LEVELFLAG_SOLVED) && plevel->flags & LEVELFLAG_EXIT) + { + plevel->flags |= LEVELFLAG_SOLVED; + display_stars(plevel); + } + + if(!(plevel->flags & LEVELFLAG_FAILED) && plevel->alive[0] == 0 && plevel->alive[1] ==0) + { + plevel->flags |= LEVELFLAG_FAILED; + display_moves(plevel, plevelreplay); + } + } +} + +void display_edit(struct level* plevel) +{ + int key; + int quit; + static int editor_piece = PIECE_SPACE; + int redraw, moved, pmoved; + int i; + int player; + int piece_count; + + redraw = 1; + moved = 1; + pmoved = 1; + + /* Store player */ + player = plevel->player; + plevel->player = 2; + + piece_count = 0; + while(editor_piece_maps[plevel->mode][piece_count] != PIECE_GONE) + piece_count ++; + + if(editor_piece > piece_count) + editor_piece = 0; + + quit = 0; + while(!quit) + { + redraw += display_focus(plevel); + + if(redraw) + { + redraw = 0; + + display_level(plevel); + + for(i = 0; i < piece_count; i ++) + { + move(display_size_y - 1, 1 + i * 2); + display_piece(plevel, editor_piece_maps[plevel->mode][i]); + } + + move(display_size_y - 1, display_size_x - 4); + printw("[ ]"); + + curs_set(1); + + pmoved = 1; + } + + if(pmoved) + { + pmoved = 0; + + move(display_size_y - 1, editor_piece * 2); + printw(">"); + move(display_size_y - 1, 2 + editor_piece * 2); + printw("<"); + move(display_size_y - 1, display_size_x - 3); + display_piece(plevel, editor_piece_maps[plevel->mode][editor_piece]); + moved = 1; + } + + if(moved) + { + moved = 0; + + move(display_offset_y - display_start_y + plevel->player_y[2], display_offset_x - display_start_x + plevel->player_x[2]); + refresh(); + } + + key = getch(); + if(key < 0 || key >= KEY_MAX) + key = 0; + if(key >= 'a' && key <='z') + key -= 32; + + switch(actions[key]) + { + case ACTION_REDRAW: + redraw = 1; + break; + + case ACTION_HIDE: + display_hide(); + redraw = 1; + break; + + case ACTION_QUIT: + quit = 1; + break; + + case ACTION_LEFT: + if(plevel->player_x[2] > 0) + { + plevel->player_x[2] --; moved = 1; + } + break; + + case ACTION_RIGHT: + if(plevel->player_x[2] < plevel->size_x - 1) + { + plevel->player_x[2] ++; moved = 1; + } + break; + + case ACTION_UP: + if(plevel->player_y[2] > 0) + { + plevel->player_y[2] --; moved = 1; + } + break; + + case ACTION_DOWN: + if(plevel->player_y[2] < plevel->size_y -1) + { + plevel->player_y[2] ++; moved = 1; + } + break; + + case ACTION_SWAP: + level_setpiece(plevel, plevel->player_x[2], plevel->player_y[2], editor_piece_maps[plevel->mode][editor_piece]); + display_piece(plevel, editor_piece_maps[plevel->mode][editor_piece]); + moved = 1; + break; + + case ACTION_PIECE_LEFT: + move(display_size_y - 1, editor_piece * 2); + printw(" "); + move(display_size_y - 1, 2 + editor_piece * 2); + printw(" "); + editor_piece --; + if(editor_piece < 0) + editor_piece = piece_count - 1; + pmoved = 1; + break; + + case ACTION_PIECE_RIGHT: + move(display_size_y - 1, editor_piece * 2); + printw(" "); + move(display_size_y - 1, 2 + editor_piece * 2); + printw(" "); + editor_piece ++; + if(editor_piece >= piece_count) + editor_piece = 0; + pmoved = 1; + break; + } + } + + /* Restore real player */ + plevel->player = player; +} + +int display_type() +{ + return DISPLAY_CURSES; +} + +void display_options() +{ + struct menu* pmenu; + struct menu* pcoloursmenu; + struct menuentry* pentrycolours; + struct menuentry* pentryspeed; + struct menuentry* pentryreplayspeed; + char buffer[256]; + int ok; + int result; + + pmenu = menu_new(gettext("Display Options")); + + menuentry_new(pmenu, gettext("Return to previous menu"), 'Q', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + menuentry_new(pmenu, gettext("Save Options"), 'S', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentrycolours = menuentry_new(pmenu, gettext("Colour Scheme"), 'C', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentryspeed = menuentry_new(pmenu, gettext("Move Speed"), 'M', MENU_SCROLLABLE); + pentryreplayspeed = menuentry_new(pmenu, gettext("Replay Speed"), 'R', MENU_SCROLLABLE); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + menuentry_new(pmenu, gettext("Change Keys"), 'K', 0); + + /* XOR and Enigma options are only visible once an appropriate level has + * been seen so as not to confuse those simply playing Chroma levels */ + if(0 +#ifdef XOR_COMPATIBILITY + || options_xor_options +#endif +#ifdef ENIGMA_COMPATIBILITY + || options_enigma_options +#endif + ) + { + menuentry_new(pmenu, "", 0, MENU_SPACE); + menuentry_new(pmenu, gettext("Other Games Options"), 'X', 0); + } + + if(options_debug & DEBUG_MENU) + { + menuentry_new(pmenu, "", 0, MENU_SPACE); + menuentry_new(pmenu, gettext("Debug Options"), 'D', 0); + } + + ok = 0; + while(!ok) + { + if(pdisplaycolours == NULL) + menuentry_extratext(pentrycolours, gettext("** NONE **"), NULL, NULL); + else if(pdisplaycolours->title == NULL) + menuentry_extratext(pentrycolours, gettext("[untitled colours]"), NULL, NULL); + else if(pdisplaycolours->flags & COLOURS_TRANSLATE) + menuentry_extratext(pentrycolours, gettext(pdisplaycolours->title), NULL, NULL); + else + menuentry_extratext(pentrycolours, pdisplaycolours->title, NULL, NULL); + + switch(options_curses_delay) + { + case -1: + sprintf(buffer, gettext("after a key is pressed")); + break; + case 0: + sprintf(buffer, gettext("instantaneous")); + break; + default: + sprintf(buffer, gettext("%d00 milliseconds"), options_curses_delay); + break; + } + menuentry_extratext(pentryspeed, buffer, NULL, NULL); + + switch(options_curses_replay_delay) + { + case -1: + sprintf(buffer, gettext("after a key is pressed")); + break; + case 0: + sprintf(buffer, gettext("instantaneous")); + break; + default: + sprintf(buffer, gettext("%d00 milliseconds"), options_curses_replay_delay); + break; + } + menuentry_extratext(pentryreplayspeed, buffer, NULL, NULL); + + result = menu_process(pmenu); + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'Q': + ok = 1; + break; + + case 'C': + pcoloursmenu = colours_menu(); + if(menu_process(pcoloursmenu) == MENU_SELECT) + { + if(pcoloursmenu->entry_selected != NULL && pcoloursmenu->entry_selected->value != NULL) + { + strcpy(options_colours, pcoloursmenu->entry_selected->value); + colours_init(); + display_initcolours(); + } + } + menu_delete(pcoloursmenu); + break; + + case 'S': + display_options_save(); + ok = 1; + break; + + case 'K': + display_keys(); + break; + + case 'X': + display_options_othergames(); + break; + + case 'D': + display_debug(); + break; + } + } + + if(result == MENU_SCROLLLEFT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'M': + options_curses_delay --; + if(options_curses_delay < -1) + options_curses_delay = 10; +#ifdef PDCURSES + if(options_curses_delay > 0) + options_curses_delay = 0; +#endif + break; + case 'R': + options_curses_replay_delay --; + if(options_curses_replay_delay < -1) + options_curses_replay_delay = 10; + +#ifdef PDCURSES + if(options_curses_replay_delay > 0) + options_curses_replay_delay = 0; +#endif + break; + } + } + + if(result == MENU_SCROLLRIGHT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'M': + options_curses_delay ++; + if(options_curses_delay > 10) + options_curses_delay = -1; +#ifdef PDCURSES + if(options_curses_delay > 0) + options_curses_delay = 0; +#endif + break; + case 'R': + options_curses_replay_delay ++; + if(options_curses_replay_delay > 10) + options_curses_replay_delay = -1; +#ifdef PDCURSES + if(options_curses_replay_delay > 0) + options_curses_replay_delay = 0; +#endif + break; + } + } + } + + menu_delete(pmenu); +} + +int display_keyfixed(int i) +{ + if(i == 0 || i == KEY_RESIZE || i == 27 || i == 'Q' || i == '\n' || i == '\r' || i == KEY_UP || i == KEY_DOWN || i == KEY_LEFT || i == KEY_RIGHT) + return 1; + + return 0; +} + +char *display_keyname(int i) +{ + static char buffer[4]; + + if(i == '\t') + return "TAB"; + if(i == '\n') + return "ENTER"; + if(i == 27) + return "ESCAPE"; + if(i == 32) + return "SPACE"; + if(i == KEY_DC) + return "DELETE"; + if(i == KEY_IC) + return "INSERT"; + + if(keyname(i) == NULL) + return "UNKNOWN"; + + if(strcmp(keyname(i), "NO KEY NAME") == 0) + { + if(i >= 0 && i < 32) + { + sprintf(buffer, "^%c", i + '@'); + return buffer; + } + if(i > 32 && i < 127) + { + sprintf(buffer, "%c", i); + return buffer; + } + + return "UNKNOWN"; + } + + if(strncmp(keyname(i), "KEY_", 4) == 0) + return (char *)(keyname(i) + 4); + + return (char *)keyname(i); +} + +void display_addkeytomenu(struct menu* pmenu, int action, char *text) +{ + struct menuentry *pentry; + char buffer[256]; + int i; + + sprintf(buffer, "%d", action); + pentry = menuentry_newwithvalue(pmenu, text, 0, MENU_DOUBLE, buffer); + + strcpy(buffer, ""); + for(i = 0; i < KEY_MAX; i ++) + { + if(actions[i] == action && i != KEY_RESIZE) + { + if(strlen(buffer) != 0) + strcat(buffer,", "); + strcat(buffer, "["); + strcat(buffer, display_keyname(i)); + strcat(buffer, "]"); + } + } + + if(strcmp(buffer, "") == 0) + strcpy(buffer, "(none)"); + + menuentry_extratext(pentry, NULL, NULL, buffer); + +} + +void display_keys() +{ + struct menu *pmenu; + struct menu *psubmenu; + struct menuentry *pentry; + int action; + int result; + int redraw; + int ok; + int subok; + char buffer[256]; + int i; + int key; + + ok = 0; + while(!ok) + { + pmenu = menu_new(gettext("Keys")); + + menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + display_addkeytomenu(pmenu, ACTION_LEFT, gettext(action_name[ACTION_LEFT])); + display_addkeytomenu(pmenu, ACTION_RIGHT, gettext(action_name[ACTION_RIGHT])); + display_addkeytomenu(pmenu, ACTION_UP, gettext(action_name[ACTION_UP])); + display_addkeytomenu(pmenu, ACTION_DOWN, gettext(action_name[ACTION_DOWN])); + display_addkeytomenu(pmenu, ACTION_SWAP, gettext(action_name[ACTION_SWAP])); + display_addkeytomenu(pmenu, ACTION_UNDO, gettext(action_name[ACTION_UNDO])); + display_addkeytomenu(pmenu, ACTION_REDO, gettext(action_name[ACTION_REDO])); + display_addkeytomenu(pmenu, ACTION_FAST, gettext(action_name[ACTION_FAST])); + display_addkeytomenu(pmenu, ACTION_PAUSE, gettext(action_name[ACTION_PAUSE])); + display_addkeytomenu(pmenu, ACTION_QUIT, gettext(action_name[ACTION_QUIT])); + display_addkeytomenu(pmenu, ACTION_REDRAW, gettext(action_name[ACTION_REDRAW])); + display_addkeytomenu(pmenu, ACTION_HIDE, gettext(action_name[ACTION_HIDE])); + display_addkeytomenu(pmenu, ACTION_PIECE_LEFT, gettext(action_name[ACTION_PIECE_LEFT])); + display_addkeytomenu(pmenu, ACTION_PIECE_RIGHT, gettext(action_name[ACTION_PIECE_RIGHT])); + + menu_assignletters(pmenu); + + result = menu_process(pmenu); + + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT) + { + if(pmenu->entry_selected->key == 'Q') + ok = 1; + else if(pmenu->entry_selected->value != NULL) + { + redraw = MENUREDRAW_ALL; + subok = 0; + while(!subok) + { + action = atoi(pmenu->entry_selected->value); + + sprintf(buffer, gettext("Set keys for '%s'"), gettext(action_name[action])); + psubmenu = menu_new(buffer); + + menuentry_new(psubmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(psubmenu, "", 0, MENU_SPACE); + + for(i = 0; i < KEY_MAX; i ++) + { + if(actions[i] == action && i != KEY_RESIZE) + { + sprintf(buffer, "[%s]", display_keyname(i)); + pentry = menuentry_new(psubmenu, buffer, 0, MENU_GREY); + if(display_keyfixed(i)) + menuentry_extratext(pentry, gettext("(fixed)"), NULL, NULL); + } + } + menuentry_new(psubmenu, "", 0, MENU_SPACE); + + menuentry_new(psubmenu, gettext("Press a key to add or remove it from this list."), 0, MENU_NOTE | MENU_CENTRE); + + menu_display(psubmenu, redraw); + redraw = MENUREDRAW_ENTRIES; + menu_delete(psubmenu); + + key = getch(); + if(key == KEY_RESIZE) + { + getmaxyx(stdscr, display_size_y, display_size_x); + redraw = MENUREDRAW_ALL; + } + + if(key >= 'a' && key <='z') + key -=32; + + if(key == 27 || key == 'q' || key == 'Q' || key== '\n') + subok = 1; + else if(!display_keyfixed(key)) + { + if(actions[key] == action) + actions[key] = ACTION_NONE; + else + actions[key] = action; + } + } + } + } + + menu_delete(pmenu); + } +} + +void display_debug() +{ + struct menu* pmenu; + struct menuentry* pentrymovers; + struct menuentry* pentryhidden; + int ok; + int result; + + pmenu = menu_new(gettext("Debug Options")); + + menuentry_new(pmenu, gettext("Return to previous menu"), 'Q', 0); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentrymovers = menuentry_new(pmenu, gettext("Display order of movers"), 'O', MENU_SCROLLABLE); + pentryhidden = menuentry_new(pmenu, gettext("Show hidden items"), 'H', MENU_SCROLLABLE); + + ok = 0; + while(!ok) + { + menuentry_extratext(pentrymovers, options_debug & DEBUG_ORDER ? gettext("yes") : gettext("no"), NULL, NULL); + menuentry_extratext(pentryhidden, options_debug & DEBUG_HIDDEN ? gettext("yes") : gettext("no"), NULL, NULL); + + result = menu_process(pmenu); + if(result == MENU_QUIT) + ok = 1; + + if((result == MENU_SELECT || result == MENU_SCROLLLEFT || result == MENU_SCROLLRIGHT) && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'Q': + ok = 1; + break; + + case 'O': + options_debug ^= DEBUG_ORDER; + break; + + case 'H': + options_debug ^= DEBUG_HIDDEN; + break; + } + + pmenu->redraw = MENUREDRAW_CHANGED; + pmenu->entry_selected->redraw = 1; + } + + } + + menu_delete(pmenu); +} + +void display_options_othergames() +{ + struct menu* pmenu; +#ifdef XOR_COMPATIBILITY + struct menuentry* pentryxormode; + struct menuentry* pentryxordisplay; +#endif +#ifdef ENIGMA_COMPATIBILITY + struct menuentry* pentryenigmamode; +#endif + + int ok; + int result; + + pmenu = menu_new(gettext("Other Games Options")); + + menuentry_new(pmenu, gettext("Return to previous menu"), 'Q', 0); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + +#ifdef XOR_COMPATIBILITY + pentryxormode = menuentry_new(pmenu, gettext("XOR Engine"), 'X', options_xor_options ? 0 : MENU_INVISIBLE | MENU_GREY); + pentryxordisplay = menuentry_new(pmenu, gettext("XOR Display"), 'D', options_xor_options ? 0 : MENU_INVISIBLE | MENU_GREY); + if(options_xor_options) + menuentry_new(pmenu, "", 0, MENU_SPACE); +#endif + +#ifdef ENIGMA_COMPATIBILITY + pentryenigmamode = menuentry_new(pmenu, gettext("Enigma Engine"), 'E', options_enigma_options ? 0 : MENU_INVISIBLE | MENU_GREY); +#endif + + ok = 0; + while(!ok) + { +#ifdef XOR_COMPATIBILITY + menuentry_extratext(pentryxormode, options_xor_mode ? gettext("exact") : gettext("approximate"), NULL, NULL); + menuentry_extratext(pentryxordisplay, options_xor_display ? gettext("partial") : gettext("full"), NULL, NULL); +#endif +#ifdef ENIGMA_COMPATIBILITY + menuentry_extratext(pentryenigmamode, options_enigma_mode ? gettext("exact") : gettext("approximate"), NULL, NULL); +#endif + + result = menu_process(pmenu); + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'Q': + ok = 1; + break; + +#ifdef XOR_COMPATIBILITY + case 'X': + options_xor_mode = 1 - options_xor_mode; + break; + + case 'D': + options_xor_display = 1 - options_xor_display; + break; +#endif + +#ifdef ENIGMA_COMPATIBILITY + case 'E': + options_enigma_mode = 1 - options_enigma_mode; + break; +#endif + } + + pmenu->redraw = MENUREDRAW_CHANGED; + pmenu->entry_selected->redraw = 1; + } + + } + + menu_delete(pmenu); +} + +void display_options_save() +{ + FILE *file; + char filename[FILENAME_MAX]; + int i; + + getfilename("curses.chroma", filename, 1, 0); + + file = fopen(filename, "w"); + if(file == NULL) + { + warning("Unable to save options"); + return; + } + + fprintf(file, "\n" + "\n" + "\n"); + + fprintf(file, " \n", options_colours); + + if(options_curses_delay == -1) + fprintf(file, " \n"); + else + fprintf(file, " \n", options_curses_delay * 100); + + if(options_curses_replay_delay == -1) + fprintf(file, " \n"); + else + fprintf(file, " \n", options_curses_replay_delay * 100); + +#ifdef XOR_COMPATIBILITY + if(options_xor_options) + fprintf(file, " \n", options_xor_mode ? "exact" : "approximate", options_xor_display ? "partial" : "full"); +#endif +#ifdef ENIGMA_COMPATIBILITY + if(options_enigma_options) + fprintf(file, " \n", options_enigma_mode ? "exact" : "approximate"); +#endif + + fprintf(file, " \n"); + fprintf(file, " \n"); + + fprintf(file, " \n"); + + for(i = 0; i < KEY_MAX; i ++) + { + if(actions[i] != ACTION_NONE && i != KEY_RESIZE) + fprintf(file, " \n", display_keyname(i), action_shortname[actions[i]]); + } + + fprintf(file, " \n"); + + fprintf(file, "\n"); + + fclose(file); +} + +void display_options_load() +{ + struct parser* pparser; + char filename[FILENAME_MAX]; + int state; + int i; + int key, action; + + /* Sensible defaults */ +#ifdef PDCURSES + /* halfdelay() is broken in PDCurses */ + options_curses_delay = 0; + options_curses_replay_delay = 0; +#else + options_curses_delay = 1; + options_curses_replay_delay = 1; +#endif +#ifdef XOR_COMPATIBILITY + options_xor_options = 0; + options_xor_mode = 1; + options_xor_display = 0; +#endif +#ifdef ENIGMA_COMPATIBILITY + options_enigma_options = 0; + options_enigma_mode = 1; +#endif + options_debug = 0; + + getfilename("colours", filename, 0, 1); + sprintf(options_colours, "%s/%s", filename, COLOURS_DEFAULT); + + getfilename("curses.chroma", filename, 0, 0); + + for(i = 0; i < KEY_MAX; i ++) + { + actions[i] = ACTION_NONE; + } + + /* Fixed keys */ + actions[KEY_RESIZE] = ACTION_REDRAW; + actions[KEY_UP] = ACTION_UP; + actions[KEY_DOWN] = ACTION_DOWN; + actions[KEY_LEFT] = ACTION_LEFT; + actions[KEY_RIGHT] = ACTION_RIGHT; + actions['\r'] = ACTION_SWAP; + actions['\n'] = ACTION_SWAP; + actions['Q'] = ACTION_QUIT; + actions[27] = ACTION_QUIT; + + /* Sensible default keys */ + if(!isfile(filename)) + { + actions[12] = ACTION_REDRAW; + actions[' '] = ACTION_SWAP; + actions['F'] = ACTION_FAST; + actions[KEY_BACKSPACE] = ACTION_UNDO; + actions[KEY_DC] = ACTION_UNDO; + actions['U'] = ACTION_UNDO; + actions[KEY_IC] = ACTION_REDO; + actions['Y'] = ACTION_REDO; + actions['Z'] = ACTION_PIECE_LEFT; + actions['X'] = ACTION_PIECE_RIGHT; + actions[KEY_PPAGE] = ACTION_PIECE_LEFT;; + actions[KEY_NPAGE] = ACTION_PIECE_RIGHT; + actions['P'] = ACTION_PAUSE; + return; + } + + /* Parse XML file */ + /* + + + + + + + + + + + */ + + pparser = parser_new(filename); + + enum { + OPTIONSPARSER_END, /* End of file */ + OPTIONSPARSER_OUTSIDE, /* Outside of */ + OPTIONSPARSER_CHROMA, /* Inside */ + OPTIONSPARSER_KEYS /* Inside */ + }; + + state = OPTIONSPARSER_OUTSIDE; + key = 0; + action = 0; + + while(state != OPTIONSPARSER_END) + { + switch(parser_parse(pparser)) + { + case PARSER_END: + state = OPTIONSPARSER_END; + break; + + case PARSER_ELEMENT_START: + switch(state) + { + case OPTIONSPARSER_CHROMA: + if(parser_match(pparser, 0, "keys")) + state = OPTIONSPARSER_KEYS; + break; + + case OPTIONSPARSER_KEYS: + if(parser_match(pparser, 0, "key")) + { + key = 0; + action = ACTION_NONE; + } + break; + + default: + break; + } + break; + + case PARSER_ELEMENT_END: + switch(state) + { + case OPTIONSPARSER_KEYS: + if(parser_match(pparser, 0, "keys")) + { + state = OPTIONSPARSER_CHROMA; + } + if(parser_match(pparser, 0, "key")) + { + if(key != 0 && !display_keyfixed(key)) + actions[key] = action; + } + break; + + default: + break; + } + break; + + case PARSER_CONTENT: + break; + + case PARSER_ATTRIBUTE: + switch(state) + { + case OPTIONSPARSER_OUTSIDE: + if(parser_match(pparser, 2, "chroma") && parser_match(pparser, 1, "type")) + { + if(parser_match(pparser, 0, "options")) + state = OPTIONSPARSER_CHROMA; + } + break; + + case OPTIONSPARSER_CHROMA: + if(parser_match(pparser, 2, "colour") && parser_match(pparser, 1, "scheme")) + { + strncpy(options_colours, parser_text(pparser, 0), FILENAME_MAX); + } + if(parser_match(pparser, 2, "move") && parser_match(pparser, 1, "speed")) + { + if(parser_match(pparser, 0, "key")) + options_curses_delay = -1; + else + options_curses_delay = atoi(parser_text(pparser, 0)) / 100; +#ifdef PDCURSES + if(options_curses_delay > 0) + options_curses_delay = 0; +#endif + } + if(parser_match(pparser, 2, "replay") && parser_match(pparser, 1, "speed")) + { + if(parser_match(pparser, 0, "key")) + options_curses_replay_delay = -1; + else + options_curses_replay_delay = atoi(parser_text(pparser, 0)) / 100; +#ifdef PDCURSES + if(options_curses_replay_delay > 0) + options_curses_replay_delay = 0; +#endif + } +#ifdef XOR_COMPATIBILITY + if(parser_match(pparser, 2, "xor") && parser_match(pparser, 1, "mode")) + { + options_xor_options = 1; + + if(parser_match(pparser, 0, "approximate")) + options_xor_mode = 0; + if(parser_match(pparser, 0, "exact")) + options_xor_mode = 1; + } + if(parser_match(pparser, 2, "xor") && parser_match(pparser, 1, "display")) + { + options_xor_options = 1; + + if(parser_match(pparser, 0, "full")) + options_xor_display = 0; + if(parser_match(pparser, 0, "partial")) + options_xor_display = 1; + } +#endif +#ifdef ENIGMA_COMPATIBILITY + if(parser_match(pparser, 2, "enigma") && parser_match(pparser, 1, "mode")) + { + options_enigma_options = 1; + + if(parser_match(pparser, 0, "approximate")) + options_enigma_mode = 0; + if(parser_match(pparser, 0, "exact")) + options_enigma_mode = 1; + } +#endif + if(parser_match(pparser, 2, "debug") && parser_match(pparser, 1, "menu")) + { + if(parser_match(pparser, 0, "yes")) + options_debug |= DEBUG_MENU; + } + if(parser_match(pparser, 2, "debug") && parser_match(pparser, 1, "order")) + { + if(parser_match(pparser, 0, "yes")) + options_debug |= DEBUG_ORDER; + } + if(parser_match(pparser, 2, "debug") && parser_match(pparser, 1, "hidden")) + { + if(parser_match(pparser, 0, "yes")) + options_debug |= DEBUG_HIDDEN; + } + break; + + case OPTIONSPARSER_KEYS: + if(parser_match(pparser, 2, "key") && parser_match(pparser, 1, "name")) + { + for(i = 0; i < KEY_MAX; i ++) + { + if(parser_match(pparser, 0, display_keyname(i))) + { + key = i; + i = KEY_MAX; + } + } + } + if(parser_match(pparser, 2, "key") && parser_match(pparser, 1, "action")) + { + for(i = ACTION_KEY_MIN; i < ACTION_KEY_MAX; i ++) + { + if(parser_match(pparser, 0, action_shortname[i])) + { + action = i; + i = ACTION_KEY_MAX; + } + } + } + break; + } + break; + + case PARSER_ERROR: + state = OPTIONSPARSER_END; + break; + } + } + + parser_delete(pparser); +} diff --git a/cursesmenudisplay.c b/cursesmenudisplay.c new file mode 100644 index 0000000..fdb36eb --- /dev/null +++ b/cursesmenudisplay.c @@ -0,0 +1,887 @@ +/* + cursesmenudisplay.c + + Copyright (C) 2010-2019 Amf + + 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 +#include +#include + +#ifdef CHROMA_CURSES_HEADER +#include CHROMA_CURSES_HEADER +#else +#ifdef __WIN32__ +#include +#else +#include +#endif +#endif + +#include "chroma.h" +#include "menu.h" +#include "actions.h" +#include "level.h" +#include "display.h" +#include "util.h" + +#define MAX_WIDTH 65 + +extern int display_size_x, display_size_y; +extern int actions[KEY_MAX]; + +extern short colourpair_menu; +extern short colourpair_menugrey; +extern short colourpair_red; +extern short colourpair_green; +extern short colourpair_yellow; +extern short colourpair_blue; +extern short colourpair_cyan; +extern short colourpair_magenta; +extern short colourpair_cyan; +extern short colourpair_white; + +int menu_offset; +int menu_width; +int menu_height_notes; +int menu_height_entries; +int menu_y_min; +int menu_y_max; +int menu_y_logo_top; +int menu_y_logo_bottom; +int menu_scroll_y_min; +int menu_scroll_y_max; +int menu_scroll_top; +int menu_scroll_bottom; + +int menu_entryheight(struct menuentry *pentry) +{ + if(pentry->flags & MENU_INVISIBLE) + return 0; + if(pentry->flags & MENU_DOUBLE) + return 2; + return 1; +} + +void menu_displayentry(struct menu *pmenu, struct menuentry *pentry, int y, int selected) +{ + char buffer[MAX_WIDTH + 1]; + int x, i; + + if(menu_width < 1) + return; + + if(pentry->flags & MENU_INVISIBLE) + return; + + if(pentry->flags & (MENU_GREY | MENU_NOTE | MENU_TEXT)) + selected = 0; + + /* Plot first line, if visible */ + if((y >= menu_y_min && y < menu_y_max) || (pentry->flags & MENU_NOTE)) + { + /* Plot key press */ + attron(COLOR_PAIR(colourpair_white)); + if(pentry->key != 0 && pentry->key != MENU_KEY_ANY) + { + mvprintw(y, menu_offset - 4, "[ ] "); + attron(A_BOLD); + mvprintw(y, menu_offset - 3, "%c", pentry->key); + attroff(A_BOLD); + } + else + mvprintw(y, menu_offset - 4, " "); + attroff(COLOR_PAIR(colourpair_white)); + + /* Determine colour */ + if(pentry->flags & (MENU_GREY | MENU_SPACE)) + attron(COLOR_PAIR(colourpair_menugrey)); + else if(pentry->flags & MENU_NOTE) + { + if(pmenu->logo == 0) + attron(COLOR_PAIR(colourpair_menugrey)); + } + else if(pentry->flags & MENU_TEXT) + attron(COLOR_PAIR(colourpair_white)); + else + attron(COLOR_PAIR(colourpair_menu)); + if(selected) + attron(A_REVERSE); + + /* Blank line */ + move(y, menu_offset); + for(i = 0; i < menu_width; i ++) + addch(' '); + + /* Plot right hand side text */ + if(pentry->text2 != NULL) + { + utf8strncpy(buffer, pentry->text2, menu_width - 2); + x = menu_offset + menu_width - 1 - utf8strlen(buffer); + mvprintw(y, x, buffer); + } + + /* Plot main text */ + if(pentry->text != NULL) + { + utf8strncpy(buffer, pentry->text, menu_width - 2); + + x = menu_offset + 1; + if(pentry->flags & MENU_RIGHT) + x = menu_offset + menu_width - utf8strlen(buffer); + if(pentry->flags & MENU_CENTRE) + x = menu_offset + ((menu_width - utf8strlen(buffer))/2); + + if(pentry->flags & MENU_BOLD) + attron(A_BOLD); + mvprintw(y, x, buffer); + if(pentry->flags & MENU_BOLD) + attroff(A_BOLD); + } + + if(selected) + attroff(A_REVERSE); + if(pentry->flags & (MENU_GREY | MENU_NOTE | MENU_SPACE)) + attroff(COLOR_PAIR(colourpair_menugrey)); + else if(pentry->flags & MENU_TEXT) + attroff(COLOR_PAIR(colourpair_white)); + else + attroff(COLOR_PAIR(colourpair_menu)); + } + + if(!(pentry->flags & MENU_DOUBLE)) + return; + + y ++; + + /* Plot second line, if visible */ + if((y >= menu_y_min && y < menu_y_max) || (pentry->flags & MENU_NOTE)) + { + /* Blank key press area */ + attron(COLOR_PAIR(colourpair_white)); + mvprintw(y, menu_offset - 4, " "); + attroff(COLOR_PAIR(colourpair_white)); + + /* Determine colour */ + if(pentry->flags & (MENU_GREY | MENU_NOTE | MENU_SPACE)) + attron(COLOR_PAIR(colourpair_menugrey)); + else + attron(COLOR_PAIR(colourpair_menu)); + if(selected) + attron(A_REVERSE); + + /* Blank line */ + move(y, menu_offset); + for(i = 0; i < menu_width; i ++) + addch(' '); + + /* Plot right hand side text */ + if(pentry->text4 != NULL) + { + utf8strncpy(buffer, pentry->text4, menu_width - 2); + + x = menu_offset + menu_width - 1 - utf8strlen(buffer); + if(pentry->flags & MENU_EDITING) + attron(COLOR_PAIR(colourpair_white)); + mvprintw(y, x, buffer); + if(pentry->flags & MENU_EDITING) + attroff(COLOR_PAIR(colourpair_white)); + } + + /* Plot left hand side text */ + if(pentry->text3 != NULL) + { + utf8strncpy(buffer, pentry->text3, menu_width - 2); + + x = menu_offset + 1; + mvprintw(y, x, buffer); + } + + if(selected) + attroff(A_REVERSE); + if(pentry->flags & (MENU_GREY | MENU_SPACE)) + attroff(COLOR_PAIR(colourpair_menugrey)); + else if(pentry->flags & MENU_NOTE) + { + if(pmenu->logo == 0) + attroff(COLOR_PAIR(colourpair_menugrey)); + } + else + attroff(COLOR_PAIR(colourpair_menu)); + } +} + +void menu_display(struct menu *pmenu, int redraw) +{ + struct menuentry *pentry; + int x, y, selected; + char title[] = "chroma"; + char buffer[256]; + int i; + int state; + int y_editing; + short cp; + int j; + + /* 012345678901234567890123456789012345678901 */ + char logo[] = " 8 " + " 8 " + ".oPYo. 8oPYo. oPYo. .oPYo. ooYoYo. .oPYo. " + "8 ' 8 8 8 `' 8 8 8' 8 8 .oooo8 " + "8 . 8 8 8 8 8 8 8 8 8 8 " + "`YooP' 8 8 8 `YooP' 8 8 8 `YooP8 "; + +#define LOGO_HEIGHT 7 + + /* Calculate various widths */ + menu_width = display_size_x - 2; + if(menu_width > MAX_WIDTH) + menu_width = MAX_WIDTH; + + menu_offset = (display_size_x - menu_width) / 2; + if(menu_offset < 0) + menu_offset = 0; + + menu_width -= 5; + menu_offset += 4; + + /* Calculate various heights */ + menu_height_notes = 0; + menu_height_entries = 0; + + pentry = pmenu->entry_first; + while(pentry != NULL) + { + if(pentry->flags & MENU_NOTE) + menu_height_notes += menu_entryheight(pentry); + else + menu_height_entries += menu_entryheight(pentry); + pentry = pentry->next; + } + + /* Add an extra line to pad the notes out, if there are any */ + if(menu_height_notes != 0) + menu_height_notes += 1; + + if(pmenu->logo) + { + menu_y_logo_top = (display_size_y - menu_height_entries - LOGO_HEIGHT) / 2; + if(menu_y_logo_top < 0) + menu_y_logo_top = 0; + menu_y_logo_bottom = menu_y_logo_top + LOGO_HEIGHT; + menu_y_min = display_size_y - menu_height_entries - 1; + if(menu_y_min < menu_y_logo_bottom) + menu_y_min = menu_y_logo_bottom; + menu_y_max = display_size_y - 1; + } + else + { + menu_y_min = 4; + menu_y_max = display_size_y - menu_height_notes - 1; + if(pmenu->title != NULL) + menu_y_min += 2; + } + + /* If a full redraw, clear the screen and plot the title */ + if(redraw == MENUREDRAW_ALL) + { + clear(); + curs_set(0); + + if(pmenu->logo) + { + x = (display_size_x - 42) / 2; + y = menu_y_logo_top; + cp = colourpair_red; + + move(y, x); + + for(i = 0; i < strlen(logo); i ++) + { + addch(logo[i] | A_BOLD | COLOR_PAIR(cp)); + switch(i % 42) + { + case 6: + cp = colourpair_yellow; + break; + case 13: + cp = colourpair_green; + break; + case 18: + cp = colourpair_cyan; + break; + case 25: + cp = colourpair_blue; + break; + case 33: + cp = colourpair_magenta; + break; + case 41: + y ++; + move(y, x); + cp = colourpair_red; + break; + } + } + + y ++; + + } + else + { + /* Display game title */ + x = (display_size_x / 2) - strlen(title); + + attron(A_BOLD); + for(i = 0; i < strlen(title); i ++) + { + if(i == 0) attron(COLOR_PAIR(colourpair_red)); + if(i == 1) attron(COLOR_PAIR(colourpair_yellow)); + if(i == 2) attron(COLOR_PAIR(colourpair_green)); + if(i == 3) attron(COLOR_PAIR(colourpair_cyan)); + if(i == 4) attron(COLOR_PAIR(colourpair_blue)); + if(i == 5) attron(COLOR_PAIR(colourpair_magenta)); + + sprintf(buffer, "%c", title[i]); + mvprintw(2, x, buffer); + x +=2; + } + attroff(COLOR_PAIR(colourpair_red)); + attroff(A_BOLD); + + /* Display menu title */ + y = 4; + x = (display_size_x / 2) - utf8strlen(pmenu->title); + + attron(A_BOLD); + attroff(COLOR_PAIR(colourpair_white)); + /* If the title is too long, plot normally */ + if(x < 0) + { + x = (display_size_x - utf8strlen(pmenu->title)) / 2; + mvprintw(y, x, pmenu->title); + } + else + { + /* Otherwise, spread it out */ + for(i = 0; i < strlen(pmenu->title); i ++) + { + j = 0; + buffer[j] = pmenu->title[i]; j ++; + while((pmenu->title[i + j] & 0xc0) == 0x80) + { + buffer[j] = pmenu->title[i + j]; j ++; + } + buffer[j] = 0; + mvprintw(y, x, buffer); + x += 2; i += j - 1; + } + } + attroff(A_BOLD); + } + } + + /* Keep scroll bar within reasonable limits */ + if(pmenu->offset > (menu_height_entries - (menu_y_max - menu_y_min))) + pmenu->offset = menu_height_entries - (menu_y_max - menu_y_min); + if(pmenu->offset < 0) + pmenu->offset = 0; + + /* Display scrollbar, if needed */ + if(menu_height_entries > (menu_y_max - menu_y_min) || pmenu->offset != 0) + { + if(redraw >= MENUREDRAW_ENTRIES) + { + menu_scroll_y_min = menu_y_min + 1; + menu_scroll_y_max = menu_y_max - 1; + menu_scroll_top = menu_scroll_y_min + ((menu_scroll_y_max - menu_scroll_y_min) * pmenu->offset / menu_height_entries); + menu_scroll_bottom = menu_scroll_top + ((menu_scroll_y_max - menu_scroll_y_min) * (1 + menu_y_max - menu_y_min) / menu_height_entries); + + attron(COLOR_PAIR(colourpair_menugrey)); + x = menu_offset + menu_width + 1; + mvaddch(menu_y_min, x, '^'); + mvaddch(menu_y_max - 1, x, 'v'); + + attron(COLOR_PAIR(colourpair_white)); + for(y = menu_y_min + 1; y < menu_y_max - 1; y ++) + { + /* >= and <= to guarantee at least one character scrollbar */ + if(y >= menu_scroll_top && y <= menu_scroll_bottom) + { + attron(A_REVERSE); + mvaddch(y, x, '|'); + attroff(A_REVERSE); + } + else + mvaddch(y, x, '.'); + } + } + } + + /* Display notes */ + if((menu_height_notes != 0) && redraw >= MENUREDRAW_ENTRIES) + { + if(pmenu->logo) + y = menu_y_logo_bottom; + else + y = menu_y_max + 1; + + pentry = pmenu->entry_first; + while(pentry != NULL) + { + if(pentry->flags & MENU_NOTE) + { + menu_displayentry(pmenu, pentry, y, 0); + y += menu_entryheight(pentry); + } + pentry = pentry->next; + } + } + + /* Select an entry if the selected one is not on screen */ + if(pmenu->entry_selected == NULL) + pmenu->entry_selected = pmenu->entry_first; + y = menu_y_min - pmenu->offset; + pentry = pmenu->entry_first; + pmenu->display_first = NULL; + pmenu->display_last = NULL; + state = 1; + while(pentry != NULL) + { + /* Don't count notes */ + if(pentry->flags & MENU_NOTE) + { + pentry = pentry->next; + continue; + } + /* Is the entry off the top of the screen? */ + if(y < (menu_y_min - menu_entryheight(pentry))) + { + if(pentry == pmenu->entry_selected) + state = -1; + y += menu_entryheight(pentry); + pentry = pentry->next; + continue; + } + /* Stop processing once we hit the bottom of the screen */ + if(y > menu_y_max) + { + pentry = NULL; + continue; + } + if(pentry == pmenu->entry_selected) + state = 0; + + if(pmenu->display_first == NULL) + pmenu->display_first = pentry->next; + pmenu->display_last = pentry->previous; + + y += menu_entryheight(pentry); + pentry = pentry->next; + } + if(state == -1) + pmenu->entry_selected = pmenu->display_first; + if(state == 1) + pmenu->entry_selected = pmenu->display_last; + if(state != 0 && redraw < MENUREDRAW_ENTRIES) + redraw = MENUREDRAW_ENTRIES; + + /* Display entries */ + pentry = pmenu->entry_first; + y = menu_y_min - pmenu->offset; + y_editing = 0; + while(pentry != NULL) + { + /* Don't display notes */ + if(pentry->flags & MENU_NOTE) + { + pentry = pentry->next; + continue; + } + /* Don't display entries off the top of the screen */ + if(y < (menu_y_min - menu_entryheight(pentry))) + { + y += menu_entryheight(pentry); + pentry = pentry->next; + continue; + } + /* Stop processing once we hit the bottom of the screen */ + if(y > menu_y_max) + { + pentry = NULL; + continue; + } + selected = (pmenu->entry_selected == pentry) ? 1 : 0; + + if(redraw >= MENUREDRAW_ENTRIES || + (redraw >= MENUREDRAW_CHANGED && pentry->redraw)) + menu_displayentry(pmenu, pentry, y, selected); + if(pentry->flags & MENU_EDITING) + y_editing = y + 1; + + + pentry->redraw = 0; + y += menu_entryheight(pentry); + pentry = pentry->next; + } + + /* Display cursor if we're editing a text field */ + if(y_editing) + { + curs_set(1); + move(y_editing, menu_offset + menu_width - 2); + } + else + curs_set(0); + + /* Redraw the screen */ + refresh(); +} + +int menu_process(struct menu* pmenu) +{ + int ok; + int redraw; + int c; + struct menuentry* pentry; + char *buffer; + + redraw = pmenu->redraw; + + ok = 0; + while(!ok) + { + if(redraw != MENUREDRAW_NONE) + { + menu_display(pmenu, redraw); + redraw = MENUREDRAW_NONE; + } + + c = getch(); + + /* Are we editing a text field? */ + if(pmenu->entry_selected != NULL && pmenu->entry_selected->flags & MENU_EDITING) + { + switch(c) + { + case KEY_RESIZE: + getmaxyx(stdscr, display_size_y, display_size_x); + redraw = MENUREDRAW_ALL; + break; + + case '\n': + case '\r': + case 27: + case KEY_UP: + case KEY_DOWN: + case KEY_PPAGE: + case KEY_NPAGE: + pmenu->entry_selected->flags -= MENU_EDITING; + pmenu->entry_selected->redraw = 1; + redraw = MENUREDRAW_CHANGED; + break; + + case KEY_BACKSPACE: + case KEY_DC: + case 8: + if(strlen(pmenu->entry_selected->text4) == 0) + break; + + buffer = malloc(strlen(pmenu->entry_selected->text4) + 1); + if(buffer != NULL) + { + strcpy(buffer, pmenu->entry_selected->text4); + + /* not particularly efficient, but does the job of deleting one UTF8 character */ + while(strlen(buffer) > 0 && ((buffer[strlen(buffer) - 1] & 0xc0) == 0x80)) + buffer[strlen(buffer) - 1] = 0; + buffer[strlen(buffer) - 1] = 0; + } + menuentry_extratext(pmenu->entry_selected, NULL, NULL, buffer); + free(buffer); + + pmenu->entry_selected->redraw = 1; + redraw = MENUREDRAW_CHANGED; + break; + + default: + if(c > 31 && c != 127) + { + buffer = malloc(strlen(pmenu->entry_selected->text4) + 2); + if(buffer != NULL) + { + strcpy(buffer, pmenu->entry_selected->text4); + buffer[strlen(buffer) + 1] = 0; + buffer[strlen(buffer)] = c; + } + menuentry_extratext(pmenu->entry_selected, NULL, NULL, buffer); + free(buffer); + + pmenu->entry_selected->redraw = 1; + redraw = MENUREDRAW_CHANGED; + break; + } + break; + } + continue; + } + + /* Not a text field, but a regular entry */ + /* First, check if the key corresponds to an entry */ + if(c >= 0 && c < 127) + c = toupper(c); + pentry = pmenu->entry_first; + while(pentry != NULL) + { + if(pentry->key == c) + { + if(!(pentry->flags & (MENU_GREY | MENU_INVISIBLE | MENU_SPACE))) + { + if(pmenu->entry_selected != NULL) + pmenu->entry_selected->redraw = 1; + pmenu->entry_selected = pentry; + pentry->redraw = 1; + + if(pmenu->entry_selected->flags & MENU_EDITABLE) + { + pmenu->entry_selected->flags |= MENU_EDITING; + pmenu->entry_selected->redraw = 1; + redraw = MENUREDRAW_CHANGED; + } + else + ok = MENU_SELECT; + break; + } + } + pentry = pentry->next; + } + + if(ok == MENU_SELECT) + continue; + + if(c < 0) + continue; + + /* Otherwise, see if it corresponds to an action */ + switch(actions[c]) + { + case ACTION_UP: + pentry = pmenu->entry_selected; + while(pentry != NULL) + { + if(pentry == pmenu->display_first || pentry->flags & MENU_TEXT) + redraw = MENUREDRAW_ENTRIES; + + pentry = pentry->previous; + + if(pentry == NULL) + break; + if(redraw != MENUREDRAW_NONE) + pmenu->offset -= menu_entryheight(pentry); + if(!(pentry->flags & (MENU_GREY | MENU_NOTE | MENU_SPACE))) + break; + } + if(pentry != NULL) + { + pentry->redraw = 1; + pmenu->entry_selected->redraw = 1; + pmenu->entry_selected = pentry; + if(redraw == MENUREDRAW_NONE) + redraw = MENUREDRAW_CHANGED; + } + break; + + case ACTION_DOWN: + pentry = pmenu->entry_selected; + while(pentry != NULL) + { + if(pentry == pmenu->display_last || pentry->flags & MENU_TEXT) + redraw = MENUREDRAW_ENTRIES; + + pentry = pentry->next; + + if(pentry == NULL) + break; + if(redraw != MENUREDRAW_NONE) + pmenu->offset += menu_entryheight(pentry); + if(!(pentry->flags & (MENU_GREY | MENU_NOTE | MENU_SPACE))) + break; + } + if(pentry != NULL) + { + pentry->redraw = 1; + pmenu->entry_selected->redraw = 1; + pmenu->entry_selected = pentry; + if(redraw == MENUREDRAW_NONE) + redraw = MENUREDRAW_CHANGED; + } + break; + + case ACTION_LEFT: + if(pmenu->entry_selected != NULL && pmenu->entry_selected->flags & MENU_SCROLLABLE) + ok = MENU_SCROLLLEFT; + break; + + case ACTION_RIGHT: + if(pmenu->entry_selected != NULL && pmenu->entry_selected->flags & MENU_SCROLLABLE) + ok = MENU_SCROLLRIGHT; + break; + + case ACTION_PAGE_UP: + pmenu->offset -= (menu_y_max - menu_y_min); + redraw = MENUREDRAW_ENTRIES; + break; + + case ACTION_PAGE_DOWN: + pmenu->offset += (menu_y_max - menu_y_min); + redraw = MENUREDRAW_ENTRIES; + break; + + case ACTION_ENTER: + if(pmenu->entry_selected != NULL) + { + if(pmenu->entry_selected->flags & MENU_EDITABLE) + { + pmenu->entry_selected->flags |= MENU_EDITING; + pmenu->entry_selected->redraw = 1; + redraw = MENUREDRAW_CHANGED; + } + else + ok = MENU_SELECT; + } + break; + + case ACTION_DELETE: + if(pmenu->entry_selected != NULL && pmenu->entry_selected->flags & MENU_DELETABLE) + ok = MENU_DELETE; + break; + + case ACTION_QUIT: + ok = MENU_QUIT; + break; + + case ACTION_REDRAW: + getmaxyx(stdscr, display_size_y, display_size_x); + redraw = MENUREDRAW_ALL; + break; + + case ACTION_HIDE: + display_hide(); + redraw = MENUREDRAW_ALL; + break; + + default: + /* See if there is an "any key" entry */ + pentry = pmenu->entry_first; + while(pentry != NULL) + { + if(pentry->key == MENU_KEY_ANY) + { + if(!(pentry->flags & (MENU_GREY | MENU_INVISIBLE | MENU_SPACE))) + { + if(pmenu->entry_selected != NULL) + pmenu->entry_selected->redraw = 1; + pmenu->entry_selected = pentry; + pentry->redraw = 1; + + ok = MENU_SELECT; + break; + } + } + pentry = pentry->next; + } + break; + } + } + + /* Redraw the whole menu when we next process it */ + pmenu->redraw = MENUREDRAW_ALL; + + if(ok == MENU_SELECT) + { + if(pmenu->entry_selected->flags & MENU_SCROLLABLE) + ok = MENU_SCROLLRIGHT; + } + /* unless this is a scrollable entry */ + if(ok == MENU_SCROLLLEFT || ok == MENU_SCROLLRIGHT) + { + pmenu->redraw = MENUREDRAW_CHANGED; + pmenu->entry_selected->redraw = 1; + } + + return ok; +} + +int menu_addfile(struct menu *pmenu, char *filename) +{ + FILE *file; + char word[256], buffer[4096]; + char c; + int i; + int ok, wok; + + file = fopen(filename, "r"); + if(file == NULL) + return 0; + + ok = 0; + strcpy(buffer, ""); + while(!ok) + { + wok = 0; i = 0; + while(!wok) + { + c = fgetc(file); + if(c == 0 || c == 13 || c == 10 || c == 32 || c == 9 || feof(file) || i == 254) + wok = 1; + else + word[i++] = c; + } + word[i] = 0; + + /* We assume menu_width is defined by the time we get here - a safe + assumption provided this isn't the first menu we see. */ + if(utf8strlen(buffer) + utf8strlen(word) < menu_width - 2 && !(strcmp(word, "") == 0 && (c == 10 || c == 13)) && !(strncmp(word, "===", 3) == 0)) + { + if(buffer[0] != 0 && word[0] != 0) + strcat(buffer, " "); + strcat(buffer, word); + } + else + { + menuentry_new(pmenu, buffer, 0, MENU_TEXT); + if(strcmp(word, "") == 0 && (c == 10 || c ==13)) + menuentry_new(pmenu, "", 0, MENU_TEXT); + if(strncmp(word, "===", 3) == 0) + { + strcpy(buffer, ""); + pmenu->entry_last->flags |= MENU_GREY; + } + else + strcpy(buffer, word); + } + + if(feof(file)) + ok = 1; + } + + menuentry_new(pmenu, buffer, 0, MENU_TEXT); + + fclose(file); + + return 1; +} diff --git a/display.h b/display.h new file mode 100644 index 0000000..a7362d2 --- /dev/null +++ b/display.h @@ -0,0 +1,34 @@ +/* + display.h + + Copyright (C) 2010-2019 Amf + + 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 +*/ + +enum { DISPLAY_NONE, DISPLAY_CURSES, DISPLAY_SDL }; + +void display_init(); +void display_quit(); +void display_play(struct level*, struct level*); +void display_edit(struct level*); +int display_type(); +void display_options(); + +void display_menuentry(struct menuentry *pentry, int y, int selected); +void display_menu(struct menu *pmenu, int all); +void display_options_save(); +void display_options_load(); +void display_hide(); diff --git a/editor.c b/editor.c new file mode 100644 index 0000000..0aa8107 --- /dev/null +++ b/editor.c @@ -0,0 +1,1118 @@ +/* + editor.c + + Copyright (C) 2010-2019 Amf + + 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 +#include +#include +#include +#include + +#include "chroma.h" +#include "level.h" +#include "menu.h" +#include "display.h" +#include "util.h" + +void export(struct level*, int); + +int editor_verify(struct level*); +struct level* editor_options(struct level* plevel); + +extern int move_x[]; +extern int move_y[]; +extern char* piece_name[]; +extern struct level* plevelcurrent; +extern int options_debug; + +#ifdef XOR_COMPATIBILITY +extern int options_xor_options; +#endif +#ifdef ENIGMA_COMPATIBILITY +extern int options_enigma_options; +#endif + +int editor_pieces_chroma[] = { + PIECE_SPACE, + PIECE_WALL, + PIECE_PLAYER_ONE, + PIECE_PLAYER_TWO, + PIECE_DOTS, + PIECE_ARROW_RED_LEFT, + PIECE_ARROW_RED_UP, + PIECE_ARROW_RED_RIGHT, + PIECE_ARROW_RED_DOWN, + PIECE_BOMB_RED_LEFT, + PIECE_BOMB_RED_UP, + PIECE_BOMB_RED_RIGHT, + PIECE_BOMB_RED_DOWN, + PIECE_ARROW_GREEN_LEFT, + PIECE_ARROW_GREEN_UP, + PIECE_ARROW_GREEN_RIGHT, + PIECE_ARROW_GREEN_DOWN, + PIECE_BOMB_GREEN_LEFT, + PIECE_BOMB_GREEN_UP, + PIECE_BOMB_GREEN_RIGHT, + PIECE_BOMB_GREEN_DOWN, + PIECE_ARROW_BLUE_LEFT, + PIECE_ARROW_BLUE_UP, + PIECE_ARROW_BLUE_RIGHT, + PIECE_ARROW_BLUE_DOWN, + PIECE_BOMB_BLUE_LEFT, + PIECE_BOMB_BLUE_UP, + PIECE_BOMB_BLUE_RIGHT, + PIECE_BOMB_BLUE_DOWN, + PIECE_CIRCLE, + PIECE_STAR, + PIECE_DOOR, + PIECE_GONE +}; + +#ifdef XOR_COMPATIBILITY +int editor_pieces_xor[] = { + PIECE_SPACE, + PIECE_WALL, + PIECE_PLAYER_ONE, + PIECE_PLAYER_TWO, + PIECE_DOTS_X, + PIECE_DOTS_Y, + PIECE_ARROW_RED_DOWN, + PIECE_ARROW_RED_LEFT, + PIECE_BOMB_RED_DOWN, + PIECE_BOMB_RED_LEFT, + PIECE_STAR, + PIECE_DOOR, + PIECE_CIRCLE, + PIECE_TELEPORT, + PIECE_SWITCH, + PIECE_MAP_TOP_LEFT, + PIECE_MAP_TOP_RIGHT, + PIECE_MAP_BOTTOM_LEFT, + PIECE_MAP_BOTTOM_RIGHT, + PIECE_GONE +}; +#endif + +#ifdef ENIGMA_COMPATIBILITY +int editor_pieces_enigma[] = { + PIECE_SPACE, + PIECE_WALL, + PIECE_PLAYER_ONE, + PIECE_DOTS, + PIECE_DOTS_DOUBLE, + PIECE_ARROW_RED_LEFT, + PIECE_ARROW_RED_UP, + PIECE_ARROW_RED_RIGHT, + PIECE_ARROW_RED_DOWN, + PIECE_BOMB_RED_LEFT, + PIECE_BOMB_RED_UP, + PIECE_BOMB_RED_RIGHT, + PIECE_BOMB_RED_DOWN, + PIECE_STAR, + PIECE_DOOR, + PIECE_CIRCLE, + PIECE_CIRCLE_DOUBLE, + PIECE_GONE +}; +#endif + +int *editor_piece_maps[] = +{ + editor_pieces_chroma, +#ifdef XOR_COMPATIBILITY + editor_pieces_xor, +#endif +#ifdef ENIGMA_COMPATIBILITY + editor_pieces_enigma, +#endif + NULL +}; + +void editor() +{ + char filename[FILENAME_MAX]; + char directory[FILENAME_MAX]; + struct level* plevelload; + struct level* pleveltest; + struct menu* pmenu; + struct menu* pmenuconfirm; + struct menuentry* pentryno; + int ok; + int result; + + plevelcurrent = NULL; + + ok = 0; + while(!ok) + { + pmenu = menu_new(gettext("Editing Menu")); + + if(plevelcurrent == NULL) + menuentry_new(pmenu, gettext("Return to Main Menu"), 'Q', 0); + else + { + menuentry_new(pmenu, gettext("Return to Editor"), 'Q', 0); + menuentry_new(pmenu, gettext("Abort Editor and Return to Main Menu"), 'A', 0); + } + menuentry_new(pmenu, "", 0, MENU_SPACE); + + menuentry_new(pmenu, gettext("Load Level"), 'L', 0); + menuentry_new(pmenu, gettext("Save Level"), 'S', plevelcurrent == NULL ? MENU_GREY : 0); + menuentry_new(pmenu, gettext("Export Level"), 'E', plevelcurrent == NULL ? MENU_GREY : 0); + menuentry_new(pmenu, gettext("Test Level"), 'T', plevelcurrent == NULL ? MENU_GREY : 0); + menuentry_new(pmenu, gettext("Verify Level"), 'V', plevelcurrent == NULL ? MENU_GREY : 0); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + menuentry_new(pmenu, gettext("Level Options"), 'O', plevelcurrent == NULL ? MENU_GREY : 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + menuentry_new(pmenu, gettext("Display Options"), 'D', 0); + + menuentry_new(pmenu, gettext("Currently editing:"), 0, MENU_NOTE); + + if(plevelcurrent != NULL) + { + if(plevelcurrent->title == NULL || strcmp(plevelcurrent->title, "") == 0) + menuentry_new(pmenu, gettext("[untitled level]"), 0, MENU_NOTE | MENU_RIGHT); + else + menuentry_new(pmenu, gettext(plevelcurrent->title), 0, MENU_NOTE | MENU_RIGHT); + } + else + menuentry_new(pmenu, gettext("** NO LEVEL LOADED **"), 0, MENU_NOTE | MENU_RIGHT); + + result = menu_process(pmenu); + + if(result == MENU_SELECT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'A': + ok = 1; + break; + + case 'S': + getfilename("construct", directory, 1, 0); + if(menu_levelselector(directory, filename, gettext("Save Level"), LEVELMENU_RETURN | LEVELMENU_NEW | LEVELMENU_DELETE | LEVELMENU_FILENAMES) == MENU_SELECT) + { + + if(strcmp(filename, "") == 0) + { + /* Create new file */ + sprintf(filename, "%s/%x.chroma", directory, (int)time(NULL)); + level_save(plevelcurrent, filename, 1); + } + else + { + /* Check file we're trying to save over */ + pleveltest = level_load(filename, 1); + + if(pleveltest != NULL && pleveltest->title != NULL) + { + if(plevelcurrent->title == NULL || strcmp(plevelcurrent->title, pleveltest->title) != 0) + { + pmenuconfirm = menu_new(gettext("Confirm Save")); + + menuentry_new(pmenuconfirm, gettext("Do you wish to overwrite:"), 0, MENU_GREY); + + if(pleveltest->title == NULL || strcmp(pleveltest->title, "") == 0) + menuentry_new(pmenuconfirm, gettext("[untitled level]"), 0, MENU_GREY | MENU_RIGHT); + else + menuentry_new(pmenuconfirm, pleveltest->title, 0, MENU_GREY | MENU_RIGHT); + menuentry_new(pmenuconfirm, gettext("with:"), 0, MENU_GREY); + + if(plevelcurrent->title == NULL || strcmp(plevelcurrent->title, "") == 0) + menuentry_new(pmenuconfirm, gettext("[untitled level]"), 0, MENU_GREY | MENU_RIGHT); + else + menuentry_new(pmenuconfirm, plevelcurrent->title, 0, MENU_GREY | MENU_RIGHT); + + menuentry_new(pmenuconfirm, "", 0, MENU_SPACE); + + pentryno = menuentry_new(pmenuconfirm, gettext("No"), 'N', 0); + menuentry_new(pmenuconfirm, gettext("Yes"), 'Y', 0); + + pmenuconfirm->entry_selected = pentryno; + + result = menu_process(pmenuconfirm); + if(result == MENU_SELECT && pmenuconfirm->entry_selected != NULL && pmenuconfirm->entry_selected->key == 'Y') + level_save(plevelcurrent, filename, 1); + + menu_delete(pmenuconfirm); + + } + else + level_save(plevelcurrent, filename, 1); + } + else + level_save(plevelcurrent, filename, 1); + + level_delete(pleveltest); + } + } + break; + + case 'L': + getfilename("construct", directory, 1, 0); + if(menu_levelselector(directory, filename, gettext("Load Level"), LEVELMENU_RETURN | LEVELMENU_CREATE | LEVELMENU_DELETE | LEVELMENU_FILENAMES | LEVELMENU_IMPORT) == MENU_SELECT) + { + /* Create new level */ + if(strcmp(filename, "") == 0) + plevelload = level_create(32, 23); + /* Load existing level */ + else + plevelload = level_load(filename, 0); + + if(plevelload != NULL) + { + level_delete(plevelcurrent); + + plevelcurrent = plevelload; + + /* Set editor position */ + plevelcurrent->player_x[2] = 0; + plevelcurrent->player_y[2] = 0; + } + } + break; + + case 'E': + export(plevelcurrent, 0); + break; + + case 'T': + pleveltest = level_copy(plevelcurrent); + level_fix(pleveltest); + pleveltest->flags |= LEVELFLAG_TESTING; + display_play(pleveltest, NULL); + level_delete(pleveltest); + break; + + case 'O': + plevelcurrent = editor_options(plevelcurrent); + break; + + case 'D': + display_options(); + break; + + case 'V': + if(editor_verify(plevelcurrent)) + result = MENU_QUIT; + break; + + case 'Q': + result = MENU_QUIT; + break; + + } + } + + if(result == MENU_QUIT) + { + if(plevelcurrent != NULL) + display_edit(plevelcurrent); + else + ok = 1; + } + + menu_delete(pmenu); + + } + + if(plevelcurrent != NULL) + level_delete(plevelcurrent); + plevelcurrent = NULL; +} + +int editor_verify(struct level* plevel) +{ + struct menu* pmenu; + struct menuentry* pentry; + int result; + int ok; + int x, y; + int p, p2; + int d; + int errors; + int i; + int count_playerone, count_playertwo, count_exit, count_teleport; + int count_map_tl, count_map_tr, count_map_bl, count_map_br; + int entries; + char buffer[4096]; + int piece_ok[PIECE_MAX]; + + pmenu = menu_new(gettext("Verify Level")); + + menuentry_new(pmenu, gettext("Return to Previous Menu"), 'Q', 0); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + errors = 0; + count_playerone = 0; + count_playertwo = 0; + count_exit = 0; + count_teleport = 0; + count_map_tl = 0; + count_map_tr = 0; + count_map_bl = 0; + count_map_br = 0; + + for(i = 0; i < PIECE_MAX; i ++) + piece_ok[i] = 0; + + i = 0; + while(editor_piece_maps[plevel->mode][i] != PIECE_GONE) + { + piece_ok[editor_piece_maps[plevel->mode][i]] = 1; + i ++; + } + + for(y = 0; y < plevel->size_y; y ++) + { + for(x = 0; x < plevel->size_x; x ++) + { + p = level_piece(plevel, x, y); + + if(p == PIECE_PLAYER_ONE) + count_playerone ++; + if(p == PIECE_PLAYER_TWO) + count_playertwo ++; + if(p == PIECE_DOOR) + count_exit ++; +#ifdef XOR_COMPATIBILITY + if(p == PIECE_TELEPORT) + count_teleport ++; + if(p == PIECE_MAP_TOP_LEFT) + count_map_tl ++; + if(p == PIECE_MAP_TOP_RIGHT) + count_map_tr ++; + if(p == PIECE_MAP_BOTTOM_LEFT) + count_map_bl ++; + if(p == PIECE_MAP_BOTTOM_RIGHT) + count_map_br ++; +#endif + + if(!piece_ok[p]) + { + sprintf(buffer, gettext("Invalid piece %s at (%d,%d)"), gettext(piece_name[p]), x, y); + pentry = menuentry_new(pmenu, buffer, 0, 0); + sprintf(buffer, "%d %d", x, y); + menuentry_value(pentry, buffer); + errors ++; + } + + if(p >= PIECE_MOVERS_FIRST && p <= PIECE_MOVERS_LAST) + { + d = p % 4; + p2 = level_piece(plevel, x + move_x[d], y + move_y[d]); + + if(canfall(p, p2, d)) + { + sprintf(buffer, gettext("Unsupported %s resting on %s at (%d,%d)"), gettext(piece_name[p]), gettext(piece_name[p2]), x, y); + pentry = menuentry_new(pmenu, buffer, 0, 0); + sprintf(buffer, "%d %d", x, y); + menuentry_value(pentry, buffer); + errors ++; + } + } + } + } + + if(count_playerone == 0) + { + sprintf(buffer, gettext("No %s"), gettext(piece_name[PIECE_PLAYER_ONE])); + pentry = menuentry_new(pmenu, buffer, 0, 0); + errors ++; + } + + if(count_playertwo == 0) + { +#ifdef ENIGMA_COMPATIBILITY + if(plevel->mode != MODE_ENIGMA) + { +#endif + sprintf(buffer, gettext("No %s"), gettext(piece_name[PIECE_PLAYER_TWO])); + pentry = menuentry_new(pmenu, buffer, 0, 0); + errors ++; +#ifdef ENIGMA_COMPATIBILITY + } +#endif + } + + if(count_exit == 0) + { + sprintf(buffer, gettext("No %s"), gettext(piece_name[PIECE_DOOR])); + pentry = menuentry_new(pmenu, buffer, 0, 0); + errors ++; + } + + if(count_playerone > 1) + { + sprintf(buffer, gettext("Too many %s"), gettext(piece_name[PIECE_PLAYER_ONE])); + pentry = menuentry_new(pmenu, buffer, 0, 0); + errors ++; + } + + if(count_playertwo > 1) + { + sprintf(buffer, gettext("Too many %s"), gettext(piece_name[PIECE_PLAYER_TWO])); + pentry = menuentry_new(pmenu, buffer, 0, 0); + errors ++; + } + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + { + if(count_teleport != 0 && count_teleport != 2) + { + sprintf(buffer, gettext("Too many %s"), gettext(piece_name[PIECE_TELEPORT])); + pentry = menuentry_new(pmenu, buffer, 0, 0); + errors ++; + } + + if(count_map_tl != 1) + { + if(count_map_tl == 0) + sprintf(buffer, gettext("No %s"), gettext(piece_name[PIECE_MAP_TOP_LEFT])); + else + sprintf(buffer, gettext("Too many %s"), gettext(piece_name[PIECE_MAP_TOP_LEFT])); + pentry = menuentry_new(pmenu, buffer, 0, 0); + errors ++; + } + + if(count_map_tr != 1) + { + if(count_map_tr == 0) + sprintf(buffer, gettext("No %s"), gettext(piece_name[PIECE_MAP_TOP_RIGHT])); + else + sprintf(buffer, gettext("Too many %s"), gettext(piece_name[PIECE_MAP_TOP_RIGHT])); + pentry = menuentry_new(pmenu, buffer, 0, 0); + errors ++; + } + + if(count_map_bl != 1) + { + if(count_map_bl == 0) + sprintf(buffer, gettext("No %s"), gettext(piece_name[PIECE_MAP_BOTTOM_LEFT])); + else + sprintf(buffer, gettext("Too many %s"), gettext(piece_name[PIECE_MAP_BOTTOM_LEFT])); + pentry = menuentry_new(pmenu, buffer, 0, 0); + errors ++; + } + + if(count_map_br != 1) + { + if(count_map_br == 0) + sprintf(buffer, gettext("No %s"), gettext(piece_name[PIECE_MAP_BOTTOM_RIGHT])); + else + sprintf(buffer, gettext("Too many %s"), gettext(piece_name[PIECE_MAP_BOTTOM_RIGHT])); + pentry = menuentry_new(pmenu, buffer, 0, 0); + errors ++; + } + } +#endif + + entries = 1; + pentry = pmenu->entry_first; + while(pentry != NULL && entries < 11) + { + if(pentry->key == 0 && !(pentry->flags & (MENU_GREY | MENU_NOTE | MENU_SPACE))) + { + pentry->key = '0' + (entries % 10); + entries ++; + } + + pentry = pentry->next; + } + + if(errors == 1) + sprintf(buffer, gettext("%d error found"), errors); + else + sprintf(buffer, gettext("%d errors found"), errors); + menuentry_new(pmenu, buffer, 0, MENU_NOTE | MENU_CENTRE); + + ok = 0; + while(!ok) + { + result = menu_process(pmenu); + + if(result == MENU_SELECT && pmenu->entry_selected != NULL) + { + if(pmenu->entry_selected->value != NULL) + { + i = sscanf(pmenu->entry_selected->value, "%d %d", &x, &y); + if(i == 2) + { + plevel->player_x[2] = x; + plevel->player_y[2] = y; + ok = 2; + } + } + else + ok = 1; + } + + if(result == MENU_QUIT) + ok = 1; + } + + menu_delete(pmenu); + + if(ok == 2) + return 1; + + return 0; +} + +struct level* editor_options(struct level* plevel) +{ + struct level* plevel_new; + struct menu* pmenu; + struct menuentry* pentry_mode; + struct menuentry* pentry_left; + struct menuentry* pentry_right; + struct menuentry* pentry_top; + struct menuentry* pentry_bottom; + struct menuentry* pentry_width; + struct menuentry* pentry_height; + struct menuentry* pentry_rotate; + struct menuentry* pentry_title; + int result; + int padding_left; + int padding_right; + int padding_top; + int padding_bottom; + int width, height; + int delta_left, delta_right, delta_top, delta_bottom; + int x, y; + int ok; + int rotate = 0; + int p, d; + char buffer[256]; + + pmenu = menu_new(gettext("Level Options")); + + padding_left = 0; ok = 1; + for(x = 1; x <= plevel->size_x - 2; x ++) + { + for(y = 1; y <= plevel->size_y - 2; y ++) + { + if(level_piece(plevel, x, y) != PIECE_SPACE) + ok = 0; + } + if(ok == 1) + padding_left ++; + else + break; + } + + padding_right = 0; ok = 1; + for(x = plevel->size_x -2 ; x >= 1; x --) + { + for(y = 1; y <= plevel->size_y - 2; y ++) + { + if(level_piece(plevel, x, y) != PIECE_SPACE) + ok = 0; + } + if(ok == 1) + padding_right ++; + else + break; + } + + padding_top = 0; ok = 1; + for(y = 1; y <= plevel->size_y - 2; y ++) + { + for(x = 1; x <= plevel->size_x - 2; x ++) + { + if(level_piece(plevel, x, y) != PIECE_SPACE) + ok = 0; + } + if(ok == 1) + padding_top ++; + else + break; + } + + padding_bottom = 0; ok = 1; + for(y = plevel->size_y -2 ; y >= 1; y --) + { + for(x = 1; x <= plevel->size_x - 2; x ++) + { + if(level_piece(plevel, x, y) != PIECE_SPACE) + ok = 0; + } + if(ok == 1) + padding_bottom ++; + else + break; + } + + width = plevel->size_x; + height = plevel->size_y; + + delta_left = 0; + delta_right = 0; + delta_top = 0; + delta_bottom = 0; + + /* Create menu entries */ + menuentry_new(pmenu, gettext("Return to previous menu"), 'Q', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentry_title = menuentry_new(pmenu, gettext("Title"), 'I', MENU_DOUBLE | MENU_EDITABLE); + if(plevel->title != NULL) + menuentry_extratext(pentry_title, NULL, NULL, plevel->title); + else + menuentry_extratext(pentry_title, NULL, NULL, ""); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + if(MODE_CHROMA == MODE_MAX - 1) + pentry_mode = NULL; + else + { + pentry_mode = menuentry_new(pmenu, gettext("Level Mode"), 'M', MENU_SCROLLABLE); + menuentry_new(pmenu, "", 0, MENU_SPACE); + } + + pentry_width = menuentry_new(pmenu, gettext("Level width"), 0, MENU_GREY); + pentry_left = menuentry_new(pmenu, gettext("Padding on left edge"), 'L', MENU_SCROLLABLE); + pentry_right = menuentry_new(pmenu, gettext("Padding on right edge"), 'R', MENU_SCROLLABLE); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentry_height = menuentry_new(pmenu, gettext("Level height"), 0, MENU_GREY); + pentry_top = menuentry_new(pmenu, gettext("Padding on top edge"), 'T', MENU_SCROLLABLE); + pentry_bottom = menuentry_new(pmenu, gettext("Padding on bottom edge"), 'B', MENU_SCROLLABLE); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentry_rotate = menuentry_new(pmenu, gettext("Rotate"), 'O', MENU_SCROLLABLE); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + /* Menu loop */ + ok = 0; + while(ok == 0) + { + if(plevel->mode == MODE_CHROMA) + pentry_rotate->flags &= ~MENU_GREY; + else + pentry_rotate->flags |= MENU_GREY; + + /* Fill in values for menu entries */ + switch(plevel->mode) + { + case MODE_CHROMA: + if(pentry_mode != NULL) + menuentry_extratext(pentry_mode, gettext("Chroma"), NULL, NULL); + if(width != 32) + menuentry_text(pentry_width, gettext("Level width (Chroma standard is 32)")); + else + menuentry_text(pentry_width, gettext("Level width")); + + if(height != 23) + menuentry_text(pentry_height, gettext("Level height (Chroma standard is 23)")); + else + menuentry_text(pentry_height, gettext("Level height")); + break; + +#ifdef XOR_COMPATIBILITY + case MODE_XOR: + menuentry_extratext(pentry_mode, gettext("XOR"), NULL, NULL); + + if(width != 32) + menuentry_text(pentry_width, gettext("Level width (XOR standard is 32)")); + else + menuentry_text(pentry_width, gettext("Level width")); + + if(height != 32) + menuentry_text(pentry_height, gettext("Level height (XOR standard is 32)")); + else + menuentry_text(pentry_height, gettext("Level height")); + + break; +#endif + +#ifdef ENIGMA_COMPATIBILITY + case MODE_ENIGMA: + menuentry_extratext(pentry_mode, gettext("Enigma"), NULL, NULL); + + if(width != 36) + menuentry_text(pentry_width, gettext("Level width (Enigma standard is 36)")); + else + menuentry_text(pentry_width, gettext("Level width")); + + if(height != 20) + menuentry_text(pentry_height, gettext("Level height (Enigma standard is 20)")); + else + menuentry_text(pentry_height, gettext("Level height")); + + break; +#endif + + } + + sprintf(buffer, "%d", width); + menuentry_extratext(pentry_width, buffer, NULL, NULL); + + sprintf(buffer, "%d", padding_left); + menuentry_extratext(pentry_left, buffer, NULL, NULL); + + sprintf(buffer, "%d", padding_right); + menuentry_extratext(pentry_right, buffer, NULL, NULL); + + sprintf(buffer, "%d", height); + menuentry_extratext(pentry_height, buffer, NULL, NULL); + + sprintf(buffer, "%d", padding_top); + menuentry_extratext(pentry_top, buffer, NULL, NULL); + + sprintf(buffer, "%d", padding_bottom); + menuentry_extratext(pentry_bottom, buffer, NULL, NULL); + + if(plevel->mode == MODE_CHROMA) + { + sprintf(buffer, gettext("%d degrees"), rotate * 90); + menuentry_extratext(pentry_rotate, buffer, NULL, NULL); + } + else + menuentry_extratext(pentry_rotate, gettext("(only for Chroma levels)"), NULL, NULL); + + /* Display menu */ + result = menu_process(pmenu); + + /* Process results */ + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'Q': + ok = 1; + break; + } + } + + if(result == MENU_SCROLLLEFT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'M': + plevel->mode --; + if(plevel->mode < 0) + plevel->mode = MODE_MAX - 1; +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + options_xor_options = 1; +#endif +#ifdef ENIGMA_COMPATIBILITY + if(plevel->mode == MODE_ENIGMA) + options_enigma_options = 1; +#endif + pentry_height->redraw = 1; + pentry_width->redraw = 1; + pentry_mode->redraw = 1; + pentry_rotate->redraw = 1; + break; + + case 'L': + if(width > 2) + { + delta_left --; + padding_left --; + width --; + + pentry_left->redraw = 1; + pentry_width->redraw = 1; + } + break; + + case 'R': + if(width > 2) + { + delta_right --; + padding_right --; + width --; + + pentry_right->redraw = 1; + pentry_width->redraw = 1; + } + break; + + case 'T': + if(height > 2) + { + delta_top --; + padding_top --; + height --; + + pentry_top->redraw = 1; + pentry_height->redraw = 1; + } + break; + + case 'B': + if(height > 2) + { + delta_bottom --; + padding_bottom --; + height --; + + pentry_bottom->redraw = 1; + pentry_height->redraw = 1; + } + break; + + case 'O': + rotate -= 1; + if(rotate == -1) + rotate = 3; + break; + + } + + } + + if(result == MENU_SCROLLRIGHT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'M': + plevel->mode ++; + if(plevel->mode == MODE_MAX) + plevel->mode = 0; +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + options_xor_options = 1; +#endif +#ifdef ENIGMA_COMPATIBILITY + if(plevel->mode == MODE_ENIGMA) + options_enigma_options = 1; +#endif + pentry_height->redraw = 1; + pentry_width->redraw = 1; + pentry_mode->redraw = 1; + pentry_rotate->redraw = 1; + break; + + case 'L': + if(width < 256) + { + delta_left ++; + padding_left ++; + width ++; + + pentry_left->redraw = 1; + pentry_width->redraw = 1; + } + break; + + case 'R': + if(width < 256) + { + delta_right ++; + padding_right ++; + width ++; + + pentry_right->redraw = 1; + pentry_width->redraw = 1; + } + break; + + case 'T': + if(height < 256) + { + delta_top ++; + padding_top ++; + height ++; + + pentry_top->redraw = 1; + pentry_height->redraw = 1; + } + break; + + case 'B': + if(height < 256) + { + delta_bottom ++; + padding_bottom ++; + height ++; + + pentry_bottom->redraw = 1; + pentry_height->redraw = 1; + } + break; + + case 'O': + rotate += 1; + if(rotate == 4) + rotate = 0; + break; + } + } + } + + /* Set new title */ + if(pentry_title->text4 != NULL) + { + level_settitle(plevel, pentry_title->text4); + /* Easier than editing the configuration file! */ + if(strcmp(pentry_title->text4, "debug") == 0) + options_debug |= DEBUG_MENU; + } + + /* Resize the level if necessary */ + if(delta_left != 0 || delta_right != 0 || delta_top != 0 || delta_bottom != 0 ) + { + + /* Create a new level */ + plevel_new = level_create(width, height); + + /* Copy pieces into it */ + for(x = 1; x <= plevel->size_x - 2; x ++) + { + for(y = 1; y <= plevel->size_y - 2; y ++) + { + level_setpiece(plevel_new, x + delta_left, y + delta_top, level_piece(plevel, x, y)); + } + } + + /* Force borders */ + for(x = 0; x<= plevel_new->size_x - 1; x ++) + { + level_setpiece(plevel_new, x, 0, PIECE_WALL); + level_setpiece(plevel_new, x, plevel_new->size_y - 1, PIECE_WALL); + } + for(y = 0; y<= plevel_new->size_y - 1; y ++) + { + level_setpiece(plevel_new, 0, y, PIECE_WALL); + level_setpiece(plevel_new, plevel_new->size_x - 1, y, PIECE_WALL); + } + + /* If the original padding on any edge was zero, add a wall */ + if(padding_left - delta_left == 0) + { + for(y = 1; y <= plevel->size_y - 2; y ++) + { + level_setpiece(plevel_new, padding_left, y, PIECE_WALL); + } + } + if(padding_right - delta_right == 0) + { + for(y = 1; y <= plevel->size_y - 2; y ++) + { + level_setpiece(plevel_new, plevel_new->size_x - 1 - padding_right, y, PIECE_WALL); + } + } + if(padding_top - delta_top == 0) + { + for(x = 1; x <= plevel->size_x - 2; x ++) + { + level_setpiece(plevel_new, x, padding_top, PIECE_WALL); + } + } + if(padding_bottom - delta_bottom == 0) + { + for(x = 1; x <= plevel->size_x - 2; x ++) + { + level_setpiece(plevel_new, x, plevel_new->size_y - 1 - padding_bottom, PIECE_WALL); + } + } + + /* Copy level options */ + plevel_new->mode = plevel->mode; + level_settitle(plevel_new, plevel->title); + + /* Delete old level */ + level_delete(plevel); + plevel = plevel_new; + } + + /* Rotate the level if necessary */ + if(rotate != 0) + { + if(rotate == 2) + { + width = plevel->size_x; + height = plevel->size_y; + } + else + { + width = plevel->size_y; + height = plevel->size_x; + } + + /* Create a new level */ + plevel_new = level_create(width, height); + + /* Copy pieces into it */ + for(x = 1; x <= plevel_new->size_x - 2; x ++) + { + for(y = 1; y <= plevel_new->size_y - 2; y ++) + { + switch(rotate) + { + case 1: + p = level_piece(plevel, y, plevel->size_y - 1 - x); + break; + case 2: + p = level_piece(plevel, plevel->size_x - 1 - x, plevel->size_y - 1 - y); + break; + case 3: + p = level_piece(plevel, plevel->size_x - 1 - y, x); + break; + default: + p = level_piece(plevel, x, y); + break; + } + if(p >= PIECE_MOVERS_FIRST && p <= PIECE_MOVERS_LAST) + { + d = p % 4; + p = p - d + ((d + rotate) % 4); + } + level_setpiece(plevel_new, x, y, p); + } + } + + /* Force borders */ + for(x = 0; x<= plevel_new->size_x - 1; x ++) + { + level_setpiece(plevel_new, x, 0, PIECE_WALL); + level_setpiece(plevel_new, x, plevel_new->size_y - 1, PIECE_WALL); + } + for(y = 0; y<= plevel_new->size_y - 1; y ++) + { + level_setpiece(plevel_new, 0, y, PIECE_WALL); + level_setpiece(plevel_new, plevel_new->size_x - 1, y, PIECE_WALL); + } + + /* Copy level options */ + plevel_new->mode = plevel->mode; + + level_settitle(plevel_new, plevel->title); + + /* Delete old level */ + level_delete(plevel); + plevel = plevel_new; + } + + return plevel; +} + diff --git a/engine.c b/engine.c new file mode 100644 index 0000000..394d183 --- /dev/null +++ b/engine.c @@ -0,0 +1,1528 @@ +/* + engine.c + + Copyright (C) 2010-2019 Amf + + 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 +#include + +#include "chroma.h" +#include "level.h" +#include "util.h" + +#ifdef XOR_COMPATIBILITY +int xor_move(struct level* plevel, int move); +int xor_evolve(struct level* plevel); +void xor_focus(struct level* plevel); +extern int options_xor_mode; +#endif +#ifdef ENIGMA_COMPATIBILITY +int enigma_move(struct level* plevel, int move); +int enigma_evolve(struct level* plevel); +extern int options_enigma_mode; +#endif + +extern int options_debug; +extern char* piece_name[]; + +/* l u r d n s w */ +int move_x[] = {-1, 0, 1, 0, 0, 0, 0}; +int move_y[] = {0, -1, 0, 1, 0, 0, 0}; + +#ifdef ENIGMA_COMPATIBILITY +int enigma_move_order[] = {MOVE_DOWN, MOVE_RIGHT, MOVE_LEFT, MOVE_UP}; +#endif +#ifdef XOR_COMPATIBILITY +int xor_teleport_order[] = {MOVE_RIGHT, MOVE_UP, MOVE_LEFT, MOVE_DOWN}; +#endif + +struct mover* mover_new(struct level* plevel, int x, int y, int d, int piece, int fast); +void mover_consider(struct level* plevel, int x, int y, int d); +struct mover* mover_explode(struct level *plevel, int x, int y, int d, int p); +void explode_sides(struct level* plevel, int x, int y, int p, int d); +int canfall(int p, int into, int d); +int canmove(int p, int into, int d, int fast); +int canexplode(int p, int into, int d, int fast, int mode); +int canbepushed(int p, int into, int d, int mode); + +int explosiontype(int p) +{ + switch(p) + { + case PIECE_ARROW_RED_LEFT: + case PIECE_ARROW_RED_RIGHT: + case PIECE_BOMB_RED_LEFT: + case PIECE_BOMB_RED_RIGHT: + return PIECE_EXPLOSION_NEW_RED_VERTICAL; + case PIECE_ARROW_RED_UP: + case PIECE_ARROW_RED_DOWN: + case PIECE_BOMB_RED_UP: + case PIECE_BOMB_RED_DOWN: + return PIECE_EXPLOSION_NEW_RED_HORIZONTAL; + + case PIECE_ARROW_GREEN_LEFT: + case PIECE_ARROW_GREEN_RIGHT: + case PIECE_BOMB_GREEN_LEFT: + case PIECE_BOMB_GREEN_RIGHT: + return PIECE_EXPLOSION_NEW_GREEN_VERTICAL; + case PIECE_ARROW_GREEN_UP: + case PIECE_ARROW_GREEN_DOWN: + case PIECE_BOMB_GREEN_UP: + case PIECE_BOMB_GREEN_DOWN: + return PIECE_EXPLOSION_NEW_GREEN_HORIZONTAL; + + case PIECE_ARROW_BLUE_LEFT: + case PIECE_ARROW_BLUE_RIGHT: + case PIECE_BOMB_BLUE_LEFT: + case PIECE_BOMB_BLUE_RIGHT: + return PIECE_EXPLOSION_NEW_BLUE_VERTICAL; + case PIECE_ARROW_BLUE_UP: + case PIECE_ARROW_BLUE_DOWN: + case PIECE_BOMB_BLUE_UP: + case PIECE_BOMB_BLUE_DOWN: + return PIECE_EXPLOSION_NEW_BLUE_HORIZONTAL; + + default: + /* This should never happen */ + return PIECE_GONE; + } +} + +void level_moved(struct level* plevel, int move) +{ + if(move != MOVE_REDO) + level_addmove(plevel, move); + else + { + if(plevel->move_current != NULL) + plevel->move_current = plevel->move_current->next; + else + plevel->move_current = plevel->move_first; + } + + plevel->moves ++; + plevel->flags |= LEVELFLAG_MOVES; + + level_storemovers(plevel); +} + +int level_move(struct level* plevel, int move) +{ + int x, y; + int tx, ty; + int px, py; + int p; + int ok; +#ifdef XOR_COMPATIBILITY + int dx, dy; + int teleport; + int td; + int i; +#endif + int realmove; + struct move* pmove; + + realmove = move; + + if(plevel == NULL || plevel->mover_first != NULL) + return 0; + + if(move == MOVE_REDO) + { + if(plevel->move_current == NULL) + pmove = plevel->move_first; + else + pmove = plevel->move_current->next; + + if(pmove == NULL) + return 0; + + move = pmove->direction; + } + + if(move == MOVE_SWAP) + { + if(plevel->alive[1 - plevel->player]) + { + plevel->player = 1 - plevel->player; + + /* Create new movers for the stationary swapped players to allow + the display to redraw them after the swap. */ + mover_new(plevel, plevel->player_x[plevel->player], plevel->player_y[plevel->player], MOVE_SWAP, PIECE_PLAYER_ONE + plevel->player, 0); + + /* Is the first player still alive? */ + if(plevel->alive[1 - plevel->player]) + mover_new(plevel, plevel->player_x[1 - plevel->player], plevel->player_y[1 - plevel->player], MOVE_SWAPPED, PIECE_PLAYER_ONE + 1 - plevel->player, 0); + + level_moved(plevel, realmove); + + return 1; + } + return 0; + } + + if(plevel->alive[plevel->player] == 0) + return 0; + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR && options_xor_mode == 1) + { + if(xor_move(plevel, move)) + { + level_moved(plevel, realmove); + xor_focus(plevel); + return 1; + } + return 0; + } +#endif +#ifdef ENIGMA_COMPATIBILITY + if(plevel->mode == MODE_ENIGMA && options_enigma_mode == 1) + { + if(enigma_move(plevel, move)) + { + level_moved(plevel, realmove); + return 1; + } + return 0; + } + +#endif + + /* Consider where we are moving to */ + x = plevel->player_x[plevel->player] + move_x[move]; + y = plevel->player_y[plevel->player] + move_y[move]; + + p = level_piece(plevel, x, y); + + ok = 0; + + /* Can we move into the piece in that direction? */ + switch(p) + { + case PIECE_DOOR: + if(plevel->stars_caught == plevel->stars_total) + { + plevel->flags |= LEVELFLAG_EXIT; + ok = 1; + } + break; + + case PIECE_STAR: + plevel->stars_caught ++; + plevel->flags |= LEVELFLAG_STARS; + ok = 1; + break; + +#ifdef XOR_COMPATIBILITY + case PIECE_TELEPORT: + /* Only XOR has teleports. We force the issue so as not to break + Chroma's rotational symmetry by introducing teleport order. */ + if(plevel->mode != MODE_XOR) + break; + + teleport = -1; + if(x == plevel->teleport_x[0] && y == plevel->teleport_y[0]) + teleport = 0; + if(x == plevel->teleport_x[1] && y == plevel->teleport_y[1]) + teleport = 1; + if(teleport != -1) + { + tx = plevel->teleport_x[1 - teleport]; + ty = plevel->teleport_y[1 - teleport]; + td = move; + + /* Does the other teleport still exist? */ + if(level_piece(plevel, tx, ty) == PIECE_TELEPORT) + { + ok = 0; + /* Find the first available exit from it */ + for(i = 0; i < 4; i ++) + { + dx = tx + move_x[xor_teleport_order[i]]; + dy = ty + move_y[xor_teleport_order[i]]; + if(!ok && level_piece(plevel, dx, dy) == PIECE_SPACE) + { + /* Change move to produce the effect of coming + out of the teleport */ + x = dx; y = dy; move = xor_teleport_order[i]; + ok = 1; + } + } + + if(ok) + { + /* Visual effects for the player going in one teleport */ + /* Store original player move direction in cosmetic mover */ + mover_new(plevel, plevel->teleport_x[teleport], plevel->teleport_y[teleport], td, PIECE_TELEPORT, 0); + level_setprevious(plevel, plevel->teleport_x[teleport], plevel->teleport_y[teleport], PIECE_PLAYER_ONE + plevel->player); + level_setpreviousmoving(plevel, plevel->teleport_x[teleport], plevel->teleport_y[teleport], realmove); + /* and out of the other teleport */ + mover_new(plevel, plevel->teleport_x[1 - teleport], plevel->teleport_y[1 - teleport], MOVE_NONE, PIECE_TELEPORT, 0); + + /* Change the viewpoint to that of the other teleport */ + plevel->view_x[plevel->player] = plevel->view_teleport_x[1 - teleport]; + plevel->view_y[plevel->player] = plevel->view_teleport_y[1 - teleport]; + + } + } + } + break; + + case PIECE_SWITCH: + plevel->switched = 1 - plevel->switched; + plevel->flags |= LEVELFLAG_SWITCH; + ok = 1; + break; + + case PIECE_MAP_TOP_LEFT: + plevel->mapped |= MAPPED_TOP_LEFT; + plevel->flags |= LEVELFLAG_MAP; + ok = 1; + break; + case PIECE_MAP_TOP_RIGHT: + plevel->mapped |= MAPPED_TOP_RIGHT; + plevel->flags |= LEVELFLAG_MAP; + ok = 1; + break; + case PIECE_MAP_BOTTOM_LEFT: + plevel->mapped |= MAPPED_BOTTOM_LEFT; + plevel->flags |= LEVELFLAG_MAP; + ok = 1; + break; + case PIECE_MAP_BOTTOM_RIGHT: + plevel->mapped |= MAPPED_BOTTOM_RIGHT; + plevel->flags |= LEVELFLAG_MAP; + ok = 1; + break; + + case PIECE_DOTS_X: + if(move == MOVE_LEFT || move == MOVE_RIGHT) + ok = 1; + break; + + case PIECE_DOTS_Y: + if(move == MOVE_UP || move == MOVE_DOWN) + ok = 1; + break; +#endif + +#ifdef ENIGMA_COMPATIBILITY + case PIECE_DOTS_DOUBLE: +#endif + case PIECE_DOTS: + case PIECE_SPACE: + ok = 1; + break; + } + + /* Is there a piece we can push? */ + if(!ok) + { + tx = x + move_x[move]; + ty = y + move_y[move]; + + if(canbepushed(p, level_piece(plevel, tx, ty), move, plevel->mode)) + { + mover_new(plevel, tx, ty, move, p, 0); + ok = 1; + } + } + + if(ok) + { + + /* Cosmetic mover for storing the player's direction in undo */ + mover_new(plevel, plevel->player_x[plevel->player], plevel->player_y[plevel->player], move, PIECE_GONE, 0); + + mover_new(plevel, x, y, move, PIECE_PLAYER_ONE + plevel->player, 0); + + px = plevel->player_x[plevel->player]; + py = plevel->player_y[plevel->player]; + +#ifdef XOR_COMPATIBILITY + /* XOR protects the players move */ + if(plevel->mode == MODE_XOR) + { + /* Blank the player's space first to avoid upsetting undo */ + level_setpiece(plevel, px, py, PIECE_SPACE); + mover_new(plevel, px, py, (move + 1) % 4, PIECE_SPACE, 1); + } + /* Chroma lets a piece follow in the player's trail */ + else + { +#endif + /* Blank the player's space first to avoid upsetting undo */ + level_setpiece(plevel, px, py, PIECE_SPACE); + mover_consider(plevel, px, py, move % 4); +#ifdef XOR_COMPATIBILITY + } +#endif + + plevel->player_x[plevel->player] = x; + plevel->player_y[plevel->player] = y; + + level_moved(plevel, realmove); + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + xor_focus(plevel); +#endif + + return 1; + } + + return 0; +} + +struct mover* mover_explode(struct level *plevel, int x, int y, int d, int p) +{ + /* Don't explode any of the edge wall */ + if(x == 0 || y == 0 || x == plevel->size_x - 1 || y == plevel->size_y - 1) + return NULL; + + /* What have we exploded? */ + switch(level_piece(plevel, x, y)) + { + case PIECE_STAR: + plevel->stars_exploded ++; + plevel->flags |= LEVELFLAG_STARS; + break; + +#ifdef XOR_COMPATIBILITY + case PIECE_SWITCH: + plevel->switched = 1 - plevel->switched; + plevel->flags |= LEVELFLAG_SWITCH; + break; +#endif + } + + return mover_new(plevel, x, y, d, p, 1); +} + +struct mover* mover_new(struct level* plevel, int x, int y, int d, int piece, int fast) +{ + struct mover* pmover; + int previous; + int data; + + /* Don't allow two movers in the same space, unless one is exploding */ + if(!isnewexplosion(piece) && level_moving(plevel, x, y) != MOVE_NONE) + return NULL; + + pmover = (struct mover*)malloc(sizeof(struct mover)); + if(pmover == NULL) + fatal("Out of memory in mover_new()"); + + previous = level_piece(plevel, x, y); + + pmover->x = x; + pmover->y = y; + pmover->direction = d; + pmover->piece = piece; + pmover->piece_previous = previous; + pmover->fast = fast; + pmover->next = NULL; + pmover->previous = plevel->mover_last; + + if(plevel->mover_first == NULL) + plevel->mover_first = pmover; + + if(plevel->mover_last != NULL) + plevel->mover_last->next = pmover; + + plevel->mover_last = pmover; + + /* Show pieces collected by players */ + if(piece == PIECE_PLAYER_ONE || piece == PIECE_PLAYER_TWO) + { + if((previous < PIECE_MOVERS_FIRST || previous > PIECE_MOVERS_LAST) + && previous != PIECE_CIRCLE +#ifdef ENIGMA_COMPATIBILITY + && previous != PIECE_CIRCLE_DOUBLE +#endif + && previous != PIECE_PLAYER_ONE + && previous != PIECE_PLAYER_TWO) + level_setprevious(plevel, x, y, previous); + } + + /* Show players squashed by movers */ + if(piece >= PIECE_MOVERS_FIRST && piece <= PIECE_MOVERS_LAST) + { + if(previous == PIECE_PLAYER_ONE || previous == PIECE_PLAYER_TWO) + level_setprevious(plevel, x, y, previous); + } + + /* Show pieces removed by movers or explosions */ + if(previous == PIECE_DOTS +#ifdef ENIGMA_COMPATIBILITY + || previous == PIECE_DOTS_DOUBLE +#endif +#ifdef XOR_COMPATIBILITY + || previous == PIECE_DOTS_X + || previous == PIECE_DOTS_Y +#endif + || isexplosion(previous)) + level_setprevious(plevel, x, y, previous); + + /* Show exploded pieces */ + if(isnewexplosion(piece) && !isnewexplosion(previous)) + { + level_setprevious(plevel, x, y, previous); + level_setpreviousmoving(plevel, x, y, level_moving(plevel, x, y)); + } + + /* Explosions occur later */ + if(!isnewexplosion(piece) && piece != PIECE_GONE) + { + level_setpiece(plevel, x, y, piece); + level_setmoving(plevel, x, y, d); + } + + /* Maintain piece graphic */ + if(d != MOVE_NONE) + { + data = level_data(plevel, x - move_x[d], y - move_y[d]) & 0xff00; + data = (level_data(plevel, x, y) & ~0xff00) | data; + level_setdata(plevel, x, y, data); + } + + return pmover; +} + +struct mover* mover_addtostack(struct level* plevel, int x, int y, int move) +{ + struct mover* pmover; + + pmover = (struct mover*)malloc(sizeof(struct mover)); + if(pmover == NULL) + fatal("Out of memory in mover_addtostack()"); + + pmover->x = x; + pmover->y = y; + pmover->direction = move; + pmover->piece = PIECE_SPACE; + pmover->fast = 0; + pmover->next = NULL; + + if(plevel->stack_first == NULL) + plevel->stack_first = pmover; + + if(plevel->stack_last != NULL) + plevel->stack_last->next = pmover; + + plevel->stack_last = pmover; + + return pmover; +} + +void level_storemovers(struct level* plevel) +{ + struct mover* pmover; + int previous; + + int count = 0; + + if(plevel->move_current == NULL || plevel->mover_first == NULL) + return; + + if((options_debug & DEBUG_MOVERS) && plevel->move_current->mover_first == NULL) + fprintf(stderr, "\n"); + + pmover = plevel->mover_first; + while(pmover != NULL) + { + /* If something is moving into an explosion, don't store it as the + previous piece for this space; it will have its own mover, and thus + will be stored elsewhere. */ + previous = pmover->piece_previous; + if(isexplosion(pmover->piece) && level_previousmoving(plevel, pmover->x, pmover->y) != MOVE_NONE) + previous = PIECE_SPACE; + + mover_newundo(plevel, pmover->x, pmover->y, + pmover->direction, pmover->piece, previous, + MOVER_STORE | (pmover->next == NULL ? 0 : MOVER_FAST)); + + if(options_debug & DEBUG_MOVERS) + fprintf(stderr, "[%d] Storing undo mover at (%d,%d) is %s was %s (direction=%c) (flags=%d)\n", + count ++, pmover->x, pmover->y, + piece_name[pmover->piece], piece_name[previous], + directiontochar(pmover->direction), + (pmover->next == NULL ? 0 : MOVER_FAST)); + + pmover = pmover->next; + } +} + +int level_evolve(struct level* plevel) +{ + struct mover* poldmovers; + struct mover* pmover; + int x, y; + int i; + int d; + int ad; + int ed; + int ax, ay; + int bp, bd; + int filled; + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR && options_xor_mode == 1) + { + return xor_evolve(plevel); + } +#endif +#ifdef ENIGMA_COMPATIBILITY + if(plevel->mode == MODE_ENIGMA && options_enigma_mode == 1) + { + return enigma_evolve(plevel); + } +#endif + + poldmovers = plevel->mover_first; + + plevel->mover_first = NULL; + plevel->mover_last = NULL; + + /* Chroma's engine isn't perfect. Pieces that appear to be in continuous + motion are actually momentarily stationary at the start of every cycle. + In pathological cases, this can give rise to some counterintuitive + situations, where the outcome depends on the order of the movers. + + See levels/regression/chroma-regression.chroma for some examples. + */ + + pmover = poldmovers; + while(pmover != NULL) + { + level_setmoving(plevel, pmover->x, pmover->y, MOVE_NONE); + level_setprevious(plevel, pmover->x, pmover->y, PIECE_SPACE); + level_setpreviousmoving(plevel, pmover->x, pmover->y, MOVE_NONE); + level_setdetonator(plevel, pmover->x, pmover->y, PIECE_SPACE); + level_setdetonatormoving(plevel, pmover->x, pmover->y, MOVE_NONE); + pmover = pmover->next; + } + + pmover = poldmovers; + while(pmover != NULL) + { + + /* Remove the mover if something has already moved into its space */ + if(level_moving(plevel, pmover->x, pmover->y) != MOVE_NONE + /* or it isn't what it should be */ + || level_piece(plevel, pmover->x, pmover->y) != pmover->piece + ) + pmover->piece = PIECE_GONE; + + switch(pmover->piece) + { + case PIECE_SPACE: + case PIECE_EXPLOSION_RED_LEFT: + case PIECE_EXPLOSION_RED_HORIZONTAL: + case PIECE_EXPLOSION_RED_RIGHT: + case PIECE_EXPLOSION_RED_TOP: + case PIECE_EXPLOSION_RED_VERTICAL: + case PIECE_EXPLOSION_RED_BOTTOM: + case PIECE_EXPLOSION_GREEN_LEFT: + case PIECE_EXPLOSION_GREEN_HORIZONTAL: + case PIECE_EXPLOSION_GREEN_RIGHT: + case PIECE_EXPLOSION_GREEN_TOP: + case PIECE_EXPLOSION_GREEN_VERTICAL: + case PIECE_EXPLOSION_GREEN_BOTTOM: + case PIECE_EXPLOSION_BLUE_LEFT: + case PIECE_EXPLOSION_BLUE_HORIZONTAL: + case PIECE_EXPLOSION_BLUE_RIGHT: + case PIECE_EXPLOSION_BLUE_TOP: + case PIECE_EXPLOSION_BLUE_VERTICAL: + case PIECE_EXPLOSION_BLUE_BOTTOM: + i = 0; + filled = 0; + + /* Consider the pieces around the space */ + for(i = 0; i < 4; i ++) + { + if(filled) + continue; + +#ifdef ENIGMA_COMPATIBILITY + /* Enigma has a fixed move order */ + if(plevel->mode == MODE_ENIGMA) + d = enigma_move_order[i]; + else +#endif + /* Chroma and XOR depend on how the space was emptied */ + d = (pmover->direction + i) % 4; + + ad = (d + 2) % 4; + ax = pmover->x + move_x[ad]; + ay = pmover->y + move_y[ad]; + + /* Can the piece move into the space? */ + if(canfall(level_piece(plevel, ax, ay), PIECE_SPACE, d) + /* and that piece isn't already moving */ + && level_moving(plevel, ax, ay) == MOVE_NONE + ) + { + x = pmover->x + move_x[d]; + y = pmover->y + move_y[d]; + + /* Can the piece from the opposite direction also + move into this space? */ + if(canfall(level_piece(plevel, x, y), PIECE_SPACE, ad) + /* and that piece isn't already moving */ + && level_moving(plevel, x, y) == MOVE_NONE + /* If so, can the two explode? */ + && canexplode(level_piece(plevel, ax, ay), level_piece(plevel, x, y), d, 1, plevel->mode) + /* (but not for XOR and Enigma) */ + && plevel->mode == MODE_CHROMA + ) + { + /* If so, detonate them in the middle */ + if((level_piece(plevel, x, y) & 4) == 4) + { + /* The first piece is the bomb */ + bp = level_piece(plevel, x, y); + bd = ad; + ed = level_piece(plevel, x, y) & 3; + + level_setdetonator(plevel, pmover->x, pmover->y, level_piece(plevel, ax, ay)); + level_setdetonatormoving(plevel, pmover->x, pmover->y, d); + } + else + { + /* The second piece is the bomb */ + bp = level_piece(plevel, ax, ay); + bd = d; + ed = level_piece(plevel, ax, ay) & 3; + + level_setdetonator(plevel, pmover->x, pmover->y, level_piece(plevel, x, y)); + level_setdetonatormoving(plevel, pmover->x, pmover->y, ad); + } + + /* and consider anything following them */ + mover_consider(plevel, x, y, ad); + mover_consider(plevel, ax, ay, d); + + /* Move the bomb into the space */ + level_setpiece(plevel, pmover->x, pmover->y, bp); + level_setmoving(plevel, pmover->x, pmover->y, bd); + + /* and explode it */ + mover_explode(plevel, pmover->x, pmover->y, ed, explosiontype(bp)); + + /* Create the central explosion now, to prevent the + piece there being processed as a later mover. */ + level_setpiece(plevel, pmover->x, pmover->y, explosiontype(bp)); + + explode_sides(plevel, pmover->x, pmover->y, bp, ed); + + filled = 1; + break; + } + + /* Otherwise, keep the piece moving */ + mover_new(plevel, pmover->x, pmover->y, d, level_piece(plevel, ax, ay), 1); + /* and see if anything is following in its trail */ + mover_consider(plevel, ax, ay, d); + + filled = 1; + break; + } + } + + /* If the explosion has not been filled */ + if(isexplosion(pmover->piece) && filled == 0 + /* and nothing else is moving into it */ + && level_moving(plevel, pmover->x, pmover->y) == MOVE_NONE + ) + /* then turn it into a space */ + mover_new(plevel, pmover->x, pmover->y, pmover->direction, PIECE_SPACE, 0); + + break; + + case PIECE_PLAYER_ONE: + case PIECE_PLAYER_TWO: + case PIECE_GONE: + /* These 'movers' are purely for cosmetic purposes */ + break; + +#ifdef XOR_COMPATIBILITY + case PIECE_TELEPORT: + /* These 'movers' are purely for cosmetic purposes */ + break; +#endif + + default: + /* A pushed arrow still falls in its natural direction */ + if(pmover->fast == 0 && pmover->piece >= PIECE_MOVERS_FIRST && pmover->piece <= PIECE_MOVERS_LAST) + pmover->direction = pmover->piece % 4; + + /* Consider the space in front of the mover */ + x = pmover->x + move_x[pmover->direction]; + y = pmover->y + move_y[pmover->direction]; + + /* Can the mover move into the space in front of it? */ + if(canmove(pmover->piece, level_piece(plevel, x, y), pmover->direction, pmover->fast) + /* and that space doesn't already have something + moving into it */ + && (level_moving(plevel, x, y) == MOVE_NONE) + ) + { + /* If so, keep it moving */ + mover_new(plevel, x, y, pmover->direction, pmover->piece, 1); + /* and see if anything is following in its trail */ + mover_consider(plevel, pmover->x, pmover->y, pmover->direction); + break; + } + + /* Can the mover explode the piece in front of it? */ + if(canexplode(pmover->piece, level_piece(plevel, x, y), pmover->direction, pmover->fast, plevel->mode) + /* and the piece in front isn't moving */ + && (level_moving(plevel, x, y) == MOVE_NONE + /* or it is moving towards us */ + || (level_moving(plevel, x, y) == ((pmover->direction + 2) % 4) + /* (but not for XOR or Enigma) */ + && plevel->mode==MODE_CHROMA)) + ) + { + bp = level_piece(plevel, x, y); + level_setdetonator(plevel, x, y, pmover->piece); + level_setdetonatormoving(plevel, x, y, pmover->direction); + + /* Explosion direction is bomb fall direction */ + if(bp & 4) + ed = bp & 3; + else + ed = pmover->piece & 3; + + mover_explode(plevel, x, y, ed, explosiontype(bp)); + + /* Create the central explosion now, to prevent the piece + there being processed as a later mover. */ + level_setpiece(plevel, x, y, explosiontype(bp)); + + mover_consider(plevel, pmover->x, pmover->y, pmover->direction); + + explode_sides(plevel, x, y, bp, ed); + + break; + } + } + + pmover = pmover->next; + } + + /* Create the side explosions at the end, rather than during the previous + loop. This allows multiple explosions to occur in parallel. Centre + explosions will have already been created earlier on. */ + pmover = plevel->mover_first; + while(pmover != NULL) + { + if(isnewexplosion(pmover->piece)) + { + if(!isnewexplosion(level_piece(plevel, pmover->x, pmover->y))) + { + level_setprevious(plevel, pmover->x, pmover->y, level_piece(plevel, pmover->x, pmover->y)); + level_setpreviousmoving(plevel, pmover->x, pmover->y, level_moving(plevel, pmover->x, pmover->y)); + } + + /* Use PIECE_EXPLOSION_NEW to allow detection of overlapping + explosions further down. */ + level_setpiece(plevel, pmover->x, pmover->y, pmover->piece); + level_setmoving(plevel, pmover->x, pmover->y, pmover->direction); + + pmover->piece += PIECE_EXPLOSION_FIRST - PIECE_EXPLOSION_NEW_FIRST; + } + + pmover = pmover->next; + } + + pmover = plevel->mover_first; + while(pmover != NULL) + { + if(isexplosion(pmover->piece)) + { + /* Remove any explosions that overlap other explosions */ + if(isexplosion(level_piece(plevel, pmover->x, pmover->y))) + pmover->piece = PIECE_GONE; + /* Otherwise, convert new explosions into explosions proper */ + else + level_setpiece(plevel, pmover->x, pmover->y, pmover->piece); + } + /* Remove any movers that have exploded, or aren't as they should be */ + if(level_piece(plevel, pmover->x, pmover->y) != pmover->piece) + { + pmover->piece = PIECE_GONE; + } + pmover = pmover->next; + } + + /* Is player one still alive? */ + if(level_piece(plevel, plevel->player_x[0], plevel->player_y[0]) != PIECE_PLAYER_ONE) + { + plevel->flags |= LEVELFLAG_MOVES; + plevel->alive[0] = 0; + } + + /* Is player two still alive? */ + if(level_piece(plevel, plevel->player_x[1], plevel->player_y[1]) != PIECE_PLAYER_TWO) + { + plevel->flags |= LEVELFLAG_MOVES; + plevel->alive[1] = 0; + } + + /* Free old movers */ + while(poldmovers != NULL) + { + pmover = poldmovers; + poldmovers = poldmovers->next; + free(pmover); + } + + return 0; +} + +void mover_consider(struct level* plevel, int x, int y, int d) +{ + int tx, ty; + int ad; + + /* Is there already a mover in this space? If so, don't allow another */ + if(level_moving(plevel, x, y) != MOVE_NONE) + return; + +#ifdef ENIGMA_COMPATIBILITY + /* Enigma doesn't consider the direction in which a space was emptied */ + if(plevel->mode == MODE_ENIGMA) + { + mover_new(plevel, x, y, d, PIECE_SPACE, 1); + return; + } +#endif + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + { + mover_new(plevel, x, y, d, PIECE_SPACE, 1); + return; + } +#endif + + ad = (d + 2) % 4; + tx = x + move_x[ad]; + ty = y + move_y[ad]; + + /* Can a piece follow in the trail of this one? */ + if(canfall(level_piece(plevel, tx, ty), PIECE_SPACE, d)) + { + /* If it's moving already, just clear this space (1.07) */ + if(level_moving(plevel, tx, ty) != MOVE_NONE) + { + mover_new(plevel, x, y, MOVE_NONE, PIECE_SPACE, 0); + return; + } + + /* Otherwise, set it moving */ + mover_new(plevel, x, y, d, level_piece(plevel, tx, ty), 1); + /* and see if there's anything following in its trail */ + mover_consider(plevel, tx, ty, d); + return; + } + + mover_new(plevel, x, y, d, PIECE_SPACE, 1); +} + +void explode_sides(struct level* plevel, int x, int y, int p, int d) +{ + /* Chroma is subtle. This may be too subtle to have any effect in practice, + but the principle elsewhere is that things should be rotationally + symmetric, and this carries through here. */ + if(plevel->mode == MODE_CHROMA) + { + switch(p % 4) + { + case 0: /* left */ + mover_explode(plevel, x, y - 1, d, explosiontype(p) - 1); + mover_explode(plevel, x, y + 1, d, explosiontype(p) + 1); + break; + + case 1: /* up */ + mover_explode(plevel, x + 1, y, d, explosiontype(p) + 1); + mover_explode(plevel, x - 1, y, d, explosiontype(p) - 1); + break; + + case 2: /* right */ + mover_explode(plevel, x, y + 1, d, explosiontype(p) + 1); + mover_explode(plevel, x, y - 1, d, explosiontype(p) - 1); + break; + + case 3: /* down */ + mover_explode(plevel, x - 1, y, d, explosiontype(p) - 1); + mover_explode(plevel, x + 1, y, d, explosiontype(p) + 1); + break; + } + } + else + { + switch(p % 2) + { + case 0: /* left / right */ + mover_explode(plevel, x, y - 1, d, explosiontype(p) - 1); + mover_explode(plevel, x, y + 1, d, explosiontype(p) + 1); + break; + case 1: /* up /down */ + mover_explode(plevel, x - 1, y, d, explosiontype(p) - 1); + mover_explode(plevel, x + 1, y, d, explosiontype(p) + 1); + break; + } + } +} + + +int canfall(int p, int into, int d) +{ + /* Determine whether a piece can start moving */ + + /* Arrows and bombs */ + if(p >= PIECE_MOVERS_FIRST && p<= PIECE_MOVERS_LAST) + { + /* can start falling in their natural direction */ + if(d == (p % 4)) + { + /* but only into empty space */ + if(into == PIECE_SPACE) + return 1; +#ifdef XOR_COMPATIBILITY + /* or into directional dots if appropriate */ + if(into == PIECE_DOTS_X && (d == MOVE_LEFT || d == MOVE_RIGHT )) + return 1; + if(into == PIECE_DOTS_Y && (d == MOVE_UP || d == MOVE_DOWN )) + return 1; +#endif + } + } + + return 0; +} + + +int canmove(int p, int into, int d, int fast) +{ + /* Determine whether a piece can continue moving */ + + /* Arrows and bombs */ + if(p >= PIECE_MOVERS_FIRST && p<= PIECE_MOVERS_LAST) + { + /* can continue moving in their natural direction */ + if(d == (p % 4)) + { + /* into empty space */ + if(into == PIECE_SPACE) + return 1; + /* into dots if they're already moving */ + if(into == PIECE_DOTS && fast) + return 1; +#ifdef XOR_COMPATIBILITY + /* into directional dots if appropriate */ + if(into == PIECE_DOTS_X && (d == MOVE_LEFT || d == MOVE_RIGHT )) + return 1; + if(into == PIECE_DOTS_Y && (d == MOVE_UP || d == MOVE_DOWN )) + return 1; +#endif + /* through dying explosions */ + if(isexplosion(into)) + return 1; + /* can kill players if already moving */ + if(into == PIECE_PLAYER_ONE && fast) + return 1; + if(into == PIECE_PLAYER_TWO && fast) + return 1; + } + return 0; + } + + /* Circles */ + if(p == PIECE_CIRCLE) + { + /* are stopped by everything other than empty space */ + if(into == PIECE_SPACE) + return 1; + /* and dying explosions */ + if(isexplosion(into)) + return 1; + return 0; + } + + return 0; +} + +int canbepushed(int p, int into, int d, int mode) +{ + /* Determine whether a piece can be pushed by the player */ + + /* Arrows and bombs */ + if(p >= PIECE_MOVERS_FIRST && p<= PIECE_MOVERS_LAST) + { + /* can be pushed, but not against their natural direction */ + if(d != ((p + 2) % 4)) + { + /* into empty space or through dots */ + if(into == PIECE_SPACE || into == PIECE_DOTS) + return 1; +#ifdef XOR_COMPATIBILITY + /* through directional dots if appropriate */ + if(into == PIECE_DOTS_X && (d == MOVE_LEFT || d == MOVE_RIGHT)) + return 1; + if(into == PIECE_DOTS_Y && (d == MOVE_UP || d == MOVE_DOWN)) + return 1; +#endif + } + return 0; + } + + /* Circles can be pushed in any direction */ + if(p == PIECE_CIRCLE +#ifdef ENIGMA_COMPATIBILITY + || p == PIECE_CIRCLE_DOUBLE +#endif + ) + { + /* into empty space */ + if(into == PIECE_SPACE) + return 1; +#ifdef XOR_COMPATIBILITY + /* XOR won't let circles (dolls) pass through dots */ + if(mode == MODE_XOR) + return 0; +#endif + /* pushed through dots */ + if(into == PIECE_DOTS) + return 1; + return 0; + } + + return 0; +} + +int canexplode(int p, int i, int d, int fast, int mode) +{ + /* Only an already moving arrow or bomb can act as a detonator */ + if(fast == 0) + return 0; + + /* Arrows can detonate bombs */ + if(p >= PIECE_ARROW_RED_LEFT && p<= PIECE_ARROW_RED_DOWN && + i >= PIECE_BOMB_RED_LEFT && i<= PIECE_BOMB_RED_DOWN) + return 1; + if(p >= PIECE_ARROW_GREEN_LEFT && p<= PIECE_ARROW_GREEN_DOWN && + i >= PIECE_BOMB_GREEN_LEFT && i<= PIECE_BOMB_GREEN_DOWN) + return 1; + if(p >= PIECE_ARROW_BLUE_LEFT && p<= PIECE_ARROW_BLUE_DOWN && + i >= PIECE_BOMB_BLUE_LEFT && i<= PIECE_BOMB_BLUE_DOWN) + return 1; + +#ifdef ENIGMA_COMPATIBILITY + /* Enigma requires a moving arrow to detonate a stationary bomb, and + does not permit bombs to detonate other bombs */ + if(mode == MODE_ENIGMA) + return 0; +#endif + + /* Bombs can be detonated by arrows pointing towards them */ + if(p >= PIECE_BOMB_RED_LEFT && p<= PIECE_BOMB_RED_DOWN && + i == (PIECE_ARROW_RED_LEFT + ((d + 2) % 4))) + return 1; + if(p >= PIECE_BOMB_GREEN_LEFT && p<= PIECE_BOMB_GREEN_DOWN && + i == (PIECE_ARROW_GREEN_LEFT + ((d + 2) % 4))) + return 1; + if(p >= PIECE_BOMB_BLUE_LEFT && p<= PIECE_BOMB_BLUE_DOWN && + i == (PIECE_ARROW_BLUE_LEFT + ((d + 2) % 4))) + return 1; + + /* Bombs can detonate other bombs */ + if(p >= PIECE_BOMB_RED_LEFT && p<= PIECE_BOMB_RED_DOWN && + i >= PIECE_BOMB_RED_LEFT && i<= PIECE_BOMB_RED_DOWN) + return 1; + if(p >= PIECE_BOMB_GREEN_LEFT && p<= PIECE_BOMB_GREEN_DOWN && + i >= PIECE_BOMB_GREEN_LEFT && i<= PIECE_BOMB_GREEN_DOWN) + return 1; + if(p >= PIECE_BOMB_BLUE_LEFT && p<= PIECE_BOMB_BLUE_DOWN && + i >= PIECE_BOMB_BLUE_LEFT && i<= PIECE_BOMB_BLUE_DOWN) + return 1; + + return 0; +} + +struct mover* mover_newundo(struct level* plevel, int x, int y, int d, int piece, int previous, int flags) +{ + struct mover* pmover; + + static int count = 0; + + if(plevel->flags & LEVELFLAG_NOUNDO) + return NULL; + + pmover = (struct mover*)malloc(sizeof(struct mover)); + if(pmover == NULL) + fatal("Out of memory in mover_newundo()"); + + pmover->x = x; + pmover->y = y; + pmover->direction = d; + pmover->piece = piece; + pmover->piece_previous = previous; + pmover->next = NULL; + pmover->previous = plevel->mover_last; + + if(flags & MOVER_FAST) + pmover->fast = 1; + else + pmover->fast = 0; + + if(flags & MOVER_UNDO) + { + level_setmoving(plevel, pmover->x, pmover->y, pmover->direction); + + if(options_debug & DEBUG_MOVERS) + { + if(plevel->mover_first == NULL) + count = 0; + + fprintf(stderr, "[%d] Cosmetic mover at (%d,%d) is %s was %s (direction=%c) (flags=%d)\n", + count ++, pmover->x, pmover->y, + piece_name[pmover->piece], piece_name[pmover->piece_previous], + directiontochar(pmover->direction), pmover->fast); + } + + if(plevel->mover_first == NULL) + plevel->mover_first = pmover; + + if(plevel->mover_last != NULL) + plevel->mover_last->next = pmover; + + plevel->mover_last = pmover; + + } + + if(flags & MOVER_STORE) + { + pmover->previous = plevel->move_current->mover_last; + pmover->next = NULL; + + if(plevel->move_current->mover_first == NULL) + plevel->move_current->mover_first = pmover; + if(plevel->move_current->mover_last != NULL) + plevel->move_current->mover_last->next = pmover; + plevel->move_current->mover_last = pmover; + + } + + return pmover; +} + + +int level_undo(struct level* plevel) +{ + struct mover* pmover; + struct mover* ptmp; + struct mover* pmoverfirst; + + int d, td; + + int count = 0; + + /* Can't undo if the level has no undo data (eg, a partial save) */ + if(plevel->move_first == NULL || (plevel->move_first->mover_first == NULL && plevel->move_current != plevel->move_first)) + return 0; + + /* Working backwards, undo any changes made to the map by movers in the + previous step. */ + pmoverfirst = NULL; + pmover = plevel->mover_first; + while(pmover != NULL) + { + pmoverfirst = pmover; + pmover = pmover->next; + } + pmover = pmoverfirst; + while(pmover != NULL) + { + /* Not setting SPACEs fixes a pathological case without apparently breaking anything (1.07) */ + if(pmover->piece != PIECE_SPACE) + { + level_setpiece(plevel, pmover->x, pmover->y, pmover->piece); + if(options_debug & DEBUG_MOVERS) + fprintf(stderr, "+ level_setpiece(%d, %d, %s)\n", pmover->x, pmover->y, piece_name[pmover->piece]); + } + + pmover = pmover->previous; + if(pmover == NULL) + break; + } + + /* Is player one still alive? */ + if(level_piece(plevel, plevel->player_x[0], plevel->player_y[0]) != PIECE_PLAYER_ONE) + plevel->alive[0] = 0; + /* Is player two still alive? */ + if(level_piece(plevel, plevel->player_x[1], plevel->player_y[1]) != PIECE_PLAYER_TWO) + plevel->alive[1] = 0; + + /* Tidy up any movers created in the previous step */ + pmover = plevel->mover_first; + while(pmover != NULL) + { + level_setmoving(plevel, pmover->x, pmover->y, MOVE_NONE); + level_setprevious(plevel, pmover->x, pmover->y, PIECE_SPACE); + ptmp = pmover; + pmover = pmover->next; + free(ptmp); + } + plevel->mover_first = NULL; + plevel->mover_last = NULL; + + /* Can't undo at very start of level */ + if(plevel->move_current == NULL) + return 0; + + /* If there is no previous step to undo, remove this move entirely */ + if(plevel->move_current->mover_last == NULL) + { + plevel->move_current = plevel->move_current->previous; + plevel->flags |= LEVELFLAG_MOVES; + + return 0; + } + + if(options_debug & DEBUG_MOVERS) + fprintf(stderr, "\n"); + + /* Start from the last mover for this step. */ + pmover = plevel->move_current->mover_last; + + pmoverfirst = NULL; + + td = MOVE_NONE; + + /* Working backwards, remove these pieces from the map */ + while(pmover != NULL) + { + pmoverfirst = pmover; + + level_setpiece(plevel, pmover->x, pmover->y, PIECE_SPACE); + + if(options_debug & DEBUG_MOVERS) + fprintf(stderr, "- level_setpiece(%d, %d, %s)\n", pmover->x, pmover->y, piece_name[PIECE_SPACE]); + + /* If the piece is the player, update position and status */ + if(pmover->piece_previous == PIECE_PLAYER_ONE || pmover->piece_previous == PIECE_PLAYER_TWO) + { + plevel->player_x[pmover->piece_previous - PIECE_PLAYER_ONE] = pmover->x; + plevel->player_y[pmover->piece_previous - PIECE_PLAYER_ONE] = pmover->y; + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + { + /* If a player is being resurrected in this move, and the + other player is alive, undo the automatic swap */ + if(plevel->alive[pmover->piece_previous - PIECE_PLAYER_ONE] == 0 && plevel->alive[plevel->player]) + { + /* Cosmetic mover to deactivate other player */ + mover_newundo(plevel, plevel->player_x[plevel->player], plevel->player_y[plevel->player], MOVE_SWAPPED, PIECE_PLAYER_ONE + plevel->player, PIECE_SPACE, MOVER_UNDO); + plevel->player = pmover->piece_previous - PIECE_PLAYER_ONE; + } + + /* The active player is the one which moves first + (last in undo */ + plevel->player = pmover->piece_previous - PIECE_PLAYER_ONE; + } +#endif + + plevel->alive[pmover->piece_previous - PIECE_PLAYER_ONE] = 1; + } + +#ifdef XOR_COMPATIBILITY + /* If the piece is a teleport, store the direction of the original move + into it for later use. */ + if(pmover->piece == PIECE_TELEPORT) + td = pmover->direction; +#endif + + /* until we reach the first mover for this step. */ + pmover = pmover->previous; + if(pmover != NULL && pmover->fast == 0) + break; + } + + pmover = pmoverfirst; + + /* Now, move forwards through the movers and create cosmetic effects. */ + while(pmover != NULL) + { + + if(options_debug & DEBUG_MOVERS) + fprintf(stderr, "[%d] Undo mover at (%d,%d) is %s was %s (direction=%c) (flags=%d)\n", + count++, pmover->x, pmover->y, + piece_name[pmover->piece], piece_name[pmover->piece_previous], + directiontochar(pmover->direction), pmover->fast); + + d = pmover->direction; + + if(d != MOVE_NONE && d != MOVE_SWAP && d != MOVE_SWAPPED) + d = (d + 2) % 4; + + if(isexplosion(pmover->piece)) + { + /* Explosions don't move. */ + d = MOVE_NONE; + /* Show dying explosion when undoing new explosion */ + if(options_debug & DEBUG_MOVERS) + fprintf(stderr, "* level_setprevious(%d, %d, %s)\n", pmover->x, pmover->y, piece_name[pmover->piece]); + level_setprevious(plevel, pmover->x, pmover->y, pmover->piece); + } + + /* Do we need to patch up the direction this piece is moving in? */ + /* Is it the player? */ + if((pmover->piece_previous == PIECE_PLAYER_ONE || pmover->piece_previous == PIECE_PLAYER_TWO) && (pmover->piece == PIECE_SPACE || pmover->piece == PIECE_GONE)) + { + /* If so, are they moving out of a teleport? Use original direction + of move if so. */ + if(td != MOVE_NONE) + d = (td + 2) % 4; + } + /* Otherwise, if the previous piece wasn't a move, it must have been a + static piece being eaten by a mover, and thus shouldn't move. */ + else if((pmover->piece_previous < PIECE_MOVERS_FIRST || pmover->piece_previous > PIECE_MOVERS_LAST) && pmover->piece_previous != PIECE_CIRCLE +#ifdef ENIGMA_COMPATIBILITY + && pmover->piece_previous != PIECE_CIRCLE_DOUBLE +#endif + ) + d = MOVE_NONE; + + /* Plot a cosmetic mover. */ + if(level_previous(plevel, pmover->x, pmover->y) != PIECE_SPACE) + d = MOVE_NONE; + /* but not if there are overlapping explosions */ + if(!(pmover->piece_previous >= PIECE_EXPLOSION_NEW_FIRST && pmover->piece_previous <= PIECE_EXPLOSION_NEW_LAST)) + mover_newundo(plevel, pmover->x, pmover->y, d, pmover->piece_previous, PIECE_SPACE, MOVER_UNDO); + + pmover = pmover->next; + } + + pmover = pmoverfirst->previous; + + /* If there is another step, set it up for the next iteration */ + if(pmover != NULL) + { + plevel->move_current->mover_last = pmover; + pmover = pmover->next; + } + else + { + pmover = plevel->move_current->mover_first; + plevel->move_current->mover_first = NULL; + plevel->move_current->mover_last = NULL; + + plevel->moves --; + } + + /* Remove the movers in the step we've just done */ + if(pmover != NULL) + { + while(pmover != NULL) + { + /* Undo any pieces exploded or caught */ + if(pmover->piece_previous == PIECE_STAR) + { + if(pmover->piece == PIECE_PLAYER_ONE || pmover->piece == PIECE_PLAYER_TWO) + plevel->stars_caught --; + else + plevel->stars_exploded --; + + plevel->flags |= LEVELFLAG_STARS; + } +#ifdef XOR_COMPATIBILITY + if(pmover->piece_previous == PIECE_SWITCH) + { + plevel->switched = 1 - plevel->switched; + plevel->flags |= LEVELFLAG_SWITCH; + } + if(pmover->piece_previous == PIECE_MAP_TOP_LEFT) + { + plevel->mapped ^= MAPPED_TOP_LEFT; + plevel->flags |= LEVELFLAG_MAP; + } + if(pmover->piece_previous == PIECE_MAP_TOP_RIGHT) + { + plevel->mapped ^= MAPPED_TOP_RIGHT; + plevel->flags |= LEVELFLAG_MAP; + } + if(pmover->piece_previous == PIECE_MAP_BOTTOM_LEFT) + { + plevel->mapped ^= MAPPED_BOTTOM_LEFT; + plevel->flags |= LEVELFLAG_MAP; + } + if(pmover->piece_previous == PIECE_MAP_BOTTOM_RIGHT) + { + plevel->mapped ^= MAPPED_BOTTOM_RIGHT; + plevel->flags |= LEVELFLAG_MAP; + } +#endif + + ptmp = pmover; + pmover = pmover->next; + free(ptmp); + } + } + + if(plevel->move_current->mover_last != NULL) + plevel->move_current->mover_last->next = NULL; + + /* If the move was a swap, revert to the previous player */ + if(plevel->move_current->direction == MOVE_SWAP) + plevel->player = 1 - plevel->player; + + /* Have we just undone failure? */ + if((plevel->flags & LEVELFLAG_FAILED) && (plevel->alive[0] != 0 || plevel->alive[1] != 0)) + { + plevel->flags &= ~LEVELFLAG_FAILED; + plevel->flags |= LEVELFLAG_MOVES; + } + + /* Have we just undone success? */ + if(plevel->flags & (LEVELFLAG_SOLVED | LEVELFLAG_EXIT)) + { + plevel->flags &= ~LEVELFLAG_SOLVED; + plevel->flags &= ~LEVELFLAG_EXIT; + plevel->flags |= LEVELFLAG_STARS; + } + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + xor_focus(plevel); +#endif + + /* If there are no more steps in this move, chroma-curses needs advanced + warning that the move counter is going to change. */ + if(plevel->move_current->mover_last == NULL) + { + plevel->flags |= LEVELFLAG_MOVES; + } + + return 1; +} diff --git a/enigma.c b/enigma.c new file mode 100644 index 0000000..274fdf2 --- /dev/null +++ b/enigma.c @@ -0,0 +1,312 @@ +/* + enigma.c + + A reverse engineering of the original Enigma game engine. This maintains + the usual list of movers, and a separate stack of spaces to be considered. + In each round, we examine this stack to generate fresh movers, then examine + those movers to determine whether newly exposed spaces should be added to + the stack, and also to generate further movers for the next round. + + See levels/regression/enigma-regression.chroma for some subtleties this + catches that aren't handled correctly by the Chroma game engine. Such + situations don't seem to occur in the original Enigma levels, however. + + + Copyright (C) 2010-2019 Amf + + 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 +#include + +#include "chroma.h" +#include "level.h" +#include "util.h" + +#ifdef ENIGMA_COMPATIBILITY + +extern int move_x[]; +extern int move_y[]; +extern int enigma_move_order[]; + +int enigma_move(struct level* plevel, int move) +{ + int px, py; + int dx, dy; + int p; + int into; + + if(plevel->alive[plevel->player] == 0) + return 0; + if(move == MOVE_SWAP) + return 0; + + px = plevel->player_x[plevel->player]; + py = plevel->player_y[plevel->player]; + + dx = px + move_x[move]; + dy = py + move_y[move]; + + /* Can we make the move? */ + p = level_piece(plevel, dx, dy); + switch(p) + { + /* Pieces that can be collected */ + case PIECE_SPACE: + case PIECE_DOTS: + case PIECE_DOTS_DOUBLE: + break; + case PIECE_STAR: + plevel->stars_caught ++; + plevel->flags |= LEVELFLAG_STARS; + break; + case PIECE_DOOR: + if(plevel->stars_caught == plevel->stars_total) + plevel->flags |= LEVELFLAG_EXIT; + else + return 0; + break; + /* Pieces that can be pushed */ + case PIECE_ARROW_RED_LEFT: + case PIECE_ARROW_RED_RIGHT: + case PIECE_ARROW_RED_UP: + case PIECE_ARROW_RED_DOWN: + case PIECE_BOMB_RED_LEFT: + case PIECE_BOMB_RED_RIGHT: + case PIECE_BOMB_RED_UP: + case PIECE_BOMB_RED_DOWN: + /* Can't push against gravity */ + if(((level_piece(plevel, dx, dy) + 2) % 4) == move) + return 0; + /* fallthrough */ + case PIECE_CIRCLE: + case PIECE_CIRCLE_DOUBLE: + /* Can't push into other pieces */ + into = level_piece(plevel, dx + move_x[move], dy + move_y[move]); + if(into != PIECE_SPACE && into != PIECE_DOTS) + return 0; + mover_new(plevel, dx + move_x[move], dy + move_y[move], move, p, 0); + break; + + /* Can't move */ + default: + return 0; + } + + mover_new(plevel, dx, dy, move, PIECE_PLAYER_ONE + plevel->player, 0); + mover_new(plevel, px, py, move, PIECE_SPACE, 0); + level_setmoving(plevel, px, py, MOVE_NONE); + plevel->player_x[plevel->player] = dx; + plevel->player_y[plevel->player] = dy; + mover_addtostack(plevel, px, py, move); + + return 1; +} + +int enigma_evolve(struct level* plevel) +{ + struct mover* pmover; + struct mover* ptmp; + + int into; + + int d; + int i, p, ep; + + int px, py; + int dx, dy; + + int ok; + + ok = 0; + while(!ok) + { + /* Examine the stack, and generate movers from it */ + pmover = plevel->stack_first; + while(pmover != NULL) + { + /* Can anything fall into this space? */ + for(i = 0; i < 4; i ++) + { + d = enigma_move_order[i]; + px = pmover->x - move_x[d]; + py = pmover->y - move_y[d]; + p = level_piece(plevel, px, py); + if(p >= PIECE_ARROW_RED_LEFT && p <= PIECE_BOMB_RED_DOWN && (p % 4 == d)) + { + if(level_moving(plevel, px, py) == MOVE_NONE) + { + mover_new(plevel, px, py, d, p, 1); + i = 4; + } + } + } + ptmp = pmover; + pmover = pmover->next; + free(ptmp); + } + plevel->stack_first = NULL; + plevel->stack_last = NULL; + + /* Examine the movers, adding new movers to a separate list */ + pmover = plevel->mover_first; + plevel->mover_first = NULL; + plevel->mover_last = NULL; + while(pmover != NULL) + { + level_setmoving(plevel, pmover->x, pmover->y, MOVE_NONE); + level_setprevious(plevel, pmover->x, pmover->y, PIECE_SPACE); + level_setpreviousmoving(plevel, pmover->x, pmover->y, MOVE_NONE); + level_setdetonator(plevel, pmover->x, pmover->y, PIECE_SPACE); + level_setdetonatormoving(plevel, pmover->x, pmover->y, MOVE_NONE); + + p = pmover->piece; + if(p == PIECE_EXPLOSION_RED_HORIZONTAL || p == PIECE_EXPLOSION_RED_VERTICAL) + { + mover_new(plevel, pmover->x, pmover->y, MOVE_NONE, PIECE_SPACE, 0); + mover_addtostack(plevel, pmover->x, pmover->y, MOVE_NONE); + if(p == PIECE_EXPLOSION_RED_HORIZONTAL) + { + if(pmover->x - 1 > 0) + { + mover_new(plevel, pmover->x - 1, pmover->y, MOVE_NONE, PIECE_SPACE, 0); + mover_addtostack(plevel, pmover->x - 1, pmover->y, MOVE_NONE); + } + if(pmover->x + 1 < plevel->size_x - 1) + { + mover_new(plevel, pmover->x + 1, pmover->y, MOVE_NONE, PIECE_SPACE, 0); + mover_addtostack(plevel, pmover->x + 1, pmover->y, MOVE_NONE); + } + } + else + { + if(pmover->y - 1 > 0) + { + mover_new(plevel, pmover->x, pmover->y - 1, MOVE_NONE, PIECE_SPACE, 0); + mover_addtostack(plevel, pmover->x, pmover->y - 1, MOVE_NONE); + } + if(pmover->y + 1 < plevel->size_y - 1) + { + mover_new(plevel, pmover->x, pmover->y + 1, MOVE_NONE, PIECE_SPACE, 0); + mover_addtostack(plevel, pmover->x, pmover->y + 1, MOVE_NONE); + } + } + } + if((p >= PIECE_ARROW_RED_LEFT && p <= PIECE_BOMB_RED_DOWN) || p == PIECE_CIRCLE) + { + if(p == PIECE_CIRCLE) + d = pmover->direction; + else + d = p % 4; + dx = pmover->x + move_x[d]; + dy = pmover->y + move_y[d]; + + into = level_piece(plevel, dx, dy); + /* Can it detonate something? */ + if(p >= PIECE_ARROW_RED_LEFT && p <= PIECE_ARROW_RED_DOWN && into >= PIECE_BOMB_RED_LEFT && into <= PIECE_BOMB_RED_DOWN && pmover->fast && level_moving(plevel, dx, dy) == MOVE_NONE) + { + /* Add the central explosion to the stack */ + mover_new(plevel, pmover->x, pmover->y, d, PIECE_SPACE, 0); + level_setprevious(plevel, dx, dy, into); + level_setdetonator(plevel, dx, dy, p); + level_setdetonatormoving(plevel, dx, dy, d); + mover_addtostack(plevel, pmover->x, pmover->y, MOVE_NONE); + + /* Generate cosmetic side explosions */ + if(into % 2) + { + if(dx - 1 > 0) + { + ep = level_piece(plevel, dx - 1, dy); + if(ep == PIECE_STAR) + { + plevel->stars_exploded ++; + plevel->flags |= LEVELFLAG_STARS; + } + level_setmoving(plevel, dx - 1, dy, MOVE_NONE); + mover_new(plevel, dx - 1, dy, level_moving(plevel, dx - 1, dy), PIECE_EXPLOSION_RED_LEFT, 1); + level_setprevious(plevel, dx - 1, dy, ep); + } + if(dx + 1 < plevel->size_x - 1) + { + ep = level_piece(plevel, dx + 1, dy); + if(ep == PIECE_STAR) + { + plevel->stars_exploded ++; + plevel->flags |= LEVELFLAG_STARS; + } + level_setmoving(plevel, dx + 1, dy, MOVE_NONE); + mover_new(plevel, dx + 1, dy, level_moving(plevel, dx + 1, dy), PIECE_EXPLOSION_RED_RIGHT, 0); + level_setprevious(plevel, dx + 1, dy, ep); + } + mover_new(plevel, dx, dy, MOVE_NONE, PIECE_EXPLOSION_RED_HORIZONTAL, 0); + } + else + { + if(dy - 1 > 0) + { + ep = level_piece(plevel, dx, dy - 1); + if(ep == PIECE_STAR) + { + plevel->stars_exploded ++; + plevel->flags |= LEVELFLAG_STARS; + } + level_setmoving(plevel, dx, dy - 1, MOVE_NONE); + mover_new(plevel, dx, dy - 1, level_moving(plevel, dx, dy - 1), PIECE_EXPLOSION_RED_TOP, 0); + level_setprevious(plevel, dx, dy - 1, ep); + } + if(dy + 1 < plevel->size_y - 1) + { + ep = level_piece(plevel, dx, dy + 1); + if(ep == PIECE_STAR) + { + plevel->stars_exploded ++; + plevel->flags |= LEVELFLAG_STARS; + } + level_setmoving(plevel, dx, dy + 1, MOVE_NONE); + mover_new(plevel, dx, dy + 1, level_moving(plevel, dx, dy + 1), PIECE_EXPLOSION_RED_BOTTOM, 0); + level_setprevious(plevel, dx, dy + 1, ep); + } + mover_new(plevel, dx, dy, MOVE_NONE, PIECE_EXPLOSION_RED_VERTICAL, 0); + } + } + /* Can it keep moving? */ + else if(into == PIECE_SPACE || ((into == PIECE_DOTS || into == PIECE_PLAYER_ONE) && p != PIECE_CIRCLE && pmover->fast == 1)) + { + mover_new(plevel, dx, dy, d, p, 1); + mover_new(plevel, pmover->x, pmover->y, d, PIECE_SPACE, 0); + level_setmoving(plevel, pmover->x, pmover->y, MOVE_NONE); + mover_addtostack(plevel, pmover->x, pmover->y, MOVE_NONE); + } + } + + ptmp = pmover->next; + free(pmover); + pmover = ptmp; + } + + if(plevel->mover_first != NULL || plevel->stack_first == NULL) + ok = 1; + } + + /* Is player one still alive? */ + if(level_piece(plevel, plevel->player_x[0], plevel->player_y[0]) != PIECE_PLAYER_ONE) + plevel->alive[0] = 0; + + return 0; +} + +#endif diff --git a/graphics.c b/graphics.c new file mode 100644 index 0000000..be2090d --- /dev/null +++ b/graphics.c @@ -0,0 +1,1746 @@ +/* + graphics.c + + Copyright (C) 2010-2019 Amf + + 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chroma.h" +#include "level.h" +#include "colours.h" +#include "graphics.h" +#include "util.h" +#include "sdlfont.h" +#include "menu.h" +#include "xmlparser.h" + +struct graphics* pdisplaygraphics = NULL; + +extern char *piece_name[]; +extern char options_graphics[]; +extern struct colours* pdisplaycolours; +extern struct level* plevelcurrent; + +extern int options_sdl_size_x; +extern int options_sdl_size_y; +extern int options_graphic_level; +extern int options_debug; +#ifdef XOR_COMPATIBILITY +extern int options_xor_display; +#endif +extern int screen_width; +extern int screen_height; +extern int screen_flags; + +extern int font_height; +extern int font_height_game; +extern int font_size_menu; +extern int font_size_game; + +void graphics_createfromfont(struct graphics *pgraphics); +SDL_Surface* graphics_scaleimage(SDL_Surface*, int, int); + +struct graphics* graphics_load(char *filename, int partial); + +#define SIZE_HUGE 1000000 + +void graphics_init() +{ + char filename[FILENAME_MAX]; + char directory[FILENAME_MAX]; + + if(pdisplaygraphics != NULL) + graphics_delete(pdisplaygraphics); + + pdisplaygraphics = graphics_load(options_graphics, 0); + + if(pdisplaygraphics == NULL) + { + /* Revert to default */ + getfilename("graphics", directory, 0, LOCATION_SYSTEM); + sprintf(filename, "%s%s%s", directory, "/", GRAPHICS_DEFAULT); + pdisplaygraphics = graphics_load(filename, 0); + + /* If we can't even load the default, use a curses based scheme */ + if(pdisplaygraphics == NULL) + pdisplaygraphics = graphics_load(NULL, 0); + } +} + +void graphics_delete(struct graphics* pgraphics) +{ + int i, j; + struct graphicssize* psize; + struct graphicssize* psizetmp; + struct shadow* pshadow; + struct shadow* pshadowtmp; + + for(i = 0; i < PIECE_MAX; i ++) + { + for(j = 0; j < IMAGE_MAX; j ++) + { + if(pgraphics->image[i][j] != NULL && !(pgraphics->image_flags[i] & GRAPHICS_CLONE)) + SDL_FreeSurface(pgraphics->image[i][j]); + } + } + + if(pgraphics->title != NULL) + free(pgraphics->title); + + psize = pgraphics->sizes; + while(psize != NULL) + { + psizetmp = psize; + psize = psize->next; + free(psizetmp); + } + + pshadow = pgraphics->shadows; + while(pshadow != NULL) + { + pshadowtmp = pshadow; + pshadow = pshadow->next; + free(pshadowtmp); + } + + free(pgraphics); +} + +void graphics_createfromfont(struct graphics* pgraphics) +{ + int piece; + struct SDL_Surface* psurface; + struct SDL_Surface* psurfacetmp; + SDL_Rect drect; + char buffer[4]; + int fg, bg, tg; + int size_x, size_y; + int reverse; + + /* Slightly smaller to ensure j's and g's fit within piece */ + font_set_size(pgraphics->size_y * 0.8); + + pgraphics->small_size_x = font_height_game; + pgraphics->small_size_y = font_height_game; + + if(pdisplaycolours == NULL) + return; + + /* Create pieces */ + for(piece = 0; piece < PIECE_MAX; piece ++) + { + size_x = pgraphics->size_x; + size_y = pgraphics->size_y; + + if(piece == PIECE_PLAYER_ONE || piece == PIECE_PLAYER_TWO) + size_x = pgraphics->size_x * 2; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + psurface = SDL_CreateRGBSurface(screen_flags, size_x, size_y, 32, 0xff000000, 0xff0000, 0xff00, 0xff); +#else + psurface = SDL_CreateRGBSurface(screen_flags, size_x, size_y, 32, 0xff, 0xff00, 0xff0000, 0xff000000); +#endif + SDL_FillRect(psurface, NULL, SDL_MapRGBA(psurface->format, 0, 0, 0, 255) ); + + fg = pdisplaycolours->foreground[piece]; + bg = pdisplaycolours->background[piece]; + reverse = pdisplaycolours->reverse[piece]; + + /* Player pieces are special. The swapped in piece always takes player + one's colours, which we force here */ + if(piece == PIECE_PLAYER_TWO) + { + fg = pdisplaycolours->foreground[PIECE_PLAYER_ONE]; + bg = pdisplaycolours->background[PIECE_PLAYER_ONE]; + reverse = pdisplaycolours->reverse[PIECE_PLAYER_ONE]; + } + + if(reverse) + { + tg = fg; fg = bg; bg = tg; + } + if(fg == -1) + fg = 0; + if(bg == -1 && (piece == PIECE_SPACE || isexplosion(piece))) + bg = 0; + + if(bg != -1) + { + drect.x = 0; + drect.y = 0; + drect.w = pgraphics->size_x; + drect.h = pgraphics->size_y; + SDL_FillRect(psurface, &drect, SDL_MapRGB(psurface->format, bg & 1 ? 255 : 0, bg & 2 ? 255 : 0, bg & 4 ? 255 : 0)); + } + sprintf(buffer, "%c", pdisplaycolours->character[piece]); + psurfacetmp = font_render(buffer, fg); + drect.x = (pgraphics->size_x - psurfacetmp->w) / 2; + drect.y = (pgraphics->size_y - psurfacetmp->h) / 2; + SDL_BlitSurface(psurfacetmp, NULL, psurface, &drect); + SDL_FreeSurface(psurfacetmp); + + /* Player pieces get a second image for when they're swapped out. + The swapped out piece always takes player two's colours. */ + if(piece == PIECE_PLAYER_ONE || piece == PIECE_PLAYER_TWO) + { + fg = pdisplaycolours->foreground[PIECE_PLAYER_TWO]; + bg = pdisplaycolours->background[PIECE_PLAYER_TWO]; + + if(pdisplaycolours->reverse[PIECE_PLAYER_TWO]) + { + tg = fg; fg = bg; bg = tg; + } + if(fg == -1) + fg = 0; + + if(bg != -1) + { + drect.x = pgraphics->size_x; + drect.y = 0; + drect.w = pgraphics->size_x; + drect.h = pgraphics->size_y; + SDL_FillRect(psurface, &drect, SDL_MapRGB(psurface->format, bg & 1 ? 255 : 0, bg & 2 ? 255 : 0, bg & 4 ? 255 : 0)); + } + sprintf(buffer, "%c", pdisplaycolours->character[piece]); + psurfacetmp = font_render(buffer, fg); + drect.x = pgraphics->size_x + ((pgraphics->size_x - psurfacetmp->w) / 2); + drect.y = (pgraphics->size_y - psurfacetmp->h) / 2; + SDL_BlitSurface(psurfacetmp, NULL, psurface, &drect); + SDL_FreeSurface(psurfacetmp); + + } + + if(bg == -1 || piece == PIECE_PLAYER_ONE || piece == PIECE_PLAYER_TWO) + pgraphics->image[piece][IMAGE_PIECE] = SDL_DisplayFormatAlpha(psurface); + else + pgraphics->image[piece][IMAGE_PIECE] = SDL_DisplayFormat(psurface); + SDL_FreeSurface(psurface); + + } + + /* Create small pieces */ + font_set_size(font_size_game); + + for(piece = 0; piece < PIECE_MAX; piece ++) + { + /* but only for the pieces we need */ + if(piece != PIECE_PLAYER_ONE && piece != PIECE_PLAYER_TWO && + piece != PIECE_STAR && piece != PIECE_DOOR) + continue; + + size_x = pgraphics->small_size_x; + size_y = pgraphics->small_size_y; + + if(piece == PIECE_PLAYER_ONE || piece == PIECE_PLAYER_TWO) + size_x = pgraphics->size_x * 2; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + psurface = SDL_CreateRGBSurface(screen_flags, size_x, size_y, 32, 0xff000000, 0xff0000, 0xff00, 0xff); +#else + psurface = SDL_CreateRGBSurface(screen_flags, size_x, size_y, 32, 0xff, 0xff00, 0xff0000, 0xff000000); +#endif + SDL_FillRect(psurface, NULL, SDL_MapRGBA(psurface->format, 0, 0, 0, 255) ); + + fg = pdisplaycolours->foreground[piece]; + bg = pdisplaycolours->background[piece]; + reverse = pdisplaycolours->reverse[piece]; + + /* Player pieces are special. The swapped in piece always takes player + one's colours, which we force here */ + if(piece == PIECE_PLAYER_TWO) + { + fg = pdisplaycolours->foreground[PIECE_PLAYER_ONE]; + bg = pdisplaycolours->background[PIECE_PLAYER_ONE]; + reverse = pdisplaycolours->reverse[PIECE_PLAYER_ONE]; + } + + if(reverse) + { + tg = fg; fg = bg; bg = tg; + } + if(fg == -1) + fg = 0; + if(bg == -1) + bg = 0; + + drect.x = 0; + drect.y = 0; + drect.w = font_height_game; + drect.h = font_height_game; + SDL_FillRect(psurface, &drect, SDL_MapRGB(psurface->format, bg & 1 ? 255 : 0, bg & 2 ? 255 : 0, bg & 4 ? 255 : 0)); + + sprintf(buffer, "%c", pdisplaycolours->character[piece]); + psurfacetmp = font_render(buffer, fg); + drect.x = (font_height_game - psurfacetmp->w) / 2; + drect.y = (psurface->h - psurfacetmp->h) / 2; + SDL_BlitSurface(psurfacetmp, NULL, psurface, &drect); + SDL_FreeSurface(psurfacetmp); + + /* Player pieces get a second image for when they're swapped out. + The swapped out piece always takes player two's colours. */ + if(piece == PIECE_PLAYER_ONE || piece == PIECE_PLAYER_TWO) + { + fg = pdisplaycolours->foreground[PIECE_PLAYER_TWO]; + bg = pdisplaycolours->background[PIECE_PLAYER_TWO]; + + if(pdisplaycolours->reverse[PIECE_PLAYER_TWO]) + { + tg = fg; fg = bg; bg = tg; + } + if(fg == -1) + fg = 0; + + if(bg != -1) + { + drect.x = font_height_game; + drect.y = 0; + drect.w = font_height_game; + drect.h = font_height_game; + SDL_FillRect(psurface, &drect, SDL_MapRGB(psurface->format, bg & 1 ? 255 : 0, bg & 2 ? 255 : 0, bg & 4 ? 255 : 0)); + } + sprintf(buffer, "%c", pdisplaycolours->character[piece]); + psurfacetmp = font_render(buffer, fg); + drect.x = font_height_game + ((font_height_game - psurfacetmp->w) / 2); + drect.y = (psurface->h - psurfacetmp->h) / 2; + SDL_BlitSurface(psurfacetmp, NULL, psurface, &drect); + SDL_FreeSurface(psurfacetmp); + + } + + if(bg == -1 || piece == PIECE_PLAYER_ONE || piece == PIECE_PLAYER_TWO) + pgraphics->image[piece][IMAGE_SMALL] = SDL_DisplayFormatAlpha(psurface); + else + pgraphics->image[piece][IMAGE_SMALL] = SDL_DisplayFormat(psurface); + SDL_FreeSurface(psurface); + + } +} + +struct menu* graphics_menu() +{ + DIR *pdir; + struct dirent *dentry; + struct menu* pmenu; + struct menuentry* pentry; + char directory[FILENAME_MAX]; + char filename[FILENAME_MAX]; + struct graphics* pgraphics; + int location; + + pmenu = menu_new(gettext("Graphics Schemes")); + + menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + menuentry_new(pmenu, gettext("Current graphics scheme:"), 0, MENU_NOTE); + + if(pdisplaygraphics == NULL) + menuentry_new(pmenu, gettext("** NONE **"), 0, MENU_NOTE | MENU_RIGHT); + else if(pdisplaygraphics->title == NULL) + menuentry_new(pmenu, gettext("[untitled graphics]"), 0, MENU_NOTE | MENU_RIGHT); + else if(pdisplaygraphics->flags & GRAPHICS_TRANSLATE) + menuentry_new(pmenu, gettext(pdisplaygraphics->title), 0, MENU_NOTE | MENU_RIGHT); + else + menuentry_new(pmenu, pdisplaygraphics->title, 0, MENU_NOTE | MENU_RIGHT); + + /* Global, then user */ + for(location = 1; location >= 0; location --) + { + getfilename("graphics", directory, 0, location); + + pdir = opendir(directory); + + if(pdir == NULL) + continue; + + while((dentry = readdir(pdir)) != NULL) + { + if(strcmp(dentry->d_name, ".") == 0) + continue; + if(strcmp(dentry->d_name, "..") == 0) + continue; + + sprintf(filename, "%s%s%s", directory, "/", dentry->d_name); + + if(isfile(filename) && strlen(filename) > 7 && strcmp(filename + strlen(filename) - 7, ".chroma") == 0) + { + pgraphics = graphics_load(filename, 1); + if(pgraphics != NULL) + { + if(pgraphics->title == NULL) + pentry = menuentry_newwithvalue(pmenu, gettext("[untitled graphics]"), 0, MENU_SORT, filename); + else if(pgraphics->flags & GRAPHICS_TRANSLATE) + pentry = menuentry_newwithvalue(pmenu, gettext(pgraphics->title), 0, MENU_SORT, filename); + else + pentry = menuentry_newwithvalue(pmenu, pgraphics->title, 0, MENU_SORT, filename); + + graphics_delete(pgraphics); + + if(strcmp(options_graphics, filename) == 0) + pmenu->entry_selected = pentry; + } + } + } + + closedir(pdir); + + menu_unsort(pmenu); + + if(location == 1) + menuentry_new(pmenu, "", 0, MENU_SPACE); + } + + menu_assignletters(pmenu); + + return pmenu; +} + +SDL_Surface *graphics_loadimage(char *filename) +{ + char fullfilename[FILENAME_MAX]; + char directory[FILENAME_MAX]; + + getfilename("graphics", directory, 0, LOCATION_SYSTEM); + sprintf(fullfilename, "%s%s%s", directory, "/", filename); + + return IMG_Load(fullfilename); +} + +struct menu* graphics_error(struct menu *pmenu, char *filename, struct parser *pparser, char *error) +{ + char buffer[256]; + + if(pmenu == NULL) + { + pmenu = menu_new(gettext("Graphics Errors")); + + menuentry_new(pmenu, gettext("Return to previous menu"), 'Q', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + } + + if(pparser != NULL) + sprintf(buffer, "%d: %s", pparser->line, error); + else + sprintf(buffer, "%s", error); + + fprintf(stderr, gettext("In file '%s':\n"), filename); + fprintf(stderr, "%s\n", buffer); + + menuentry_new(pmenu, buffer, 0, MENU_SORT); + + return pmenu; +} + +int graphics_translatecolour(char *text, int *red, int *green, int *blue, int *alpha) +{ + char buffer[8]; + + /* #rrggbb */ + if(strlen(text) == 7 && text[0] == '#') + { + strcpy(buffer, "0xff"); + buffer[2] = text[1]; buffer[3] = text[2]; *red = strtol(buffer, NULL, 0); + buffer[2] = text[3]; buffer[3] = text[4]; *green = strtol(buffer, NULL, 0); + buffer[2] = text[5]; buffer[3] = text[6]; *blue = strtol(buffer, NULL, 0); + *alpha = 255; + return 1; + } + + /* #rrggbbaa */ + if(strlen(text) == 9 && text[0] == '#') + { + strcpy(buffer, "0xff"); + buffer[2] = text[1]; buffer[3] = text[2]; *red = strtol(buffer, NULL, 0); + buffer[2] = text[3]; buffer[3] = text[4]; *green = strtol(buffer, NULL, 0); + buffer[2] = text[5]; buffer[3] = text[6]; *blue = strtol(buffer, NULL, 0); + buffer[2] = text[7]; buffer[3] = text[8]; *alpha = strtol(buffer, NULL, 0); + return 1; + } + + /* #rgb */ + if(strlen(text) == 4 && text[0] == '#') + { + strcpy(buffer, "0xff"); + buffer[2] = text[1]; buffer[3] = text[1]; *red = strtol(buffer, NULL, 0); + buffer[2] = text[2]; buffer[3] = text[2]; *green = strtol(buffer, NULL, 0); + buffer[2] = text[3]; buffer[3] = text[3]; *blue = strtol(buffer, NULL, 0); + *alpha = 255; + return 1; + } + + /* #rgba */ + if(strlen(text) == 5 && text[0] == '#') + { + strcpy(buffer, "0xff"); + buffer[2] = text[1]; buffer[3] = text[1]; *red = strtol(buffer, NULL, 0); + buffer[2] = text[2]; buffer[3] = text[2]; *green = strtol(buffer, NULL, 0); + buffer[2] = text[3]; buffer[3] = text[3]; *blue = strtol(buffer, NULL, 0); + buffer[2] = text[4]; buffer[3] = text[4]; *alpha = strtol(buffer, NULL, 0); + return 1; + } + + /* Couldn't make sense of it */ + return 0; +} + +void graphics_addimage(struct graphics* pgraphics, int piece, int type, SDL_Surface* psurface) +{ + SDL_Surface *psurfacetmp; + SDL_Rect drect; + + if(psurface == NULL) + return; + + if(piece >= 0 && piece < PIECE_MAX) + { + /* If this is the first image, create a new piece image */ + if(pgraphics->image[piece][type] == NULL) + { + if(psurface->flags & SDL_SRCALPHA) + pgraphics->image[piece][type] = SDL_DisplayFormatAlpha(psurface); + else + pgraphics->image[piece][type] = SDL_DisplayFormat(psurface); + } + else + { + /* Otherwise, create a larger piece image */ +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + psurfacetmp = SDL_CreateRGBSurface(screen_flags, pgraphics->image[piece][type]->w + psurface->w, pgraphics->image[piece][type]->h, 32, 0xff000000, 0xff0000, 0xff00, 0xff); +#else + psurfacetmp = SDL_CreateRGBSurface(screen_flags, pgraphics->image[piece][type]->w + psurface->w, pgraphics->image[piece][type]->h, 32, 0xff, 0xff00, 0xff0000, 0xff000000); +#endif + if(psurfacetmp == NULL) + fatal("Out of memory in graphics_addimage()"); + + SDL_SetAlpha(pgraphics->image[piece][type], 0, 0); + + /* Copy the old piece image into it */ + if(pgraphics->image_flags[piece] & GRAPHICS_KEY) + /* Copy as is; we'll deal with the keying later */ + SDL_SetAlpha(psurfacetmp, 0, 0); + else + SDL_SetAlpha(psurfacetmp, SDL_SRCALPHA, 255); + + SDL_BlitSurface(pgraphics->image[piece][type], NULL, psurfacetmp, NULL); + + /* Copy the new piece image into it */ + drect.x = pgraphics->image[piece][type]->w; + drect.y = 0; + drect.w = psurface->w; + drect.h = pgraphics->size_y; + + SDL_SetAlpha(psurface, 0, 0); + SDL_BlitSurface(psurface, NULL, psurfacetmp, &drect); + + /* Free the old piece image */ + SDL_FreeSurface(pgraphics->image[piece][type]); + + if(psurfacetmp->flags & SDL_SRCALPHA) + pgraphics->image[piece][type] = SDL_DisplayFormatAlpha(psurfacetmp); + else + pgraphics->image[piece][type] = SDL_DisplayFormat(psurfacetmp); + + SDL_FreeSurface(psurfacetmp); + + } + } +} + +int graphics_evaluate(struct graphics *pgraphics, char *text) +{ + int v, e; + + if(strcmp(text, "true") == 0) + return 1; + if(strcmp(text, "false") == 0) + return 0; + + if(strlen(text) > 2) + { + if(text[1] == '=') + { + switch(text[0]) + { + case 'x': + v = pgraphics->size_x; + break; + case 'y': + v = pgraphics->size_y; + break; + case 's': + v = pgraphics->small_size_x; + break; + case 't': + v = pgraphics->small_size_y; + break; + case 'l': + v = pgraphics->level; + break; + default: + return 0; + } + e = atoi(text + 2); + if(v == e) + return 1; + else + return 0; + } + } + + return 0; +} + +int graphics_evaluatesize(char *text, int base) +{ + if(strlen(text) > 0 && text[strlen(text) - 1] == '%') + return (int)(atof(text) * base / 100); + else + return atoi(text); +} + +struct graphics* graphics_load(char *filename, int partial) +{ + struct graphics* pgraphics; + struct graphicssize* psize; + struct graphicssize* psizetmp; + struct shadow* pshadow; + struct shadow* pshadowtmp; + struct parser* pparser; + struct menu* pmenu; + int i, j, k; + int state; + int piece; + int clone; + + int width, height, offset_x, offset_y; + int size_x, size_y; + + char basepath[FILENAME_MAX]; + char path[FILENAME_MAX]; + char file[FILENAME_MAX]; + char buffer[256]; + char c; + + SDL_Surface *psurface; + SDL_Surface *psurfacetmp; + SDL_Rect drect; + int imagetype; + int red, green, blue, alpha; + + int tg, fg, bg; + SDL_Rect rect; + int x, y, z, w, h; + int failed; + int flags; + + int shadow_flags[9] = + { + SHADOW_TOP_LEFT, SHADOW_TOP, SHADOW_TOP_RIGHT, + SHADOW_LEFT, SHADOW_MIDDLE, SHADOW_RIGHT, + SHADOW_BOTTOM_LEFT, SHADOW_BOTTOM, SHADOW_BOTTOM_RIGHT + }; + + if(filename != NULL && !isfile(filename)) + return NULL; + + pgraphics = (struct graphics*)malloc(sizeof(struct graphics)); + if(pgraphics == NULL) + fatal(gettext("Out of memory in graphics_load()")); + + /* Initialise graphics structure */ + pgraphics->title = NULL; + pgraphics->sizes = NULL; + pgraphics->shadows = NULL; + + pgraphics->size_x = 0; + pgraphics->size_y = 0; + pgraphics->small_size_x = 0; + pgraphics->small_size_y = 0; + pgraphics->levels = 0; + pgraphics->flags = 0; + + pgraphics->level = 0; + + for(i = 0; i < PIECE_MAX; i ++) + { + for(j = 0; j < IMAGE_MAX; j ++) + pgraphics->image[i][j] = NULL; + + pgraphics->image_flags[i] = 0; + pgraphics->shadow_flags[i] = 0; + pgraphics->shadow_z[i] = 0; + + for(j = 0; j < 10; j ++) + { + pgraphics->shadow_offset_x[i][j] = 0; + pgraphics->shadow_offset_y[i][j] = 0; + pgraphics->shadow_start_x[i][j] = 0; + pgraphics->shadow_start_y[i][j] = 0; + pgraphics->shadow_width[i][j] = 0; + pgraphics->shadow_height[i][j] = 0; + } + } + for(i = 0; i < 3; i ++) + { + pgraphics->background[i] = 0; + } + + /* Emergency default graphics scheme */ + if(filename == NULL) + { + graphics_createfromfont(pgraphics); + return pgraphics; + } + + /* Determine base directory */ + strcpy(basepath, filename); + for(i = strlen(filename); i >= 0; i --) + { + if(basepath[i] == '/') + { + basepath[i] = 0; + break; + } + } + strcpy(path, ""); + + piece = PIECE_UNKNOWN; + psurface = NULL; + pmenu = NULL; + failed = 0; + psize = NULL; + imagetype = 0; + w = 0; h = 0; z = 0; + flags = 0; + clone = PIECE_UNKNOWN; + x = 0; y = 0; + + /* Parse XML file */ + /* + + + title + + + + + + + + + + + + + + + + + + + + */ + + pparser = parser_new(filename); + if(pparser == NULL) + { + graphics_delete(pgraphics); + return NULL; + } + + enum{ + GRAPHICSPARSER_BAD, /* End of bad file */ + GRAPHICSPARSER_END, /* End of good file */ + GRAPHICSPARSER_OUTSIDE, /* Outside of */ + GRAPHICSPARSER_CHROMA, /* Inside */ + GRAPHICSPARSER_PIECES, /* Inside */ + GRAPHICSPARSER_PIECE, /* Inside */ + GRAPHICSPARSER_SIZES, /* Inside */ + GRAPHICSPARSER_SHADOWS, /* Inside */ + GRAPHICSPARSER_IF /* Inside failed */ + }; + + /* Another state machine! */ + state = GRAPHICSPARSER_OUTSIDE; + + while(state != GRAPHICSPARSER_BAD && state != GRAPHICSPARSER_END) + { + switch(parser_parse(pparser)) + { + case PARSER_END: + if(state == GRAPHICSPARSER_OUTSIDE) + state = GRAPHICSPARSER_BAD; + else + state = GRAPHICSPARSER_END; + break; + + case PARSER_ELEMENT_START: + switch(state) + { + case GRAPHICSPARSER_CHROMA: + if(parser_match(pparser, 0, "pieces")) + { + state = GRAPHICSPARSER_PIECES; + strcpy(path, ""); + } + if(parser_match(pparser, 0, "sizes")) + { + state = GRAPHICSPARSER_SIZES; + } + if(parser_match(pparser, 0, "shadows")) + { + state = GRAPHICSPARSER_SHADOWS; + } + break; + + case GRAPHICSPARSER_PIECES: + if(parser_match(pparser, 0, "piece")) + { + piece = PIECE_UNKNOWN; + clone = PIECE_UNKNOWN; + } + break; + + case GRAPHICSPARSER_PIECE: + if(parser_match(pparser, 0, "image")) + { + psurface = NULL; + imagetype = IMAGE_PIECE; + x = 0; + y = 0; + z = 0; + w = pgraphics->size_x; + h = pgraphics->size_y; + } + break; + + case GRAPHICSPARSER_SIZES: + if(parser_match(pparser, 0, "size")) + { + x = -1; y = -1; + flags = SIZE_PIECES | SIZE_SMALL; + + } + break; + + case GRAPHICSPARSER_SHADOWS: + if(parser_match(pparser, 0, "shadow")) + { + x = 0; y = 0; + } + break; + + default: + break; + } + break; + + case PARSER_ELEMENT_END: + + /* */ + if(parser_match(pparser, 0, "if") && failed > 0) + { + failed --; + if(failed == 0) + state -= GRAPHICSPARSER_IF; + } + + switch(state) + { + case GRAPHICSPARSER_CHROMA: + /* If we're only partially loading the file, end parsing at */ + /* */ + if(parser_match(pparser, 0, "head")) + { + if(partial) + state = GRAPHICSPARSER_END; + /* If we haven't found a size... */ + if(!(pgraphics->flags & GRAPHICS_CURSES) && pgraphics->size_x == 0 && pgraphics->size_y == 0) + + { + pmenu = graphics_error(pmenu, filename, NULL, gettext("No size specified")); + /* Make it appear in the menu, but not be loadable */ + if(partial) + state = GRAPHICSPARSER_END; + else + state = GRAPHICSPARSER_BAD; + } + } + + /* */ + if(parser_match(pparser, 0, "curses")) + pgraphics->flags |= GRAPHICS_CURSES; + + break; + + case GRAPHICSPARSER_PIECES: + if(parser_match(pparser, 0, "pieces")) + state = GRAPHICSPARSER_CHROMA; + break; + + case GRAPHICSPARSER_PIECE: + if(parser_match(pparser, 0, "piece")) + { + if(piece != PIECE_UNKNOWN && pgraphics->image[piece][IMAGE_PIECE] != NULL) + { + /* Key transparency */ + if(pgraphics->image_flags[piece] & GRAPHICS_KEY) + { + SDL_SetAlpha(pgraphics->image[piece][IMAGE_PIECE], SDL_SRCALPHA, 255); + SDL_SetColorKey(pgraphics->image[piece][IMAGE_PIECE], SDL_SRCCOLORKEY, SDL_MapRGB(pgraphics->image[piece][IMAGE_PIECE]->format, red, green, blue)); + + if(pgraphics->image[piece][IMAGE_SMALL] != NULL) + { + SDL_SetAlpha(pgraphics->image[piece][IMAGE_SMALL], SDL_SRCALPHA, 255); + SDL_SetColorKey(pgraphics->image[piece][IMAGE_SMALL], SDL_SRCCOLORKEY, SDL_MapRGB(pgraphics->image[piece][IMAGE_SMALL]->format, red, green, blue)); + } + } + } + + state = GRAPHICSPARSER_PIECES; + } + if(parser_match(pparser, 0, "image") && psurface != NULL) + { + /* If this is the first shadow image for this + piece, make a note of its size and offset for + later use. */ + if(imagetype == IMAGE_SHADOW && piece >= 0 && pgraphics->image[piece][IMAGE_SHADOW] == NULL) + { + pgraphics->shadow_z[piece] = z; + pgraphics->shadow_offset_x[piece][9] = x; + pgraphics->shadow_offset_y[piece][9] = y; + pgraphics->shadow_width[piece][9] = psurface->w; + pgraphics->shadow_height[piece][9] = psurface->h; + } + graphics_addimage(pgraphics, piece, imagetype, psurface); + SDL_FreeSurface(psurface); + } + if(parser_match(pparser, 0, "clone") && piece >= 0) + { + if(clone != PIECE_UNKNOWN) + { + if(!(pgraphics->image_flags[clone] & GRAPHICS_CLONE) && clone != piece) + { + pgraphics->image_flags[piece] |= GRAPHICS_CLONE; + pgraphics->clone[piece] = clone; + } + else + pmenu = graphics_error(pmenu, filename, pparser, gettext("Clone loop")); + } + else + pmenu = graphics_error(pmenu, filename, pparser, gettext("Invalid piece for clone")); + } + break; + + case GRAPHICSPARSER_SIZES: + /* : process available sizes */ + if(parser_match(pparser, 0, "sizes")) + { + /* Move out of into */ + state = GRAPHICSPARSER_CHROMA; + + /* Find an appropriate size for the pieces */ + /* First, is there an exact match? */ + pgraphics->size_x = 0; + pgraphics->size_y = 0; + psize = pgraphics->sizes; + while(psize != NULL) + { + if(psize->x == options_sdl_size_x && psize->y == options_sdl_size_y && psize->flags & SIZE_PIECES) + { + pgraphics->size_x = psize->x; + pgraphics->size_y = psize->y; + } + psize = psize->next; + } + /* If none matches, choose the largest that will + allow the level to be fully displayed */ + if(pgraphics->size_y == 0) + { + psize = pgraphics->sizes; + while(psize != NULL) + { + size_x = 32; + size_y = 24; + if(plevelcurrent != NULL) + { + size_x = plevelcurrent->size_x; + size_y = plevelcurrent->size_y; +#ifdef XOR_COMPATIBILITY + if(plevelcurrent->mode == MODE_XOR && options_xor_display) + { + size_x = 8; + size_y = 8; + } +#endif + } + + if(psize->y > pgraphics->size_y && psize->x <= screen_width / size_x && psize->y <= screen_height / size_y && psize->flags & SIZE_PIECES) + { + pgraphics->size_x = psize->x; + pgraphics->size_y = psize->y; + } + psize = psize->next; + } + } + /* If still no match, use the smallest */ + if(pgraphics->size_y == 0) + { + pgraphics->size_x = SIZE_HUGE; + pgraphics->size_y = SIZE_HUGE; + psize = pgraphics->sizes; + while(psize != NULL) + { + if(psize->y < pgraphics->size_y && psize->flags & SIZE_PIECES) + { + pgraphics->size_x = psize->x; + pgraphics->size_y = psize->y; + } + psize = psize->next; + } + } + if(pgraphics->size_y == SIZE_HUGE) + { + /* Something failed badly */ + /* An error will be generated at */ + pgraphics->size_x = 0; + pgraphics->size_y = 0; + } + + /* Find an appropriate size for the small pieces */ + pgraphics->small_size_x = 0; + pgraphics->small_size_y = 0; + psize = pgraphics->sizes; + while(psize != NULL) + { + if(psize->y < font_height_game && psize->flags & SIZE_SMALL) + { + pgraphics->small_size_x = psize->x; + pgraphics->small_size_y = psize->y; + } + psize = psize->next; + } + /* If no size was small enough, use the smallest */ + if(pgraphics->small_size_y == 0) + { + pgraphics->small_size_x = SIZE_HUGE; + pgraphics->small_size_y = SIZE_HUGE; + psize = pgraphics->sizes; + while(psize != NULL) + { + if(psize->y < pgraphics->small_size_y && psize->flags & SIZE_SMALL) + { + pgraphics->small_size_x = psize->x; + pgraphics->small_size_y = psize->y; + } + psize = psize->next; + } + if(pgraphics->small_size_y == SIZE_HUGE) + { + /* Something failed badly! */ + pgraphics->small_size_x = 0; + pgraphics->small_size_y = 0; + } + } + } + + /* : Store this size in the list of sizes */ + if(parser_match(pparser, 0, "size")) + { + if(x != -1 && y != -1) + { + psize = malloc(sizeof(struct graphicssize)); + if(psize == NULL) + fatal(gettext("Out of memory in graphics_load()")); + psize->x = x; + psize->y = y; + psize->flags = flags; + psize->next = NULL; + + if(pgraphics->sizes == NULL) + pgraphics->sizes = psize; + else + { + psizetmp = pgraphics->sizes; + while(psizetmp->next != NULL) + psizetmp = psizetmp->next; + psizetmp->next = psize; + } + } + else + pmenu = graphics_error(pmenu, filename, pparser, gettext("Invalid size")); + } + break; + + case GRAPHICSPARSER_SHADOWS: + if(parser_match(pparser, 0, "shadow")) + { + if(x >= -1 && x <= 1 && y >= -1 && y <= 1) + { + pshadow = malloc(sizeof(struct shadow)); + if(pshadow == NULL) + fatal(gettext("Out of memory in graphics_load()")); + pshadow->x = x; + pshadow->y = y; + pshadow->next = NULL; + + if(pgraphics->shadows == NULL) + pgraphics->shadows = pshadow; + else + { + pshadowtmp = pgraphics->shadows; + while(pshadowtmp->next != NULL) + pshadowtmp = pshadowtmp->next; + pshadowtmp->next = pshadow; + } + } + else + pmenu = graphics_error(pmenu, filename, pparser, gettext("Invalid shadow")); + } + if(parser_match(pparser, 0, "shadows")) + { + state = GRAPHICSPARSER_CHROMA; + } + break; + + default: + break; + } + + break; + + case PARSER_CONTENT: + switch(state) + { + case GRAPHICSPARSER_CHROMA: + if(parser_match(pparser, 1, "title")) + { + pgraphics->title = malloc(strlen(parser_text(pparser, 0)) + 1); + if(pgraphics->title == NULL) + fatal(gettext("Out of memory in graphics_load()")); + strcpy(pgraphics->title, parser_text(pparser, 0)); + } + + break; + + default: + break; + } + break; + + case PARSER_ATTRIBUTE: + if(parser_match(pparser, 2, "if") && parser_match(pparser, 1, "condition")) + { + if(state >= GRAPHICSPARSER_IF) + failed ++; + else + { + if(!graphics_evaluate(pgraphics, parser_text(pparser, 0))) + { + state += GRAPHICSPARSER_IF; + failed ++; + } + } + } + + switch(state) + { + case GRAPHICSPARSER_OUTSIDE: + if(parser_match(pparser, 2, "chroma") && parser_match(pparser, 1, "type")) + { + if(parser_match(pparser, 0, "graphics")) + state = GRAPHICSPARSER_CHROMA; + } + break; + + case GRAPHICSPARSER_CHROMA: + if(parser_match(pparser, 2, "chroma") && parser_match(pparser, 1, "hidden")) + { + if(parser_match(pparser, 0, "yes")) + { + if(partial && !(options_debug & DEBUG_HIDDEN)) + state = GRAPHICSPARSER_BAD; + } + } + if(parser_match(pparser, 2, "title") && parser_match(pparser, 1, "translate")) + { + if(parser_match(pparser, 0, "yes")) + pgraphics->flags |= GRAPHICS_TRANSLATE; + } + if(parser_match(pparser, 2, "background") && (parser_match(pparser, 1, "colour") || parser_match(pparser, 1, "color"))) + { + if(graphics_translatecolour(parser_text(pparser,0), &red, &green, &blue, &alpha)) + { + pgraphics->background[0] = red; + pgraphics->background[1] = green; + pgraphics->background[2] = blue; + pgraphics->flags |= GRAPHICS_BACKGROUND; + + } + else + pmenu = graphics_error(pmenu, filename, pparser, gettext("Invalid colour")); + } + + break; + + case GRAPHICSPARSER_PIECES: + if(parser_match(pparser, 2, "pieces") && parser_match(pparser, 1, "path")) + strcpy(path, parser_text(pparser, 0)); + + if(parser_match(pparser, 2, "pieces") && parser_match(pparser, 1, "levels")) + { + pgraphics->levels = atoi(parser_text(pparser, 0)); + if(pgraphics->levels > 1) + { + if(options_graphic_level != 0) + pgraphics->level = options_graphic_level % (pgraphics->levels + 1); + else + { + if(plevelcurrent != NULL && plevelcurrent->level != 0) + pgraphics->level = plevelcurrent->level; + else + pgraphics->level = 1; + } + } + } + + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "name")) + { + for(i = 0; i < PIECE_UNKNOWN; i ++) + { + if(strcasecmp(parser_text(pparser, 0), piece_name[i]) == 0) + piece = i; + } + if(piece != PIECE_UNKNOWN) + state = GRAPHICSPARSER_PIECE; + else + pmenu = graphics_error(pmenu, filename, pparser, gettext("Invalid piece name")); + } + break; + + case GRAPHICSPARSER_PIECE: + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "bevel")) + { + if(strcmp(parser_text(pparser, 0), "piece") == 0) + pgraphics->image_flags[piece] |= GRAPHICS_BEVEL; + else if(strcmp(parser_text(pparser, 0), "shadow") == 0) + pgraphics->image_flags[piece] |= GRAPHICS_BEVEL_SHADOW; + else if(strcmp(parser_text(pparser, 0), "piece shadow") == 0) + pgraphics->image_flags[piece] |= GRAPHICS_BEVEL | GRAPHICS_BEVEL_SHADOW; + else if(strcmp(parser_text(pparser, 0), "16") == 0) + pgraphics->image_flags[piece] |= GRAPHICS_BEVEL16; + else + pmenu = graphics_error(pmenu, filename, pparser, gettext("Invalid bevel type")); + } + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "mover")) + pgraphics->image_flags[piece] |= GRAPHICS_MOVER; + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "random")) + pgraphics->image_flags[piece] |= GRAPHICS_RANDOM; + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "animate")) + pgraphics->image_flags[piece] |= GRAPHICS_ANIMATE; + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "level")) + pgraphics->image_flags[piece] |= GRAPHICS_LEVEL; + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "tile")) + pgraphics->image_flags[piece] |= GRAPHICS_TILE; + if(parser_match(pparser, 2, "piece") && parser_match(pparser, 1, "scale")) + pgraphics->image_flags[piece] |= GRAPHICS_SCALE; + + /* small_size_x; + h = pgraphics->small_size_y; + imagetype = IMAGE_SMALL; + } + } + + /* size_x); + if(parser_match(pparser, 2, "image") && parser_match(pparser, 1, "y")) + y = graphics_evaluatesize(parser_text(pparser, 0), pgraphics->size_y); + if(parser_match(pparser, 2, "image") && parser_match(pparser, 1, "z")) + z = atoi(parser_text(pparser, 0)); + if(parser_match(pparser, 2, "image") && (parser_match(pparser, 1, "w") || parser_match(pparser, 1, "width"))) + w = graphics_evaluatesize(parser_text(pparser, 0), pgraphics->size_x); + if(parser_match(pparser, 2, "image") && (parser_match(pparser, 1, "h") || parser_match(pparser, 1, "height"))) + h = graphics_evaluatesize(parser_text(pparser, 0), pgraphics->size_y); + + /* Create solid colour image */ + if(parser_match(pparser, 2, "image") && (parser_match(pparser, 1, "colour") || parser_match(pparser, 1, "color"))) + { + if(graphics_translatecolour(parser_text(pparser,0), &red, &green, &blue, &alpha)) + { +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + psurface = SDL_CreateRGBSurface(screen_flags, w, h, 32, 0xff000000, 0xff0000, 0xff00, 0xff); +#else + psurface = SDL_CreateRGBSurface(screen_flags, w, h, 32, 0xff, 0xff00, 0xff0000, 0xff000000); + +#endif + if(alpha == 255) + { + SDL_SetAlpha(psurface, 0, 0); + SDL_FillRect(psurface, NULL, SDL_MapRGB(psurface->format, red, green, blue)); + } + else + { + SDL_FillRect(psurface, NULL, SDL_MapRGBA(psurface->format, red, green, blue, alpha)); + } + } + else + pmenu = graphics_error(pmenu, filename, pparser, gettext("Invalid colour")); + } + + /* Load file from image */ + if(parser_match(pparser, 2, "image") && parser_match(pparser, 1, "file")) + { + /* Construct pathname */ + if(strcmp(path, "") == 0) + sprintf(file, "%s/", basepath); + else + sprintf(file, "%s/%s/", basepath, path); + + /* Substitute %s as necessary */ + j = strlen(file); + for(i = 0; i <= strlen(parser_text(pparser, 0)); i ++) + { + c = pparser->stack[pparser->depth - 1][i]; + if(c == '%') + { + i ++; + c = pparser->stack[pparser->depth - 1][i]; + file[j] = 0; + switch(c) + { + case '%': + strcat(file, "%"); + break; + case 'x': + sprintf(buffer, "%d", imagetype == IMAGE_SMALL ? pgraphics->small_size_x : pgraphics->size_x); + strcat(file, buffer); + break; + case 'y': + sprintf(buffer, "%d", imagetype == IMAGE_SMALL ? pgraphics->small_size_y : pgraphics->size_y); + strcat(file, buffer); + break; + case 'l': + if(pgraphics->levels != 0) + sprintf(buffer, "%d", pgraphics->level); + else + sprintf(buffer, "%d", 0); + strcat(file, buffer); + break; + default: + sprintf(buffer, "%%%c", c); + strcat(file, buffer); + break; + } + j = strlen(file); + } + else + file[j ++ ] = c; + } + + /* Load the file */ + if(isfile(file)) + psurface = IMG_Load(file); + else + { + sprintf(buffer, gettext("Invalid filename '%s'"), file); + pmenu = graphics_error(pmenu, filename, pparser, buffer); + } + if(psurface != NULL && (psurface->w != w || psurface->h != h) && (pgraphics->image_flags[piece] & GRAPHICS_SCALE)) + { + psurface = graphics_scaleimage(psurface, w, h); + + } + } + + /* Key transparency */ + if(parser_match(pparser, 2, "image") && parser_match(pparser, 1, "key")) + { + /* Store values in red, green, blue for use later */ + if(graphics_translatecolour(parser_text(pparser,0), &red, &green, &blue, &alpha)) + { + pgraphics->image_flags[piece] |= GRAPHICS_KEY; + } + else + pmenu = graphics_error(pmenu, filename, pparser, gettext("Invalid colour")); + } + + if(parser_match(pparser, 2, "clone") && parser_match(pparser, 1, "piece")) + { + for(i = 0; i < PIECE_UNKNOWN; i ++) + { + if(strcasecmp(parser_text(pparser, 0), piece_name[i]) == 0) + clone = i; + } + } + break; + + case GRAPHICSPARSER_SIZES: + if(parser_match(pparser, 2, "size") && parser_match(pparser, 1, "x")) + x = atoi(parser_text(pparser, 0)); + if(parser_match(pparser, 2, "size") && parser_match(pparser, 1, "y")) + y = atoi(parser_text(pparser, 0)); + if(parser_match(pparser, 2, "size") && parser_match(pparser, 1, "pieces")) + { + if(strcasecmp(parser_text(pparser, 0), "yes") == 0) + flags |= SIZE_PIECES; + if(strcasecmp(parser_text(pparser, 0), "no") == 0) + flags &= ~SIZE_PIECES; + } + if(parser_match(pparser, 2, "size") && parser_match(pparser, 1, "small")) + { + if(strcasecmp(parser_text(pparser, 0), "yes") == 0) + flags |= SIZE_SMALL; + if(strcasecmp(parser_text(pparser, 0), "no") == 0) + flags &= ~SIZE_SMALL; + } + break; + + case GRAPHICSPARSER_SHADOWS: + if(parser_match(pparser, 2, "shadow") && parser_match(pparser, 1, "x")) + x = atoi(parser_text(pparser, 0)); + if(parser_match(pparser, 2, "shadow") && parser_match(pparser, 1, "y")) + y = atoi(parser_text(pparser, 0)); + break; + + default: + break; + } + + break; + + case PARSER_ERROR: + pmenu = graphics_error(pmenu, filename, pparser, parser_text(pparser, 0)); + break; + + default: + break; + } + } + + parser_delete(pparser); + + /* If we failed to find , this isn't a valid graphics file */ + if(state == GRAPHICSPARSER_BAD) + { + graphics_delete(pgraphics); + return NULL; + } + + if(partial) + return pgraphics; + + /* If curses emulation, create graphics from the font */ + if(pgraphics->flags & GRAPHICS_CURSES) + graphics_createfromfont(pgraphics); + + /* Next, perform a sanity check on the graphics */ + + /* Patch up any pieces without an image with a random one */ + for(i = 0; i < PIECE_MAX; i ++) + { + if(pgraphics->image[i][IMAGE_PIECE] == NULL && !(pgraphics->image_flags[i] & GRAPHICS_CLONE)) + { +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + psurface = SDL_CreateRGBSurface(screen_flags, pgraphics->size_x, pgraphics->size_y, 32, 0xff000000, 0xff0000, 0xff00, 0xff); +#else + psurface = SDL_CreateRGBSurface(screen_flags, pgraphics->size_x, pgraphics->size_y, 32, 0xff, 0xff00, 0xff0000, 0xff000000); +#endif + + fg = pdisplaycolours->foreground[i]; + bg = pdisplaycolours->background[i]; + + if(bg == -1) + bg = 0; + if(fg == -1) + fg = 7; + + if(pdisplaycolours->reverse[i]) + { + tg = fg; fg = bg; bg = tg; + } + + SDL_FillRect(psurface, NULL, SDL_MapRGB(psurface->format, bg & 1 ? 255 : 0, bg & 2 ? 255 : 0, bg & 4 ? 255 : 0)); + sprintf(buffer, "%c", pdisplaycolours->character[i]); + + psurfacetmp = font_render(buffer, fg); + drect.x = (psurface->w - psurfacetmp->w) / 2; + drect.y = (psurface->h - psurfacetmp->h) / 2; + SDL_BlitSurface(psurfacetmp, NULL, psurface, &drect); + SDL_FreeSurface(psurfacetmp); + + pgraphics->image[i][IMAGE_PIECE] = SDL_DisplayFormat(psurface); + SDL_FreeSurface(psurface); + } + } + + /* Set clones */ + for(i = 0; i < PIECE_MAX; i ++) + { + if(pgraphics->image_flags[i] & GRAPHICS_CLONE) + { + x = pgraphics->clone[i]; + pgraphics->image[i][IMAGE_PIECE] = pgraphics->image[x][IMAGE_PIECE]; + + pgraphics->image[i][IMAGE_SHADOW] = pgraphics->image[x][IMAGE_SHADOW]; + pgraphics->shadow_width[i][9] = pgraphics->shadow_width[x][9]; + pgraphics->shadow_height[i][9] = pgraphics->shadow_height[x][9]; + pgraphics->shadow_offset_x[i][9] = pgraphics->shadow_offset_x[x][9]; + pgraphics->shadow_offset_y[i][9] = pgraphics->shadow_offset_y[x][9]; + } + } + + /* Bevelling requires five images */ + if(pgraphics->image_flags[PIECE_SPACE] & GRAPHICS_BEVEL) + { + if(pgraphics->image[PIECE_SPACE][IMAGE_PIECE]->w < pgraphics->size_x * 5) + { + pgraphics->image_flags[PIECE_SPACE] ^= GRAPHICS_BEVEL; + sprintf(buffer, gettext("%s bevelling requires five images"), piece_name[PIECE_SPACE]); + pmenu = graphics_error(pmenu, filename, NULL, buffer); + } + } + if(pgraphics->image_flags[PIECE_WALL] & GRAPHICS_BEVEL) + { + if(pgraphics->image[PIECE_WALL][IMAGE_PIECE]->w < pgraphics->size_x * 5) + { + pgraphics->image_flags[PIECE_WALL] ^= GRAPHICS_BEVEL; + sprintf(buffer, gettext("%s bevelling requires five images"), piece_name[PIECE_WALL]); + pmenu = graphics_error(pmenu, filename, NULL, buffer); + } + } + + if(pgraphics->image_flags[PIECE_WALL] & GRAPHICS_BEVEL_SHADOW) + { + if(pgraphics->image[PIECE_WALL][IMAGE_SHADOW]->w < pgraphics->size_x * 5) + { + pgraphics->image_flags[PIECE_WALL] ^= GRAPHICS_BEVEL_SHADOW; + sprintf(buffer, gettext("%s bevelling requires five images"), piece_name[PIECE_WALL]); + pmenu = graphics_error(pmenu, filename, NULL, buffer); + } + } + + /* Create cursor */ +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + psurface = SDL_CreateRGBSurface(screen_flags, pgraphics->size_x, pgraphics->size_y, 32, 0xff000000, 0xff0000, 0xff00, 0xff); +#else + psurface = SDL_CreateRGBSurface(screen_flags, pgraphics->size_x, pgraphics->size_y, 32, 0xff, 0xff00, 0xff0000, 0xff000000); +#endif + i = pgraphics->size_x / 16; + if(i < 1) + i = 1; + rect.x = i * 1; rect.y = i * 1; rect.w = pgraphics->size_x - i * 2; rect.h = pgraphics->size_y - i * 2; + SDL_FillRect(psurface, &rect, SDL_MapRGB(psurface->format, 0, 0, 0)); + rect.x = i * 2; rect.y = i * 2; rect.w = pgraphics->size_x - i * 4; rect.h = pgraphics->size_y - i * 4; + SDL_FillRect(psurface, &rect, SDL_MapRGB(psurface->format, 255, 255, 255)); + rect.x = i * 3; rect.y = i * 3; rect.w = pgraphics->size_x - i * 6; rect.h = pgraphics->size_y - i * 6; + SDL_FillRect(psurface, &rect, SDL_MapRGB(psurface->format, 0, 0, 0)); + rect.x = i * 4; rect.y = i * 4; rect.w = pgraphics->size_x - i * 8; rect.h = pgraphics->size_y - i * 8; + SDL_FillRect(psurface, &rect, SDL_MapRGBA(psurface->format, 0, 0, 0, 64)); + pgraphics->image[PIECE_CURSOR][IMAGE_PIECE] = psurface; + + /* Calculate quadrants for shadow images */ + for(i = 0; i < PIECE_MAX; i ++) + { + if(pgraphics->image[i][IMAGE_SHADOW] != NULL) + { + if(pgraphics->shadow_z[i] != 0) + pgraphics->flags |= GRAPHICS_ZORDER; + + width = pgraphics->shadow_width[i][9]; + height = pgraphics->shadow_height[i][9]; + offset_x = pgraphics->shadow_offset_x[i][9]; + offset_y = pgraphics->shadow_offset_y[i][9]; + + for(j = 0; j < 3; j ++) + { + for(k = 0; k < 3; k ++) + { + x = (j - 1) * pgraphics->size_x - offset_x; + y = (k - 1) * pgraphics->size_y - offset_y; + + /* Does the shadow fall into this square? */ + if(x > -(pgraphics->size_x) && x < width && y > -(pgraphics->size_y) && y < height) + { + if(x >= 0) + { + pgraphics->shadow_start_x[i][j+k*3]= x; + pgraphics->shadow_offset_x[i][j+k*3] = 0; + + if(x + pgraphics->size_x > width) + pgraphics->shadow_width[i][j+k*3] = width - x; + else + pgraphics->shadow_width[i][j+k*3] = pgraphics->size_x; + } + else + { + pgraphics->shadow_start_x[i][j+k*3] = 0; + pgraphics->shadow_offset_x[i][j+k*3] = -x; + + pgraphics->shadow_width[i][j+k*3] = pgraphics->size_x + x; + + } + + if(y >= 0) + { + pgraphics->shadow_start_y[i][j+k*3]= y; + pgraphics->shadow_offset_y[i][j+k*3] = 0; + + if(y + pgraphics->size_y > height) + pgraphics->shadow_height[i][j+k*3] = height - y; + else + pgraphics->shadow_height[i][j+k*3] = pgraphics->size_y; + } + else + { + pgraphics->shadow_start_y[i][j+k*3] = 0; + pgraphics->shadow_offset_y[i][j+k*3] = -y; + + pgraphics->shadow_height[i][j+k*3] = pgraphics->size_y + y; + } + + pgraphics->shadow_flags[i] |= shadow_flags[j+k*3]; + } + } + } + } + } + + /* Calcuate flags for shadows */ + pshadow = pgraphics->shadows; + while(pshadow != NULL) + { + pshadow->flag = shadow_flags[(pshadow->x + 1) + 3 * (pshadow->y + 1)]; + pshadow->shadow = (1 + pshadow->x) + 3 * (1 + pshadow->y); + pshadow->nextordered = pshadow->next; + pshadow = pshadow->next; + } + + /* Display any errors that have arisen */ + if(pmenu != NULL) + { + menu_process(pmenu); + menu_delete(pmenu); + } + + return pgraphics; +} + +void graphics_reload() +{ + struct graphics *pgraphicstmp; + int reload; + + /* Fixed size, so no automatic resizing */ + if(options_graphic_level != pdisplaygraphics->level) + reload = 1; + else if(options_sdl_size_x != 0 || options_sdl_size_y != 0) + reload = 0; + else + { + /* Partially load the graphics again and see if they're different */ + pgraphicstmp = graphics_load(options_graphics, 1); + + reload = 0; + if(pgraphicstmp == NULL || pdisplaygraphics == NULL || + pdisplaygraphics->size_x != pgraphicstmp->size_x || + pdisplaygraphics->size_y != pgraphicstmp->size_y || + pdisplaygraphics->small_size_x != pgraphicstmp->small_size_x || + pdisplaygraphics->small_size_y != pgraphicstmp->small_size_y) + reload = 1; + + if(pgraphicstmp != NULL) + graphics_delete(pgraphicstmp); + } + + if(reload) + graphics_init(); +} + +SDL_Surface *graphics_scaleimage(SDL_Surface* psurface, int width, int height) +{ + SDL_Surface* pnew; + Uint32 *src; + Uint32 *dst; + SDL_Color *colour; + int i, j; + Uint8 r, g, b, a; + +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + pnew = SDL_CreateRGBSurface(screen_flags, width, height, 32, 0xff000000, 0xff0000, 0xff00, 0xff); +#else + pnew = SDL_CreateRGBSurface(screen_flags, width, height, 32, 0xff, 0xff00, 0xff0000, 0xff000000); +#endif + + SDL_SetAlpha(pnew, 0, 0); + + /* This is probably not an optimal way of doing this! */ + for(j = 0; j < height; j ++) + { + for(i = 0; i < width; i ++) + { + src = psurface->pixels + + (j * psurface->h / height) * psurface->pitch + + (i * psurface->w / width) * psurface->format->BytesPerPixel; + dst = pnew->pixels + + j * pnew->pitch + + i * pnew->format->BytesPerPixel; + if(psurface->format->BitsPerPixel == 8) + { + colour = &(psurface->format->palette->colors[(Uint8)*src]); +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + *dst = colour->r * 0x1000000 + colour->g * 0x10000 + colour->b * 0x100 + 0xff; +#else + *dst = colour->r + colour->g * 0x100 + colour->b * 0x10000 + 0xff000000; +#endif + } + else + { + SDL_GetRGBA(*src, psurface->format, &r, &g, &b, &a); +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + *dst = r * 0x1000000 + g * 0x10000 + b * 0x100 + a; +#else + *dst = r + g * 0x100 + b * 0x10000 + a * 0x10000000; +#endif + } + } + } + + SDL_FreeSurface(psurface); + + return pnew; +} diff --git a/graphics.h b/graphics.h new file mode 100644 index 0000000..8f98509 --- /dev/null +++ b/graphics.h @@ -0,0 +1,130 @@ +/* + graphics.h + + Copyright (C) 2010-2019 Amf + + 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 GRAPHICS_DEFAULT "chroma-zen.chroma" + +/* Flags for pieces */ +#define GRAPHICS_BEVEL 1 +#define GRAPHICS_BEVEL_SHADOW 2 +#define GRAPHICS_BEVEL16 4 +#define GRAPHICS_RANDOM 8 +#define GRAPHICS_KEY 16 +#define GRAPHICS_MOVER 32 +#define GRAPHICS_TILE 64 +#define GRAPHICS_ANIMATE 128 +#define GRAPHICS_LEVEL 256 +#define GRAPHICS_CLONE 512 +#define GRAPHICS_SCALE 1024 + +/* Flags for set */ +#define GRAPHICS_CURSES 1 +#define GRAPHICS_ZORDER 2 +#define GRAPHICS_BACKGROUND 4 +#define GRAPHICS_TRANSLATE 8 + +#define BEVEL_BASE 0x10000 +#define BEVEL_L (BEVEL_BASE * 1) +#define BEVEL_R (BEVEL_BASE * 2) +#define BEVEL_U (BEVEL_BASE * 4) +#define BEVEL_D (BEVEL_BASE * 8) +#define BEVEL_TL (BEVEL_BASE * 16) +#define BEVEL_TR (BEVEL_BASE * 32) +#define BEVEL_BL (BEVEL_BASE * 64) +#define BEVEL_BR (BEVEL_BASE * 128) +#define BEVEL_ALL (BEVEL_BASE * 255) + +#define SHADOW_BASE 0x1000000 +#define SHADOW_TOP_LEFT 1 +#define SHADOW_TOP 2 +#define SHADOW_TOP_RIGHT 4 +#define SHADOW_LEFT 8 +#define SHADOW_MIDDLE 16 +#define SHADOW_RIGHT 32 +#define SHADOW_BOTTOM_LEFT 64 +#define SHADOW_BOTTOM 128 +#define SHADOW_BOTTOM_RIGHT 256 + +#define IMAGE_PIECE 0 +#define IMAGE_SHADOW 1 +#define IMAGE_SMALL 2 +#define IMAGE_MAX 3 + +#define SIZE_PIECES 1 +#define SIZE_SMALL 2 + +struct graphicssize +{ + int x; + int y; + int flags; + struct graphicssize *next; +}; + +struct shadow +{ + int x; + int y; + int z; + int p; + int flag; + int shadow; + struct shadow *next; + struct shadow *nextordered; + struct shadow *previousordered; +}; + + +struct graphics +{ + int size_x; + int size_y; + int small_size_x; + int small_size_y; + int flags; + char *title; + int background[3]; + int level; + int levels; + + int image_flags[PIECE_MAX]; + SDL_Surface *image[PIECE_MAX][3]; + + int clone[PIECE_MAX]; + int shadow_z[PIECE_MAX]; + int shadow_offset_x[PIECE_MAX][10]; + int shadow_offset_y[PIECE_MAX][10]; + int shadow_start_x[PIECE_MAX][10]; + int shadow_start_y[PIECE_MAX][10]; + int shadow_width[PIECE_MAX][10]; + int shadow_height[PIECE_MAX][10]; + int shadow_flags[PIECE_MAX]; + + struct graphicssize *sizes; + struct shadow *shadows; + +}; + +void graphics_init(); +struct graphics* graphics_load(char *filename, int partial); +void graphics_delete(struct graphics*); +struct menu* graphics_menu(); +SDL_Surface *graphics_loadimage(char *filename); +void graphics_reload(); + diff --git a/graphics/chroma-marble.chroma b/graphics/chroma-marble.chroma new file mode 100644 index 0000000..8ff4f08 --- /dev/null +++ b/graphics/chroma-marble.chroma @@ -0,0 +1,323 @@ + + + + + +Chroma Marble + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/graphics/chroma-marble/16_arrow_blue_down.png b/graphics/chroma-marble/16_arrow_blue_down.png new file mode 100644 index 0000000..a2b1c4e Binary files /dev/null and b/graphics/chroma-marble/16_arrow_blue_down.png differ diff --git a/graphics/chroma-marble/16_arrow_blue_left.png b/graphics/chroma-marble/16_arrow_blue_left.png new file mode 100644 index 0000000..c983166 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_blue_left.png differ diff --git a/graphics/chroma-marble/16_arrow_blue_right.png b/graphics/chroma-marble/16_arrow_blue_right.png new file mode 100644 index 0000000..23e1856 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_blue_right.png differ diff --git a/graphics/chroma-marble/16_arrow_blue_up.png b/graphics/chroma-marble/16_arrow_blue_up.png new file mode 100644 index 0000000..e8b84b6 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_blue_up.png differ diff --git a/graphics/chroma-marble/16_arrow_green_down.png b/graphics/chroma-marble/16_arrow_green_down.png new file mode 100644 index 0000000..05c1c7f Binary files /dev/null and b/graphics/chroma-marble/16_arrow_green_down.png differ diff --git a/graphics/chroma-marble/16_arrow_green_left.png b/graphics/chroma-marble/16_arrow_green_left.png new file mode 100644 index 0000000..32acea0 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_green_left.png differ diff --git a/graphics/chroma-marble/16_arrow_green_right.png b/graphics/chroma-marble/16_arrow_green_right.png new file mode 100644 index 0000000..8a5a684 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_green_right.png differ diff --git a/graphics/chroma-marble/16_arrow_green_up.png b/graphics/chroma-marble/16_arrow_green_up.png new file mode 100644 index 0000000..67769e1 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_green_up.png differ diff --git a/graphics/chroma-marble/16_arrow_red_down.png b/graphics/chroma-marble/16_arrow_red_down.png new file mode 100644 index 0000000..8e75701 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_red_down.png differ diff --git a/graphics/chroma-marble/16_arrow_red_left.png b/graphics/chroma-marble/16_arrow_red_left.png new file mode 100644 index 0000000..504137b Binary files /dev/null and b/graphics/chroma-marble/16_arrow_red_left.png differ diff --git a/graphics/chroma-marble/16_arrow_red_right.png b/graphics/chroma-marble/16_arrow_red_right.png new file mode 100644 index 0000000..0a0796b Binary files /dev/null and b/graphics/chroma-marble/16_arrow_red_right.png differ diff --git a/graphics/chroma-marble/16_arrow_red_up.png b/graphics/chroma-marble/16_arrow_red_up.png new file mode 100644 index 0000000..848db56 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_red_up.png differ diff --git a/graphics/chroma-marble/16_arrow_shadow_down.png b/graphics/chroma-marble/16_arrow_shadow_down.png new file mode 100644 index 0000000..f15e94e Binary files /dev/null and b/graphics/chroma-marble/16_arrow_shadow_down.png differ diff --git a/graphics/chroma-marble/16_arrow_shadow_left.png b/graphics/chroma-marble/16_arrow_shadow_left.png new file mode 100644 index 0000000..9c7c034 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_shadow_left.png differ diff --git a/graphics/chroma-marble/16_arrow_shadow_right.png b/graphics/chroma-marble/16_arrow_shadow_right.png new file mode 100644 index 0000000..3338430 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_shadow_right.png differ diff --git a/graphics/chroma-marble/16_arrow_shadow_up.png b/graphics/chroma-marble/16_arrow_shadow_up.png new file mode 100644 index 0000000..80a9390 Binary files /dev/null and b/graphics/chroma-marble/16_arrow_shadow_up.png differ diff --git a/graphics/chroma-marble/16_bomb_blue_down.png b/graphics/chroma-marble/16_bomb_blue_down.png new file mode 100644 index 0000000..e5f3867 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_blue_down.png differ diff --git a/graphics/chroma-marble/16_bomb_blue_left.png b/graphics/chroma-marble/16_bomb_blue_left.png new file mode 100644 index 0000000..7e257a3 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_blue_left.png differ diff --git a/graphics/chroma-marble/16_bomb_blue_right.png b/graphics/chroma-marble/16_bomb_blue_right.png new file mode 100644 index 0000000..0696947 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_blue_right.png differ diff --git a/graphics/chroma-marble/16_bomb_blue_up.png b/graphics/chroma-marble/16_bomb_blue_up.png new file mode 100644 index 0000000..de523f7 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_blue_up.png differ diff --git a/graphics/chroma-marble/16_bomb_green_down.png b/graphics/chroma-marble/16_bomb_green_down.png new file mode 100644 index 0000000..5d736ca Binary files /dev/null and b/graphics/chroma-marble/16_bomb_green_down.png differ diff --git a/graphics/chroma-marble/16_bomb_green_left.png b/graphics/chroma-marble/16_bomb_green_left.png new file mode 100644 index 0000000..f84f152 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_green_left.png differ diff --git a/graphics/chroma-marble/16_bomb_green_right.png b/graphics/chroma-marble/16_bomb_green_right.png new file mode 100644 index 0000000..12fcdb9 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_green_right.png differ diff --git a/graphics/chroma-marble/16_bomb_green_up.png b/graphics/chroma-marble/16_bomb_green_up.png new file mode 100644 index 0000000..d721b40 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_green_up.png differ diff --git a/graphics/chroma-marble/16_bomb_red_down.png b/graphics/chroma-marble/16_bomb_red_down.png new file mode 100644 index 0000000..49e2ce5 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_red_down.png differ diff --git a/graphics/chroma-marble/16_bomb_red_left.png b/graphics/chroma-marble/16_bomb_red_left.png new file mode 100644 index 0000000..46e39d9 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_red_left.png differ diff --git a/graphics/chroma-marble/16_bomb_red_right.png b/graphics/chroma-marble/16_bomb_red_right.png new file mode 100644 index 0000000..f58f24b Binary files /dev/null and b/graphics/chroma-marble/16_bomb_red_right.png differ diff --git a/graphics/chroma-marble/16_bomb_red_up.png b/graphics/chroma-marble/16_bomb_red_up.png new file mode 100644 index 0000000..723a625 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_red_up.png differ diff --git a/graphics/chroma-marble/16_bomb_shadow_down.png b/graphics/chroma-marble/16_bomb_shadow_down.png new file mode 100644 index 0000000..9604738 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_shadow_down.png differ diff --git a/graphics/chroma-marble/16_bomb_shadow_left.png b/graphics/chroma-marble/16_bomb_shadow_left.png new file mode 100644 index 0000000..73024c7 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_shadow_left.png differ diff --git a/graphics/chroma-marble/16_bomb_shadow_right.png b/graphics/chroma-marble/16_bomb_shadow_right.png new file mode 100644 index 0000000..f4ade22 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_shadow_right.png differ diff --git a/graphics/chroma-marble/16_bomb_shadow_up.png b/graphics/chroma-marble/16_bomb_shadow_up.png new file mode 100644 index 0000000..ab2de16 Binary files /dev/null and b/graphics/chroma-marble/16_bomb_shadow_up.png differ diff --git a/graphics/chroma-marble/16_circle.png b/graphics/chroma-marble/16_circle.png new file mode 100644 index 0000000..2429440 Binary files /dev/null and b/graphics/chroma-marble/16_circle.png differ diff --git a/graphics/chroma-marble/16_circle_double.png b/graphics/chroma-marble/16_circle_double.png new file mode 100644 index 0000000..d1d008d Binary files /dev/null and b/graphics/chroma-marble/16_circle_double.png differ diff --git a/graphics/chroma-marble/16_circle_double_shadow.png b/graphics/chroma-marble/16_circle_double_shadow.png new file mode 100644 index 0000000..bbad610 Binary files /dev/null and b/graphics/chroma-marble/16_circle_double_shadow.png differ diff --git a/graphics/chroma-marble/16_circle_shadow.png b/graphics/chroma-marble/16_circle_shadow.png new file mode 100644 index 0000000..0b6f7cb Binary files /dev/null and b/graphics/chroma-marble/16_circle_shadow.png differ diff --git a/graphics/chroma-marble/16_door.png b/graphics/chroma-marble/16_door.png new file mode 100644 index 0000000..0751c71 Binary files /dev/null and b/graphics/chroma-marble/16_door.png differ diff --git a/graphics/chroma-marble/16_door_shadow.png b/graphics/chroma-marble/16_door_shadow.png new file mode 100644 index 0000000..24c2411 Binary files /dev/null and b/graphics/chroma-marble/16_door_shadow.png differ diff --git a/graphics/chroma-marble/16_dots.png b/graphics/chroma-marble/16_dots.png new file mode 100644 index 0000000..d9f0fc7 Binary files /dev/null and b/graphics/chroma-marble/16_dots.png differ diff --git a/graphics/chroma-marble/16_dots_double.png b/graphics/chroma-marble/16_dots_double.png new file mode 100644 index 0000000..983191f Binary files /dev/null and b/graphics/chroma-marble/16_dots_double.png differ diff --git a/graphics/chroma-marble/16_dots_double_shadow.png b/graphics/chroma-marble/16_dots_double_shadow.png new file mode 100644 index 0000000..af5019c Binary files /dev/null and b/graphics/chroma-marble/16_dots_double_shadow.png differ diff --git a/graphics/chroma-marble/16_dots_shadow.png b/graphics/chroma-marble/16_dots_shadow.png new file mode 100644 index 0000000..9c49be5 Binary files /dev/null and b/graphics/chroma-marble/16_dots_shadow.png differ diff --git a/graphics/chroma-marble/16_dots_x.png b/graphics/chroma-marble/16_dots_x.png new file mode 100644 index 0000000..a5433ee Binary files /dev/null and b/graphics/chroma-marble/16_dots_x.png differ diff --git a/graphics/chroma-marble/16_dots_x_shadow.png b/graphics/chroma-marble/16_dots_x_shadow.png new file mode 100644 index 0000000..03ab7e6 Binary files /dev/null and b/graphics/chroma-marble/16_dots_x_shadow.png differ diff --git a/graphics/chroma-marble/16_dots_y.png b/graphics/chroma-marble/16_dots_y.png new file mode 100644 index 0000000..c0a37a2 Binary files /dev/null and b/graphics/chroma-marble/16_dots_y.png differ diff --git a/graphics/chroma-marble/16_dots_y_shadow.png b/graphics/chroma-marble/16_dots_y_shadow.png new file mode 100644 index 0000000..e294f87 Binary files /dev/null and b/graphics/chroma-marble/16_dots_y_shadow.png differ diff --git a/graphics/chroma-marble/16_map_bottom_left.png b/graphics/chroma-marble/16_map_bottom_left.png new file mode 100644 index 0000000..c34a31f Binary files /dev/null and b/graphics/chroma-marble/16_map_bottom_left.png differ diff --git a/graphics/chroma-marble/16_map_bottom_right.png b/graphics/chroma-marble/16_map_bottom_right.png new file mode 100644 index 0000000..fbb186c Binary files /dev/null and b/graphics/chroma-marble/16_map_bottom_right.png differ diff --git a/graphics/chroma-marble/16_map_shadow.png b/graphics/chroma-marble/16_map_shadow.png new file mode 100644 index 0000000..9e6cc25 Binary files /dev/null and b/graphics/chroma-marble/16_map_shadow.png differ diff --git a/graphics/chroma-marble/16_map_top_left.png b/graphics/chroma-marble/16_map_top_left.png new file mode 100644 index 0000000..76cb4ff Binary files /dev/null and b/graphics/chroma-marble/16_map_top_left.png differ diff --git a/graphics/chroma-marble/16_map_top_right.png b/graphics/chroma-marble/16_map_top_right.png new file mode 100644 index 0000000..2abfad8 Binary files /dev/null and b/graphics/chroma-marble/16_map_top_right.png differ diff --git a/graphics/chroma-marble/16_player_one.png b/graphics/chroma-marble/16_player_one.png new file mode 100644 index 0000000..dc4222b Binary files /dev/null and b/graphics/chroma-marble/16_player_one.png differ diff --git a/graphics/chroma-marble/16_player_one_swapped.png b/graphics/chroma-marble/16_player_one_swapped.png new file mode 100644 index 0000000..80d93e5 Binary files /dev/null and b/graphics/chroma-marble/16_player_one_swapped.png differ diff --git a/graphics/chroma-marble/16_player_shadow.png b/graphics/chroma-marble/16_player_shadow.png new file mode 100644 index 0000000..bee3a88 Binary files /dev/null and b/graphics/chroma-marble/16_player_shadow.png differ diff --git a/graphics/chroma-marble/16_player_two.png b/graphics/chroma-marble/16_player_two.png new file mode 100644 index 0000000..b152172 Binary files /dev/null and b/graphics/chroma-marble/16_player_two.png differ diff --git a/graphics/chroma-marble/16_player_two_swapped.png b/graphics/chroma-marble/16_player_two_swapped.png new file mode 100644 index 0000000..9caddd5 Binary files /dev/null and b/graphics/chroma-marble/16_player_two_swapped.png differ diff --git a/graphics/chroma-marble/16_space.png b/graphics/chroma-marble/16_space.png new file mode 100644 index 0000000..5fb066a Binary files /dev/null and b/graphics/chroma-marble/16_space.png differ diff --git a/graphics/chroma-marble/16_star.png b/graphics/chroma-marble/16_star.png new file mode 100644 index 0000000..e2c4a08 Binary files /dev/null and b/graphics/chroma-marble/16_star.png differ diff --git a/graphics/chroma-marble/16_star_shadow.png b/graphics/chroma-marble/16_star_shadow.png new file mode 100644 index 0000000..2fa0317 Binary files /dev/null and b/graphics/chroma-marble/16_star_shadow.png differ diff --git a/graphics/chroma-marble/16_switch.png b/graphics/chroma-marble/16_switch.png new file mode 100644 index 0000000..45167c7 Binary files /dev/null and b/graphics/chroma-marble/16_switch.png differ diff --git a/graphics/chroma-marble/16_switch_shadow.png b/graphics/chroma-marble/16_switch_shadow.png new file mode 100644 index 0000000..f407d1d Binary files /dev/null and b/graphics/chroma-marble/16_switch_shadow.png differ diff --git a/graphics/chroma-marble/16_teleport.png b/graphics/chroma-marble/16_teleport.png new file mode 100644 index 0000000..efe2bc9 Binary files /dev/null and b/graphics/chroma-marble/16_teleport.png differ diff --git a/graphics/chroma-marble/16_teleport_shadow.png b/graphics/chroma-marble/16_teleport_shadow.png new file mode 100644 index 0000000..28fb007 Binary files /dev/null and b/graphics/chroma-marble/16_teleport_shadow.png differ diff --git a/graphics/chroma-marble/16_wall.png b/graphics/chroma-marble/16_wall.png new file mode 100644 index 0000000..49256c4 Binary files /dev/null and b/graphics/chroma-marble/16_wall.png differ diff --git a/graphics/chroma-marble/16_wall_inside.png b/graphics/chroma-marble/16_wall_inside.png new file mode 100644 index 0000000..7780796 Binary files /dev/null and b/graphics/chroma-marble/16_wall_inside.png differ diff --git a/graphics/chroma-marble/16_wall_inside_shadow.png b/graphics/chroma-marble/16_wall_inside_shadow.png new file mode 100644 index 0000000..95430bf Binary files /dev/null and b/graphics/chroma-marble/16_wall_inside_shadow.png differ diff --git a/graphics/chroma-marble/16_wall_outside.png b/graphics/chroma-marble/16_wall_outside.png new file mode 100644 index 0000000..9e5f3ab Binary files /dev/null and b/graphics/chroma-marble/16_wall_outside.png differ diff --git a/graphics/chroma-marble/16_wall_outside_shadow.png b/graphics/chroma-marble/16_wall_outside_shadow.png new file mode 100644 index 0000000..647972b Binary files /dev/null and b/graphics/chroma-marble/16_wall_outside_shadow.png differ diff --git a/graphics/chroma-marble/16_wall_x.png b/graphics/chroma-marble/16_wall_x.png new file mode 100644 index 0000000..24383e3 Binary files /dev/null and b/graphics/chroma-marble/16_wall_x.png differ diff --git a/graphics/chroma-marble/16_wall_x_shadow.png b/graphics/chroma-marble/16_wall_x_shadow.png new file mode 100644 index 0000000..6311b40 Binary files /dev/null and b/graphics/chroma-marble/16_wall_x_shadow.png differ diff --git a/graphics/chroma-marble/16_wall_y.png b/graphics/chroma-marble/16_wall_y.png new file mode 100644 index 0000000..016ca57 Binary files /dev/null and b/graphics/chroma-marble/16_wall_y.png differ diff --git a/graphics/chroma-marble/16_wall_y_shadow.png b/graphics/chroma-marble/16_wall_y_shadow.png new file mode 100644 index 0000000..97b25e6 Binary files /dev/null and b/graphics/chroma-marble/16_wall_y_shadow.png differ diff --git a/graphics/chroma-marble/20_arrow_blue_down.png b/graphics/chroma-marble/20_arrow_blue_down.png new file mode 100644 index 0000000..980de95 Binary files /dev/null and b/graphics/chroma-marble/20_arrow_blue_down.png differ diff --git a/graphics/chroma-marble/20_arrow_blue_left.png b/graphics/chroma-marble/20_arrow_blue_left.png new file mode 100644 index 0000000..67c2463 Binary files /dev/null and b/graphics/chroma-marble/20_arrow_blue_left.png differ diff --git a/graphics/chroma-marble/20_arrow_blue_right.png b/graphics/chroma-marble/20_arrow_blue_right.png new file mode 100644 index 0000000..2b99555 Binary files /dev/null and b/graphics/chroma-marble/20_arrow_blue_right.png differ diff --git a/graphics/chroma-marble/20_arrow_blue_up.png b/graphics/chroma-marble/20_arrow_blue_up.png new file mode 100644 index 0000000..5d46184 Binary files /dev/null and b/graphics/chroma-marble/20_arrow_blue_up.png differ diff --git a/graphics/chroma-marble/20_arrow_green_down.png b/graphics/chroma-marble/20_arrow_green_down.png new file mode 100644 index 0000000..578f265 Binary files /dev/null and b/graphics/chroma-marble/20_arrow_green_down.png differ diff --git a/graphics/chroma-marble/20_arrow_green_left.png b/graphics/chroma-marble/20_arrow_green_left.png new file mode 100644 index 0000000..cef1218 Binary files /dev/null and b/graphics/chroma-marble/20_arrow_green_left.png differ diff --git a/graphics/chroma-marble/20_arrow_green_right.png b/graphics/chroma-marble/20_arrow_green_right.png new file mode 100644 index 0000000..1f533cd Binary files /dev/null and b/graphics/chroma-marble/20_arrow_green_right.png differ diff --git a/graphics/chroma-marble/20_arrow_green_up.png b/graphics/chroma-marble/20_arrow_green_up.png new file mode 100644 index 0000000..c764bfa Binary files /dev/null and b/graphics/chroma-marble/20_arrow_green_up.png differ diff --git a/graphics/chroma-marble/20_arrow_red_down.png b/graphics/chroma-marble/20_arrow_red_down.png new file mode 100644 index 0000000..7d4ae7a Binary files /dev/null and b/graphics/chroma-marble/20_arrow_red_down.png differ diff --git a/graphics/chroma-marble/20_arrow_red_left.png b/graphics/chroma-marble/20_arrow_red_left.png new file mode 100644 index 0000000..59269f7 Binary files /dev/null and b/graphics/chroma-marble/20_arrow_red_left.png differ diff --git a/graphics/chroma-marble/20_arrow_red_right.png b/graphics/chroma-marble/20_arrow_red_right.png new file mode 100644 index 0000000..1a0e4fd Binary files /dev/null and b/graphics/chroma-marble/20_arrow_red_right.png differ diff --git a/graphics/chroma-marble/20_arrow_red_up.png b/graphics/chroma-marble/20_arrow_red_up.png new file mode 100644 index 0000000..b927ebb Binary files /dev/null and b/graphics/chroma-marble/20_arrow_red_up.png differ diff --git a/graphics/chroma-marble/20_arrow_shadow_down.png b/graphics/chroma-marble/20_arrow_shadow_down.png new file mode 100644 index 0000000..7dc1b08 Binary files /dev/null and b/graphics/chroma-marble/20_arrow_shadow_down.png differ diff --git a/graphics/chroma-marble/20_arrow_shadow_left.png b/graphics/chroma-marble/20_arrow_shadow_left.png new file mode 100644 index 0000000..2595078 Binary files /dev/null and b/graphics/chroma-marble/20_arrow_shadow_left.png differ diff --git a/graphics/chroma-marble/20_arrow_shadow_right.png b/graphics/chroma-marble/20_arrow_shadow_right.png new file mode 100644 index 0000000..56f1645 Binary files /dev/null and b/graphics/chroma-marble/20_arrow_shadow_right.png differ diff --git a/graphics/chroma-marble/20_arrow_shadow_up.png b/graphics/chroma-marble/20_arrow_shadow_up.png new file mode 100644 index 0000000..053bb9a Binary files /dev/null and b/graphics/chroma-marble/20_arrow_shadow_up.png differ diff --git a/graphics/chroma-marble/20_bomb_blue_down.png b/graphics/chroma-marble/20_bomb_blue_down.png new file mode 100644 index 0000000..68c40bc Binary files /dev/null and b/graphics/chroma-marble/20_bomb_blue_down.png differ diff --git a/graphics/chroma-marble/20_bomb_blue_left.png b/graphics/chroma-marble/20_bomb_blue_left.png new file mode 100644 index 0000000..5e1a8fa Binary files /dev/null and b/graphics/chroma-marble/20_bomb_blue_left.png differ diff --git a/graphics/chroma-marble/20_bomb_blue_right.png b/graphics/chroma-marble/20_bomb_blue_right.png new file mode 100644 index 0000000..792a3e2 Binary files /dev/null and b/graphics/chroma-marble/20_bomb_blue_right.png differ diff --git a/graphics/chroma-marble/20_bomb_blue_up.png b/graphics/chroma-marble/20_bomb_blue_up.png new file mode 100644 index 0000000..73e47d6 Binary files /dev/null and b/graphics/chroma-marble/20_bomb_blue_up.png differ diff --git a/graphics/chroma-marble/20_bomb_green_down.png b/graphics/chroma-marble/20_bomb_green_down.png new file mode 100644 index 0000000..016cf89 Binary files /dev/null and b/graphics/chroma-marble/20_bomb_green_down.png differ diff --git a/graphics/chroma-marble/20_bomb_green_left.png b/graphics/chroma-marble/20_bomb_green_left.png new file mode 100644 index 0000000..e4679e4 Binary files /dev/null and b/graphics/chroma-marble/20_bomb_green_left.png differ diff --git a/graphics/chroma-marble/20_bomb_green_right.png b/graphics/chroma-marble/20_bomb_green_right.png new file mode 100644 index 0000000..06c5bf2 Binary files /dev/null and b/graphics/chroma-marble/20_bomb_green_right.png differ diff --git a/graphics/chroma-marble/20_bomb_green_up.png b/graphics/chroma-marble/20_bomb_green_up.png new file mode 100644 index 0000000..2601622 Binary files /dev/null and b/graphics/chroma-marble/20_bomb_green_up.png differ diff --git a/graphics/chroma-marble/20_bomb_red_down.png b/graphics/chroma-marble/20_bomb_red_down.png new file mode 100644 index 0000000..087b7cb Binary files /dev/null and b/graphics/chroma-marble/20_bomb_red_down.png differ diff --git a/graphics/chroma-marble/20_bomb_red_left.png b/graphics/chroma-marble/20_bomb_red_left.png new file mode 100644 index 0000000..bdd15d2 Binary files /dev/null and b/graphics/chroma-marble/20_bomb_red_left.png differ diff --git a/graphics/chroma-marble/20_bomb_red_right.png b/graphics/chroma-marble/20_bomb_red_right.png new file mode 100644 index 0000000..d54735a Binary files /dev/null and b/graphics/chroma-marble/20_bomb_red_right.png differ diff --git a/graphics/chroma-marble/20_bomb_red_up.png b/graphics/chroma-marble/20_bomb_red_up.png new file mode 100644 index 0000000..cc631df Binary files /dev/null and b/graphics/chroma-marble/20_bomb_red_up.png differ diff --git a/graphics/chroma-marble/20_bomb_shadow_down.png b/graphics/chroma-marble/20_bomb_shadow_down.png new file mode 100644 index 0000000..6431919 Binary files /dev/null and b/graphics/chroma-marble/20_bomb_shadow_down.png differ diff --git a/graphics/chroma-marble/20_bomb_shadow_left.png b/graphics/chroma-marble/20_bomb_shadow_left.png new file mode 100644 index 0000000..886239a Binary files /dev/null and b/graphics/chroma-marble/20_bomb_shadow_left.png differ diff --git a/graphics/chroma-marble/20_bomb_shadow_right.png b/graphics/chroma-marble/20_bomb_shadow_right.png new file mode 100644 index 0000000..d3fa4a0 Binary files /dev/null and b/graphics/chroma-marble/20_bomb_shadow_right.png differ diff --git a/graphics/chroma-marble/20_bomb_shadow_up.png b/graphics/chroma-marble/20_bomb_shadow_up.png new file mode 100644 index 0000000..8fd933c Binary files /dev/null and b/graphics/chroma-marble/20_bomb_shadow_up.png differ diff --git a/graphics/chroma-marble/20_circle.png b/graphics/chroma-marble/20_circle.png new file mode 100644 index 0000000..cf44095 Binary files /dev/null and b/graphics/chroma-marble/20_circle.png differ diff --git a/graphics/chroma-marble/20_circle_double.png b/graphics/chroma-marble/20_circle_double.png new file mode 100644 index 0000000..cec2c07 Binary files /dev/null and b/graphics/chroma-marble/20_circle_double.png differ diff --git a/graphics/chroma-marble/20_circle_double_shadow.png b/graphics/chroma-marble/20_circle_double_shadow.png new file mode 100644 index 0000000..b2ed69c Binary files /dev/null and b/graphics/chroma-marble/20_circle_double_shadow.png differ diff --git a/graphics/chroma-marble/20_circle_shadow.png b/graphics/chroma-marble/20_circle_shadow.png new file mode 100644 index 0000000..c00f360 Binary files /dev/null and b/graphics/chroma-marble/20_circle_shadow.png differ diff --git a/graphics/chroma-marble/20_door.png b/graphics/chroma-marble/20_door.png new file mode 100644 index 0000000..f16dbd2 Binary files /dev/null and b/graphics/chroma-marble/20_door.png differ diff --git a/graphics/chroma-marble/20_door_shadow.png b/graphics/chroma-marble/20_door_shadow.png new file mode 100644 index 0000000..7c35cac Binary files /dev/null and b/graphics/chroma-marble/20_door_shadow.png differ diff --git a/graphics/chroma-marble/20_dots.png b/graphics/chroma-marble/20_dots.png new file mode 100644 index 0000000..1b0f88c Binary files /dev/null and b/graphics/chroma-marble/20_dots.png differ diff --git a/graphics/chroma-marble/20_dots_double.png b/graphics/chroma-marble/20_dots_double.png new file mode 100644 index 0000000..a51f28f Binary files /dev/null and b/graphics/chroma-marble/20_dots_double.png differ diff --git a/graphics/chroma-marble/20_dots_double_shadow.png b/graphics/chroma-marble/20_dots_double_shadow.png new file mode 100644 index 0000000..2167314 Binary files /dev/null and b/graphics/chroma-marble/20_dots_double_shadow.png differ diff --git a/graphics/chroma-marble/20_dots_shadow.png b/graphics/chroma-marble/20_dots_shadow.png new file mode 100644 index 0000000..d2abd37 Binary files /dev/null and b/graphics/chroma-marble/20_dots_shadow.png differ diff --git a/graphics/chroma-marble/20_dots_x.png b/graphics/chroma-marble/20_dots_x.png new file mode 100644 index 0000000..2e42a7c Binary files /dev/null and b/graphics/chroma-marble/20_dots_x.png differ diff --git a/graphics/chroma-marble/20_dots_x_shadow.png b/graphics/chroma-marble/20_dots_x_shadow.png new file mode 100644 index 0000000..c3b0aa0 Binary files /dev/null and b/graphics/chroma-marble/20_dots_x_shadow.png differ diff --git a/graphics/chroma-marble/20_dots_y.png b/graphics/chroma-marble/20_dots_y.png new file mode 100644 index 0000000..94d2351 Binary files /dev/null and b/graphics/chroma-marble/20_dots_y.png differ diff --git a/graphics/chroma-marble/20_dots_y_shadow.png b/graphics/chroma-marble/20_dots_y_shadow.png new file mode 100644 index 0000000..b6eaa11 Binary files /dev/null and b/graphics/chroma-marble/20_dots_y_shadow.png differ diff --git a/graphics/chroma-marble/20_map_bottom_left.png b/graphics/chroma-marble/20_map_bottom_left.png new file mode 100644 index 0000000..a661c43 Binary files /dev/null and b/graphics/chroma-marble/20_map_bottom_left.png differ diff --git a/graphics/chroma-marble/20_map_bottom_right.png b/graphics/chroma-marble/20_map_bottom_right.png new file mode 100644 index 0000000..e441251 Binary files /dev/null and b/graphics/chroma-marble/20_map_bottom_right.png differ diff --git a/graphics/chroma-marble/20_map_shadow.png b/graphics/chroma-marble/20_map_shadow.png new file mode 100644 index 0000000..48769a9 Binary files /dev/null and b/graphics/chroma-marble/20_map_shadow.png differ diff --git a/graphics/chroma-marble/20_map_top_left.png b/graphics/chroma-marble/20_map_top_left.png new file mode 100644 index 0000000..e67b24f Binary files /dev/null and b/graphics/chroma-marble/20_map_top_left.png differ diff --git a/graphics/chroma-marble/20_map_top_right.png b/graphics/chroma-marble/20_map_top_right.png new file mode 100644 index 0000000..46bd9ec Binary files /dev/null and b/graphics/chroma-marble/20_map_top_right.png differ diff --git a/graphics/chroma-marble/20_player_one.png b/graphics/chroma-marble/20_player_one.png new file mode 100644 index 0000000..336c334 Binary files /dev/null and b/graphics/chroma-marble/20_player_one.png differ diff --git a/graphics/chroma-marble/20_player_one_swapped.png b/graphics/chroma-marble/20_player_one_swapped.png new file mode 100644 index 0000000..f9dc310 Binary files /dev/null and b/graphics/chroma-marble/20_player_one_swapped.png differ diff --git a/graphics/chroma-marble/20_player_shadow.png b/graphics/chroma-marble/20_player_shadow.png new file mode 100644 index 0000000..bcbe4ed Binary files /dev/null and b/graphics/chroma-marble/20_player_shadow.png differ diff --git a/graphics/chroma-marble/20_player_two.png b/graphics/chroma-marble/20_player_two.png new file mode 100644 index 0000000..fbd5996 Binary files /dev/null and b/graphics/chroma-marble/20_player_two.png differ diff --git a/graphics/chroma-marble/20_player_two_swapped.png b/graphics/chroma-marble/20_player_two_swapped.png new file mode 100644 index 0000000..b5547df Binary files /dev/null and b/graphics/chroma-marble/20_player_two_swapped.png differ diff --git a/graphics/chroma-marble/20_space.png b/graphics/chroma-marble/20_space.png new file mode 100644 index 0000000..4672185 Binary files /dev/null and b/graphics/chroma-marble/20_space.png differ diff --git a/graphics/chroma-marble/20_star.png b/graphics/chroma-marble/20_star.png new file mode 100644 index 0000000..3da1bdf Binary files /dev/null and b/graphics/chroma-marble/20_star.png differ diff --git a/graphics/chroma-marble/20_star_shadow.png b/graphics/chroma-marble/20_star_shadow.png new file mode 100644 index 0000000..6369d64 Binary files /dev/null and b/graphics/chroma-marble/20_star_shadow.png differ diff --git a/graphics/chroma-marble/20_switch.png b/graphics/chroma-marble/20_switch.png new file mode 100644 index 0000000..3e62967 Binary files /dev/null and b/graphics/chroma-marble/20_switch.png differ diff --git a/graphics/chroma-marble/20_switch_shadow.png b/graphics/chroma-marble/20_switch_shadow.png new file mode 100644 index 0000000..df333b6 Binary files /dev/null and b/graphics/chroma-marble/20_switch_shadow.png differ diff --git a/graphics/chroma-marble/20_teleport.png b/graphics/chroma-marble/20_teleport.png new file mode 100644 index 0000000..7158634 Binary files /dev/null and b/graphics/chroma-marble/20_teleport.png differ diff --git a/graphics/chroma-marble/20_teleport_shadow.png b/graphics/chroma-marble/20_teleport_shadow.png new file mode 100644 index 0000000..6b00c1c Binary files /dev/null and b/graphics/chroma-marble/20_teleport_shadow.png differ diff --git a/graphics/chroma-marble/20_wall.png b/graphics/chroma-marble/20_wall.png new file mode 100644 index 0000000..488a902 Binary files /dev/null and b/graphics/chroma-marble/20_wall.png differ diff --git a/graphics/chroma-marble/20_wall_inside.png b/graphics/chroma-marble/20_wall_inside.png new file mode 100644 index 0000000..0ddc045 Binary files /dev/null and b/graphics/chroma-marble/20_wall_inside.png differ diff --git a/graphics/chroma-marble/20_wall_inside_shadow.png b/graphics/chroma-marble/20_wall_inside_shadow.png new file mode 100644 index 0000000..491b259 Binary files /dev/null and b/graphics/chroma-marble/20_wall_inside_shadow.png differ diff --git a/graphics/chroma-marble/20_wall_outside.png b/graphics/chroma-marble/20_wall_outside.png new file mode 100644 index 0000000..8a9b07e Binary files /dev/null and b/graphics/chroma-marble/20_wall_outside.png differ diff --git a/graphics/chroma-marble/20_wall_outside_shadow.png b/graphics/chroma-marble/20_wall_outside_shadow.png new file mode 100644 index 0000000..494daa7 Binary files /dev/null and b/graphics/chroma-marble/20_wall_outside_shadow.png differ diff --git a/graphics/chroma-marble/20_wall_x.png b/graphics/chroma-marble/20_wall_x.png new file mode 100644 index 0000000..fd11b0c Binary files /dev/null and b/graphics/chroma-marble/20_wall_x.png differ diff --git a/graphics/chroma-marble/20_wall_x_shadow.png b/graphics/chroma-marble/20_wall_x_shadow.png new file mode 100644 index 0000000..ab75efd Binary files /dev/null and b/graphics/chroma-marble/20_wall_x_shadow.png differ diff --git a/graphics/chroma-marble/20_wall_y.png b/graphics/chroma-marble/20_wall_y.png new file mode 100644 index 0000000..06beed2 Binary files /dev/null and b/graphics/chroma-marble/20_wall_y.png differ diff --git a/graphics/chroma-marble/20_wall_y_shadow.png b/graphics/chroma-marble/20_wall_y_shadow.png new file mode 100644 index 0000000..101cb5e Binary files /dev/null and b/graphics/chroma-marble/20_wall_y_shadow.png differ diff --git a/graphics/chroma-marble/24_arrow_blue_down.png b/graphics/chroma-marble/24_arrow_blue_down.png new file mode 100644 index 0000000..fa0e519 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_blue_down.png differ diff --git a/graphics/chroma-marble/24_arrow_blue_left.png b/graphics/chroma-marble/24_arrow_blue_left.png new file mode 100644 index 0000000..788c2ce Binary files /dev/null and b/graphics/chroma-marble/24_arrow_blue_left.png differ diff --git a/graphics/chroma-marble/24_arrow_blue_right.png b/graphics/chroma-marble/24_arrow_blue_right.png new file mode 100644 index 0000000..223d4e2 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_blue_right.png differ diff --git a/graphics/chroma-marble/24_arrow_blue_up.png b/graphics/chroma-marble/24_arrow_blue_up.png new file mode 100644 index 0000000..c03a832 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_blue_up.png differ diff --git a/graphics/chroma-marble/24_arrow_green_down.png b/graphics/chroma-marble/24_arrow_green_down.png new file mode 100644 index 0000000..e57f8d1 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_green_down.png differ diff --git a/graphics/chroma-marble/24_arrow_green_left.png b/graphics/chroma-marble/24_arrow_green_left.png new file mode 100644 index 0000000..7c886d1 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_green_left.png differ diff --git a/graphics/chroma-marble/24_arrow_green_right.png b/graphics/chroma-marble/24_arrow_green_right.png new file mode 100644 index 0000000..b60b7d2 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_green_right.png differ diff --git a/graphics/chroma-marble/24_arrow_green_up.png b/graphics/chroma-marble/24_arrow_green_up.png new file mode 100644 index 0000000..c226754 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_green_up.png differ diff --git a/graphics/chroma-marble/24_arrow_red_down.png b/graphics/chroma-marble/24_arrow_red_down.png new file mode 100644 index 0000000..efb2eba Binary files /dev/null and b/graphics/chroma-marble/24_arrow_red_down.png differ diff --git a/graphics/chroma-marble/24_arrow_red_left.png b/graphics/chroma-marble/24_arrow_red_left.png new file mode 100644 index 0000000..ee1e57d Binary files /dev/null and b/graphics/chroma-marble/24_arrow_red_left.png differ diff --git a/graphics/chroma-marble/24_arrow_red_right.png b/graphics/chroma-marble/24_arrow_red_right.png new file mode 100644 index 0000000..257bb20 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_red_right.png differ diff --git a/graphics/chroma-marble/24_arrow_red_up.png b/graphics/chroma-marble/24_arrow_red_up.png new file mode 100644 index 0000000..c8e7c51 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_red_up.png differ diff --git a/graphics/chroma-marble/24_arrow_shadow_down.png b/graphics/chroma-marble/24_arrow_shadow_down.png new file mode 100644 index 0000000..a1ac563 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_shadow_down.png differ diff --git a/graphics/chroma-marble/24_arrow_shadow_left.png b/graphics/chroma-marble/24_arrow_shadow_left.png new file mode 100644 index 0000000..d541bbe Binary files /dev/null and b/graphics/chroma-marble/24_arrow_shadow_left.png differ diff --git a/graphics/chroma-marble/24_arrow_shadow_right.png b/graphics/chroma-marble/24_arrow_shadow_right.png new file mode 100644 index 0000000..8bf26ae Binary files /dev/null and b/graphics/chroma-marble/24_arrow_shadow_right.png differ diff --git a/graphics/chroma-marble/24_arrow_shadow_up.png b/graphics/chroma-marble/24_arrow_shadow_up.png new file mode 100644 index 0000000..1aa3658 Binary files /dev/null and b/graphics/chroma-marble/24_arrow_shadow_up.png differ diff --git a/graphics/chroma-marble/24_bomb_blue_down.png b/graphics/chroma-marble/24_bomb_blue_down.png new file mode 100644 index 0000000..96f6233 Binary files /dev/null and b/graphics/chroma-marble/24_bomb_blue_down.png differ diff --git a/graphics/chroma-marble/24_bomb_blue_left.png b/graphics/chroma-marble/24_bomb_blue_left.png new file mode 100644 index 0000000..aba8db2 Binary files /dev/null and b/graphics/chroma-marble/24_bomb_blue_left.png differ diff --git a/graphics/chroma-marble/24_bomb_blue_right.png b/graphics/chroma-marble/24_bomb_blue_right.png new file mode 100644 index 0000000..e30a85c Binary files /dev/null and b/graphics/chroma-marble/24_bomb_blue_right.png differ diff --git a/graphics/chroma-marble/24_bomb_blue_up.png b/graphics/chroma-marble/24_bomb_blue_up.png new file mode 100644 index 0000000..d5cafae Binary files /dev/null and b/graphics/chroma-marble/24_bomb_blue_up.png differ diff --git a/graphics/chroma-marble/24_bomb_green_down.png b/graphics/chroma-marble/24_bomb_green_down.png new file mode 100644 index 0000000..037d405 Binary files /dev/null and b/graphics/chroma-marble/24_bomb_green_down.png differ diff --git a/graphics/chroma-marble/24_bomb_green_left.png b/graphics/chroma-marble/24_bomb_green_left.png new file mode 100644 index 0000000..5d330d0 Binary files /dev/null and b/graphics/chroma-marble/24_bomb_green_left.png differ diff --git a/graphics/chroma-marble/24_bomb_green_right.png b/graphics/chroma-marble/24_bomb_green_right.png new file mode 100644 index 0000000..e083667 Binary files /dev/null and b/graphics/chroma-marble/24_bomb_green_right.png differ diff --git a/graphics/chroma-marble/24_bomb_green_up.png b/graphics/chroma-marble/24_bomb_green_up.png new file mode 100644 index 0000000..9842816 Binary files /dev/null and b/graphics/chroma-marble/24_bomb_green_up.png differ diff --git a/graphics/chroma-marble/24_bomb_red_down.png b/graphics/chroma-marble/24_bomb_red_down.png new file mode 100644 index 0000000..f9a41cb Binary files /dev/null and b/graphics/chroma-marble/24_bomb_red_down.png differ diff --git a/graphics/chroma-marble/24_bomb_red_left.png b/graphics/chroma-marble/24_bomb_red_left.png new file mode 100644 index 0000000..61af17f Binary files /dev/null and b/graphics/chroma-marble/24_bomb_red_left.png differ diff --git a/graphics/chroma-marble/24_bomb_red_right.png b/graphics/chroma-marble/24_bomb_red_right.png new file mode 100644 index 0000000..1918e54 Binary files /dev/null and b/graphics/chroma-marble/24_bomb_red_right.png differ diff --git a/graphics/chroma-marble/24_bomb_red_up.png b/graphics/chroma-marble/24_bomb_red_up.png new file mode 100644 index 0000000..da7826f Binary files /dev/null and b/graphics/chroma-marble/24_bomb_red_up.png differ diff --git a/graphics/chroma-marble/24_bomb_shadow_down.png b/graphics/chroma-marble/24_bomb_shadow_down.png new file mode 100644 index 0000000..911c647 Binary files /dev/null and b/graphics/chroma-marble/24_bomb_shadow_down.png differ diff --git a/graphics/chroma-marble/24_bomb_shadow_left.png b/graphics/chroma-marble/24_bomb_shadow_left.png new file mode 100644 index 0000000..0ef63e9 Binary files /dev/null and b/graphics/chroma-marble/24_bomb_shadow_left.png differ diff --git a/graphics/chroma-marble/24_bomb_shadow_right.png b/graphics/chroma-marble/24_bomb_shadow_right.png new file mode 100644 index 0000000..dcd132f Binary files /dev/null and b/graphics/chroma-marble/24_bomb_shadow_right.png differ diff --git a/graphics/chroma-marble/24_bomb_shadow_up.png b/graphics/chroma-marble/24_bomb_shadow_up.png new file mode 100644 index 0000000..f934a02 Binary files /dev/null and b/graphics/chroma-marble/24_bomb_shadow_up.png differ diff --git a/graphics/chroma-marble/24_circle.png b/graphics/chroma-marble/24_circle.png new file mode 100644 index 0000000..2295734 Binary files /dev/null and b/graphics/chroma-marble/24_circle.png differ diff --git a/graphics/chroma-marble/24_circle_double.png b/graphics/chroma-marble/24_circle_double.png new file mode 100644 index 0000000..ebc20f1 Binary files /dev/null and b/graphics/chroma-marble/24_circle_double.png differ diff --git a/graphics/chroma-marble/24_circle_double_shadow.png b/graphics/chroma-marble/24_circle_double_shadow.png new file mode 100644 index 0000000..d3f1e7a Binary files /dev/null and b/graphics/chroma-marble/24_circle_double_shadow.png differ diff --git a/graphics/chroma-marble/24_circle_shadow.png b/graphics/chroma-marble/24_circle_shadow.png new file mode 100644 index 0000000..0c1ab70 Binary files /dev/null and b/graphics/chroma-marble/24_circle_shadow.png differ diff --git a/graphics/chroma-marble/24_door.png b/graphics/chroma-marble/24_door.png new file mode 100644 index 0000000..4542c85 Binary files /dev/null and b/graphics/chroma-marble/24_door.png differ diff --git a/graphics/chroma-marble/24_door_shadow.png b/graphics/chroma-marble/24_door_shadow.png new file mode 100644 index 0000000..01dec54 Binary files /dev/null and b/graphics/chroma-marble/24_door_shadow.png differ diff --git a/graphics/chroma-marble/24_dots.png b/graphics/chroma-marble/24_dots.png new file mode 100644 index 0000000..762b225 Binary files /dev/null and b/graphics/chroma-marble/24_dots.png differ diff --git a/graphics/chroma-marble/24_dots_double.png b/graphics/chroma-marble/24_dots_double.png new file mode 100644 index 0000000..1e11d3d Binary files /dev/null and b/graphics/chroma-marble/24_dots_double.png differ diff --git a/graphics/chroma-marble/24_dots_double_shadow.png b/graphics/chroma-marble/24_dots_double_shadow.png new file mode 100644 index 0000000..d2a1be9 Binary files /dev/null and b/graphics/chroma-marble/24_dots_double_shadow.png differ diff --git a/graphics/chroma-marble/24_dots_shadow.png b/graphics/chroma-marble/24_dots_shadow.png new file mode 100644 index 0000000..f23fb5b Binary files /dev/null and b/graphics/chroma-marble/24_dots_shadow.png differ diff --git a/graphics/chroma-marble/24_dots_x.png b/graphics/chroma-marble/24_dots_x.png new file mode 100644 index 0000000..7642ec5 Binary files /dev/null and b/graphics/chroma-marble/24_dots_x.png differ diff --git a/graphics/chroma-marble/24_dots_x_shadow.png b/graphics/chroma-marble/24_dots_x_shadow.png new file mode 100644 index 0000000..67df783 Binary files /dev/null and b/graphics/chroma-marble/24_dots_x_shadow.png differ diff --git a/graphics/chroma-marble/24_dots_y.png b/graphics/chroma-marble/24_dots_y.png new file mode 100644 index 0000000..6524375 Binary files /dev/null and b/graphics/chroma-marble/24_dots_y.png differ diff --git a/graphics/chroma-marble/24_dots_y_shadow.png b/graphics/chroma-marble/24_dots_y_shadow.png new file mode 100644 index 0000000..e045853 Binary files /dev/null and b/graphics/chroma-marble/24_dots_y_shadow.png differ diff --git a/graphics/chroma-marble/24_map_bottom_left.png b/graphics/chroma-marble/24_map_bottom_left.png new file mode 100644 index 0000000..f8e093a Binary files /dev/null and b/graphics/chroma-marble/24_map_bottom_left.png differ diff --git a/graphics/chroma-marble/24_map_bottom_right.png b/graphics/chroma-marble/24_map_bottom_right.png new file mode 100644 index 0000000..4dc05fb Binary files /dev/null and b/graphics/chroma-marble/24_map_bottom_right.png differ diff --git a/graphics/chroma-marble/24_map_shadow.png b/graphics/chroma-marble/24_map_shadow.png new file mode 100644 index 0000000..5f8e69c Binary files /dev/null and b/graphics/chroma-marble/24_map_shadow.png differ diff --git a/graphics/chroma-marble/24_map_top_left.png b/graphics/chroma-marble/24_map_top_left.png new file mode 100644 index 0000000..a8879e9 Binary files /dev/null and b/graphics/chroma-marble/24_map_top_left.png differ diff --git a/graphics/chroma-marble/24_map_top_right.png b/graphics/chroma-marble/24_map_top_right.png new file mode 100644 index 0000000..086f4b2 Binary files /dev/null and b/graphics/chroma-marble/24_map_top_right.png differ diff --git a/graphics/chroma-marble/24_player_one.png b/graphics/chroma-marble/24_player_one.png new file mode 100644 index 0000000..009308e Binary files /dev/null and b/graphics/chroma-marble/24_player_one.png differ diff --git a/graphics/chroma-marble/24_player_one_swapped.png b/graphics/chroma-marble/24_player_one_swapped.png new file mode 100644 index 0000000..7bd0d03 Binary files /dev/null and b/graphics/chroma-marble/24_player_one_swapped.png differ diff --git a/graphics/chroma-marble/24_player_shadow.png b/graphics/chroma-marble/24_player_shadow.png new file mode 100644 index 0000000..df688ac Binary files /dev/null and b/graphics/chroma-marble/24_player_shadow.png differ diff --git a/graphics/chroma-marble/24_player_two.png b/graphics/chroma-marble/24_player_two.png new file mode 100644 index 0000000..4ba56cb Binary files /dev/null and b/graphics/chroma-marble/24_player_two.png differ diff --git a/graphics/chroma-marble/24_player_two_swapped.png b/graphics/chroma-marble/24_player_two_swapped.png new file mode 100644 index 0000000..d503985 Binary files /dev/null and b/graphics/chroma-marble/24_player_two_swapped.png differ diff --git a/graphics/chroma-marble/24_space.png b/graphics/chroma-marble/24_space.png new file mode 100644 index 0000000..fdfc7b0 Binary files /dev/null and b/graphics/chroma-marble/24_space.png differ diff --git a/graphics/chroma-marble/24_star.png b/graphics/chroma-marble/24_star.png new file mode 100644 index 0000000..93620cf Binary files /dev/null and b/graphics/chroma-marble/24_star.png differ diff --git a/graphics/chroma-marble/24_star_shadow.png b/graphics/chroma-marble/24_star_shadow.png new file mode 100644 index 0000000..8edbf98 Binary files /dev/null and b/graphics/chroma-marble/24_star_shadow.png differ diff --git a/graphics/chroma-marble/24_switch.png b/graphics/chroma-marble/24_switch.png new file mode 100644 index 0000000..91103fd Binary files /dev/null and b/graphics/chroma-marble/24_switch.png differ diff --git a/graphics/chroma-marble/24_switch_shadow.png b/graphics/chroma-marble/24_switch_shadow.png new file mode 100644 index 0000000..8412e23 Binary files /dev/null and b/graphics/chroma-marble/24_switch_shadow.png differ diff --git a/graphics/chroma-marble/24_teleport.png b/graphics/chroma-marble/24_teleport.png new file mode 100644 index 0000000..b590828 Binary files /dev/null and b/graphics/chroma-marble/24_teleport.png differ diff --git a/graphics/chroma-marble/24_teleport_shadow.png b/graphics/chroma-marble/24_teleport_shadow.png new file mode 100644 index 0000000..99a9f87 Binary files /dev/null and b/graphics/chroma-marble/24_teleport_shadow.png differ diff --git a/graphics/chroma-marble/24_wall.png b/graphics/chroma-marble/24_wall.png new file mode 100644 index 0000000..235ff31 Binary files /dev/null and b/graphics/chroma-marble/24_wall.png differ diff --git a/graphics/chroma-marble/24_wall_inside.png b/graphics/chroma-marble/24_wall_inside.png new file mode 100644 index 0000000..f78191d Binary files /dev/null and b/graphics/chroma-marble/24_wall_inside.png differ diff --git a/graphics/chroma-marble/24_wall_inside_shadow.png b/graphics/chroma-marble/24_wall_inside_shadow.png new file mode 100644 index 0000000..4dffde7 Binary files /dev/null and b/graphics/chroma-marble/24_wall_inside_shadow.png differ diff --git a/graphics/chroma-marble/24_wall_outside.png b/graphics/chroma-marble/24_wall_outside.png new file mode 100644 index 0000000..2ee6060 Binary files /dev/null and b/graphics/chroma-marble/24_wall_outside.png differ diff --git a/graphics/chroma-marble/24_wall_outside_shadow.png b/graphics/chroma-marble/24_wall_outside_shadow.png new file mode 100644 index 0000000..30be7a4 Binary files /dev/null and b/graphics/chroma-marble/24_wall_outside_shadow.png differ diff --git a/graphics/chroma-marble/24_wall_x.png b/graphics/chroma-marble/24_wall_x.png new file mode 100644 index 0000000..a4944a8 Binary files /dev/null and b/graphics/chroma-marble/24_wall_x.png differ diff --git a/graphics/chroma-marble/24_wall_x_shadow.png b/graphics/chroma-marble/24_wall_x_shadow.png new file mode 100644 index 0000000..0ea59b6 Binary files /dev/null and b/graphics/chroma-marble/24_wall_x_shadow.png differ diff --git a/graphics/chroma-marble/24_wall_y.png b/graphics/chroma-marble/24_wall_y.png new file mode 100644 index 0000000..c42fd8e Binary files /dev/null and b/graphics/chroma-marble/24_wall_y.png differ diff --git a/graphics/chroma-marble/24_wall_y_shadow.png b/graphics/chroma-marble/24_wall_y_shadow.png new file mode 100644 index 0000000..ff82c2c Binary files /dev/null and b/graphics/chroma-marble/24_wall_y_shadow.png differ diff --git a/graphics/chroma-marble/32_arrow_blue_down.png b/graphics/chroma-marble/32_arrow_blue_down.png new file mode 100644 index 0000000..07affa2 Binary files /dev/null and b/graphics/chroma-marble/32_arrow_blue_down.png differ diff --git a/graphics/chroma-marble/32_arrow_blue_left.png b/graphics/chroma-marble/32_arrow_blue_left.png new file mode 100644 index 0000000..7e73a2b Binary files /dev/null and b/graphics/chroma-marble/32_arrow_blue_left.png differ diff --git a/graphics/chroma-marble/32_arrow_blue_right.png b/graphics/chroma-marble/32_arrow_blue_right.png new file mode 100644 index 0000000..e2503d0 Binary files /dev/null and b/graphics/chroma-marble/32_arrow_blue_right.png differ diff --git a/graphics/chroma-marble/32_arrow_blue_up.png b/graphics/chroma-marble/32_arrow_blue_up.png new file mode 100644 index 0000000..10d2efd Binary files /dev/null and b/graphics/chroma-marble/32_arrow_blue_up.png differ diff --git a/graphics/chroma-marble/32_arrow_green_down.png b/graphics/chroma-marble/32_arrow_green_down.png new file mode 100644 index 0000000..d8707f9 Binary files /dev/null and b/graphics/chroma-marble/32_arrow_green_down.png differ diff --git a/graphics/chroma-marble/32_arrow_green_left.png b/graphics/chroma-marble/32_arrow_green_left.png new file mode 100644 index 0000000..762411c Binary files /dev/null and b/graphics/chroma-marble/32_arrow_green_left.png differ diff --git a/graphics/chroma-marble/32_arrow_green_right.png b/graphics/chroma-marble/32_arrow_green_right.png new file mode 100644 index 0000000..0bd1d76 Binary files /dev/null and b/graphics/chroma-marble/32_arrow_green_right.png differ diff --git a/graphics/chroma-marble/32_arrow_green_up.png b/graphics/chroma-marble/32_arrow_green_up.png new file mode 100644 index 0000000..ca75d49 Binary files /dev/null and b/graphics/chroma-marble/32_arrow_green_up.png differ diff --git a/graphics/chroma-marble/32_arrow_red_down.png b/graphics/chroma-marble/32_arrow_red_down.png new file mode 100644 index 0000000..fd9d994 Binary files /dev/null and b/graphics/chroma-marble/32_arrow_red_down.png differ diff --git a/graphics/chroma-marble/32_arrow_red_left.png b/graphics/chroma-marble/32_arrow_red_left.png new file mode 100644 index 0000000..d7fd29e Binary files /dev/null and b/graphics/chroma-marble/32_arrow_red_left.png differ diff --git a/graphics/chroma-marble/32_arrow_red_right.png b/graphics/chroma-marble/32_arrow_red_right.png new file mode 100644 index 0000000..2b33987 Binary files /dev/null and b/graphics/chroma-marble/32_arrow_red_right.png differ diff --git a/graphics/chroma-marble/32_arrow_red_up.png b/graphics/chroma-marble/32_arrow_red_up.png new file mode 100644 index 0000000..5a5fb03 Binary files /dev/null and b/graphics/chroma-marble/32_arrow_red_up.png differ diff --git a/graphics/chroma-marble/32_arrow_shadow_down.png b/graphics/chroma-marble/32_arrow_shadow_down.png new file mode 100644 index 0000000..327bc23 Binary files /dev/null and b/graphics/chroma-marble/32_arrow_shadow_down.png differ diff --git a/graphics/chroma-marble/32_arrow_shadow_left.png b/graphics/chroma-marble/32_arrow_shadow_left.png new file mode 100644 index 0000000..25e26f2 Binary files /dev/null and b/graphics/chroma-marble/32_arrow_shadow_left.png differ diff --git a/graphics/chroma-marble/32_arrow_shadow_right.png b/graphics/chroma-marble/32_arrow_shadow_right.png new file mode 100644 index 0000000..0f7564e Binary files /dev/null and b/graphics/chroma-marble/32_arrow_shadow_right.png differ diff --git a/graphics/chroma-marble/32_arrow_shadow_up.png b/graphics/chroma-marble/32_arrow_shadow_up.png new file mode 100644 index 0000000..c9cfa2a Binary files /dev/null and b/graphics/chroma-marble/32_arrow_shadow_up.png differ diff --git a/graphics/chroma-marble/32_bomb_blue_down.png b/graphics/chroma-marble/32_bomb_blue_down.png new file mode 100644 index 0000000..7442a99 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_blue_down.png differ diff --git a/graphics/chroma-marble/32_bomb_blue_left.png b/graphics/chroma-marble/32_bomb_blue_left.png new file mode 100644 index 0000000..87c3df0 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_blue_left.png differ diff --git a/graphics/chroma-marble/32_bomb_blue_right.png b/graphics/chroma-marble/32_bomb_blue_right.png new file mode 100644 index 0000000..0d2bf94 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_blue_right.png differ diff --git a/graphics/chroma-marble/32_bomb_blue_up.png b/graphics/chroma-marble/32_bomb_blue_up.png new file mode 100644 index 0000000..333b438 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_blue_up.png differ diff --git a/graphics/chroma-marble/32_bomb_green_down.png b/graphics/chroma-marble/32_bomb_green_down.png new file mode 100644 index 0000000..9d7f12c Binary files /dev/null and b/graphics/chroma-marble/32_bomb_green_down.png differ diff --git a/graphics/chroma-marble/32_bomb_green_left.png b/graphics/chroma-marble/32_bomb_green_left.png new file mode 100644 index 0000000..dfc9654 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_green_left.png differ diff --git a/graphics/chroma-marble/32_bomb_green_right.png b/graphics/chroma-marble/32_bomb_green_right.png new file mode 100644 index 0000000..04b1f6e Binary files /dev/null and b/graphics/chroma-marble/32_bomb_green_right.png differ diff --git a/graphics/chroma-marble/32_bomb_green_up.png b/graphics/chroma-marble/32_bomb_green_up.png new file mode 100644 index 0000000..cd53edd Binary files /dev/null and b/graphics/chroma-marble/32_bomb_green_up.png differ diff --git a/graphics/chroma-marble/32_bomb_red_down.png b/graphics/chroma-marble/32_bomb_red_down.png new file mode 100644 index 0000000..82e7cb0 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_red_down.png differ diff --git a/graphics/chroma-marble/32_bomb_red_left.png b/graphics/chroma-marble/32_bomb_red_left.png new file mode 100644 index 0000000..47f2a01 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_red_left.png differ diff --git a/graphics/chroma-marble/32_bomb_red_right.png b/graphics/chroma-marble/32_bomb_red_right.png new file mode 100644 index 0000000..c2bf90d Binary files /dev/null and b/graphics/chroma-marble/32_bomb_red_right.png differ diff --git a/graphics/chroma-marble/32_bomb_red_up.png b/graphics/chroma-marble/32_bomb_red_up.png new file mode 100644 index 0000000..0575d37 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_red_up.png differ diff --git a/graphics/chroma-marble/32_bomb_shadow_down.png b/graphics/chroma-marble/32_bomb_shadow_down.png new file mode 100644 index 0000000..9f9e030 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_shadow_down.png differ diff --git a/graphics/chroma-marble/32_bomb_shadow_left.png b/graphics/chroma-marble/32_bomb_shadow_left.png new file mode 100644 index 0000000..3ee628a Binary files /dev/null and b/graphics/chroma-marble/32_bomb_shadow_left.png differ diff --git a/graphics/chroma-marble/32_bomb_shadow_right.png b/graphics/chroma-marble/32_bomb_shadow_right.png new file mode 100644 index 0000000..7791182 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_shadow_right.png differ diff --git a/graphics/chroma-marble/32_bomb_shadow_up.png b/graphics/chroma-marble/32_bomb_shadow_up.png new file mode 100644 index 0000000..959bdd9 Binary files /dev/null and b/graphics/chroma-marble/32_bomb_shadow_up.png differ diff --git a/graphics/chroma-marble/32_circle.png b/graphics/chroma-marble/32_circle.png new file mode 100644 index 0000000..339abf4 Binary files /dev/null and b/graphics/chroma-marble/32_circle.png differ diff --git a/graphics/chroma-marble/32_circle_double.png b/graphics/chroma-marble/32_circle_double.png new file mode 100644 index 0000000..2f328a2 Binary files /dev/null and b/graphics/chroma-marble/32_circle_double.png differ diff --git a/graphics/chroma-marble/32_circle_double_shadow.png b/graphics/chroma-marble/32_circle_double_shadow.png new file mode 100644 index 0000000..2f54c48 Binary files /dev/null and b/graphics/chroma-marble/32_circle_double_shadow.png differ diff --git a/graphics/chroma-marble/32_circle_shadow.png b/graphics/chroma-marble/32_circle_shadow.png new file mode 100644 index 0000000..39c2886 Binary files /dev/null and b/graphics/chroma-marble/32_circle_shadow.png differ diff --git a/graphics/chroma-marble/32_door.png b/graphics/chroma-marble/32_door.png new file mode 100644 index 0000000..0724c5a Binary files /dev/null and b/graphics/chroma-marble/32_door.png differ diff --git a/graphics/chroma-marble/32_door_shadow.png b/graphics/chroma-marble/32_door_shadow.png new file mode 100644 index 0000000..cc7aedb Binary files /dev/null and b/graphics/chroma-marble/32_door_shadow.png differ diff --git a/graphics/chroma-marble/32_dots.png b/graphics/chroma-marble/32_dots.png new file mode 100644 index 0000000..b07974e Binary files /dev/null and b/graphics/chroma-marble/32_dots.png differ diff --git a/graphics/chroma-marble/32_dots_double.png b/graphics/chroma-marble/32_dots_double.png new file mode 100644 index 0000000..8e200a3 Binary files /dev/null and b/graphics/chroma-marble/32_dots_double.png differ diff --git a/graphics/chroma-marble/32_dots_double_shadow.png b/graphics/chroma-marble/32_dots_double_shadow.png new file mode 100644 index 0000000..44f8741 Binary files /dev/null and b/graphics/chroma-marble/32_dots_double_shadow.png differ diff --git a/graphics/chroma-marble/32_dots_shadow.png b/graphics/chroma-marble/32_dots_shadow.png new file mode 100644 index 0000000..576ffa2 Binary files /dev/null and b/graphics/chroma-marble/32_dots_shadow.png differ diff --git a/graphics/chroma-marble/32_dots_x.png b/graphics/chroma-marble/32_dots_x.png new file mode 100644 index 0000000..eb57966 Binary files /dev/null and b/graphics/chroma-marble/32_dots_x.png differ diff --git a/graphics/chroma-marble/32_dots_x_shadow.png b/graphics/chroma-marble/32_dots_x_shadow.png new file mode 100644 index 0000000..5b11f6b Binary files /dev/null and b/graphics/chroma-marble/32_dots_x_shadow.png differ diff --git a/graphics/chroma-marble/32_dots_y.png b/graphics/chroma-marble/32_dots_y.png new file mode 100644 index 0000000..e9a461b Binary files /dev/null and b/graphics/chroma-marble/32_dots_y.png differ diff --git a/graphics/chroma-marble/32_dots_y_shadow.png b/graphics/chroma-marble/32_dots_y_shadow.png new file mode 100644 index 0000000..a6ae75c Binary files /dev/null and b/graphics/chroma-marble/32_dots_y_shadow.png differ diff --git a/graphics/chroma-marble/32_map_bottom_left.png b/graphics/chroma-marble/32_map_bottom_left.png new file mode 100644 index 0000000..1eea29d Binary files /dev/null and b/graphics/chroma-marble/32_map_bottom_left.png differ diff --git a/graphics/chroma-marble/32_map_bottom_right.png b/graphics/chroma-marble/32_map_bottom_right.png new file mode 100644 index 0000000..32ccc37 Binary files /dev/null and b/graphics/chroma-marble/32_map_bottom_right.png differ diff --git a/graphics/chroma-marble/32_map_shadow.png b/graphics/chroma-marble/32_map_shadow.png new file mode 100644 index 0000000..7ff01e6 Binary files /dev/null and b/graphics/chroma-marble/32_map_shadow.png differ diff --git a/graphics/chroma-marble/32_map_top_left.png b/graphics/chroma-marble/32_map_top_left.png new file mode 100644 index 0000000..7a5848c Binary files /dev/null and b/graphics/chroma-marble/32_map_top_left.png differ diff --git a/graphics/chroma-marble/32_map_top_right.png b/graphics/chroma-marble/32_map_top_right.png new file mode 100644 index 0000000..00c12d8 Binary files /dev/null and b/graphics/chroma-marble/32_map_top_right.png differ diff --git a/graphics/chroma-marble/32_player_one.png b/graphics/chroma-marble/32_player_one.png new file mode 100644 index 0000000..7987db3 Binary files /dev/null and b/graphics/chroma-marble/32_player_one.png differ diff --git a/graphics/chroma-marble/32_player_one_swapped.png b/graphics/chroma-marble/32_player_one_swapped.png new file mode 100644 index 0000000..9cab14e Binary files /dev/null and b/graphics/chroma-marble/32_player_one_swapped.png differ diff --git a/graphics/chroma-marble/32_player_shadow.png b/graphics/chroma-marble/32_player_shadow.png new file mode 100644 index 0000000..29005e6 Binary files /dev/null and b/graphics/chroma-marble/32_player_shadow.png differ diff --git a/graphics/chroma-marble/32_player_two.png b/graphics/chroma-marble/32_player_two.png new file mode 100644 index 0000000..d6f13fa Binary files /dev/null and b/graphics/chroma-marble/32_player_two.png differ diff --git a/graphics/chroma-marble/32_player_two_swapped.png b/graphics/chroma-marble/32_player_two_swapped.png new file mode 100644 index 0000000..be0b4d8 Binary files /dev/null and b/graphics/chroma-marble/32_player_two_swapped.png differ diff --git a/graphics/chroma-marble/32_space.png b/graphics/chroma-marble/32_space.png new file mode 100644 index 0000000..d4d54e2 Binary files /dev/null and b/graphics/chroma-marble/32_space.png differ diff --git a/graphics/chroma-marble/32_star.png b/graphics/chroma-marble/32_star.png new file mode 100644 index 0000000..b1d76e9 Binary files /dev/null and b/graphics/chroma-marble/32_star.png differ diff --git a/graphics/chroma-marble/32_star_shadow.png b/graphics/chroma-marble/32_star_shadow.png new file mode 100644 index 0000000..51a9a07 Binary files /dev/null and b/graphics/chroma-marble/32_star_shadow.png differ diff --git a/graphics/chroma-marble/32_switch.png b/graphics/chroma-marble/32_switch.png new file mode 100644 index 0000000..e5c693b Binary files /dev/null and b/graphics/chroma-marble/32_switch.png differ diff --git a/graphics/chroma-marble/32_switch_shadow.png b/graphics/chroma-marble/32_switch_shadow.png new file mode 100644 index 0000000..6faee46 Binary files /dev/null and b/graphics/chroma-marble/32_switch_shadow.png differ diff --git a/graphics/chroma-marble/32_teleport.png b/graphics/chroma-marble/32_teleport.png new file mode 100644 index 0000000..a6d55f2 Binary files /dev/null and b/graphics/chroma-marble/32_teleport.png differ diff --git a/graphics/chroma-marble/32_teleport_shadow.png b/graphics/chroma-marble/32_teleport_shadow.png new file mode 100644 index 0000000..0f58adc Binary files /dev/null and b/graphics/chroma-marble/32_teleport_shadow.png differ diff --git a/graphics/chroma-marble/32_wall.png b/graphics/chroma-marble/32_wall.png new file mode 100644 index 0000000..43d0c68 Binary files /dev/null and b/graphics/chroma-marble/32_wall.png differ diff --git a/graphics/chroma-marble/32_wall_inside.png b/graphics/chroma-marble/32_wall_inside.png new file mode 100644 index 0000000..42757b8 Binary files /dev/null and b/graphics/chroma-marble/32_wall_inside.png differ diff --git a/graphics/chroma-marble/32_wall_inside_shadow.png b/graphics/chroma-marble/32_wall_inside_shadow.png new file mode 100644 index 0000000..83de38a Binary files /dev/null and b/graphics/chroma-marble/32_wall_inside_shadow.png differ diff --git a/graphics/chroma-marble/32_wall_outside.png b/graphics/chroma-marble/32_wall_outside.png new file mode 100644 index 0000000..93d614c Binary files /dev/null and b/graphics/chroma-marble/32_wall_outside.png differ diff --git a/graphics/chroma-marble/32_wall_outside_shadow.png b/graphics/chroma-marble/32_wall_outside_shadow.png new file mode 100644 index 0000000..29ed0e9 Binary files /dev/null and b/graphics/chroma-marble/32_wall_outside_shadow.png differ diff --git a/graphics/chroma-marble/32_wall_x.png b/graphics/chroma-marble/32_wall_x.png new file mode 100644 index 0000000..1e89a47 Binary files /dev/null and b/graphics/chroma-marble/32_wall_x.png differ diff --git a/graphics/chroma-marble/32_wall_x_shadow.png b/graphics/chroma-marble/32_wall_x_shadow.png new file mode 100644 index 0000000..dbc0823 Binary files /dev/null and b/graphics/chroma-marble/32_wall_x_shadow.png differ diff --git a/graphics/chroma-marble/32_wall_y.png b/graphics/chroma-marble/32_wall_y.png new file mode 100644 index 0000000..4833cd1 Binary files /dev/null and b/graphics/chroma-marble/32_wall_y.png differ diff --git a/graphics/chroma-marble/32_wall_y_shadow.png b/graphics/chroma-marble/32_wall_y_shadow.png new file mode 100644 index 0000000..384e784 Binary files /dev/null and b/graphics/chroma-marble/32_wall_y_shadow.png differ diff --git a/graphics/chroma-marble/40_arrow_blue_down.png b/graphics/chroma-marble/40_arrow_blue_down.png new file mode 100644 index 0000000..ed0f3a6 Binary files /dev/null and b/graphics/chroma-marble/40_arrow_blue_down.png differ diff --git a/graphics/chroma-marble/40_arrow_blue_left.png b/graphics/chroma-marble/40_arrow_blue_left.png new file mode 100644 index 0000000..c4d72e9 Binary files /dev/null and b/graphics/chroma-marble/40_arrow_blue_left.png differ diff --git a/graphics/chroma-marble/40_arrow_blue_right.png b/graphics/chroma-marble/40_arrow_blue_right.png new file mode 100644 index 0000000..6605694 Binary files /dev/null and b/graphics/chroma-marble/40_arrow_blue_right.png differ diff --git a/graphics/chroma-marble/40_arrow_blue_up.png b/graphics/chroma-marble/40_arrow_blue_up.png new file mode 100644 index 0000000..0f64a4c Binary files /dev/null and b/graphics/chroma-marble/40_arrow_blue_up.png differ diff --git a/graphics/chroma-marble/40_arrow_green_down.png b/graphics/chroma-marble/40_arrow_green_down.png new file mode 100644 index 0000000..1947ac0 Binary files /dev/null and b/graphics/chroma-marble/40_arrow_green_down.png differ diff --git a/graphics/chroma-marble/40_arrow_green_left.png b/graphics/chroma-marble/40_arrow_green_left.png new file mode 100644 index 0000000..e9ee742 Binary files /dev/null and b/graphics/chroma-marble/40_arrow_green_left.png differ diff --git a/graphics/chroma-marble/40_arrow_green_right.png b/graphics/chroma-marble/40_arrow_green_right.png new file mode 100644 index 0000000..bcfed1a Binary files /dev/null and b/graphics/chroma-marble/40_arrow_green_right.png differ diff --git a/graphics/chroma-marble/40_arrow_green_up.png b/graphics/chroma-marble/40_arrow_green_up.png new file mode 100644 index 0000000..c6219be Binary files /dev/null and b/graphics/chroma-marble/40_arrow_green_up.png differ diff --git a/graphics/chroma-marble/40_arrow_red_down.png b/graphics/chroma-marble/40_arrow_red_down.png new file mode 100644 index 0000000..6914985 Binary files /dev/null and b/graphics/chroma-marble/40_arrow_red_down.png differ diff --git a/graphics/chroma-marble/40_arrow_red_left.png b/graphics/chroma-marble/40_arrow_red_left.png new file mode 100644 index 0000000..4b44fdd Binary files /dev/null and b/graphics/chroma-marble/40_arrow_red_left.png differ diff --git a/graphics/chroma-marble/40_arrow_red_right.png b/graphics/chroma-marble/40_arrow_red_right.png new file mode 100644 index 0000000..4078e96 Binary files /dev/null and b/graphics/chroma-marble/40_arrow_red_right.png differ diff --git a/graphics/chroma-marble/40_arrow_red_up.png b/graphics/chroma-marble/40_arrow_red_up.png new file mode 100644 index 0000000..49ac75a Binary files /dev/null and b/graphics/chroma-marble/40_arrow_red_up.png differ diff --git a/graphics/chroma-marble/40_arrow_shadow_down.png b/graphics/chroma-marble/40_arrow_shadow_down.png new file mode 100644 index 0000000..5e7f5fc Binary files /dev/null and b/graphics/chroma-marble/40_arrow_shadow_down.png differ diff --git a/graphics/chroma-marble/40_arrow_shadow_left.png b/graphics/chroma-marble/40_arrow_shadow_left.png new file mode 100644 index 0000000..aa4c028 Binary files /dev/null and b/graphics/chroma-marble/40_arrow_shadow_left.png differ diff --git a/graphics/chroma-marble/40_arrow_shadow_right.png b/graphics/chroma-marble/40_arrow_shadow_right.png new file mode 100644 index 0000000..ce4aa57 Binary files /dev/null and b/graphics/chroma-marble/40_arrow_shadow_right.png differ diff --git a/graphics/chroma-marble/40_arrow_shadow_up.png b/graphics/chroma-marble/40_arrow_shadow_up.png new file mode 100644 index 0000000..51a16a3 Binary files /dev/null and b/graphics/chroma-marble/40_arrow_shadow_up.png differ diff --git a/graphics/chroma-marble/40_bomb_blue_down.png b/graphics/chroma-marble/40_bomb_blue_down.png new file mode 100644 index 0000000..bbb1724 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_blue_down.png differ diff --git a/graphics/chroma-marble/40_bomb_blue_left.png b/graphics/chroma-marble/40_bomb_blue_left.png new file mode 100644 index 0000000..9070a77 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_blue_left.png differ diff --git a/graphics/chroma-marble/40_bomb_blue_right.png b/graphics/chroma-marble/40_bomb_blue_right.png new file mode 100644 index 0000000..a516e41 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_blue_right.png differ diff --git a/graphics/chroma-marble/40_bomb_blue_up.png b/graphics/chroma-marble/40_bomb_blue_up.png new file mode 100644 index 0000000..7331132 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_blue_up.png differ diff --git a/graphics/chroma-marble/40_bomb_green_down.png b/graphics/chroma-marble/40_bomb_green_down.png new file mode 100644 index 0000000..7d0ee2b Binary files /dev/null and b/graphics/chroma-marble/40_bomb_green_down.png differ diff --git a/graphics/chroma-marble/40_bomb_green_left.png b/graphics/chroma-marble/40_bomb_green_left.png new file mode 100644 index 0000000..a145919 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_green_left.png differ diff --git a/graphics/chroma-marble/40_bomb_green_right.png b/graphics/chroma-marble/40_bomb_green_right.png new file mode 100644 index 0000000..5daf92e Binary files /dev/null and b/graphics/chroma-marble/40_bomb_green_right.png differ diff --git a/graphics/chroma-marble/40_bomb_green_up.png b/graphics/chroma-marble/40_bomb_green_up.png new file mode 100644 index 0000000..9644e28 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_green_up.png differ diff --git a/graphics/chroma-marble/40_bomb_red_down.png b/graphics/chroma-marble/40_bomb_red_down.png new file mode 100644 index 0000000..c57c934 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_red_down.png differ diff --git a/graphics/chroma-marble/40_bomb_red_left.png b/graphics/chroma-marble/40_bomb_red_left.png new file mode 100644 index 0000000..b6768d2 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_red_left.png differ diff --git a/graphics/chroma-marble/40_bomb_red_right.png b/graphics/chroma-marble/40_bomb_red_right.png new file mode 100644 index 0000000..c136b46 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_red_right.png differ diff --git a/graphics/chroma-marble/40_bomb_red_up.png b/graphics/chroma-marble/40_bomb_red_up.png new file mode 100644 index 0000000..dc05c21 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_red_up.png differ diff --git a/graphics/chroma-marble/40_bomb_shadow_down.png b/graphics/chroma-marble/40_bomb_shadow_down.png new file mode 100644 index 0000000..ccfd83e Binary files /dev/null and b/graphics/chroma-marble/40_bomb_shadow_down.png differ diff --git a/graphics/chroma-marble/40_bomb_shadow_left.png b/graphics/chroma-marble/40_bomb_shadow_left.png new file mode 100644 index 0000000..abe7a65 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_shadow_left.png differ diff --git a/graphics/chroma-marble/40_bomb_shadow_right.png b/graphics/chroma-marble/40_bomb_shadow_right.png new file mode 100644 index 0000000..6f07e93 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_shadow_right.png differ diff --git a/graphics/chroma-marble/40_bomb_shadow_up.png b/graphics/chroma-marble/40_bomb_shadow_up.png new file mode 100644 index 0000000..546e5f4 Binary files /dev/null and b/graphics/chroma-marble/40_bomb_shadow_up.png differ diff --git a/graphics/chroma-marble/40_circle.png b/graphics/chroma-marble/40_circle.png new file mode 100644 index 0000000..5ab03d8 Binary files /dev/null and b/graphics/chroma-marble/40_circle.png differ diff --git a/graphics/chroma-marble/40_circle_double.png b/graphics/chroma-marble/40_circle_double.png new file mode 100644 index 0000000..7d927f7 Binary files /dev/null and b/graphics/chroma-marble/40_circle_double.png differ diff --git a/graphics/chroma-marble/40_circle_double_shadow.png b/graphics/chroma-marble/40_circle_double_shadow.png new file mode 100644 index 0000000..0f9cd92 Binary files /dev/null and b/graphics/chroma-marble/40_circle_double_shadow.png differ diff --git a/graphics/chroma-marble/40_circle_shadow.png b/graphics/chroma-marble/40_circle_shadow.png new file mode 100644 index 0000000..d048c92 Binary files /dev/null and b/graphics/chroma-marble/40_circle_shadow.png differ diff --git a/graphics/chroma-marble/40_door.png b/graphics/chroma-marble/40_door.png new file mode 100644 index 0000000..b132005 Binary files /dev/null and b/graphics/chroma-marble/40_door.png differ diff --git a/graphics/chroma-marble/40_door_shadow.png b/graphics/chroma-marble/40_door_shadow.png new file mode 100644 index 0000000..b19d941 Binary files /dev/null and b/graphics/chroma-marble/40_door_shadow.png differ diff --git a/graphics/chroma-marble/40_dots.png b/graphics/chroma-marble/40_dots.png new file mode 100644 index 0000000..95895b4 Binary files /dev/null and b/graphics/chroma-marble/40_dots.png differ diff --git a/graphics/chroma-marble/40_dots_double.png b/graphics/chroma-marble/40_dots_double.png new file mode 100644 index 0000000..be48372 Binary files /dev/null and b/graphics/chroma-marble/40_dots_double.png differ diff --git a/graphics/chroma-marble/40_dots_double_shadow.png b/graphics/chroma-marble/40_dots_double_shadow.png new file mode 100644 index 0000000..e0543ed Binary files /dev/null and b/graphics/chroma-marble/40_dots_double_shadow.png differ diff --git a/graphics/chroma-marble/40_dots_shadow.png b/graphics/chroma-marble/40_dots_shadow.png new file mode 100644 index 0000000..f551127 Binary files /dev/null and b/graphics/chroma-marble/40_dots_shadow.png differ diff --git a/graphics/chroma-marble/40_dots_x.png b/graphics/chroma-marble/40_dots_x.png new file mode 100644 index 0000000..60e5e76 Binary files /dev/null and b/graphics/chroma-marble/40_dots_x.png differ diff --git a/graphics/chroma-marble/40_dots_x_shadow.png b/graphics/chroma-marble/40_dots_x_shadow.png new file mode 100644 index 0000000..c018945 Binary files /dev/null and b/graphics/chroma-marble/40_dots_x_shadow.png differ diff --git a/graphics/chroma-marble/40_dots_y.png b/graphics/chroma-marble/40_dots_y.png new file mode 100644 index 0000000..29891d7 Binary files /dev/null and b/graphics/chroma-marble/40_dots_y.png differ diff --git a/graphics/chroma-marble/40_dots_y_shadow.png b/graphics/chroma-marble/40_dots_y_shadow.png new file mode 100644 index 0000000..6562e37 Binary files /dev/null and b/graphics/chroma-marble/40_dots_y_shadow.png differ diff --git a/graphics/chroma-marble/40_map_bottom_left.png b/graphics/chroma-marble/40_map_bottom_left.png new file mode 100644 index 0000000..aa25c6c Binary files /dev/null and b/graphics/chroma-marble/40_map_bottom_left.png differ diff --git a/graphics/chroma-marble/40_map_bottom_right.png b/graphics/chroma-marble/40_map_bottom_right.png new file mode 100644 index 0000000..691b315 Binary files /dev/null and b/graphics/chroma-marble/40_map_bottom_right.png differ diff --git a/graphics/chroma-marble/40_map_shadow.png b/graphics/chroma-marble/40_map_shadow.png new file mode 100644 index 0000000..19660a5 Binary files /dev/null and b/graphics/chroma-marble/40_map_shadow.png differ diff --git a/graphics/chroma-marble/40_map_top_left.png b/graphics/chroma-marble/40_map_top_left.png new file mode 100644 index 0000000..81b11b7 Binary files /dev/null and b/graphics/chroma-marble/40_map_top_left.png differ diff --git a/graphics/chroma-marble/40_map_top_right.png b/graphics/chroma-marble/40_map_top_right.png new file mode 100644 index 0000000..2a40528 Binary files /dev/null and b/graphics/chroma-marble/40_map_top_right.png differ diff --git a/graphics/chroma-marble/40_player_one.png b/graphics/chroma-marble/40_player_one.png new file mode 100644 index 0000000..a554840 Binary files /dev/null and b/graphics/chroma-marble/40_player_one.png differ diff --git a/graphics/chroma-marble/40_player_one_swapped.png b/graphics/chroma-marble/40_player_one_swapped.png new file mode 100644 index 0000000..e1b8169 Binary files /dev/null and b/graphics/chroma-marble/40_player_one_swapped.png differ diff --git a/graphics/chroma-marble/40_player_shadow.png b/graphics/chroma-marble/40_player_shadow.png new file mode 100644 index 0000000..b1a29dc Binary files /dev/null and b/graphics/chroma-marble/40_player_shadow.png differ diff --git a/graphics/chroma-marble/40_player_two.png b/graphics/chroma-marble/40_player_two.png new file mode 100644 index 0000000..a1bd1c1 Binary files /dev/null and b/graphics/chroma-marble/40_player_two.png differ diff --git a/graphics/chroma-marble/40_player_two_swapped.png b/graphics/chroma-marble/40_player_two_swapped.png new file mode 100644 index 0000000..c2ff953 Binary files /dev/null and b/graphics/chroma-marble/40_player_two_swapped.png differ diff --git a/graphics/chroma-marble/40_space.png b/graphics/chroma-marble/40_space.png new file mode 100644 index 0000000..9fd06c4 Binary files /dev/null and b/graphics/chroma-marble/40_space.png differ diff --git a/graphics/chroma-marble/40_star.png b/graphics/chroma-marble/40_star.png new file mode 100644 index 0000000..727e289 Binary files /dev/null and b/graphics/chroma-marble/40_star.png differ diff --git a/graphics/chroma-marble/40_star_shadow.png b/graphics/chroma-marble/40_star_shadow.png new file mode 100644 index 0000000..59a78ba Binary files /dev/null and b/graphics/chroma-marble/40_star_shadow.png differ diff --git a/graphics/chroma-marble/40_switch.png b/graphics/chroma-marble/40_switch.png new file mode 100644 index 0000000..2393f1a Binary files /dev/null and b/graphics/chroma-marble/40_switch.png differ diff --git a/graphics/chroma-marble/40_switch_shadow.png b/graphics/chroma-marble/40_switch_shadow.png new file mode 100644 index 0000000..4017091 Binary files /dev/null and b/graphics/chroma-marble/40_switch_shadow.png differ diff --git a/graphics/chroma-marble/40_teleport.png b/graphics/chroma-marble/40_teleport.png new file mode 100644 index 0000000..7e0f280 Binary files /dev/null and b/graphics/chroma-marble/40_teleport.png differ diff --git a/graphics/chroma-marble/40_teleport_shadow.png b/graphics/chroma-marble/40_teleport_shadow.png new file mode 100644 index 0000000..724ecd8 Binary files /dev/null and b/graphics/chroma-marble/40_teleport_shadow.png differ diff --git a/graphics/chroma-marble/40_wall.png b/graphics/chroma-marble/40_wall.png new file mode 100644 index 0000000..150a460 Binary files /dev/null and b/graphics/chroma-marble/40_wall.png differ diff --git a/graphics/chroma-marble/40_wall_inside.png b/graphics/chroma-marble/40_wall_inside.png new file mode 100644 index 0000000..d8090d2 Binary files /dev/null and b/graphics/chroma-marble/40_wall_inside.png differ diff --git a/graphics/chroma-marble/40_wall_inside_shadow.png b/graphics/chroma-marble/40_wall_inside_shadow.png new file mode 100644 index 0000000..0e7f526 Binary files /dev/null and b/graphics/chroma-marble/40_wall_inside_shadow.png differ diff --git a/graphics/chroma-marble/40_wall_outside.png b/graphics/chroma-marble/40_wall_outside.png new file mode 100644 index 0000000..df5091e Binary files /dev/null and b/graphics/chroma-marble/40_wall_outside.png differ diff --git a/graphics/chroma-marble/40_wall_outside_shadow.png b/graphics/chroma-marble/40_wall_outside_shadow.png new file mode 100644 index 0000000..5acddea Binary files /dev/null and b/graphics/chroma-marble/40_wall_outside_shadow.png differ diff --git a/graphics/chroma-marble/40_wall_x.png b/graphics/chroma-marble/40_wall_x.png new file mode 100644 index 0000000..9f84535 Binary files /dev/null and b/graphics/chroma-marble/40_wall_x.png differ diff --git a/graphics/chroma-marble/40_wall_x_shadow.png b/graphics/chroma-marble/40_wall_x_shadow.png new file mode 100644 index 0000000..4cadc42 Binary files /dev/null and b/graphics/chroma-marble/40_wall_x_shadow.png differ diff --git a/graphics/chroma-marble/40_wall_y.png b/graphics/chroma-marble/40_wall_y.png new file mode 100644 index 0000000..c6efb36 Binary files /dev/null and b/graphics/chroma-marble/40_wall_y.png differ diff --git a/graphics/chroma-marble/40_wall_y_shadow.png b/graphics/chroma-marble/40_wall_y_shadow.png new file mode 100644 index 0000000..acb0846 Binary files /dev/null and b/graphics/chroma-marble/40_wall_y_shadow.png differ diff --git a/graphics/chroma-marble/64_arrow_blue_down.png b/graphics/chroma-marble/64_arrow_blue_down.png new file mode 100644 index 0000000..b024477 Binary files /dev/null and b/graphics/chroma-marble/64_arrow_blue_down.png differ diff --git a/graphics/chroma-marble/64_arrow_blue_left.png b/graphics/chroma-marble/64_arrow_blue_left.png new file mode 100644 index 0000000..29bde5f Binary files /dev/null and b/graphics/chroma-marble/64_arrow_blue_left.png differ diff --git a/graphics/chroma-marble/64_arrow_blue_right.png b/graphics/chroma-marble/64_arrow_blue_right.png new file mode 100644 index 0000000..c1d147f Binary files /dev/null and b/graphics/chroma-marble/64_arrow_blue_right.png differ diff --git a/graphics/chroma-marble/64_arrow_blue_up.png b/graphics/chroma-marble/64_arrow_blue_up.png new file mode 100644 index 0000000..f50e69e Binary files /dev/null and b/graphics/chroma-marble/64_arrow_blue_up.png differ diff --git a/graphics/chroma-marble/64_arrow_green_down.png b/graphics/chroma-marble/64_arrow_green_down.png new file mode 100644 index 0000000..efec907 Binary files /dev/null and b/graphics/chroma-marble/64_arrow_green_down.png differ diff --git a/graphics/chroma-marble/64_arrow_green_left.png b/graphics/chroma-marble/64_arrow_green_left.png new file mode 100644 index 0000000..eb75614 Binary files /dev/null and b/graphics/chroma-marble/64_arrow_green_left.png differ diff --git a/graphics/chroma-marble/64_arrow_green_right.png b/graphics/chroma-marble/64_arrow_green_right.png new file mode 100644 index 0000000..6aeebc1 Binary files /dev/null and b/graphics/chroma-marble/64_arrow_green_right.png differ diff --git a/graphics/chroma-marble/64_arrow_green_up.png b/graphics/chroma-marble/64_arrow_green_up.png new file mode 100644 index 0000000..5dd2122 Binary files /dev/null and b/graphics/chroma-marble/64_arrow_green_up.png differ diff --git a/graphics/chroma-marble/64_arrow_red_down.png b/graphics/chroma-marble/64_arrow_red_down.png new file mode 100644 index 0000000..1e43293 Binary files /dev/null and b/graphics/chroma-marble/64_arrow_red_down.png differ diff --git a/graphics/chroma-marble/64_arrow_red_left.png b/graphics/chroma-marble/64_arrow_red_left.png new file mode 100644 index 0000000..25f93cc Binary files /dev/null and b/graphics/chroma-marble/64_arrow_red_left.png differ diff --git a/graphics/chroma-marble/64_arrow_red_right.png b/graphics/chroma-marble/64_arrow_red_right.png new file mode 100644 index 0000000..8c1058d Binary files /dev/null and b/graphics/chroma-marble/64_arrow_red_right.png differ diff --git a/graphics/chroma-marble/64_arrow_red_up.png b/graphics/chroma-marble/64_arrow_red_up.png new file mode 100644 index 0000000..057cb40 Binary files /dev/null and b/graphics/chroma-marble/64_arrow_red_up.png differ diff --git a/graphics/chroma-marble/64_arrow_shadow_down.png b/graphics/chroma-marble/64_arrow_shadow_down.png new file mode 100644 index 0000000..5a14879 Binary files /dev/null and b/graphics/chroma-marble/64_arrow_shadow_down.png differ diff --git a/graphics/chroma-marble/64_arrow_shadow_left.png b/graphics/chroma-marble/64_arrow_shadow_left.png new file mode 100644 index 0000000..cc8f728 Binary files /dev/null and b/graphics/chroma-marble/64_arrow_shadow_left.png differ diff --git a/graphics/chroma-marble/64_arrow_shadow_right.png b/graphics/chroma-marble/64_arrow_shadow_right.png new file mode 100644 index 0000000..c28bb21 Binary files /dev/null and b/graphics/chroma-marble/64_arrow_shadow_right.png differ diff --git a/graphics/chroma-marble/64_arrow_shadow_up.png b/graphics/chroma-marble/64_arrow_shadow_up.png new file mode 100644 index 0000000..1370e5f Binary files /dev/null and b/graphics/chroma-marble/64_arrow_shadow_up.png differ diff --git a/graphics/chroma-marble/64_bomb_blue_down.png b/graphics/chroma-marble/64_bomb_blue_down.png new file mode 100644 index 0000000..17912b4 Binary files /dev/null and b/graphics/chroma-marble/64_bomb_blue_down.png differ diff --git a/graphics/chroma-marble/64_bomb_blue_left.png b/graphics/chroma-marble/64_bomb_blue_left.png new file mode 100644 index 0000000..fd23987 Binary files /dev/null and b/graphics/chroma-marble/64_bomb_blue_left.png differ diff --git a/graphics/chroma-marble/64_bomb_blue_right.png b/graphics/chroma-marble/64_bomb_blue_right.png new file mode 100644 index 0000000..7a106ce Binary files /dev/null and b/graphics/chroma-marble/64_bomb_blue_right.png differ diff --git a/graphics/chroma-marble/64_bomb_blue_up.png b/graphics/chroma-marble/64_bomb_blue_up.png new file mode 100644 index 0000000..0b09d4b Binary files /dev/null and b/graphics/chroma-marble/64_bomb_blue_up.png differ diff --git a/graphics/chroma-marble/64_bomb_green_down.png b/graphics/chroma-marble/64_bomb_green_down.png new file mode 100644 index 0000000..780def2 Binary files /dev/null and b/graphics/chroma-marble/64_bomb_green_down.png differ diff --git a/graphics/chroma-marble/64_bomb_green_left.png b/graphics/chroma-marble/64_bomb_green_left.png new file mode 100644 index 0000000..6119c5e Binary files /dev/null and b/graphics/chroma-marble/64_bomb_green_left.png differ diff --git a/graphics/chroma-marble/64_bomb_green_right.png b/graphics/chroma-marble/64_bomb_green_right.png new file mode 100644 index 0000000..a5d7294 Binary files /dev/null and b/graphics/chroma-marble/64_bomb_green_right.png differ diff --git a/graphics/chroma-marble/64_bomb_green_up.png b/graphics/chroma-marble/64_bomb_green_up.png new file mode 100644 index 0000000..72e9aab Binary files /dev/null and b/graphics/chroma-marble/64_bomb_green_up.png differ diff --git a/graphics/chroma-marble/64_bomb_red_down.png b/graphics/chroma-marble/64_bomb_red_down.png new file mode 100644 index 0000000..62bbdda Binary files /dev/null and b/graphics/chroma-marble/64_bomb_red_down.png differ diff --git a/graphics/chroma-marble/64_bomb_red_left.png b/graphics/chroma-marble/64_bomb_red_left.png new file mode 100644 index 0000000..848a69e Binary files /dev/null and b/graphics/chroma-marble/64_bomb_red_left.png differ diff --git a/graphics/chroma-marble/64_bomb_red_right.png b/graphics/chroma-marble/64_bomb_red_right.png new file mode 100644 index 0000000..b042dbe Binary files /dev/null and b/graphics/chroma-marble/64_bomb_red_right.png differ diff --git a/graphics/chroma-marble/64_bomb_red_up.png b/graphics/chroma-marble/64_bomb_red_up.png new file mode 100644 index 0000000..1dfb4f1 Binary files /dev/null and b/graphics/chroma-marble/64_bomb_red_up.png differ diff --git a/graphics/chroma-marble/64_bomb_shadow_down.png b/graphics/chroma-marble/64_bomb_shadow_down.png new file mode 100644 index 0000000..e6050bf Binary files /dev/null and b/graphics/chroma-marble/64_bomb_shadow_down.png differ diff --git a/graphics/chroma-marble/64_bomb_shadow_left.png b/graphics/chroma-marble/64_bomb_shadow_left.png new file mode 100644 index 0000000..8e45940 Binary files /dev/null and b/graphics/chroma-marble/64_bomb_shadow_left.png differ diff --git a/graphics/chroma-marble/64_bomb_shadow_right.png b/graphics/chroma-marble/64_bomb_shadow_right.png new file mode 100644 index 0000000..9b1fd4e Binary files /dev/null and b/graphics/chroma-marble/64_bomb_shadow_right.png differ diff --git a/graphics/chroma-marble/64_bomb_shadow_up.png b/graphics/chroma-marble/64_bomb_shadow_up.png new file mode 100644 index 0000000..46305d7 Binary files /dev/null and b/graphics/chroma-marble/64_bomb_shadow_up.png differ diff --git a/graphics/chroma-marble/64_circle.png b/graphics/chroma-marble/64_circle.png new file mode 100644 index 0000000..a03d790 Binary files /dev/null and b/graphics/chroma-marble/64_circle.png differ diff --git a/graphics/chroma-marble/64_circle_double.png b/graphics/chroma-marble/64_circle_double.png new file mode 100644 index 0000000..d7c501a Binary files /dev/null and b/graphics/chroma-marble/64_circle_double.png differ diff --git a/graphics/chroma-marble/64_circle_double_shadow.png b/graphics/chroma-marble/64_circle_double_shadow.png new file mode 100644 index 0000000..087e3c5 Binary files /dev/null and b/graphics/chroma-marble/64_circle_double_shadow.png differ diff --git a/graphics/chroma-marble/64_circle_shadow.png b/graphics/chroma-marble/64_circle_shadow.png new file mode 100644 index 0000000..cce076e Binary files /dev/null and b/graphics/chroma-marble/64_circle_shadow.png differ diff --git a/graphics/chroma-marble/64_door.png b/graphics/chroma-marble/64_door.png new file mode 100644 index 0000000..eb06936 Binary files /dev/null and b/graphics/chroma-marble/64_door.png differ diff --git a/graphics/chroma-marble/64_door_shadow.png b/graphics/chroma-marble/64_door_shadow.png new file mode 100644 index 0000000..25764f5 Binary files /dev/null and b/graphics/chroma-marble/64_door_shadow.png differ diff --git a/graphics/chroma-marble/64_dots.png b/graphics/chroma-marble/64_dots.png new file mode 100644 index 0000000..8169cab Binary files /dev/null and b/graphics/chroma-marble/64_dots.png differ diff --git a/graphics/chroma-marble/64_dots_double.png b/graphics/chroma-marble/64_dots_double.png new file mode 100644 index 0000000..ae9d6b8 Binary files /dev/null and b/graphics/chroma-marble/64_dots_double.png differ diff --git a/graphics/chroma-marble/64_dots_double_shadow.png b/graphics/chroma-marble/64_dots_double_shadow.png new file mode 100644 index 0000000..00716fd Binary files /dev/null and b/graphics/chroma-marble/64_dots_double_shadow.png differ diff --git a/graphics/chroma-marble/64_dots_shadow.png b/graphics/chroma-marble/64_dots_shadow.png new file mode 100644 index 0000000..62e9465 Binary files /dev/null and b/graphics/chroma-marble/64_dots_shadow.png differ diff --git a/graphics/chroma-marble/64_dots_x.png b/graphics/chroma-marble/64_dots_x.png new file mode 100644 index 0000000..d4c0dcc Binary files /dev/null and b/graphics/chroma-marble/64_dots_x.png differ diff --git a/graphics/chroma-marble/64_dots_x_shadow.png b/graphics/chroma-marble/64_dots_x_shadow.png new file mode 100644 index 0000000..8cab7d5 Binary files /dev/null and b/graphics/chroma-marble/64_dots_x_shadow.png differ diff --git a/graphics/chroma-marble/64_dots_y.png b/graphics/chroma-marble/64_dots_y.png new file mode 100644 index 0000000..a659ca6 Binary files /dev/null and b/graphics/chroma-marble/64_dots_y.png differ diff --git a/graphics/chroma-marble/64_dots_y_shadow.png b/graphics/chroma-marble/64_dots_y_shadow.png new file mode 100644 index 0000000..202a350 Binary files /dev/null and b/graphics/chroma-marble/64_dots_y_shadow.png differ diff --git a/graphics/chroma-marble/64_map_bottom_left.png b/graphics/chroma-marble/64_map_bottom_left.png new file mode 100644 index 0000000..26cdb8e Binary files /dev/null and b/graphics/chroma-marble/64_map_bottom_left.png differ diff --git a/graphics/chroma-marble/64_map_bottom_right.png b/graphics/chroma-marble/64_map_bottom_right.png new file mode 100644 index 0000000..3bbc29d Binary files /dev/null and b/graphics/chroma-marble/64_map_bottom_right.png differ diff --git a/graphics/chroma-marble/64_map_shadow.png b/graphics/chroma-marble/64_map_shadow.png new file mode 100644 index 0000000..8f083c3 Binary files /dev/null and b/graphics/chroma-marble/64_map_shadow.png differ diff --git a/graphics/chroma-marble/64_map_top_left.png b/graphics/chroma-marble/64_map_top_left.png new file mode 100644 index 0000000..e23e93e Binary files /dev/null and b/graphics/chroma-marble/64_map_top_left.png differ diff --git a/graphics/chroma-marble/64_map_top_right.png b/graphics/chroma-marble/64_map_top_right.png new file mode 100644 index 0000000..6d9649d Binary files /dev/null and b/graphics/chroma-marble/64_map_top_right.png differ diff --git a/graphics/chroma-marble/64_player_one.png b/graphics/chroma-marble/64_player_one.png new file mode 100644 index 0000000..20fd0d1 Binary files /dev/null and b/graphics/chroma-marble/64_player_one.png differ diff --git a/graphics/chroma-marble/64_player_one_swapped.png b/graphics/chroma-marble/64_player_one_swapped.png new file mode 100644 index 0000000..dd05970 Binary files /dev/null and b/graphics/chroma-marble/64_player_one_swapped.png differ diff --git a/graphics/chroma-marble/64_player_shadow.png b/graphics/chroma-marble/64_player_shadow.png new file mode 100644 index 0000000..ac35628 Binary files /dev/null and b/graphics/chroma-marble/64_player_shadow.png differ diff --git a/graphics/chroma-marble/64_player_two.png b/graphics/chroma-marble/64_player_two.png new file mode 100644 index 0000000..5427881 Binary files /dev/null and b/graphics/chroma-marble/64_player_two.png differ diff --git a/graphics/chroma-marble/64_player_two_swapped.png b/graphics/chroma-marble/64_player_two_swapped.png new file mode 100644 index 0000000..48cca78 Binary files /dev/null and b/graphics/chroma-marble/64_player_two_swapped.png differ diff --git a/graphics/chroma-marble/64_space.png b/graphics/chroma-marble/64_space.png new file mode 100644 index 0000000..4d5caf7 Binary files /dev/null and b/graphics/chroma-marble/64_space.png differ diff --git a/graphics/chroma-marble/64_star.png b/graphics/chroma-marble/64_star.png new file mode 100644 index 0000000..2ae6c17 Binary files /dev/null and b/graphics/chroma-marble/64_star.png differ diff --git a/graphics/chroma-marble/64_star_shadow.png b/graphics/chroma-marble/64_star_shadow.png new file mode 100644 index 0000000..63e7382 Binary files /dev/null and b/graphics/chroma-marble/64_star_shadow.png differ diff --git a/graphics/chroma-marble/64_switch.png b/graphics/chroma-marble/64_switch.png new file mode 100644 index 0000000..7728125 Binary files /dev/null and b/graphics/chroma-marble/64_switch.png differ diff --git a/graphics/chroma-marble/64_switch_shadow.png b/graphics/chroma-marble/64_switch_shadow.png new file mode 100644 index 0000000..d73636a Binary files /dev/null and b/graphics/chroma-marble/64_switch_shadow.png differ diff --git a/graphics/chroma-marble/64_teleport.png b/graphics/chroma-marble/64_teleport.png new file mode 100644 index 0000000..d0f3b51 Binary files /dev/null and b/graphics/chroma-marble/64_teleport.png differ diff --git a/graphics/chroma-marble/64_teleport_shadow.png b/graphics/chroma-marble/64_teleport_shadow.png new file mode 100644 index 0000000..683e7ec Binary files /dev/null and b/graphics/chroma-marble/64_teleport_shadow.png differ diff --git a/graphics/chroma-marble/64_wall.png b/graphics/chroma-marble/64_wall.png new file mode 100644 index 0000000..cadde2d Binary files /dev/null and b/graphics/chroma-marble/64_wall.png differ diff --git a/graphics/chroma-marble/64_wall_inside.png b/graphics/chroma-marble/64_wall_inside.png new file mode 100644 index 0000000..881d93f Binary files /dev/null and b/graphics/chroma-marble/64_wall_inside.png differ diff --git a/graphics/chroma-marble/64_wall_inside_shadow.png b/graphics/chroma-marble/64_wall_inside_shadow.png new file mode 100644 index 0000000..e15cd69 Binary files /dev/null and b/graphics/chroma-marble/64_wall_inside_shadow.png differ diff --git a/graphics/chroma-marble/64_wall_outside.png b/graphics/chroma-marble/64_wall_outside.png new file mode 100644 index 0000000..38b60d8 Binary files /dev/null and b/graphics/chroma-marble/64_wall_outside.png differ diff --git a/graphics/chroma-marble/64_wall_outside_shadow.png b/graphics/chroma-marble/64_wall_outside_shadow.png new file mode 100644 index 0000000..4380f83 Binary files /dev/null and b/graphics/chroma-marble/64_wall_outside_shadow.png differ diff --git a/graphics/chroma-marble/64_wall_x.png b/graphics/chroma-marble/64_wall_x.png new file mode 100644 index 0000000..84677a8 Binary files /dev/null and b/graphics/chroma-marble/64_wall_x.png differ diff --git a/graphics/chroma-marble/64_wall_x_shadow.png b/graphics/chroma-marble/64_wall_x_shadow.png new file mode 100644 index 0000000..4b2a6c6 Binary files /dev/null and b/graphics/chroma-marble/64_wall_x_shadow.png differ diff --git a/graphics/chroma-marble/64_wall_y.png b/graphics/chroma-marble/64_wall_y.png new file mode 100644 index 0000000..5a99362 Binary files /dev/null and b/graphics/chroma-marble/64_wall_y.png differ diff --git a/graphics/chroma-marble/64_wall_y_shadow.png b/graphics/chroma-marble/64_wall_y_shadow.png new file mode 100644 index 0000000..8fbd6b3 Binary files /dev/null and b/graphics/chroma-marble/64_wall_y_shadow.png differ diff --git a/graphics/chroma-neon.chroma b/graphics/chroma-neon.chroma new file mode 100644 index 0000000..436804a --- /dev/null +++ b/graphics/chroma-neon.chroma @@ -0,0 +1,327 @@ + + + + + +Chroma Neon + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/graphics/chroma-neon/16_arrow_blue_down.png b/graphics/chroma-neon/16_arrow_blue_down.png new file mode 100644 index 0000000..0e2a874 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_blue_down.png differ diff --git a/graphics/chroma-neon/16_arrow_blue_down_shadow.png b/graphics/chroma-neon/16_arrow_blue_down_shadow.png new file mode 100644 index 0000000..d2ec838 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_blue_left.png b/graphics/chroma-neon/16_arrow_blue_left.png new file mode 100644 index 0000000..243a6ac Binary files /dev/null and b/graphics/chroma-neon/16_arrow_blue_left.png differ diff --git a/graphics/chroma-neon/16_arrow_blue_left_shadow.png b/graphics/chroma-neon/16_arrow_blue_left_shadow.png new file mode 100644 index 0000000..016bc3b Binary files /dev/null and b/graphics/chroma-neon/16_arrow_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_blue_right.png b/graphics/chroma-neon/16_arrow_blue_right.png new file mode 100644 index 0000000..9fba765 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_blue_right.png differ diff --git a/graphics/chroma-neon/16_arrow_blue_right_shadow.png b/graphics/chroma-neon/16_arrow_blue_right_shadow.png new file mode 100644 index 0000000..753dc84 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_blue_up.png b/graphics/chroma-neon/16_arrow_blue_up.png new file mode 100644 index 0000000..19f1b3e Binary files /dev/null and b/graphics/chroma-neon/16_arrow_blue_up.png differ diff --git a/graphics/chroma-neon/16_arrow_blue_up_shadow.png b/graphics/chroma-neon/16_arrow_blue_up_shadow.png new file mode 100644 index 0000000..8d6e7c7 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_green_down.png b/graphics/chroma-neon/16_arrow_green_down.png new file mode 100644 index 0000000..70b6174 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_green_down.png differ diff --git a/graphics/chroma-neon/16_arrow_green_down_shadow.png b/graphics/chroma-neon/16_arrow_green_down_shadow.png new file mode 100644 index 0000000..9048d6a Binary files /dev/null and b/graphics/chroma-neon/16_arrow_green_down_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_green_left.png b/graphics/chroma-neon/16_arrow_green_left.png new file mode 100644 index 0000000..65169dd Binary files /dev/null and b/graphics/chroma-neon/16_arrow_green_left.png differ diff --git a/graphics/chroma-neon/16_arrow_green_left_shadow.png b/graphics/chroma-neon/16_arrow_green_left_shadow.png new file mode 100644 index 0000000..0c08056 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_green_left_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_green_right.png b/graphics/chroma-neon/16_arrow_green_right.png new file mode 100644 index 0000000..b6ef871 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_green_right.png differ diff --git a/graphics/chroma-neon/16_arrow_green_right_shadow.png b/graphics/chroma-neon/16_arrow_green_right_shadow.png new file mode 100644 index 0000000..f398411 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_green_right_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_green_up.png b/graphics/chroma-neon/16_arrow_green_up.png new file mode 100644 index 0000000..8a3bf46 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_green_up.png differ diff --git a/graphics/chroma-neon/16_arrow_green_up_shadow.png b/graphics/chroma-neon/16_arrow_green_up_shadow.png new file mode 100644 index 0000000..7ffa9aa Binary files /dev/null and b/graphics/chroma-neon/16_arrow_green_up_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_red_down.png b/graphics/chroma-neon/16_arrow_red_down.png new file mode 100644 index 0000000..2b4b7de Binary files /dev/null and b/graphics/chroma-neon/16_arrow_red_down.png differ diff --git a/graphics/chroma-neon/16_arrow_red_down_shadow.png b/graphics/chroma-neon/16_arrow_red_down_shadow.png new file mode 100644 index 0000000..8a66892 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_red_down_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_red_left.png b/graphics/chroma-neon/16_arrow_red_left.png new file mode 100644 index 0000000..b899719 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_red_left.png differ diff --git a/graphics/chroma-neon/16_arrow_red_left_shadow.png b/graphics/chroma-neon/16_arrow_red_left_shadow.png new file mode 100644 index 0000000..c404303 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_red_left_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_red_right.png b/graphics/chroma-neon/16_arrow_red_right.png new file mode 100644 index 0000000..1869b05 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_red_right.png differ diff --git a/graphics/chroma-neon/16_arrow_red_right_shadow.png b/graphics/chroma-neon/16_arrow_red_right_shadow.png new file mode 100644 index 0000000..b5963a6 Binary files /dev/null and b/graphics/chroma-neon/16_arrow_red_right_shadow.png differ diff --git a/graphics/chroma-neon/16_arrow_red_up.png b/graphics/chroma-neon/16_arrow_red_up.png new file mode 100644 index 0000000..9c8caff Binary files /dev/null and b/graphics/chroma-neon/16_arrow_red_up.png differ diff --git a/graphics/chroma-neon/16_arrow_red_up_shadow.png b/graphics/chroma-neon/16_arrow_red_up_shadow.png new file mode 100644 index 0000000..297119b Binary files /dev/null and b/graphics/chroma-neon/16_arrow_red_up_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_blue_down.png b/graphics/chroma-neon/16_bomb_blue_down.png new file mode 100644 index 0000000..d8b5afe Binary files /dev/null and b/graphics/chroma-neon/16_bomb_blue_down.png differ diff --git a/graphics/chroma-neon/16_bomb_blue_down_shadow.png b/graphics/chroma-neon/16_bomb_blue_down_shadow.png new file mode 100644 index 0000000..696cca0 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_blue_left.png b/graphics/chroma-neon/16_bomb_blue_left.png new file mode 100644 index 0000000..cdd50eb Binary files /dev/null and b/graphics/chroma-neon/16_bomb_blue_left.png differ diff --git a/graphics/chroma-neon/16_bomb_blue_left_shadow.png b/graphics/chroma-neon/16_bomb_blue_left_shadow.png new file mode 100644 index 0000000..0733f35 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_blue_right.png b/graphics/chroma-neon/16_bomb_blue_right.png new file mode 100644 index 0000000..5c15189 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_blue_right.png differ diff --git a/graphics/chroma-neon/16_bomb_blue_right_shadow.png b/graphics/chroma-neon/16_bomb_blue_right_shadow.png new file mode 100644 index 0000000..3a6cd1e Binary files /dev/null and b/graphics/chroma-neon/16_bomb_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_blue_up.png b/graphics/chroma-neon/16_bomb_blue_up.png new file mode 100644 index 0000000..ffaf32c Binary files /dev/null and b/graphics/chroma-neon/16_bomb_blue_up.png differ diff --git a/graphics/chroma-neon/16_bomb_blue_up_shadow.png b/graphics/chroma-neon/16_bomb_blue_up_shadow.png new file mode 100644 index 0000000..129a215 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_green_down.png b/graphics/chroma-neon/16_bomb_green_down.png new file mode 100644 index 0000000..cf35e58 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_green_down.png differ diff --git a/graphics/chroma-neon/16_bomb_green_down_shadow.png b/graphics/chroma-neon/16_bomb_green_down_shadow.png new file mode 100644 index 0000000..c3057d4 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_green_down_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_green_left.png b/graphics/chroma-neon/16_bomb_green_left.png new file mode 100644 index 0000000..ae132ea Binary files /dev/null and b/graphics/chroma-neon/16_bomb_green_left.png differ diff --git a/graphics/chroma-neon/16_bomb_green_left_shadow.png b/graphics/chroma-neon/16_bomb_green_left_shadow.png new file mode 100644 index 0000000..9bafccd Binary files /dev/null and b/graphics/chroma-neon/16_bomb_green_left_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_green_right.png b/graphics/chroma-neon/16_bomb_green_right.png new file mode 100644 index 0000000..37e3d7d Binary files /dev/null and b/graphics/chroma-neon/16_bomb_green_right.png differ diff --git a/graphics/chroma-neon/16_bomb_green_right_shadow.png b/graphics/chroma-neon/16_bomb_green_right_shadow.png new file mode 100644 index 0000000..8160bc2 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_green_right_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_green_up.png b/graphics/chroma-neon/16_bomb_green_up.png new file mode 100644 index 0000000..ea76411 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_green_up.png differ diff --git a/graphics/chroma-neon/16_bomb_green_up_shadow.png b/graphics/chroma-neon/16_bomb_green_up_shadow.png new file mode 100644 index 0000000..b5251fb Binary files /dev/null and b/graphics/chroma-neon/16_bomb_green_up_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_red_down.png b/graphics/chroma-neon/16_bomb_red_down.png new file mode 100644 index 0000000..f74ba21 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_red_down.png differ diff --git a/graphics/chroma-neon/16_bomb_red_down_shadow.png b/graphics/chroma-neon/16_bomb_red_down_shadow.png new file mode 100644 index 0000000..a1ff93e Binary files /dev/null and b/graphics/chroma-neon/16_bomb_red_down_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_red_left.png b/graphics/chroma-neon/16_bomb_red_left.png new file mode 100644 index 0000000..b34ec72 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_red_left.png differ diff --git a/graphics/chroma-neon/16_bomb_red_left_shadow.png b/graphics/chroma-neon/16_bomb_red_left_shadow.png new file mode 100644 index 0000000..4935610 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_red_left_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_red_right.png b/graphics/chroma-neon/16_bomb_red_right.png new file mode 100644 index 0000000..161bc59 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_red_right.png differ diff --git a/graphics/chroma-neon/16_bomb_red_right_shadow.png b/graphics/chroma-neon/16_bomb_red_right_shadow.png new file mode 100644 index 0000000..86a8987 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_red_right_shadow.png differ diff --git a/graphics/chroma-neon/16_bomb_red_up.png b/graphics/chroma-neon/16_bomb_red_up.png new file mode 100644 index 0000000..0a95127 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_red_up.png differ diff --git a/graphics/chroma-neon/16_bomb_red_up_shadow.png b/graphics/chroma-neon/16_bomb_red_up_shadow.png new file mode 100644 index 0000000..2d45cd4 Binary files /dev/null and b/graphics/chroma-neon/16_bomb_red_up_shadow.png differ diff --git a/graphics/chroma-neon/16_circle.png b/graphics/chroma-neon/16_circle.png new file mode 100644 index 0000000..b3e5a16 Binary files /dev/null and b/graphics/chroma-neon/16_circle.png differ diff --git a/graphics/chroma-neon/16_circle_double.png b/graphics/chroma-neon/16_circle_double.png new file mode 100644 index 0000000..32c20fb Binary files /dev/null and b/graphics/chroma-neon/16_circle_double.png differ diff --git a/graphics/chroma-neon/16_circle_double_shadow.png b/graphics/chroma-neon/16_circle_double_shadow.png new file mode 100644 index 0000000..49fc80c Binary files /dev/null and b/graphics/chroma-neon/16_circle_double_shadow.png differ diff --git a/graphics/chroma-neon/16_circle_shadow.png b/graphics/chroma-neon/16_circle_shadow.png new file mode 100644 index 0000000..eff211a Binary files /dev/null and b/graphics/chroma-neon/16_circle_shadow.png differ diff --git a/graphics/chroma-neon/16_door.png b/graphics/chroma-neon/16_door.png new file mode 100644 index 0000000..8e0fa8a Binary files /dev/null and b/graphics/chroma-neon/16_door.png differ diff --git a/graphics/chroma-neon/16_door_shadow.png b/graphics/chroma-neon/16_door_shadow.png new file mode 100644 index 0000000..eedab0c Binary files /dev/null and b/graphics/chroma-neon/16_door_shadow.png differ diff --git a/graphics/chroma-neon/16_dots.png b/graphics/chroma-neon/16_dots.png new file mode 100644 index 0000000..87ad933 Binary files /dev/null and b/graphics/chroma-neon/16_dots.png differ diff --git a/graphics/chroma-neon/16_dots_double.png b/graphics/chroma-neon/16_dots_double.png new file mode 100644 index 0000000..7de5e3d Binary files /dev/null and b/graphics/chroma-neon/16_dots_double.png differ diff --git a/graphics/chroma-neon/16_dots_double_shadow.png b/graphics/chroma-neon/16_dots_double_shadow.png new file mode 100644 index 0000000..8cad823 Binary files /dev/null and b/graphics/chroma-neon/16_dots_double_shadow.png differ diff --git a/graphics/chroma-neon/16_dots_shadow.png b/graphics/chroma-neon/16_dots_shadow.png new file mode 100644 index 0000000..250c70e Binary files /dev/null and b/graphics/chroma-neon/16_dots_shadow.png differ diff --git a/graphics/chroma-neon/16_dots_x.png b/graphics/chroma-neon/16_dots_x.png new file mode 100644 index 0000000..4f9b2c5 Binary files /dev/null and b/graphics/chroma-neon/16_dots_x.png differ diff --git a/graphics/chroma-neon/16_dots_x_shadow.png b/graphics/chroma-neon/16_dots_x_shadow.png new file mode 100644 index 0000000..e2526d7 Binary files /dev/null and b/graphics/chroma-neon/16_dots_x_shadow.png differ diff --git a/graphics/chroma-neon/16_dots_y.png b/graphics/chroma-neon/16_dots_y.png new file mode 100644 index 0000000..698f5c9 Binary files /dev/null and b/graphics/chroma-neon/16_dots_y.png differ diff --git a/graphics/chroma-neon/16_dots_y_shadow.png b/graphics/chroma-neon/16_dots_y_shadow.png new file mode 100644 index 0000000..244fba9 Binary files /dev/null and b/graphics/chroma-neon/16_dots_y_shadow.png differ diff --git a/graphics/chroma-neon/16_earth.png b/graphics/chroma-neon/16_earth.png new file mode 100644 index 0000000..0cb36bd Binary files /dev/null and b/graphics/chroma-neon/16_earth.png differ diff --git a/graphics/chroma-neon/16_earth_double.png b/graphics/chroma-neon/16_earth_double.png new file mode 100644 index 0000000..5c1c8c2 Binary files /dev/null and b/graphics/chroma-neon/16_earth_double.png differ diff --git a/graphics/chroma-neon/16_earth_double_shadow.png b/graphics/chroma-neon/16_earth_double_shadow.png new file mode 100644 index 0000000..50b442d Binary files /dev/null and b/graphics/chroma-neon/16_earth_double_shadow.png differ diff --git a/graphics/chroma-neon/16_earth_shadow.png b/graphics/chroma-neon/16_earth_shadow.png new file mode 100644 index 0000000..7d08614 Binary files /dev/null and b/graphics/chroma-neon/16_earth_shadow.png differ diff --git a/graphics/chroma-neon/16_earth_x.png b/graphics/chroma-neon/16_earth_x.png new file mode 100644 index 0000000..016131a Binary files /dev/null and b/graphics/chroma-neon/16_earth_x.png differ diff --git a/graphics/chroma-neon/16_earth_x_shadow.png b/graphics/chroma-neon/16_earth_x_shadow.png new file mode 100644 index 0000000..1497f90 Binary files /dev/null and b/graphics/chroma-neon/16_earth_x_shadow.png differ diff --git a/graphics/chroma-neon/16_earth_y.png b/graphics/chroma-neon/16_earth_y.png new file mode 100644 index 0000000..702212b Binary files /dev/null and b/graphics/chroma-neon/16_earth_y.png differ diff --git a/graphics/chroma-neon/16_earth_y_shadow.png b/graphics/chroma-neon/16_earth_y_shadow.png new file mode 100644 index 0000000..e1d4604 Binary files /dev/null and b/graphics/chroma-neon/16_earth_y_shadow.png differ diff --git a/graphics/chroma-neon/16_map_bottom_left.png b/graphics/chroma-neon/16_map_bottom_left.png new file mode 100644 index 0000000..67bff5f Binary files /dev/null and b/graphics/chroma-neon/16_map_bottom_left.png differ diff --git a/graphics/chroma-neon/16_map_bottom_left_shadow.png b/graphics/chroma-neon/16_map_bottom_left_shadow.png new file mode 100644 index 0000000..2d96ce1 Binary files /dev/null and b/graphics/chroma-neon/16_map_bottom_left_shadow.png differ diff --git a/graphics/chroma-neon/16_map_bottom_right.png b/graphics/chroma-neon/16_map_bottom_right.png new file mode 100644 index 0000000..6949ea7 Binary files /dev/null and b/graphics/chroma-neon/16_map_bottom_right.png differ diff --git a/graphics/chroma-neon/16_map_bottom_right_shadow.png b/graphics/chroma-neon/16_map_bottom_right_shadow.png new file mode 100644 index 0000000..c493183 Binary files /dev/null and b/graphics/chroma-neon/16_map_bottom_right_shadow.png differ diff --git a/graphics/chroma-neon/16_map_top_left.png b/graphics/chroma-neon/16_map_top_left.png new file mode 100644 index 0000000..9663688 Binary files /dev/null and b/graphics/chroma-neon/16_map_top_left.png differ diff --git a/graphics/chroma-neon/16_map_top_left_shadow.png b/graphics/chroma-neon/16_map_top_left_shadow.png new file mode 100644 index 0000000..2c305b0 Binary files /dev/null and b/graphics/chroma-neon/16_map_top_left_shadow.png differ diff --git a/graphics/chroma-neon/16_map_top_right.png b/graphics/chroma-neon/16_map_top_right.png new file mode 100644 index 0000000..0409362 Binary files /dev/null and b/graphics/chroma-neon/16_map_top_right.png differ diff --git a/graphics/chroma-neon/16_map_top_right_shadow.png b/graphics/chroma-neon/16_map_top_right_shadow.png new file mode 100644 index 0000000..d665db4 Binary files /dev/null and b/graphics/chroma-neon/16_map_top_right_shadow.png differ diff --git a/graphics/chroma-neon/16_player_one.png b/graphics/chroma-neon/16_player_one.png new file mode 100644 index 0000000..324b094 Binary files /dev/null and b/graphics/chroma-neon/16_player_one.png differ diff --git a/graphics/chroma-neon/16_player_one_shadow.png b/graphics/chroma-neon/16_player_one_shadow.png new file mode 100644 index 0000000..3f8d7e3 Binary files /dev/null and b/graphics/chroma-neon/16_player_one_shadow.png differ diff --git a/graphics/chroma-neon/16_player_one_swapped.png b/graphics/chroma-neon/16_player_one_swapped.png new file mode 100644 index 0000000..37ff6e0 Binary files /dev/null and b/graphics/chroma-neon/16_player_one_swapped.png differ diff --git a/graphics/chroma-neon/16_player_one_swapped_shadow.png b/graphics/chroma-neon/16_player_one_swapped_shadow.png new file mode 100644 index 0000000..02cefe4 Binary files /dev/null and b/graphics/chroma-neon/16_player_one_swapped_shadow.png differ diff --git a/graphics/chroma-neon/16_player_two.png b/graphics/chroma-neon/16_player_two.png new file mode 100644 index 0000000..c129ef5 Binary files /dev/null and b/graphics/chroma-neon/16_player_two.png differ diff --git a/graphics/chroma-neon/16_player_two_shadow.png b/graphics/chroma-neon/16_player_two_shadow.png new file mode 100644 index 0000000..25da48a Binary files /dev/null and b/graphics/chroma-neon/16_player_two_shadow.png differ diff --git a/graphics/chroma-neon/16_player_two_swapped.png b/graphics/chroma-neon/16_player_two_swapped.png new file mode 100644 index 0000000..68e79f4 Binary files /dev/null and b/graphics/chroma-neon/16_player_two_swapped.png differ diff --git a/graphics/chroma-neon/16_player_two_swapped_shadow.png b/graphics/chroma-neon/16_player_two_swapped_shadow.png new file mode 100644 index 0000000..2ab9c39 Binary files /dev/null and b/graphics/chroma-neon/16_player_two_swapped_shadow.png differ diff --git a/graphics/chroma-neon/16_star.png b/graphics/chroma-neon/16_star.png new file mode 100644 index 0000000..0ed4138 Binary files /dev/null and b/graphics/chroma-neon/16_star.png differ diff --git a/graphics/chroma-neon/16_star_shadow.png b/graphics/chroma-neon/16_star_shadow.png new file mode 100644 index 0000000..d068f07 Binary files /dev/null and b/graphics/chroma-neon/16_star_shadow.png differ diff --git a/graphics/chroma-neon/16_switch.png b/graphics/chroma-neon/16_switch.png new file mode 100644 index 0000000..67c0bbd Binary files /dev/null and b/graphics/chroma-neon/16_switch.png differ diff --git a/graphics/chroma-neon/16_switch_shadow.png b/graphics/chroma-neon/16_switch_shadow.png new file mode 100644 index 0000000..2c20c40 Binary files /dev/null and b/graphics/chroma-neon/16_switch_shadow.png differ diff --git a/graphics/chroma-neon/16_teleport.png b/graphics/chroma-neon/16_teleport.png new file mode 100644 index 0000000..fe19e98 Binary files /dev/null and b/graphics/chroma-neon/16_teleport.png differ diff --git a/graphics/chroma-neon/16_teleport_shadow.png b/graphics/chroma-neon/16_teleport_shadow.png new file mode 100644 index 0000000..86cb952 Binary files /dev/null and b/graphics/chroma-neon/16_teleport_shadow.png differ diff --git a/graphics/chroma-neon/16_wall.png b/graphics/chroma-neon/16_wall.png new file mode 100644 index 0000000..177c148 Binary files /dev/null and b/graphics/chroma-neon/16_wall.png differ diff --git a/graphics/chroma-neon/16_wall_inside.png b/graphics/chroma-neon/16_wall_inside.png new file mode 100644 index 0000000..42601ad Binary files /dev/null and b/graphics/chroma-neon/16_wall_inside.png differ diff --git a/graphics/chroma-neon/16_wall_outside.png b/graphics/chroma-neon/16_wall_outside.png new file mode 100644 index 0000000..6bad16d Binary files /dev/null and b/graphics/chroma-neon/16_wall_outside.png differ diff --git a/graphics/chroma-neon/16_wall_shadow.png b/graphics/chroma-neon/16_wall_shadow.png new file mode 100644 index 0000000..b416c9e Binary files /dev/null and b/graphics/chroma-neon/16_wall_shadow.png differ diff --git a/graphics/chroma-neon/16_wall_x.png b/graphics/chroma-neon/16_wall_x.png new file mode 100644 index 0000000..b7a40a5 Binary files /dev/null and b/graphics/chroma-neon/16_wall_x.png differ diff --git a/graphics/chroma-neon/16_wall_y.png b/graphics/chroma-neon/16_wall_y.png new file mode 100644 index 0000000..8c8717e Binary files /dev/null and b/graphics/chroma-neon/16_wall_y.png differ diff --git a/graphics/chroma-neon/20_arrow_blue_down.png b/graphics/chroma-neon/20_arrow_blue_down.png new file mode 100644 index 0000000..73e4d5b Binary files /dev/null and b/graphics/chroma-neon/20_arrow_blue_down.png differ diff --git a/graphics/chroma-neon/20_arrow_blue_down_shadow.png b/graphics/chroma-neon/20_arrow_blue_down_shadow.png new file mode 100644 index 0000000..b6f57d1 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_blue_left.png b/graphics/chroma-neon/20_arrow_blue_left.png new file mode 100644 index 0000000..93316ec Binary files /dev/null and b/graphics/chroma-neon/20_arrow_blue_left.png differ diff --git a/graphics/chroma-neon/20_arrow_blue_left_shadow.png b/graphics/chroma-neon/20_arrow_blue_left_shadow.png new file mode 100644 index 0000000..77ca854 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_blue_right.png b/graphics/chroma-neon/20_arrow_blue_right.png new file mode 100644 index 0000000..1a9d34c Binary files /dev/null and b/graphics/chroma-neon/20_arrow_blue_right.png differ diff --git a/graphics/chroma-neon/20_arrow_blue_right_shadow.png b/graphics/chroma-neon/20_arrow_blue_right_shadow.png new file mode 100644 index 0000000..36485a2 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_blue_up.png b/graphics/chroma-neon/20_arrow_blue_up.png new file mode 100644 index 0000000..46ee3f1 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_blue_up.png differ diff --git a/graphics/chroma-neon/20_arrow_blue_up_shadow.png b/graphics/chroma-neon/20_arrow_blue_up_shadow.png new file mode 100644 index 0000000..b35c63f Binary files /dev/null and b/graphics/chroma-neon/20_arrow_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_green_down.png b/graphics/chroma-neon/20_arrow_green_down.png new file mode 100644 index 0000000..c89e2bc Binary files /dev/null and b/graphics/chroma-neon/20_arrow_green_down.png differ diff --git a/graphics/chroma-neon/20_arrow_green_down_shadow.png b/graphics/chroma-neon/20_arrow_green_down_shadow.png new file mode 100644 index 0000000..78375da Binary files /dev/null and b/graphics/chroma-neon/20_arrow_green_down_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_green_left.png b/graphics/chroma-neon/20_arrow_green_left.png new file mode 100644 index 0000000..0ea33a5 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_green_left.png differ diff --git a/graphics/chroma-neon/20_arrow_green_left_shadow.png b/graphics/chroma-neon/20_arrow_green_left_shadow.png new file mode 100644 index 0000000..cdf6ba2 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_green_left_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_green_right.png b/graphics/chroma-neon/20_arrow_green_right.png new file mode 100644 index 0000000..fbd1dba Binary files /dev/null and b/graphics/chroma-neon/20_arrow_green_right.png differ diff --git a/graphics/chroma-neon/20_arrow_green_right_shadow.png b/graphics/chroma-neon/20_arrow_green_right_shadow.png new file mode 100644 index 0000000..92b0c94 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_green_right_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_green_up.png b/graphics/chroma-neon/20_arrow_green_up.png new file mode 100644 index 0000000..e77c328 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_green_up.png differ diff --git a/graphics/chroma-neon/20_arrow_green_up_shadow.png b/graphics/chroma-neon/20_arrow_green_up_shadow.png new file mode 100644 index 0000000..d9826af Binary files /dev/null and b/graphics/chroma-neon/20_arrow_green_up_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_red_down.png b/graphics/chroma-neon/20_arrow_red_down.png new file mode 100644 index 0000000..4792338 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_red_down.png differ diff --git a/graphics/chroma-neon/20_arrow_red_down_shadow.png b/graphics/chroma-neon/20_arrow_red_down_shadow.png new file mode 100644 index 0000000..f2ea0a7 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_red_down_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_red_left.png b/graphics/chroma-neon/20_arrow_red_left.png new file mode 100644 index 0000000..f19a3db Binary files /dev/null and b/graphics/chroma-neon/20_arrow_red_left.png differ diff --git a/graphics/chroma-neon/20_arrow_red_left_shadow.png b/graphics/chroma-neon/20_arrow_red_left_shadow.png new file mode 100644 index 0000000..6b80bde Binary files /dev/null and b/graphics/chroma-neon/20_arrow_red_left_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_red_right.png b/graphics/chroma-neon/20_arrow_red_right.png new file mode 100644 index 0000000..22f44e0 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_red_right.png differ diff --git a/graphics/chroma-neon/20_arrow_red_right_shadow.png b/graphics/chroma-neon/20_arrow_red_right_shadow.png new file mode 100644 index 0000000..bdbcb8b Binary files /dev/null and b/graphics/chroma-neon/20_arrow_red_right_shadow.png differ diff --git a/graphics/chroma-neon/20_arrow_red_up.png b/graphics/chroma-neon/20_arrow_red_up.png new file mode 100644 index 0000000..6a19385 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_red_up.png differ diff --git a/graphics/chroma-neon/20_arrow_red_up_shadow.png b/graphics/chroma-neon/20_arrow_red_up_shadow.png new file mode 100644 index 0000000..c57ead0 Binary files /dev/null and b/graphics/chroma-neon/20_arrow_red_up_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_blue_down.png b/graphics/chroma-neon/20_bomb_blue_down.png new file mode 100644 index 0000000..b94d784 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_blue_down.png differ diff --git a/graphics/chroma-neon/20_bomb_blue_down_shadow.png b/graphics/chroma-neon/20_bomb_blue_down_shadow.png new file mode 100644 index 0000000..6ef6e74 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_blue_left.png b/graphics/chroma-neon/20_bomb_blue_left.png new file mode 100644 index 0000000..5ab46d5 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_blue_left.png differ diff --git a/graphics/chroma-neon/20_bomb_blue_left_shadow.png b/graphics/chroma-neon/20_bomb_blue_left_shadow.png new file mode 100644 index 0000000..f9788ef Binary files /dev/null and b/graphics/chroma-neon/20_bomb_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_blue_right.png b/graphics/chroma-neon/20_bomb_blue_right.png new file mode 100644 index 0000000..e5e8a81 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_blue_right.png differ diff --git a/graphics/chroma-neon/20_bomb_blue_right_shadow.png b/graphics/chroma-neon/20_bomb_blue_right_shadow.png new file mode 100644 index 0000000..56e9d35 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_blue_up.png b/graphics/chroma-neon/20_bomb_blue_up.png new file mode 100644 index 0000000..e9d1f7c Binary files /dev/null and b/graphics/chroma-neon/20_bomb_blue_up.png differ diff --git a/graphics/chroma-neon/20_bomb_blue_up_shadow.png b/graphics/chroma-neon/20_bomb_blue_up_shadow.png new file mode 100644 index 0000000..a08cb08 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_green_down.png b/graphics/chroma-neon/20_bomb_green_down.png new file mode 100644 index 0000000..560ac19 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_green_down.png differ diff --git a/graphics/chroma-neon/20_bomb_green_down_shadow.png b/graphics/chroma-neon/20_bomb_green_down_shadow.png new file mode 100644 index 0000000..073633d Binary files /dev/null and b/graphics/chroma-neon/20_bomb_green_down_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_green_left.png b/graphics/chroma-neon/20_bomb_green_left.png new file mode 100644 index 0000000..bc1f1ef Binary files /dev/null and b/graphics/chroma-neon/20_bomb_green_left.png differ diff --git a/graphics/chroma-neon/20_bomb_green_left_shadow.png b/graphics/chroma-neon/20_bomb_green_left_shadow.png new file mode 100644 index 0000000..1ad6634 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_green_left_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_green_right.png b/graphics/chroma-neon/20_bomb_green_right.png new file mode 100644 index 0000000..1959bac Binary files /dev/null and b/graphics/chroma-neon/20_bomb_green_right.png differ diff --git a/graphics/chroma-neon/20_bomb_green_right_shadow.png b/graphics/chroma-neon/20_bomb_green_right_shadow.png new file mode 100644 index 0000000..4688abb Binary files /dev/null and b/graphics/chroma-neon/20_bomb_green_right_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_green_up.png b/graphics/chroma-neon/20_bomb_green_up.png new file mode 100644 index 0000000..f0e34e5 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_green_up.png differ diff --git a/graphics/chroma-neon/20_bomb_green_up_shadow.png b/graphics/chroma-neon/20_bomb_green_up_shadow.png new file mode 100644 index 0000000..254cd2f Binary files /dev/null and b/graphics/chroma-neon/20_bomb_green_up_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_red_down.png b/graphics/chroma-neon/20_bomb_red_down.png new file mode 100644 index 0000000..d5f1d35 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_red_down.png differ diff --git a/graphics/chroma-neon/20_bomb_red_down_shadow.png b/graphics/chroma-neon/20_bomb_red_down_shadow.png new file mode 100644 index 0000000..6db5f0f Binary files /dev/null and b/graphics/chroma-neon/20_bomb_red_down_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_red_left.png b/graphics/chroma-neon/20_bomb_red_left.png new file mode 100644 index 0000000..656ba94 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_red_left.png differ diff --git a/graphics/chroma-neon/20_bomb_red_left_shadow.png b/graphics/chroma-neon/20_bomb_red_left_shadow.png new file mode 100644 index 0000000..c65f593 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_red_left_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_red_right.png b/graphics/chroma-neon/20_bomb_red_right.png new file mode 100644 index 0000000..618abe3 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_red_right.png differ diff --git a/graphics/chroma-neon/20_bomb_red_right_shadow.png b/graphics/chroma-neon/20_bomb_red_right_shadow.png new file mode 100644 index 0000000..44a5209 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_red_right_shadow.png differ diff --git a/graphics/chroma-neon/20_bomb_red_up.png b/graphics/chroma-neon/20_bomb_red_up.png new file mode 100644 index 0000000..9dad4a6 Binary files /dev/null and b/graphics/chroma-neon/20_bomb_red_up.png differ diff --git a/graphics/chroma-neon/20_bomb_red_up_shadow.png b/graphics/chroma-neon/20_bomb_red_up_shadow.png new file mode 100644 index 0000000..7f8d01d Binary files /dev/null and b/graphics/chroma-neon/20_bomb_red_up_shadow.png differ diff --git a/graphics/chroma-neon/20_circle.png b/graphics/chroma-neon/20_circle.png new file mode 100644 index 0000000..a965c74 Binary files /dev/null and b/graphics/chroma-neon/20_circle.png differ diff --git a/graphics/chroma-neon/20_circle_double.png b/graphics/chroma-neon/20_circle_double.png new file mode 100644 index 0000000..2ef9409 Binary files /dev/null and b/graphics/chroma-neon/20_circle_double.png differ diff --git a/graphics/chroma-neon/20_circle_double_shadow.png b/graphics/chroma-neon/20_circle_double_shadow.png new file mode 100644 index 0000000..10f027b Binary files /dev/null and b/graphics/chroma-neon/20_circle_double_shadow.png differ diff --git a/graphics/chroma-neon/20_circle_shadow.png b/graphics/chroma-neon/20_circle_shadow.png new file mode 100644 index 0000000..805ce63 Binary files /dev/null and b/graphics/chroma-neon/20_circle_shadow.png differ diff --git a/graphics/chroma-neon/20_door.png b/graphics/chroma-neon/20_door.png new file mode 100644 index 0000000..89fb352 Binary files /dev/null and b/graphics/chroma-neon/20_door.png differ diff --git a/graphics/chroma-neon/20_door_shadow.png b/graphics/chroma-neon/20_door_shadow.png new file mode 100644 index 0000000..18cfc53 Binary files /dev/null and b/graphics/chroma-neon/20_door_shadow.png differ diff --git a/graphics/chroma-neon/20_dots.png b/graphics/chroma-neon/20_dots.png new file mode 100644 index 0000000..9a18637 Binary files /dev/null and b/graphics/chroma-neon/20_dots.png differ diff --git a/graphics/chroma-neon/20_dots_double.png b/graphics/chroma-neon/20_dots_double.png new file mode 100644 index 0000000..5520c2e Binary files /dev/null and b/graphics/chroma-neon/20_dots_double.png differ diff --git a/graphics/chroma-neon/20_dots_double_shadow.png b/graphics/chroma-neon/20_dots_double_shadow.png new file mode 100644 index 0000000..00b8d28 Binary files /dev/null and b/graphics/chroma-neon/20_dots_double_shadow.png differ diff --git a/graphics/chroma-neon/20_dots_shadow.png b/graphics/chroma-neon/20_dots_shadow.png new file mode 100644 index 0000000..23f0829 Binary files /dev/null and b/graphics/chroma-neon/20_dots_shadow.png differ diff --git a/graphics/chroma-neon/20_dots_x.png b/graphics/chroma-neon/20_dots_x.png new file mode 100644 index 0000000..db41cf2 Binary files /dev/null and b/graphics/chroma-neon/20_dots_x.png differ diff --git a/graphics/chroma-neon/20_dots_x_shadow.png b/graphics/chroma-neon/20_dots_x_shadow.png new file mode 100644 index 0000000..a761c5f Binary files /dev/null and b/graphics/chroma-neon/20_dots_x_shadow.png differ diff --git a/graphics/chroma-neon/20_dots_y.png b/graphics/chroma-neon/20_dots_y.png new file mode 100644 index 0000000..34deafb Binary files /dev/null and b/graphics/chroma-neon/20_dots_y.png differ diff --git a/graphics/chroma-neon/20_dots_y_shadow.png b/graphics/chroma-neon/20_dots_y_shadow.png new file mode 100644 index 0000000..7625430 Binary files /dev/null and b/graphics/chroma-neon/20_dots_y_shadow.png differ diff --git a/graphics/chroma-neon/20_earth.png b/graphics/chroma-neon/20_earth.png new file mode 100644 index 0000000..7b17dcd Binary files /dev/null and b/graphics/chroma-neon/20_earth.png differ diff --git a/graphics/chroma-neon/20_earth_double.png b/graphics/chroma-neon/20_earth_double.png new file mode 100644 index 0000000..a1ebf21 Binary files /dev/null and b/graphics/chroma-neon/20_earth_double.png differ diff --git a/graphics/chroma-neon/20_earth_double_shadow.png b/graphics/chroma-neon/20_earth_double_shadow.png new file mode 100644 index 0000000..2fb9028 Binary files /dev/null and b/graphics/chroma-neon/20_earth_double_shadow.png differ diff --git a/graphics/chroma-neon/20_earth_shadow.png b/graphics/chroma-neon/20_earth_shadow.png new file mode 100644 index 0000000..1cbf0e7 Binary files /dev/null and b/graphics/chroma-neon/20_earth_shadow.png differ diff --git a/graphics/chroma-neon/20_earth_x.png b/graphics/chroma-neon/20_earth_x.png new file mode 100644 index 0000000..c8531a0 Binary files /dev/null and b/graphics/chroma-neon/20_earth_x.png differ diff --git a/graphics/chroma-neon/20_earth_x_shadow.png b/graphics/chroma-neon/20_earth_x_shadow.png new file mode 100644 index 0000000..b434fdd Binary files /dev/null and b/graphics/chroma-neon/20_earth_x_shadow.png differ diff --git a/graphics/chroma-neon/20_earth_y.png b/graphics/chroma-neon/20_earth_y.png new file mode 100644 index 0000000..e180f26 Binary files /dev/null and b/graphics/chroma-neon/20_earth_y.png differ diff --git a/graphics/chroma-neon/20_earth_y_shadow.png b/graphics/chroma-neon/20_earth_y_shadow.png new file mode 100644 index 0000000..eb49262 Binary files /dev/null and b/graphics/chroma-neon/20_earth_y_shadow.png differ diff --git a/graphics/chroma-neon/20_map_bottom_left.png b/graphics/chroma-neon/20_map_bottom_left.png new file mode 100644 index 0000000..06d9ec7 Binary files /dev/null and b/graphics/chroma-neon/20_map_bottom_left.png differ diff --git a/graphics/chroma-neon/20_map_bottom_left_shadow.png b/graphics/chroma-neon/20_map_bottom_left_shadow.png new file mode 100644 index 0000000..253211c Binary files /dev/null and b/graphics/chroma-neon/20_map_bottom_left_shadow.png differ diff --git a/graphics/chroma-neon/20_map_bottom_right.png b/graphics/chroma-neon/20_map_bottom_right.png new file mode 100644 index 0000000..8e4108c Binary files /dev/null and b/graphics/chroma-neon/20_map_bottom_right.png differ diff --git a/graphics/chroma-neon/20_map_bottom_right_shadow.png b/graphics/chroma-neon/20_map_bottom_right_shadow.png new file mode 100644 index 0000000..ad3439b Binary files /dev/null and b/graphics/chroma-neon/20_map_bottom_right_shadow.png differ diff --git a/graphics/chroma-neon/20_map_top_left.png b/graphics/chroma-neon/20_map_top_left.png new file mode 100644 index 0000000..98367ec Binary files /dev/null and b/graphics/chroma-neon/20_map_top_left.png differ diff --git a/graphics/chroma-neon/20_map_top_left_shadow.png b/graphics/chroma-neon/20_map_top_left_shadow.png new file mode 100644 index 0000000..58160b9 Binary files /dev/null and b/graphics/chroma-neon/20_map_top_left_shadow.png differ diff --git a/graphics/chroma-neon/20_map_top_right.png b/graphics/chroma-neon/20_map_top_right.png new file mode 100644 index 0000000..0b6fe3a Binary files /dev/null and b/graphics/chroma-neon/20_map_top_right.png differ diff --git a/graphics/chroma-neon/20_map_top_right_shadow.png b/graphics/chroma-neon/20_map_top_right_shadow.png new file mode 100644 index 0000000..f1d54f4 Binary files /dev/null and b/graphics/chroma-neon/20_map_top_right_shadow.png differ diff --git a/graphics/chroma-neon/20_player_one.png b/graphics/chroma-neon/20_player_one.png new file mode 100644 index 0000000..7ccffd1 Binary files /dev/null and b/graphics/chroma-neon/20_player_one.png differ diff --git a/graphics/chroma-neon/20_player_one_shadow.png b/graphics/chroma-neon/20_player_one_shadow.png new file mode 100644 index 0000000..702470e Binary files /dev/null and b/graphics/chroma-neon/20_player_one_shadow.png differ diff --git a/graphics/chroma-neon/20_player_one_swapped.png b/graphics/chroma-neon/20_player_one_swapped.png new file mode 100644 index 0000000..df64e8a Binary files /dev/null and b/graphics/chroma-neon/20_player_one_swapped.png differ diff --git a/graphics/chroma-neon/20_player_one_swapped_shadow.png b/graphics/chroma-neon/20_player_one_swapped_shadow.png new file mode 100644 index 0000000..36a3739 Binary files /dev/null and b/graphics/chroma-neon/20_player_one_swapped_shadow.png differ diff --git a/graphics/chroma-neon/20_player_two.png b/graphics/chroma-neon/20_player_two.png new file mode 100644 index 0000000..c69ca55 Binary files /dev/null and b/graphics/chroma-neon/20_player_two.png differ diff --git a/graphics/chroma-neon/20_player_two_shadow.png b/graphics/chroma-neon/20_player_two_shadow.png new file mode 100644 index 0000000..5d0751e Binary files /dev/null and b/graphics/chroma-neon/20_player_two_shadow.png differ diff --git a/graphics/chroma-neon/20_player_two_swapped.png b/graphics/chroma-neon/20_player_two_swapped.png new file mode 100644 index 0000000..0763ee0 Binary files /dev/null and b/graphics/chroma-neon/20_player_two_swapped.png differ diff --git a/graphics/chroma-neon/20_player_two_swapped_shadow.png b/graphics/chroma-neon/20_player_two_swapped_shadow.png new file mode 100644 index 0000000..503884f Binary files /dev/null and b/graphics/chroma-neon/20_player_two_swapped_shadow.png differ diff --git a/graphics/chroma-neon/20_star.png b/graphics/chroma-neon/20_star.png new file mode 100644 index 0000000..4779d20 Binary files /dev/null and b/graphics/chroma-neon/20_star.png differ diff --git a/graphics/chroma-neon/20_star_shadow.png b/graphics/chroma-neon/20_star_shadow.png new file mode 100644 index 0000000..543cdd4 Binary files /dev/null and b/graphics/chroma-neon/20_star_shadow.png differ diff --git a/graphics/chroma-neon/20_switch.png b/graphics/chroma-neon/20_switch.png new file mode 100644 index 0000000..0ddc829 Binary files /dev/null and b/graphics/chroma-neon/20_switch.png differ diff --git a/graphics/chroma-neon/20_switch_shadow.png b/graphics/chroma-neon/20_switch_shadow.png new file mode 100644 index 0000000..710cb35 Binary files /dev/null and b/graphics/chroma-neon/20_switch_shadow.png differ diff --git a/graphics/chroma-neon/20_teleport.png b/graphics/chroma-neon/20_teleport.png new file mode 100644 index 0000000..f123d2e Binary files /dev/null and b/graphics/chroma-neon/20_teleport.png differ diff --git a/graphics/chroma-neon/20_teleport_shadow.png b/graphics/chroma-neon/20_teleport_shadow.png new file mode 100644 index 0000000..cacf215 Binary files /dev/null and b/graphics/chroma-neon/20_teleport_shadow.png differ diff --git a/graphics/chroma-neon/20_wall.png b/graphics/chroma-neon/20_wall.png new file mode 100644 index 0000000..8f5460e Binary files /dev/null and b/graphics/chroma-neon/20_wall.png differ diff --git a/graphics/chroma-neon/20_wall_inside.png b/graphics/chroma-neon/20_wall_inside.png new file mode 100644 index 0000000..7d2e0b1 Binary files /dev/null and b/graphics/chroma-neon/20_wall_inside.png differ diff --git a/graphics/chroma-neon/20_wall_outside.png b/graphics/chroma-neon/20_wall_outside.png new file mode 100644 index 0000000..b2a2bd1 Binary files /dev/null and b/graphics/chroma-neon/20_wall_outside.png differ diff --git a/graphics/chroma-neon/20_wall_shadow.png b/graphics/chroma-neon/20_wall_shadow.png new file mode 100644 index 0000000..37dacf6 Binary files /dev/null and b/graphics/chroma-neon/20_wall_shadow.png differ diff --git a/graphics/chroma-neon/20_wall_x.png b/graphics/chroma-neon/20_wall_x.png new file mode 100644 index 0000000..2f789b7 Binary files /dev/null and b/graphics/chroma-neon/20_wall_x.png differ diff --git a/graphics/chroma-neon/20_wall_y.png b/graphics/chroma-neon/20_wall_y.png new file mode 100644 index 0000000..1d58287 Binary files /dev/null and b/graphics/chroma-neon/20_wall_y.png differ diff --git a/graphics/chroma-neon/24_arrow_blue_down.png b/graphics/chroma-neon/24_arrow_blue_down.png new file mode 100644 index 0000000..88c6801 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_blue_down.png differ diff --git a/graphics/chroma-neon/24_arrow_blue_down_shadow.png b/graphics/chroma-neon/24_arrow_blue_down_shadow.png new file mode 100644 index 0000000..e2e4a6f Binary files /dev/null and b/graphics/chroma-neon/24_arrow_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_blue_left.png b/graphics/chroma-neon/24_arrow_blue_left.png new file mode 100644 index 0000000..f24fd19 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_blue_left.png differ diff --git a/graphics/chroma-neon/24_arrow_blue_left_shadow.png b/graphics/chroma-neon/24_arrow_blue_left_shadow.png new file mode 100644 index 0000000..c11bf6c Binary files /dev/null and b/graphics/chroma-neon/24_arrow_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_blue_right.png b/graphics/chroma-neon/24_arrow_blue_right.png new file mode 100644 index 0000000..43dd69e Binary files /dev/null and b/graphics/chroma-neon/24_arrow_blue_right.png differ diff --git a/graphics/chroma-neon/24_arrow_blue_right_shadow.png b/graphics/chroma-neon/24_arrow_blue_right_shadow.png new file mode 100644 index 0000000..90b3860 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_blue_up.png b/graphics/chroma-neon/24_arrow_blue_up.png new file mode 100644 index 0000000..8a218bd Binary files /dev/null and b/graphics/chroma-neon/24_arrow_blue_up.png differ diff --git a/graphics/chroma-neon/24_arrow_blue_up_shadow.png b/graphics/chroma-neon/24_arrow_blue_up_shadow.png new file mode 100644 index 0000000..f2abcf4 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_green_down.png b/graphics/chroma-neon/24_arrow_green_down.png new file mode 100644 index 0000000..a429354 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_green_down.png differ diff --git a/graphics/chroma-neon/24_arrow_green_down_shadow.png b/graphics/chroma-neon/24_arrow_green_down_shadow.png new file mode 100644 index 0000000..95d84e0 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_green_down_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_green_left.png b/graphics/chroma-neon/24_arrow_green_left.png new file mode 100644 index 0000000..ea3f941 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_green_left.png differ diff --git a/graphics/chroma-neon/24_arrow_green_left_shadow.png b/graphics/chroma-neon/24_arrow_green_left_shadow.png new file mode 100644 index 0000000..69d65bc Binary files /dev/null and b/graphics/chroma-neon/24_arrow_green_left_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_green_right.png b/graphics/chroma-neon/24_arrow_green_right.png new file mode 100644 index 0000000..242b646 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_green_right.png differ diff --git a/graphics/chroma-neon/24_arrow_green_right_shadow.png b/graphics/chroma-neon/24_arrow_green_right_shadow.png new file mode 100644 index 0000000..d1d1db5 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_green_right_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_green_up.png b/graphics/chroma-neon/24_arrow_green_up.png new file mode 100644 index 0000000..9902810 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_green_up.png differ diff --git a/graphics/chroma-neon/24_arrow_green_up_shadow.png b/graphics/chroma-neon/24_arrow_green_up_shadow.png new file mode 100644 index 0000000..d41cee2 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_green_up_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_red_down.png b/graphics/chroma-neon/24_arrow_red_down.png new file mode 100644 index 0000000..52dd2c5 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_red_down.png differ diff --git a/graphics/chroma-neon/24_arrow_red_down_shadow.png b/graphics/chroma-neon/24_arrow_red_down_shadow.png new file mode 100644 index 0000000..f6e4e90 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_red_down_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_red_left.png b/graphics/chroma-neon/24_arrow_red_left.png new file mode 100644 index 0000000..92b7d6d Binary files /dev/null and b/graphics/chroma-neon/24_arrow_red_left.png differ diff --git a/graphics/chroma-neon/24_arrow_red_left_shadow.png b/graphics/chroma-neon/24_arrow_red_left_shadow.png new file mode 100644 index 0000000..321125e Binary files /dev/null and b/graphics/chroma-neon/24_arrow_red_left_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_red_right.png b/graphics/chroma-neon/24_arrow_red_right.png new file mode 100644 index 0000000..3559d39 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_red_right.png differ diff --git a/graphics/chroma-neon/24_arrow_red_right_shadow.png b/graphics/chroma-neon/24_arrow_red_right_shadow.png new file mode 100644 index 0000000..3fdedd6 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_red_right_shadow.png differ diff --git a/graphics/chroma-neon/24_arrow_red_up.png b/graphics/chroma-neon/24_arrow_red_up.png new file mode 100644 index 0000000..097fee4 Binary files /dev/null and b/graphics/chroma-neon/24_arrow_red_up.png differ diff --git a/graphics/chroma-neon/24_arrow_red_up_shadow.png b/graphics/chroma-neon/24_arrow_red_up_shadow.png new file mode 100644 index 0000000..1931fef Binary files /dev/null and b/graphics/chroma-neon/24_arrow_red_up_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_blue_down.png b/graphics/chroma-neon/24_bomb_blue_down.png new file mode 100644 index 0000000..2701116 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_blue_down.png differ diff --git a/graphics/chroma-neon/24_bomb_blue_down_shadow.png b/graphics/chroma-neon/24_bomb_blue_down_shadow.png new file mode 100644 index 0000000..2776d44 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_blue_left.png b/graphics/chroma-neon/24_bomb_blue_left.png new file mode 100644 index 0000000..406276c Binary files /dev/null and b/graphics/chroma-neon/24_bomb_blue_left.png differ diff --git a/graphics/chroma-neon/24_bomb_blue_left_shadow.png b/graphics/chroma-neon/24_bomb_blue_left_shadow.png new file mode 100644 index 0000000..4125889 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_blue_right.png b/graphics/chroma-neon/24_bomb_blue_right.png new file mode 100644 index 0000000..c146061 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_blue_right.png differ diff --git a/graphics/chroma-neon/24_bomb_blue_right_shadow.png b/graphics/chroma-neon/24_bomb_blue_right_shadow.png new file mode 100644 index 0000000..73f9fe3 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_blue_up.png b/graphics/chroma-neon/24_bomb_blue_up.png new file mode 100644 index 0000000..6a1d143 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_blue_up.png differ diff --git a/graphics/chroma-neon/24_bomb_blue_up_shadow.png b/graphics/chroma-neon/24_bomb_blue_up_shadow.png new file mode 100644 index 0000000..142c944 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_green_down.png b/graphics/chroma-neon/24_bomb_green_down.png new file mode 100644 index 0000000..5df33d8 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_green_down.png differ diff --git a/graphics/chroma-neon/24_bomb_green_down_shadow.png b/graphics/chroma-neon/24_bomb_green_down_shadow.png new file mode 100644 index 0000000..2b3fd73 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_green_down_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_green_left.png b/graphics/chroma-neon/24_bomb_green_left.png new file mode 100644 index 0000000..b5bf732 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_green_left.png differ diff --git a/graphics/chroma-neon/24_bomb_green_left_shadow.png b/graphics/chroma-neon/24_bomb_green_left_shadow.png new file mode 100644 index 0000000..c2fe571 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_green_left_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_green_right.png b/graphics/chroma-neon/24_bomb_green_right.png new file mode 100644 index 0000000..45576cb Binary files /dev/null and b/graphics/chroma-neon/24_bomb_green_right.png differ diff --git a/graphics/chroma-neon/24_bomb_green_right_shadow.png b/graphics/chroma-neon/24_bomb_green_right_shadow.png new file mode 100644 index 0000000..7b6088d Binary files /dev/null and b/graphics/chroma-neon/24_bomb_green_right_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_green_up.png b/graphics/chroma-neon/24_bomb_green_up.png new file mode 100644 index 0000000..6386d03 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_green_up.png differ diff --git a/graphics/chroma-neon/24_bomb_green_up_shadow.png b/graphics/chroma-neon/24_bomb_green_up_shadow.png new file mode 100644 index 0000000..2bad1e8 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_green_up_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_red_down.png b/graphics/chroma-neon/24_bomb_red_down.png new file mode 100644 index 0000000..fdcf09c Binary files /dev/null and b/graphics/chroma-neon/24_bomb_red_down.png differ diff --git a/graphics/chroma-neon/24_bomb_red_down_shadow.png b/graphics/chroma-neon/24_bomb_red_down_shadow.png new file mode 100644 index 0000000..b87c4a0 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_red_down_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_red_left.png b/graphics/chroma-neon/24_bomb_red_left.png new file mode 100644 index 0000000..da6f6b9 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_red_left.png differ diff --git a/graphics/chroma-neon/24_bomb_red_left_shadow.png b/graphics/chroma-neon/24_bomb_red_left_shadow.png new file mode 100644 index 0000000..03139f5 Binary files /dev/null and b/graphics/chroma-neon/24_bomb_red_left_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_red_right.png b/graphics/chroma-neon/24_bomb_red_right.png new file mode 100644 index 0000000..bd0c4ff Binary files /dev/null and b/graphics/chroma-neon/24_bomb_red_right.png differ diff --git a/graphics/chroma-neon/24_bomb_red_right_shadow.png b/graphics/chroma-neon/24_bomb_red_right_shadow.png new file mode 100644 index 0000000..89148ac Binary files /dev/null and b/graphics/chroma-neon/24_bomb_red_right_shadow.png differ diff --git a/graphics/chroma-neon/24_bomb_red_up.png b/graphics/chroma-neon/24_bomb_red_up.png new file mode 100644 index 0000000..35c470c Binary files /dev/null and b/graphics/chroma-neon/24_bomb_red_up.png differ diff --git a/graphics/chroma-neon/24_bomb_red_up_shadow.png b/graphics/chroma-neon/24_bomb_red_up_shadow.png new file mode 100644 index 0000000..75a672a Binary files /dev/null and b/graphics/chroma-neon/24_bomb_red_up_shadow.png differ diff --git a/graphics/chroma-neon/24_circle.png b/graphics/chroma-neon/24_circle.png new file mode 100644 index 0000000..231bdd0 Binary files /dev/null and b/graphics/chroma-neon/24_circle.png differ diff --git a/graphics/chroma-neon/24_circle_double.png b/graphics/chroma-neon/24_circle_double.png new file mode 100644 index 0000000..34ad6ac Binary files /dev/null and b/graphics/chroma-neon/24_circle_double.png differ diff --git a/graphics/chroma-neon/24_circle_double_shadow.png b/graphics/chroma-neon/24_circle_double_shadow.png new file mode 100644 index 0000000..c296ff5 Binary files /dev/null and b/graphics/chroma-neon/24_circle_double_shadow.png differ diff --git a/graphics/chroma-neon/24_circle_shadow.png b/graphics/chroma-neon/24_circle_shadow.png new file mode 100644 index 0000000..2ac4d86 Binary files /dev/null and b/graphics/chroma-neon/24_circle_shadow.png differ diff --git a/graphics/chroma-neon/24_door.png b/graphics/chroma-neon/24_door.png new file mode 100644 index 0000000..ce5d833 Binary files /dev/null and b/graphics/chroma-neon/24_door.png differ diff --git a/graphics/chroma-neon/24_door_shadow.png b/graphics/chroma-neon/24_door_shadow.png new file mode 100644 index 0000000..d6dd114 Binary files /dev/null and b/graphics/chroma-neon/24_door_shadow.png differ diff --git a/graphics/chroma-neon/24_dots.png b/graphics/chroma-neon/24_dots.png new file mode 100644 index 0000000..4367820 Binary files /dev/null and b/graphics/chroma-neon/24_dots.png differ diff --git a/graphics/chroma-neon/24_dots_double.png b/graphics/chroma-neon/24_dots_double.png new file mode 100644 index 0000000..81fa562 Binary files /dev/null and b/graphics/chroma-neon/24_dots_double.png differ diff --git a/graphics/chroma-neon/24_dots_double_shadow.png b/graphics/chroma-neon/24_dots_double_shadow.png new file mode 100644 index 0000000..9d7f799 Binary files /dev/null and b/graphics/chroma-neon/24_dots_double_shadow.png differ diff --git a/graphics/chroma-neon/24_dots_shadow.png b/graphics/chroma-neon/24_dots_shadow.png new file mode 100644 index 0000000..e5a82b7 Binary files /dev/null and b/graphics/chroma-neon/24_dots_shadow.png differ diff --git a/graphics/chroma-neon/24_dots_x.png b/graphics/chroma-neon/24_dots_x.png new file mode 100644 index 0000000..3bccb9c Binary files /dev/null and b/graphics/chroma-neon/24_dots_x.png differ diff --git a/graphics/chroma-neon/24_dots_x_shadow.png b/graphics/chroma-neon/24_dots_x_shadow.png new file mode 100644 index 0000000..5de73fc Binary files /dev/null and b/graphics/chroma-neon/24_dots_x_shadow.png differ diff --git a/graphics/chroma-neon/24_dots_y.png b/graphics/chroma-neon/24_dots_y.png new file mode 100644 index 0000000..2b61b3f Binary files /dev/null and b/graphics/chroma-neon/24_dots_y.png differ diff --git a/graphics/chroma-neon/24_dots_y_shadow.png b/graphics/chroma-neon/24_dots_y_shadow.png new file mode 100644 index 0000000..a0551b3 Binary files /dev/null and b/graphics/chroma-neon/24_dots_y_shadow.png differ diff --git a/graphics/chroma-neon/24_earth.png b/graphics/chroma-neon/24_earth.png new file mode 100644 index 0000000..507243d Binary files /dev/null and b/graphics/chroma-neon/24_earth.png differ diff --git a/graphics/chroma-neon/24_earth_double.png b/graphics/chroma-neon/24_earth_double.png new file mode 100644 index 0000000..87c8621 Binary files /dev/null and b/graphics/chroma-neon/24_earth_double.png differ diff --git a/graphics/chroma-neon/24_earth_double_shadow.png b/graphics/chroma-neon/24_earth_double_shadow.png new file mode 100644 index 0000000..1c84d41 Binary files /dev/null and b/graphics/chroma-neon/24_earth_double_shadow.png differ diff --git a/graphics/chroma-neon/24_earth_shadow.png b/graphics/chroma-neon/24_earth_shadow.png new file mode 100644 index 0000000..4dfb471 Binary files /dev/null and b/graphics/chroma-neon/24_earth_shadow.png differ diff --git a/graphics/chroma-neon/24_earth_x.png b/graphics/chroma-neon/24_earth_x.png new file mode 100644 index 0000000..d27af93 Binary files /dev/null and b/graphics/chroma-neon/24_earth_x.png differ diff --git a/graphics/chroma-neon/24_earth_x_shadow.png b/graphics/chroma-neon/24_earth_x_shadow.png new file mode 100644 index 0000000..fa9aa98 Binary files /dev/null and b/graphics/chroma-neon/24_earth_x_shadow.png differ diff --git a/graphics/chroma-neon/24_earth_y.png b/graphics/chroma-neon/24_earth_y.png new file mode 100644 index 0000000..c235325 Binary files /dev/null and b/graphics/chroma-neon/24_earth_y.png differ diff --git a/graphics/chroma-neon/24_earth_y_shadow.png b/graphics/chroma-neon/24_earth_y_shadow.png new file mode 100644 index 0000000..68897c1 Binary files /dev/null and b/graphics/chroma-neon/24_earth_y_shadow.png differ diff --git a/graphics/chroma-neon/24_map_bottom_left.png b/graphics/chroma-neon/24_map_bottom_left.png new file mode 100644 index 0000000..421f78b Binary files /dev/null and b/graphics/chroma-neon/24_map_bottom_left.png differ diff --git a/graphics/chroma-neon/24_map_bottom_left_shadow.png b/graphics/chroma-neon/24_map_bottom_left_shadow.png new file mode 100644 index 0000000..a2a7c30 Binary files /dev/null and b/graphics/chroma-neon/24_map_bottom_left_shadow.png differ diff --git a/graphics/chroma-neon/24_map_bottom_right.png b/graphics/chroma-neon/24_map_bottom_right.png new file mode 100644 index 0000000..a6f55b6 Binary files /dev/null and b/graphics/chroma-neon/24_map_bottom_right.png differ diff --git a/graphics/chroma-neon/24_map_bottom_right_shadow.png b/graphics/chroma-neon/24_map_bottom_right_shadow.png new file mode 100644 index 0000000..197c887 Binary files /dev/null and b/graphics/chroma-neon/24_map_bottom_right_shadow.png differ diff --git a/graphics/chroma-neon/24_map_top_left.png b/graphics/chroma-neon/24_map_top_left.png new file mode 100644 index 0000000..b1c201c Binary files /dev/null and b/graphics/chroma-neon/24_map_top_left.png differ diff --git a/graphics/chroma-neon/24_map_top_left_shadow.png b/graphics/chroma-neon/24_map_top_left_shadow.png new file mode 100644 index 0000000..7c26a40 Binary files /dev/null and b/graphics/chroma-neon/24_map_top_left_shadow.png differ diff --git a/graphics/chroma-neon/24_map_top_right.png b/graphics/chroma-neon/24_map_top_right.png new file mode 100644 index 0000000..758db74 Binary files /dev/null and b/graphics/chroma-neon/24_map_top_right.png differ diff --git a/graphics/chroma-neon/24_map_top_right_shadow.png b/graphics/chroma-neon/24_map_top_right_shadow.png new file mode 100644 index 0000000..f4ba2f3 Binary files /dev/null and b/graphics/chroma-neon/24_map_top_right_shadow.png differ diff --git a/graphics/chroma-neon/24_player_one.png b/graphics/chroma-neon/24_player_one.png new file mode 100644 index 0000000..d0d353a Binary files /dev/null and b/graphics/chroma-neon/24_player_one.png differ diff --git a/graphics/chroma-neon/24_player_one_shadow.png b/graphics/chroma-neon/24_player_one_shadow.png new file mode 100644 index 0000000..0944f26 Binary files /dev/null and b/graphics/chroma-neon/24_player_one_shadow.png differ diff --git a/graphics/chroma-neon/24_player_one_swapped.png b/graphics/chroma-neon/24_player_one_swapped.png new file mode 100644 index 0000000..a5d4a29 Binary files /dev/null and b/graphics/chroma-neon/24_player_one_swapped.png differ diff --git a/graphics/chroma-neon/24_player_one_swapped_shadow.png b/graphics/chroma-neon/24_player_one_swapped_shadow.png new file mode 100644 index 0000000..0fb356f Binary files /dev/null and b/graphics/chroma-neon/24_player_one_swapped_shadow.png differ diff --git a/graphics/chroma-neon/24_player_two.png b/graphics/chroma-neon/24_player_two.png new file mode 100644 index 0000000..c8fbcb6 Binary files /dev/null and b/graphics/chroma-neon/24_player_two.png differ diff --git a/graphics/chroma-neon/24_player_two_shadow.png b/graphics/chroma-neon/24_player_two_shadow.png new file mode 100644 index 0000000..914ee43 Binary files /dev/null and b/graphics/chroma-neon/24_player_two_shadow.png differ diff --git a/graphics/chroma-neon/24_player_two_swapped.png b/graphics/chroma-neon/24_player_two_swapped.png new file mode 100644 index 0000000..69bc85e Binary files /dev/null and b/graphics/chroma-neon/24_player_two_swapped.png differ diff --git a/graphics/chroma-neon/24_player_two_swapped_shadow.png b/graphics/chroma-neon/24_player_two_swapped_shadow.png new file mode 100644 index 0000000..1bd17ef Binary files /dev/null and b/graphics/chroma-neon/24_player_two_swapped_shadow.png differ diff --git a/graphics/chroma-neon/24_star.png b/graphics/chroma-neon/24_star.png new file mode 100644 index 0000000..33c9c78 Binary files /dev/null and b/graphics/chroma-neon/24_star.png differ diff --git a/graphics/chroma-neon/24_star_shadow.png b/graphics/chroma-neon/24_star_shadow.png new file mode 100644 index 0000000..4fadbb9 Binary files /dev/null and b/graphics/chroma-neon/24_star_shadow.png differ diff --git a/graphics/chroma-neon/24_switch.png b/graphics/chroma-neon/24_switch.png new file mode 100644 index 0000000..7d51ae7 Binary files /dev/null and b/graphics/chroma-neon/24_switch.png differ diff --git a/graphics/chroma-neon/24_switch_shadow.png b/graphics/chroma-neon/24_switch_shadow.png new file mode 100644 index 0000000..f657d4c Binary files /dev/null and b/graphics/chroma-neon/24_switch_shadow.png differ diff --git a/graphics/chroma-neon/24_teleport.png b/graphics/chroma-neon/24_teleport.png new file mode 100644 index 0000000..a059534 Binary files /dev/null and b/graphics/chroma-neon/24_teleport.png differ diff --git a/graphics/chroma-neon/24_teleport_shadow.png b/graphics/chroma-neon/24_teleport_shadow.png new file mode 100644 index 0000000..768ef3b Binary files /dev/null and b/graphics/chroma-neon/24_teleport_shadow.png differ diff --git a/graphics/chroma-neon/24_wall.png b/graphics/chroma-neon/24_wall.png new file mode 100644 index 0000000..b8c024a Binary files /dev/null and b/graphics/chroma-neon/24_wall.png differ diff --git a/graphics/chroma-neon/24_wall_inside.png b/graphics/chroma-neon/24_wall_inside.png new file mode 100644 index 0000000..6565e4b Binary files /dev/null and b/graphics/chroma-neon/24_wall_inside.png differ diff --git a/graphics/chroma-neon/24_wall_outside.png b/graphics/chroma-neon/24_wall_outside.png new file mode 100644 index 0000000..9584540 Binary files /dev/null and b/graphics/chroma-neon/24_wall_outside.png differ diff --git a/graphics/chroma-neon/24_wall_shadow.png b/graphics/chroma-neon/24_wall_shadow.png new file mode 100644 index 0000000..be3f94e Binary files /dev/null and b/graphics/chroma-neon/24_wall_shadow.png differ diff --git a/graphics/chroma-neon/24_wall_x.png b/graphics/chroma-neon/24_wall_x.png new file mode 100644 index 0000000..13220c4 Binary files /dev/null and b/graphics/chroma-neon/24_wall_x.png differ diff --git a/graphics/chroma-neon/24_wall_y.png b/graphics/chroma-neon/24_wall_y.png new file mode 100644 index 0000000..08571a0 Binary files /dev/null and b/graphics/chroma-neon/24_wall_y.png differ diff --git a/graphics/chroma-neon/32_arrow_blue_down.png b/graphics/chroma-neon/32_arrow_blue_down.png new file mode 100644 index 0000000..5f7e3b9 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_blue_down.png differ diff --git a/graphics/chroma-neon/32_arrow_blue_down_shadow.png b/graphics/chroma-neon/32_arrow_blue_down_shadow.png new file mode 100644 index 0000000..91042d8 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_blue_left.png b/graphics/chroma-neon/32_arrow_blue_left.png new file mode 100644 index 0000000..bd80bc2 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_blue_left.png differ diff --git a/graphics/chroma-neon/32_arrow_blue_left_shadow.png b/graphics/chroma-neon/32_arrow_blue_left_shadow.png new file mode 100644 index 0000000..dca7238 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_blue_right.png b/graphics/chroma-neon/32_arrow_blue_right.png new file mode 100644 index 0000000..68161dc Binary files /dev/null and b/graphics/chroma-neon/32_arrow_blue_right.png differ diff --git a/graphics/chroma-neon/32_arrow_blue_right_shadow.png b/graphics/chroma-neon/32_arrow_blue_right_shadow.png new file mode 100644 index 0000000..403d32a Binary files /dev/null and b/graphics/chroma-neon/32_arrow_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_blue_up.png b/graphics/chroma-neon/32_arrow_blue_up.png new file mode 100644 index 0000000..9a0cab9 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_blue_up.png differ diff --git a/graphics/chroma-neon/32_arrow_blue_up_shadow.png b/graphics/chroma-neon/32_arrow_blue_up_shadow.png new file mode 100644 index 0000000..740c9f3 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_green_down.png b/graphics/chroma-neon/32_arrow_green_down.png new file mode 100644 index 0000000..28c5295 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_green_down.png differ diff --git a/graphics/chroma-neon/32_arrow_green_down_shadow.png b/graphics/chroma-neon/32_arrow_green_down_shadow.png new file mode 100644 index 0000000..c918134 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_green_down_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_green_left.png b/graphics/chroma-neon/32_arrow_green_left.png new file mode 100644 index 0000000..4c3175a Binary files /dev/null and b/graphics/chroma-neon/32_arrow_green_left.png differ diff --git a/graphics/chroma-neon/32_arrow_green_left_shadow.png b/graphics/chroma-neon/32_arrow_green_left_shadow.png new file mode 100644 index 0000000..eb6b547 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_green_left_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_green_right.png b/graphics/chroma-neon/32_arrow_green_right.png new file mode 100644 index 0000000..df47e77 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_green_right.png differ diff --git a/graphics/chroma-neon/32_arrow_green_right_shadow.png b/graphics/chroma-neon/32_arrow_green_right_shadow.png new file mode 100644 index 0000000..7d83b80 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_green_right_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_green_up.png b/graphics/chroma-neon/32_arrow_green_up.png new file mode 100644 index 0000000..426d90a Binary files /dev/null and b/graphics/chroma-neon/32_arrow_green_up.png differ diff --git a/graphics/chroma-neon/32_arrow_green_up_shadow.png b/graphics/chroma-neon/32_arrow_green_up_shadow.png new file mode 100644 index 0000000..8d83ff9 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_green_up_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_red_down.png b/graphics/chroma-neon/32_arrow_red_down.png new file mode 100644 index 0000000..d6b5bd6 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_red_down.png differ diff --git a/graphics/chroma-neon/32_arrow_red_down_shadow.png b/graphics/chroma-neon/32_arrow_red_down_shadow.png new file mode 100644 index 0000000..88ebbed Binary files /dev/null and b/graphics/chroma-neon/32_arrow_red_down_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_red_left.png b/graphics/chroma-neon/32_arrow_red_left.png new file mode 100644 index 0000000..e4f49c3 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_red_left.png differ diff --git a/graphics/chroma-neon/32_arrow_red_left_shadow.png b/graphics/chroma-neon/32_arrow_red_left_shadow.png new file mode 100644 index 0000000..f9b5955 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_red_left_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_red_right.png b/graphics/chroma-neon/32_arrow_red_right.png new file mode 100644 index 0000000..3440c14 Binary files /dev/null and b/graphics/chroma-neon/32_arrow_red_right.png differ diff --git a/graphics/chroma-neon/32_arrow_red_right_shadow.png b/graphics/chroma-neon/32_arrow_red_right_shadow.png new file mode 100644 index 0000000..56ce07e Binary files /dev/null and b/graphics/chroma-neon/32_arrow_red_right_shadow.png differ diff --git a/graphics/chroma-neon/32_arrow_red_up.png b/graphics/chroma-neon/32_arrow_red_up.png new file mode 100644 index 0000000..8d3737e Binary files /dev/null and b/graphics/chroma-neon/32_arrow_red_up.png differ diff --git a/graphics/chroma-neon/32_arrow_red_up_shadow.png b/graphics/chroma-neon/32_arrow_red_up_shadow.png new file mode 100644 index 0000000..cab06bc Binary files /dev/null and b/graphics/chroma-neon/32_arrow_red_up_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_blue_down.png b/graphics/chroma-neon/32_bomb_blue_down.png new file mode 100644 index 0000000..db65708 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_blue_down.png differ diff --git a/graphics/chroma-neon/32_bomb_blue_down_shadow.png b/graphics/chroma-neon/32_bomb_blue_down_shadow.png new file mode 100644 index 0000000..22a5c6e Binary files /dev/null and b/graphics/chroma-neon/32_bomb_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_blue_left.png b/graphics/chroma-neon/32_bomb_blue_left.png new file mode 100644 index 0000000..bcf5976 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_blue_left.png differ diff --git a/graphics/chroma-neon/32_bomb_blue_left_shadow.png b/graphics/chroma-neon/32_bomb_blue_left_shadow.png new file mode 100644 index 0000000..c442f85 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_blue_right.png b/graphics/chroma-neon/32_bomb_blue_right.png new file mode 100644 index 0000000..5b2c267 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_blue_right.png differ diff --git a/graphics/chroma-neon/32_bomb_blue_right_shadow.png b/graphics/chroma-neon/32_bomb_blue_right_shadow.png new file mode 100644 index 0000000..403125b Binary files /dev/null and b/graphics/chroma-neon/32_bomb_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_blue_up.png b/graphics/chroma-neon/32_bomb_blue_up.png new file mode 100644 index 0000000..5a00abf Binary files /dev/null and b/graphics/chroma-neon/32_bomb_blue_up.png differ diff --git a/graphics/chroma-neon/32_bomb_blue_up_shadow.png b/graphics/chroma-neon/32_bomb_blue_up_shadow.png new file mode 100644 index 0000000..ba124c8 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_green_down.png b/graphics/chroma-neon/32_bomb_green_down.png new file mode 100644 index 0000000..5d9ed79 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_green_down.png differ diff --git a/graphics/chroma-neon/32_bomb_green_down_shadow.png b/graphics/chroma-neon/32_bomb_green_down_shadow.png new file mode 100644 index 0000000..39b097c Binary files /dev/null and b/graphics/chroma-neon/32_bomb_green_down_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_green_left.png b/graphics/chroma-neon/32_bomb_green_left.png new file mode 100644 index 0000000..96fc04b Binary files /dev/null and b/graphics/chroma-neon/32_bomb_green_left.png differ diff --git a/graphics/chroma-neon/32_bomb_green_left_shadow.png b/graphics/chroma-neon/32_bomb_green_left_shadow.png new file mode 100644 index 0000000..bf7c659 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_green_left_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_green_right.png b/graphics/chroma-neon/32_bomb_green_right.png new file mode 100644 index 0000000..a90c82f Binary files /dev/null and b/graphics/chroma-neon/32_bomb_green_right.png differ diff --git a/graphics/chroma-neon/32_bomb_green_right_shadow.png b/graphics/chroma-neon/32_bomb_green_right_shadow.png new file mode 100644 index 0000000..e0fe421 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_green_right_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_green_up.png b/graphics/chroma-neon/32_bomb_green_up.png new file mode 100644 index 0000000..36f40ce Binary files /dev/null and b/graphics/chroma-neon/32_bomb_green_up.png differ diff --git a/graphics/chroma-neon/32_bomb_green_up_shadow.png b/graphics/chroma-neon/32_bomb_green_up_shadow.png new file mode 100644 index 0000000..3446d9e Binary files /dev/null and b/graphics/chroma-neon/32_bomb_green_up_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_red_down.png b/graphics/chroma-neon/32_bomb_red_down.png new file mode 100644 index 0000000..79b6ef9 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_red_down.png differ diff --git a/graphics/chroma-neon/32_bomb_red_down_shadow.png b/graphics/chroma-neon/32_bomb_red_down_shadow.png new file mode 100644 index 0000000..510a3fd Binary files /dev/null and b/graphics/chroma-neon/32_bomb_red_down_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_red_left.png b/graphics/chroma-neon/32_bomb_red_left.png new file mode 100644 index 0000000..9b6cd06 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_red_left.png differ diff --git a/graphics/chroma-neon/32_bomb_red_left_shadow.png b/graphics/chroma-neon/32_bomb_red_left_shadow.png new file mode 100644 index 0000000..0ac0675 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_red_left_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_red_right.png b/graphics/chroma-neon/32_bomb_red_right.png new file mode 100644 index 0000000..9472290 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_red_right.png differ diff --git a/graphics/chroma-neon/32_bomb_red_right_shadow.png b/graphics/chroma-neon/32_bomb_red_right_shadow.png new file mode 100644 index 0000000..629d6c4 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_red_right_shadow.png differ diff --git a/graphics/chroma-neon/32_bomb_red_up.png b/graphics/chroma-neon/32_bomb_red_up.png new file mode 100644 index 0000000..bc0df94 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_red_up.png differ diff --git a/graphics/chroma-neon/32_bomb_red_up_shadow.png b/graphics/chroma-neon/32_bomb_red_up_shadow.png new file mode 100644 index 0000000..dc96e40 Binary files /dev/null and b/graphics/chroma-neon/32_bomb_red_up_shadow.png differ diff --git a/graphics/chroma-neon/32_circle.png b/graphics/chroma-neon/32_circle.png new file mode 100644 index 0000000..b0a87dd Binary files /dev/null and b/graphics/chroma-neon/32_circle.png differ diff --git a/graphics/chroma-neon/32_circle_double.png b/graphics/chroma-neon/32_circle_double.png new file mode 100644 index 0000000..658800e Binary files /dev/null and b/graphics/chroma-neon/32_circle_double.png differ diff --git a/graphics/chroma-neon/32_circle_double_shadow.png b/graphics/chroma-neon/32_circle_double_shadow.png new file mode 100644 index 0000000..585356a Binary files /dev/null and b/graphics/chroma-neon/32_circle_double_shadow.png differ diff --git a/graphics/chroma-neon/32_circle_shadow.png b/graphics/chroma-neon/32_circle_shadow.png new file mode 100644 index 0000000..5cd7732 Binary files /dev/null and b/graphics/chroma-neon/32_circle_shadow.png differ diff --git a/graphics/chroma-neon/32_door.png b/graphics/chroma-neon/32_door.png new file mode 100644 index 0000000..58fe88d Binary files /dev/null and b/graphics/chroma-neon/32_door.png differ diff --git a/graphics/chroma-neon/32_door_shadow.png b/graphics/chroma-neon/32_door_shadow.png new file mode 100644 index 0000000..bde1aa3 Binary files /dev/null and b/graphics/chroma-neon/32_door_shadow.png differ diff --git a/graphics/chroma-neon/32_dots.png b/graphics/chroma-neon/32_dots.png new file mode 100644 index 0000000..0056d30 Binary files /dev/null and b/graphics/chroma-neon/32_dots.png differ diff --git a/graphics/chroma-neon/32_dots_double.png b/graphics/chroma-neon/32_dots_double.png new file mode 100644 index 0000000..e4f26de Binary files /dev/null and b/graphics/chroma-neon/32_dots_double.png differ diff --git a/graphics/chroma-neon/32_dots_double_shadow.png b/graphics/chroma-neon/32_dots_double_shadow.png new file mode 100644 index 0000000..3d70355 Binary files /dev/null and b/graphics/chroma-neon/32_dots_double_shadow.png differ diff --git a/graphics/chroma-neon/32_dots_shadow.png b/graphics/chroma-neon/32_dots_shadow.png new file mode 100644 index 0000000..33e9d7d Binary files /dev/null and b/graphics/chroma-neon/32_dots_shadow.png differ diff --git a/graphics/chroma-neon/32_dots_x.png b/graphics/chroma-neon/32_dots_x.png new file mode 100644 index 0000000..eba4196 Binary files /dev/null and b/graphics/chroma-neon/32_dots_x.png differ diff --git a/graphics/chroma-neon/32_dots_x_shadow.png b/graphics/chroma-neon/32_dots_x_shadow.png new file mode 100644 index 0000000..c960262 Binary files /dev/null and b/graphics/chroma-neon/32_dots_x_shadow.png differ diff --git a/graphics/chroma-neon/32_dots_y.png b/graphics/chroma-neon/32_dots_y.png new file mode 100644 index 0000000..f616977 Binary files /dev/null and b/graphics/chroma-neon/32_dots_y.png differ diff --git a/graphics/chroma-neon/32_dots_y_shadow.png b/graphics/chroma-neon/32_dots_y_shadow.png new file mode 100644 index 0000000..8c07ec2 Binary files /dev/null and b/graphics/chroma-neon/32_dots_y_shadow.png differ diff --git a/graphics/chroma-neon/32_earth.png b/graphics/chroma-neon/32_earth.png new file mode 100644 index 0000000..46c87ed Binary files /dev/null and b/graphics/chroma-neon/32_earth.png differ diff --git a/graphics/chroma-neon/32_earth_double.png b/graphics/chroma-neon/32_earth_double.png new file mode 100644 index 0000000..6ce0ec5 Binary files /dev/null and b/graphics/chroma-neon/32_earth_double.png differ diff --git a/graphics/chroma-neon/32_earth_double_shadow.png b/graphics/chroma-neon/32_earth_double_shadow.png new file mode 100644 index 0000000..24d80bd Binary files /dev/null and b/graphics/chroma-neon/32_earth_double_shadow.png differ diff --git a/graphics/chroma-neon/32_earth_shadow.png b/graphics/chroma-neon/32_earth_shadow.png new file mode 100644 index 0000000..1ce37fd Binary files /dev/null and b/graphics/chroma-neon/32_earth_shadow.png differ diff --git a/graphics/chroma-neon/32_earth_x.png b/graphics/chroma-neon/32_earth_x.png new file mode 100644 index 0000000..1fcd72e Binary files /dev/null and b/graphics/chroma-neon/32_earth_x.png differ diff --git a/graphics/chroma-neon/32_earth_x_shadow.png b/graphics/chroma-neon/32_earth_x_shadow.png new file mode 100644 index 0000000..cedc7f8 Binary files /dev/null and b/graphics/chroma-neon/32_earth_x_shadow.png differ diff --git a/graphics/chroma-neon/32_earth_y.png b/graphics/chroma-neon/32_earth_y.png new file mode 100644 index 0000000..a8db2fa Binary files /dev/null and b/graphics/chroma-neon/32_earth_y.png differ diff --git a/graphics/chroma-neon/32_earth_y_shadow.png b/graphics/chroma-neon/32_earth_y_shadow.png new file mode 100644 index 0000000..165bfad Binary files /dev/null and b/graphics/chroma-neon/32_earth_y_shadow.png differ diff --git a/graphics/chroma-neon/32_map_bottom_left.png b/graphics/chroma-neon/32_map_bottom_left.png new file mode 100644 index 0000000..76ab4fa Binary files /dev/null and b/graphics/chroma-neon/32_map_bottom_left.png differ diff --git a/graphics/chroma-neon/32_map_bottom_left_shadow.png b/graphics/chroma-neon/32_map_bottom_left_shadow.png new file mode 100644 index 0000000..8006467 Binary files /dev/null and b/graphics/chroma-neon/32_map_bottom_left_shadow.png differ diff --git a/graphics/chroma-neon/32_map_bottom_right.png b/graphics/chroma-neon/32_map_bottom_right.png new file mode 100644 index 0000000..db06991 Binary files /dev/null and b/graphics/chroma-neon/32_map_bottom_right.png differ diff --git a/graphics/chroma-neon/32_map_bottom_right_shadow.png b/graphics/chroma-neon/32_map_bottom_right_shadow.png new file mode 100644 index 0000000..d3a0dd5 Binary files /dev/null and b/graphics/chroma-neon/32_map_bottom_right_shadow.png differ diff --git a/graphics/chroma-neon/32_map_top_left.png b/graphics/chroma-neon/32_map_top_left.png new file mode 100644 index 0000000..d0136e8 Binary files /dev/null and b/graphics/chroma-neon/32_map_top_left.png differ diff --git a/graphics/chroma-neon/32_map_top_left_shadow.png b/graphics/chroma-neon/32_map_top_left_shadow.png new file mode 100644 index 0000000..f3db05e Binary files /dev/null and b/graphics/chroma-neon/32_map_top_left_shadow.png differ diff --git a/graphics/chroma-neon/32_map_top_right.png b/graphics/chroma-neon/32_map_top_right.png new file mode 100644 index 0000000..4196f71 Binary files /dev/null and b/graphics/chroma-neon/32_map_top_right.png differ diff --git a/graphics/chroma-neon/32_map_top_right_shadow.png b/graphics/chroma-neon/32_map_top_right_shadow.png new file mode 100644 index 0000000..2710f9c Binary files /dev/null and b/graphics/chroma-neon/32_map_top_right_shadow.png differ diff --git a/graphics/chroma-neon/32_player_one.png b/graphics/chroma-neon/32_player_one.png new file mode 100644 index 0000000..08c4c84 Binary files /dev/null and b/graphics/chroma-neon/32_player_one.png differ diff --git a/graphics/chroma-neon/32_player_one_shadow.png b/graphics/chroma-neon/32_player_one_shadow.png new file mode 100644 index 0000000..e93bebf Binary files /dev/null and b/graphics/chroma-neon/32_player_one_shadow.png differ diff --git a/graphics/chroma-neon/32_player_one_swapped.png b/graphics/chroma-neon/32_player_one_swapped.png new file mode 100644 index 0000000..abaa134 Binary files /dev/null and b/graphics/chroma-neon/32_player_one_swapped.png differ diff --git a/graphics/chroma-neon/32_player_one_swapped_shadow.png b/graphics/chroma-neon/32_player_one_swapped_shadow.png new file mode 100644 index 0000000..0e58f5b Binary files /dev/null and b/graphics/chroma-neon/32_player_one_swapped_shadow.png differ diff --git a/graphics/chroma-neon/32_player_two.png b/graphics/chroma-neon/32_player_two.png new file mode 100644 index 0000000..74cd835 Binary files /dev/null and b/graphics/chroma-neon/32_player_two.png differ diff --git a/graphics/chroma-neon/32_player_two_shadow.png b/graphics/chroma-neon/32_player_two_shadow.png new file mode 100644 index 0000000..7b68c59 Binary files /dev/null and b/graphics/chroma-neon/32_player_two_shadow.png differ diff --git a/graphics/chroma-neon/32_player_two_swapped.png b/graphics/chroma-neon/32_player_two_swapped.png new file mode 100644 index 0000000..ca16920 Binary files /dev/null and b/graphics/chroma-neon/32_player_two_swapped.png differ diff --git a/graphics/chroma-neon/32_player_two_swapped_shadow.png b/graphics/chroma-neon/32_player_two_swapped_shadow.png new file mode 100644 index 0000000..ac0aeac Binary files /dev/null and b/graphics/chroma-neon/32_player_two_swapped_shadow.png differ diff --git a/graphics/chroma-neon/32_star.png b/graphics/chroma-neon/32_star.png new file mode 100644 index 0000000..72b2f2b Binary files /dev/null and b/graphics/chroma-neon/32_star.png differ diff --git a/graphics/chroma-neon/32_star_shadow.png b/graphics/chroma-neon/32_star_shadow.png new file mode 100644 index 0000000..23b39b6 Binary files /dev/null and b/graphics/chroma-neon/32_star_shadow.png differ diff --git a/graphics/chroma-neon/32_switch.png b/graphics/chroma-neon/32_switch.png new file mode 100644 index 0000000..1b34e1d Binary files /dev/null and b/graphics/chroma-neon/32_switch.png differ diff --git a/graphics/chroma-neon/32_switch_shadow.png b/graphics/chroma-neon/32_switch_shadow.png new file mode 100644 index 0000000..793a388 Binary files /dev/null and b/graphics/chroma-neon/32_switch_shadow.png differ diff --git a/graphics/chroma-neon/32_teleport.png b/graphics/chroma-neon/32_teleport.png new file mode 100644 index 0000000..ee785bb Binary files /dev/null and b/graphics/chroma-neon/32_teleport.png differ diff --git a/graphics/chroma-neon/32_teleport_shadow.png b/graphics/chroma-neon/32_teleport_shadow.png new file mode 100644 index 0000000..30cfa9d Binary files /dev/null and b/graphics/chroma-neon/32_teleport_shadow.png differ diff --git a/graphics/chroma-neon/32_wall.png b/graphics/chroma-neon/32_wall.png new file mode 100644 index 0000000..900091f Binary files /dev/null and b/graphics/chroma-neon/32_wall.png differ diff --git a/graphics/chroma-neon/32_wall_inside.png b/graphics/chroma-neon/32_wall_inside.png new file mode 100644 index 0000000..07f200a Binary files /dev/null and b/graphics/chroma-neon/32_wall_inside.png differ diff --git a/graphics/chroma-neon/32_wall_outside.png b/graphics/chroma-neon/32_wall_outside.png new file mode 100644 index 0000000..421d32b Binary files /dev/null and b/graphics/chroma-neon/32_wall_outside.png differ diff --git a/graphics/chroma-neon/32_wall_shadow.png b/graphics/chroma-neon/32_wall_shadow.png new file mode 100644 index 0000000..42178a4 Binary files /dev/null and b/graphics/chroma-neon/32_wall_shadow.png differ diff --git a/graphics/chroma-neon/32_wall_x.png b/graphics/chroma-neon/32_wall_x.png new file mode 100644 index 0000000..d51792d Binary files /dev/null and b/graphics/chroma-neon/32_wall_x.png differ diff --git a/graphics/chroma-neon/32_wall_y.png b/graphics/chroma-neon/32_wall_y.png new file mode 100644 index 0000000..32ed40f Binary files /dev/null and b/graphics/chroma-neon/32_wall_y.png differ diff --git a/graphics/chroma-neon/40_arrow_blue_down.png b/graphics/chroma-neon/40_arrow_blue_down.png new file mode 100644 index 0000000..8aa1938 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_blue_down.png differ diff --git a/graphics/chroma-neon/40_arrow_blue_down_shadow.png b/graphics/chroma-neon/40_arrow_blue_down_shadow.png new file mode 100644 index 0000000..3255c3e Binary files /dev/null and b/graphics/chroma-neon/40_arrow_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_blue_left.png b/graphics/chroma-neon/40_arrow_blue_left.png new file mode 100644 index 0000000..7179366 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_blue_left.png differ diff --git a/graphics/chroma-neon/40_arrow_blue_left_shadow.png b/graphics/chroma-neon/40_arrow_blue_left_shadow.png new file mode 100644 index 0000000..43738e2 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_blue_right.png b/graphics/chroma-neon/40_arrow_blue_right.png new file mode 100644 index 0000000..e2cd2a6 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_blue_right.png differ diff --git a/graphics/chroma-neon/40_arrow_blue_right_shadow.png b/graphics/chroma-neon/40_arrow_blue_right_shadow.png new file mode 100644 index 0000000..07d2629 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_blue_up.png b/graphics/chroma-neon/40_arrow_blue_up.png new file mode 100644 index 0000000..d32eb09 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_blue_up.png differ diff --git a/graphics/chroma-neon/40_arrow_blue_up_shadow.png b/graphics/chroma-neon/40_arrow_blue_up_shadow.png new file mode 100644 index 0000000..f4214ed Binary files /dev/null and b/graphics/chroma-neon/40_arrow_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_green_down.png b/graphics/chroma-neon/40_arrow_green_down.png new file mode 100644 index 0000000..9bcff9b Binary files /dev/null and b/graphics/chroma-neon/40_arrow_green_down.png differ diff --git a/graphics/chroma-neon/40_arrow_green_down_shadow.png b/graphics/chroma-neon/40_arrow_green_down_shadow.png new file mode 100644 index 0000000..418ba57 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_green_down_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_green_left.png b/graphics/chroma-neon/40_arrow_green_left.png new file mode 100644 index 0000000..d67bb87 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_green_left.png differ diff --git a/graphics/chroma-neon/40_arrow_green_left_shadow.png b/graphics/chroma-neon/40_arrow_green_left_shadow.png new file mode 100644 index 0000000..7fdbaa7 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_green_left_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_green_right.png b/graphics/chroma-neon/40_arrow_green_right.png new file mode 100644 index 0000000..53fd689 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_green_right.png differ diff --git a/graphics/chroma-neon/40_arrow_green_right_shadow.png b/graphics/chroma-neon/40_arrow_green_right_shadow.png new file mode 100644 index 0000000..4e5b499 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_green_right_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_green_up.png b/graphics/chroma-neon/40_arrow_green_up.png new file mode 100644 index 0000000..2099b47 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_green_up.png differ diff --git a/graphics/chroma-neon/40_arrow_green_up_shadow.png b/graphics/chroma-neon/40_arrow_green_up_shadow.png new file mode 100644 index 0000000..1aceefc Binary files /dev/null and b/graphics/chroma-neon/40_arrow_green_up_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_red_down.png b/graphics/chroma-neon/40_arrow_red_down.png new file mode 100644 index 0000000..1cc60b0 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_red_down.png differ diff --git a/graphics/chroma-neon/40_arrow_red_down_shadow.png b/graphics/chroma-neon/40_arrow_red_down_shadow.png new file mode 100644 index 0000000..b20a763 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_red_down_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_red_left.png b/graphics/chroma-neon/40_arrow_red_left.png new file mode 100644 index 0000000..ade9135 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_red_left.png differ diff --git a/graphics/chroma-neon/40_arrow_red_left_shadow.png b/graphics/chroma-neon/40_arrow_red_left_shadow.png new file mode 100644 index 0000000..9959aea Binary files /dev/null and b/graphics/chroma-neon/40_arrow_red_left_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_red_right.png b/graphics/chroma-neon/40_arrow_red_right.png new file mode 100644 index 0000000..48574a0 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_red_right.png differ diff --git a/graphics/chroma-neon/40_arrow_red_right_shadow.png b/graphics/chroma-neon/40_arrow_red_right_shadow.png new file mode 100644 index 0000000..1a8fa6f Binary files /dev/null and b/graphics/chroma-neon/40_arrow_red_right_shadow.png differ diff --git a/graphics/chroma-neon/40_arrow_red_up.png b/graphics/chroma-neon/40_arrow_red_up.png new file mode 100644 index 0000000..10d15d8 Binary files /dev/null and b/graphics/chroma-neon/40_arrow_red_up.png differ diff --git a/graphics/chroma-neon/40_arrow_red_up_shadow.png b/graphics/chroma-neon/40_arrow_red_up_shadow.png new file mode 100644 index 0000000..0999d6e Binary files /dev/null and b/graphics/chroma-neon/40_arrow_red_up_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_blue_down.png b/graphics/chroma-neon/40_bomb_blue_down.png new file mode 100644 index 0000000..95827ea Binary files /dev/null and b/graphics/chroma-neon/40_bomb_blue_down.png differ diff --git a/graphics/chroma-neon/40_bomb_blue_down_shadow.png b/graphics/chroma-neon/40_bomb_blue_down_shadow.png new file mode 100644 index 0000000..caa5d86 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_blue_left.png b/graphics/chroma-neon/40_bomb_blue_left.png new file mode 100644 index 0000000..94a8461 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_blue_left.png differ diff --git a/graphics/chroma-neon/40_bomb_blue_left_shadow.png b/graphics/chroma-neon/40_bomb_blue_left_shadow.png new file mode 100644 index 0000000..65de777 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_blue_right.png b/graphics/chroma-neon/40_bomb_blue_right.png new file mode 100644 index 0000000..ebec0d9 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_blue_right.png differ diff --git a/graphics/chroma-neon/40_bomb_blue_right_shadow.png b/graphics/chroma-neon/40_bomb_blue_right_shadow.png new file mode 100644 index 0000000..b4c6562 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_blue_up.png b/graphics/chroma-neon/40_bomb_blue_up.png new file mode 100644 index 0000000..96c7b26 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_blue_up.png differ diff --git a/graphics/chroma-neon/40_bomb_blue_up_shadow.png b/graphics/chroma-neon/40_bomb_blue_up_shadow.png new file mode 100644 index 0000000..0251701 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_green_down.png b/graphics/chroma-neon/40_bomb_green_down.png new file mode 100644 index 0000000..3ef8bc9 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_green_down.png differ diff --git a/graphics/chroma-neon/40_bomb_green_down_shadow.png b/graphics/chroma-neon/40_bomb_green_down_shadow.png new file mode 100644 index 0000000..a0921b9 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_green_down_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_green_left.png b/graphics/chroma-neon/40_bomb_green_left.png new file mode 100644 index 0000000..7a2618e Binary files /dev/null and b/graphics/chroma-neon/40_bomb_green_left.png differ diff --git a/graphics/chroma-neon/40_bomb_green_left_shadow.png b/graphics/chroma-neon/40_bomb_green_left_shadow.png new file mode 100644 index 0000000..11ebbcc Binary files /dev/null and b/graphics/chroma-neon/40_bomb_green_left_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_green_right.png b/graphics/chroma-neon/40_bomb_green_right.png new file mode 100644 index 0000000..c1b43cb Binary files /dev/null and b/graphics/chroma-neon/40_bomb_green_right.png differ diff --git a/graphics/chroma-neon/40_bomb_green_right_shadow.png b/graphics/chroma-neon/40_bomb_green_right_shadow.png new file mode 100644 index 0000000..1e15c8f Binary files /dev/null and b/graphics/chroma-neon/40_bomb_green_right_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_green_up.png b/graphics/chroma-neon/40_bomb_green_up.png new file mode 100644 index 0000000..6be88e6 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_green_up.png differ diff --git a/graphics/chroma-neon/40_bomb_green_up_shadow.png b/graphics/chroma-neon/40_bomb_green_up_shadow.png new file mode 100644 index 0000000..97d94dd Binary files /dev/null and b/graphics/chroma-neon/40_bomb_green_up_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_red_down.png b/graphics/chroma-neon/40_bomb_red_down.png new file mode 100644 index 0000000..abf6603 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_red_down.png differ diff --git a/graphics/chroma-neon/40_bomb_red_down_shadow.png b/graphics/chroma-neon/40_bomb_red_down_shadow.png new file mode 100644 index 0000000..15c50e9 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_red_down_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_red_left.png b/graphics/chroma-neon/40_bomb_red_left.png new file mode 100644 index 0000000..e9e4979 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_red_left.png differ diff --git a/graphics/chroma-neon/40_bomb_red_left_shadow.png b/graphics/chroma-neon/40_bomb_red_left_shadow.png new file mode 100644 index 0000000..cce9fb1 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_red_left_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_red_right.png b/graphics/chroma-neon/40_bomb_red_right.png new file mode 100644 index 0000000..a7f28a5 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_red_right.png differ diff --git a/graphics/chroma-neon/40_bomb_red_right_shadow.png b/graphics/chroma-neon/40_bomb_red_right_shadow.png new file mode 100644 index 0000000..7efd624 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_red_right_shadow.png differ diff --git a/graphics/chroma-neon/40_bomb_red_up.png b/graphics/chroma-neon/40_bomb_red_up.png new file mode 100644 index 0000000..895ef1f Binary files /dev/null and b/graphics/chroma-neon/40_bomb_red_up.png differ diff --git a/graphics/chroma-neon/40_bomb_red_up_shadow.png b/graphics/chroma-neon/40_bomb_red_up_shadow.png new file mode 100644 index 0000000..6883bd3 Binary files /dev/null and b/graphics/chroma-neon/40_bomb_red_up_shadow.png differ diff --git a/graphics/chroma-neon/40_circle.png b/graphics/chroma-neon/40_circle.png new file mode 100644 index 0000000..cc54335 Binary files /dev/null and b/graphics/chroma-neon/40_circle.png differ diff --git a/graphics/chroma-neon/40_circle_double.png b/graphics/chroma-neon/40_circle_double.png new file mode 100644 index 0000000..794dc88 Binary files /dev/null and b/graphics/chroma-neon/40_circle_double.png differ diff --git a/graphics/chroma-neon/40_circle_double_shadow.png b/graphics/chroma-neon/40_circle_double_shadow.png new file mode 100644 index 0000000..687265a Binary files /dev/null and b/graphics/chroma-neon/40_circle_double_shadow.png differ diff --git a/graphics/chroma-neon/40_circle_shadow.png b/graphics/chroma-neon/40_circle_shadow.png new file mode 100644 index 0000000..a5d1ec1 Binary files /dev/null and b/graphics/chroma-neon/40_circle_shadow.png differ diff --git a/graphics/chroma-neon/40_door.png b/graphics/chroma-neon/40_door.png new file mode 100644 index 0000000..d25b209 Binary files /dev/null and b/graphics/chroma-neon/40_door.png differ diff --git a/graphics/chroma-neon/40_door_shadow.png b/graphics/chroma-neon/40_door_shadow.png new file mode 100644 index 0000000..23380ac Binary files /dev/null and b/graphics/chroma-neon/40_door_shadow.png differ diff --git a/graphics/chroma-neon/40_dots.png b/graphics/chroma-neon/40_dots.png new file mode 100644 index 0000000..e11f06e Binary files /dev/null and b/graphics/chroma-neon/40_dots.png differ diff --git a/graphics/chroma-neon/40_dots_double.png b/graphics/chroma-neon/40_dots_double.png new file mode 100644 index 0000000..fe6a3a6 Binary files /dev/null and b/graphics/chroma-neon/40_dots_double.png differ diff --git a/graphics/chroma-neon/40_dots_double_shadow.png b/graphics/chroma-neon/40_dots_double_shadow.png new file mode 100644 index 0000000..be48c6f Binary files /dev/null and b/graphics/chroma-neon/40_dots_double_shadow.png differ diff --git a/graphics/chroma-neon/40_dots_shadow.png b/graphics/chroma-neon/40_dots_shadow.png new file mode 100644 index 0000000..0087120 Binary files /dev/null and b/graphics/chroma-neon/40_dots_shadow.png differ diff --git a/graphics/chroma-neon/40_dots_x.png b/graphics/chroma-neon/40_dots_x.png new file mode 100644 index 0000000..4891e93 Binary files /dev/null and b/graphics/chroma-neon/40_dots_x.png differ diff --git a/graphics/chroma-neon/40_dots_x_shadow.png b/graphics/chroma-neon/40_dots_x_shadow.png new file mode 100644 index 0000000..6513141 Binary files /dev/null and b/graphics/chroma-neon/40_dots_x_shadow.png differ diff --git a/graphics/chroma-neon/40_dots_y.png b/graphics/chroma-neon/40_dots_y.png new file mode 100644 index 0000000..bb67b65 Binary files /dev/null and b/graphics/chroma-neon/40_dots_y.png differ diff --git a/graphics/chroma-neon/40_dots_y_shadow.png b/graphics/chroma-neon/40_dots_y_shadow.png new file mode 100644 index 0000000..c4eb4f7 Binary files /dev/null and b/graphics/chroma-neon/40_dots_y_shadow.png differ diff --git a/graphics/chroma-neon/40_earth.png b/graphics/chroma-neon/40_earth.png new file mode 100644 index 0000000..f51b825 Binary files /dev/null and b/graphics/chroma-neon/40_earth.png differ diff --git a/graphics/chroma-neon/40_earth_double.png b/graphics/chroma-neon/40_earth_double.png new file mode 100644 index 0000000..453b933 Binary files /dev/null and b/graphics/chroma-neon/40_earth_double.png differ diff --git a/graphics/chroma-neon/40_earth_double_shadow.png b/graphics/chroma-neon/40_earth_double_shadow.png new file mode 100644 index 0000000..212ceb7 Binary files /dev/null and b/graphics/chroma-neon/40_earth_double_shadow.png differ diff --git a/graphics/chroma-neon/40_earth_shadow.png b/graphics/chroma-neon/40_earth_shadow.png new file mode 100644 index 0000000..09de236 Binary files /dev/null and b/graphics/chroma-neon/40_earth_shadow.png differ diff --git a/graphics/chroma-neon/40_earth_x.png b/graphics/chroma-neon/40_earth_x.png new file mode 100644 index 0000000..5c81628 Binary files /dev/null and b/graphics/chroma-neon/40_earth_x.png differ diff --git a/graphics/chroma-neon/40_earth_x_shadow.png b/graphics/chroma-neon/40_earth_x_shadow.png new file mode 100644 index 0000000..1292bdc Binary files /dev/null and b/graphics/chroma-neon/40_earth_x_shadow.png differ diff --git a/graphics/chroma-neon/40_earth_y.png b/graphics/chroma-neon/40_earth_y.png new file mode 100644 index 0000000..b4c3522 Binary files /dev/null and b/graphics/chroma-neon/40_earth_y.png differ diff --git a/graphics/chroma-neon/40_earth_y_shadow.png b/graphics/chroma-neon/40_earth_y_shadow.png new file mode 100644 index 0000000..cae12f5 Binary files /dev/null and b/graphics/chroma-neon/40_earth_y_shadow.png differ diff --git a/graphics/chroma-neon/40_map_bottom_left.png b/graphics/chroma-neon/40_map_bottom_left.png new file mode 100644 index 0000000..6792092 Binary files /dev/null and b/graphics/chroma-neon/40_map_bottom_left.png differ diff --git a/graphics/chroma-neon/40_map_bottom_left_shadow.png b/graphics/chroma-neon/40_map_bottom_left_shadow.png new file mode 100644 index 0000000..80efdee Binary files /dev/null and b/graphics/chroma-neon/40_map_bottom_left_shadow.png differ diff --git a/graphics/chroma-neon/40_map_bottom_right.png b/graphics/chroma-neon/40_map_bottom_right.png new file mode 100644 index 0000000..bc6025e Binary files /dev/null and b/graphics/chroma-neon/40_map_bottom_right.png differ diff --git a/graphics/chroma-neon/40_map_bottom_right_shadow.png b/graphics/chroma-neon/40_map_bottom_right_shadow.png new file mode 100644 index 0000000..cb7d166 Binary files /dev/null and b/graphics/chroma-neon/40_map_bottom_right_shadow.png differ diff --git a/graphics/chroma-neon/40_map_top_left.png b/graphics/chroma-neon/40_map_top_left.png new file mode 100644 index 0000000..e2d6f28 Binary files /dev/null and b/graphics/chroma-neon/40_map_top_left.png differ diff --git a/graphics/chroma-neon/40_map_top_left_shadow.png b/graphics/chroma-neon/40_map_top_left_shadow.png new file mode 100644 index 0000000..fe00170 Binary files /dev/null and b/graphics/chroma-neon/40_map_top_left_shadow.png differ diff --git a/graphics/chroma-neon/40_map_top_right.png b/graphics/chroma-neon/40_map_top_right.png new file mode 100644 index 0000000..cca7c1a Binary files /dev/null and b/graphics/chroma-neon/40_map_top_right.png differ diff --git a/graphics/chroma-neon/40_map_top_right_shadow.png b/graphics/chroma-neon/40_map_top_right_shadow.png new file mode 100644 index 0000000..4e54a53 Binary files /dev/null and b/graphics/chroma-neon/40_map_top_right_shadow.png differ diff --git a/graphics/chroma-neon/40_player_one.png b/graphics/chroma-neon/40_player_one.png new file mode 100644 index 0000000..0cf58de Binary files /dev/null and b/graphics/chroma-neon/40_player_one.png differ diff --git a/graphics/chroma-neon/40_player_one_shadow.png b/graphics/chroma-neon/40_player_one_shadow.png new file mode 100644 index 0000000..df00edc Binary files /dev/null and b/graphics/chroma-neon/40_player_one_shadow.png differ diff --git a/graphics/chroma-neon/40_player_one_swapped.png b/graphics/chroma-neon/40_player_one_swapped.png new file mode 100644 index 0000000..321893e Binary files /dev/null and b/graphics/chroma-neon/40_player_one_swapped.png differ diff --git a/graphics/chroma-neon/40_player_one_swapped_shadow.png b/graphics/chroma-neon/40_player_one_swapped_shadow.png new file mode 100644 index 0000000..c22b7e4 Binary files /dev/null and b/graphics/chroma-neon/40_player_one_swapped_shadow.png differ diff --git a/graphics/chroma-neon/40_player_two.png b/graphics/chroma-neon/40_player_two.png new file mode 100644 index 0000000..abe56bd Binary files /dev/null and b/graphics/chroma-neon/40_player_two.png differ diff --git a/graphics/chroma-neon/40_player_two_shadow.png b/graphics/chroma-neon/40_player_two_shadow.png new file mode 100644 index 0000000..c0cd2b9 Binary files /dev/null and b/graphics/chroma-neon/40_player_two_shadow.png differ diff --git a/graphics/chroma-neon/40_player_two_swapped.png b/graphics/chroma-neon/40_player_two_swapped.png new file mode 100644 index 0000000..d1815f1 Binary files /dev/null and b/graphics/chroma-neon/40_player_two_swapped.png differ diff --git a/graphics/chroma-neon/40_player_two_swapped_shadow.png b/graphics/chroma-neon/40_player_two_swapped_shadow.png new file mode 100644 index 0000000..3e11f9e Binary files /dev/null and b/graphics/chroma-neon/40_player_two_swapped_shadow.png differ diff --git a/graphics/chroma-neon/40_star.png b/graphics/chroma-neon/40_star.png new file mode 100644 index 0000000..a4189fa Binary files /dev/null and b/graphics/chroma-neon/40_star.png differ diff --git a/graphics/chroma-neon/40_star_shadow.png b/graphics/chroma-neon/40_star_shadow.png new file mode 100644 index 0000000..b4008d2 Binary files /dev/null and b/graphics/chroma-neon/40_star_shadow.png differ diff --git a/graphics/chroma-neon/40_switch.png b/graphics/chroma-neon/40_switch.png new file mode 100644 index 0000000..59894b1 Binary files /dev/null and b/graphics/chroma-neon/40_switch.png differ diff --git a/graphics/chroma-neon/40_switch_shadow.png b/graphics/chroma-neon/40_switch_shadow.png new file mode 100644 index 0000000..244db48 Binary files /dev/null and b/graphics/chroma-neon/40_switch_shadow.png differ diff --git a/graphics/chroma-neon/40_teleport.png b/graphics/chroma-neon/40_teleport.png new file mode 100644 index 0000000..64626d7 Binary files /dev/null and b/graphics/chroma-neon/40_teleport.png differ diff --git a/graphics/chroma-neon/40_teleport_shadow.png b/graphics/chroma-neon/40_teleport_shadow.png new file mode 100644 index 0000000..3046762 Binary files /dev/null and b/graphics/chroma-neon/40_teleport_shadow.png differ diff --git a/graphics/chroma-neon/40_wall.png b/graphics/chroma-neon/40_wall.png new file mode 100644 index 0000000..a503f2f Binary files /dev/null and b/graphics/chroma-neon/40_wall.png differ diff --git a/graphics/chroma-neon/40_wall_inside.png b/graphics/chroma-neon/40_wall_inside.png new file mode 100644 index 0000000..88218b5 Binary files /dev/null and b/graphics/chroma-neon/40_wall_inside.png differ diff --git a/graphics/chroma-neon/40_wall_outside.png b/graphics/chroma-neon/40_wall_outside.png new file mode 100644 index 0000000..09c73dc Binary files /dev/null and b/graphics/chroma-neon/40_wall_outside.png differ diff --git a/graphics/chroma-neon/40_wall_shadow.png b/graphics/chroma-neon/40_wall_shadow.png new file mode 100644 index 0000000..cdc27a5 Binary files /dev/null and b/graphics/chroma-neon/40_wall_shadow.png differ diff --git a/graphics/chroma-neon/40_wall_x.png b/graphics/chroma-neon/40_wall_x.png new file mode 100644 index 0000000..bd418da Binary files /dev/null and b/graphics/chroma-neon/40_wall_x.png differ diff --git a/graphics/chroma-neon/40_wall_y.png b/graphics/chroma-neon/40_wall_y.png new file mode 100644 index 0000000..6fc2f55 Binary files /dev/null and b/graphics/chroma-neon/40_wall_y.png differ diff --git a/graphics/chroma-neon/64_arrow_blue_down.png b/graphics/chroma-neon/64_arrow_blue_down.png new file mode 100644 index 0000000..b366e31 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_blue_down.png differ diff --git a/graphics/chroma-neon/64_arrow_blue_down_shadow.png b/graphics/chroma-neon/64_arrow_blue_down_shadow.png new file mode 100644 index 0000000..0171748 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_blue_left.png b/graphics/chroma-neon/64_arrow_blue_left.png new file mode 100644 index 0000000..90e986f Binary files /dev/null and b/graphics/chroma-neon/64_arrow_blue_left.png differ diff --git a/graphics/chroma-neon/64_arrow_blue_left_shadow.png b/graphics/chroma-neon/64_arrow_blue_left_shadow.png new file mode 100644 index 0000000..ae86a81 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_blue_right.png b/graphics/chroma-neon/64_arrow_blue_right.png new file mode 100644 index 0000000..8438aa5 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_blue_right.png differ diff --git a/graphics/chroma-neon/64_arrow_blue_right_shadow.png b/graphics/chroma-neon/64_arrow_blue_right_shadow.png new file mode 100644 index 0000000..f4f2b20 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_blue_up.png b/graphics/chroma-neon/64_arrow_blue_up.png new file mode 100644 index 0000000..ded7c20 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_blue_up.png differ diff --git a/graphics/chroma-neon/64_arrow_blue_up_shadow.png b/graphics/chroma-neon/64_arrow_blue_up_shadow.png new file mode 100644 index 0000000..2b44b20 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_green_down.png b/graphics/chroma-neon/64_arrow_green_down.png new file mode 100644 index 0000000..163f647 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_green_down.png differ diff --git a/graphics/chroma-neon/64_arrow_green_down_shadow.png b/graphics/chroma-neon/64_arrow_green_down_shadow.png new file mode 100644 index 0000000..7591555 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_green_down_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_green_left.png b/graphics/chroma-neon/64_arrow_green_left.png new file mode 100644 index 0000000..882a442 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_green_left.png differ diff --git a/graphics/chroma-neon/64_arrow_green_left_shadow.png b/graphics/chroma-neon/64_arrow_green_left_shadow.png new file mode 100644 index 0000000..a898cc1 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_green_left_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_green_right.png b/graphics/chroma-neon/64_arrow_green_right.png new file mode 100644 index 0000000..8bf8176 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_green_right.png differ diff --git a/graphics/chroma-neon/64_arrow_green_right_shadow.png b/graphics/chroma-neon/64_arrow_green_right_shadow.png new file mode 100644 index 0000000..3a025be Binary files /dev/null and b/graphics/chroma-neon/64_arrow_green_right_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_green_up.png b/graphics/chroma-neon/64_arrow_green_up.png new file mode 100644 index 0000000..5472ddc Binary files /dev/null and b/graphics/chroma-neon/64_arrow_green_up.png differ diff --git a/graphics/chroma-neon/64_arrow_green_up_shadow.png b/graphics/chroma-neon/64_arrow_green_up_shadow.png new file mode 100644 index 0000000..e6f883a Binary files /dev/null and b/graphics/chroma-neon/64_arrow_green_up_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_red_down.png b/graphics/chroma-neon/64_arrow_red_down.png new file mode 100644 index 0000000..00e7ce1 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_red_down.png differ diff --git a/graphics/chroma-neon/64_arrow_red_down_shadow.png b/graphics/chroma-neon/64_arrow_red_down_shadow.png new file mode 100644 index 0000000..3afd2a3 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_red_down_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_red_left.png b/graphics/chroma-neon/64_arrow_red_left.png new file mode 100644 index 0000000..9b2104f Binary files /dev/null and b/graphics/chroma-neon/64_arrow_red_left.png differ diff --git a/graphics/chroma-neon/64_arrow_red_left_shadow.png b/graphics/chroma-neon/64_arrow_red_left_shadow.png new file mode 100644 index 0000000..fb88abe Binary files /dev/null and b/graphics/chroma-neon/64_arrow_red_left_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_red_right.png b/graphics/chroma-neon/64_arrow_red_right.png new file mode 100644 index 0000000..f88d31c Binary files /dev/null and b/graphics/chroma-neon/64_arrow_red_right.png differ diff --git a/graphics/chroma-neon/64_arrow_red_right_shadow.png b/graphics/chroma-neon/64_arrow_red_right_shadow.png new file mode 100644 index 0000000..b5aedd5 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_red_right_shadow.png differ diff --git a/graphics/chroma-neon/64_arrow_red_up.png b/graphics/chroma-neon/64_arrow_red_up.png new file mode 100644 index 0000000..619d1b7 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_red_up.png differ diff --git a/graphics/chroma-neon/64_arrow_red_up_shadow.png b/graphics/chroma-neon/64_arrow_red_up_shadow.png new file mode 100644 index 0000000..1ed78b8 Binary files /dev/null and b/graphics/chroma-neon/64_arrow_red_up_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_blue_down.png b/graphics/chroma-neon/64_bomb_blue_down.png new file mode 100644 index 0000000..e61f0bd Binary files /dev/null and b/graphics/chroma-neon/64_bomb_blue_down.png differ diff --git a/graphics/chroma-neon/64_bomb_blue_down_shadow.png b/graphics/chroma-neon/64_bomb_blue_down_shadow.png new file mode 100644 index 0000000..1468853 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_blue_down_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_blue_left.png b/graphics/chroma-neon/64_bomb_blue_left.png new file mode 100644 index 0000000..de2b8ff Binary files /dev/null and b/graphics/chroma-neon/64_bomb_blue_left.png differ diff --git a/graphics/chroma-neon/64_bomb_blue_left_shadow.png b/graphics/chroma-neon/64_bomb_blue_left_shadow.png new file mode 100644 index 0000000..00bbc9b Binary files /dev/null and b/graphics/chroma-neon/64_bomb_blue_left_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_blue_right.png b/graphics/chroma-neon/64_bomb_blue_right.png new file mode 100644 index 0000000..66af111 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_blue_right.png differ diff --git a/graphics/chroma-neon/64_bomb_blue_right_shadow.png b/graphics/chroma-neon/64_bomb_blue_right_shadow.png new file mode 100644 index 0000000..917e60d Binary files /dev/null and b/graphics/chroma-neon/64_bomb_blue_right_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_blue_up.png b/graphics/chroma-neon/64_bomb_blue_up.png new file mode 100644 index 0000000..277ea90 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_blue_up.png differ diff --git a/graphics/chroma-neon/64_bomb_blue_up_shadow.png b/graphics/chroma-neon/64_bomb_blue_up_shadow.png new file mode 100644 index 0000000..9e523be Binary files /dev/null and b/graphics/chroma-neon/64_bomb_blue_up_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_green_down.png b/graphics/chroma-neon/64_bomb_green_down.png new file mode 100644 index 0000000..7b626b7 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_green_down.png differ diff --git a/graphics/chroma-neon/64_bomb_green_down_shadow.png b/graphics/chroma-neon/64_bomb_green_down_shadow.png new file mode 100644 index 0000000..ca1e923 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_green_down_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_green_left.png b/graphics/chroma-neon/64_bomb_green_left.png new file mode 100644 index 0000000..bbf9ea3 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_green_left.png differ diff --git a/graphics/chroma-neon/64_bomb_green_left_shadow.png b/graphics/chroma-neon/64_bomb_green_left_shadow.png new file mode 100644 index 0000000..dc5cd08 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_green_left_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_green_right.png b/graphics/chroma-neon/64_bomb_green_right.png new file mode 100644 index 0000000..ea3fab4 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_green_right.png differ diff --git a/graphics/chroma-neon/64_bomb_green_right_shadow.png b/graphics/chroma-neon/64_bomb_green_right_shadow.png new file mode 100644 index 0000000..30f12fe Binary files /dev/null and b/graphics/chroma-neon/64_bomb_green_right_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_green_up.png b/graphics/chroma-neon/64_bomb_green_up.png new file mode 100644 index 0000000..1b033f3 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_green_up.png differ diff --git a/graphics/chroma-neon/64_bomb_green_up_shadow.png b/graphics/chroma-neon/64_bomb_green_up_shadow.png new file mode 100644 index 0000000..5814c1c Binary files /dev/null and b/graphics/chroma-neon/64_bomb_green_up_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_red_down.png b/graphics/chroma-neon/64_bomb_red_down.png new file mode 100644 index 0000000..0e557ca Binary files /dev/null and b/graphics/chroma-neon/64_bomb_red_down.png differ diff --git a/graphics/chroma-neon/64_bomb_red_down_shadow.png b/graphics/chroma-neon/64_bomb_red_down_shadow.png new file mode 100644 index 0000000..649f6e5 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_red_down_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_red_left.png b/graphics/chroma-neon/64_bomb_red_left.png new file mode 100644 index 0000000..4ea1f8d Binary files /dev/null and b/graphics/chroma-neon/64_bomb_red_left.png differ diff --git a/graphics/chroma-neon/64_bomb_red_left_shadow.png b/graphics/chroma-neon/64_bomb_red_left_shadow.png new file mode 100644 index 0000000..0910879 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_red_left_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_red_right.png b/graphics/chroma-neon/64_bomb_red_right.png new file mode 100644 index 0000000..acef425 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_red_right.png differ diff --git a/graphics/chroma-neon/64_bomb_red_right_shadow.png b/graphics/chroma-neon/64_bomb_red_right_shadow.png new file mode 100644 index 0000000..b415499 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_red_right_shadow.png differ diff --git a/graphics/chroma-neon/64_bomb_red_up.png b/graphics/chroma-neon/64_bomb_red_up.png new file mode 100644 index 0000000..1a59d87 Binary files /dev/null and b/graphics/chroma-neon/64_bomb_red_up.png differ diff --git a/graphics/chroma-neon/64_bomb_red_up_shadow.png b/graphics/chroma-neon/64_bomb_red_up_shadow.png new file mode 100644 index 0000000..438141d Binary files /dev/null and b/graphics/chroma-neon/64_bomb_red_up_shadow.png differ diff --git a/graphics/chroma-neon/64_circle.png b/graphics/chroma-neon/64_circle.png new file mode 100644 index 0000000..d0c4392 Binary files /dev/null and b/graphics/chroma-neon/64_circle.png differ diff --git a/graphics/chroma-neon/64_circle_double.png b/graphics/chroma-neon/64_circle_double.png new file mode 100644 index 0000000..b496015 Binary files /dev/null and b/graphics/chroma-neon/64_circle_double.png differ diff --git a/graphics/chroma-neon/64_circle_double_shadow.png b/graphics/chroma-neon/64_circle_double_shadow.png new file mode 100644 index 0000000..019f0c9 Binary files /dev/null and b/graphics/chroma-neon/64_circle_double_shadow.png differ diff --git a/graphics/chroma-neon/64_circle_shadow.png b/graphics/chroma-neon/64_circle_shadow.png new file mode 100644 index 0000000..7c90777 Binary files /dev/null and b/graphics/chroma-neon/64_circle_shadow.png differ diff --git a/graphics/chroma-neon/64_door.png b/graphics/chroma-neon/64_door.png new file mode 100644 index 0000000..54b17a9 Binary files /dev/null and b/graphics/chroma-neon/64_door.png differ diff --git a/graphics/chroma-neon/64_door_shadow.png b/graphics/chroma-neon/64_door_shadow.png new file mode 100644 index 0000000..4d2020b Binary files /dev/null and b/graphics/chroma-neon/64_door_shadow.png differ diff --git a/graphics/chroma-neon/64_dots.png b/graphics/chroma-neon/64_dots.png new file mode 100644 index 0000000..b8d683b Binary files /dev/null and b/graphics/chroma-neon/64_dots.png differ diff --git a/graphics/chroma-neon/64_dots_double.png b/graphics/chroma-neon/64_dots_double.png new file mode 100644 index 0000000..0d2410f Binary files /dev/null and b/graphics/chroma-neon/64_dots_double.png differ diff --git a/graphics/chroma-neon/64_dots_double_shadow.png b/graphics/chroma-neon/64_dots_double_shadow.png new file mode 100644 index 0000000..a2a751d Binary files /dev/null and b/graphics/chroma-neon/64_dots_double_shadow.png differ diff --git a/graphics/chroma-neon/64_dots_shadow.png b/graphics/chroma-neon/64_dots_shadow.png new file mode 100644 index 0000000..fa453dd Binary files /dev/null and b/graphics/chroma-neon/64_dots_shadow.png differ diff --git a/graphics/chroma-neon/64_dots_x.png b/graphics/chroma-neon/64_dots_x.png new file mode 100644 index 0000000..7bb4284 Binary files /dev/null and b/graphics/chroma-neon/64_dots_x.png differ diff --git a/graphics/chroma-neon/64_dots_x_shadow.png b/graphics/chroma-neon/64_dots_x_shadow.png new file mode 100644 index 0000000..63728b6 Binary files /dev/null and b/graphics/chroma-neon/64_dots_x_shadow.png differ diff --git a/graphics/chroma-neon/64_dots_y.png b/graphics/chroma-neon/64_dots_y.png new file mode 100644 index 0000000..cf72bd0 Binary files /dev/null and b/graphics/chroma-neon/64_dots_y.png differ diff --git a/graphics/chroma-neon/64_dots_y_shadow.png b/graphics/chroma-neon/64_dots_y_shadow.png new file mode 100644 index 0000000..2e7c1f3 Binary files /dev/null and b/graphics/chroma-neon/64_dots_y_shadow.png differ diff --git a/graphics/chroma-neon/64_earth.png b/graphics/chroma-neon/64_earth.png new file mode 100644 index 0000000..0295426 Binary files /dev/null and b/graphics/chroma-neon/64_earth.png differ diff --git a/graphics/chroma-neon/64_earth_double.png b/graphics/chroma-neon/64_earth_double.png new file mode 100644 index 0000000..536cd59 Binary files /dev/null and b/graphics/chroma-neon/64_earth_double.png differ diff --git a/graphics/chroma-neon/64_earth_double_shadow.png b/graphics/chroma-neon/64_earth_double_shadow.png new file mode 100644 index 0000000..25a2701 Binary files /dev/null and b/graphics/chroma-neon/64_earth_double_shadow.png differ diff --git a/graphics/chroma-neon/64_earth_shadow.png b/graphics/chroma-neon/64_earth_shadow.png new file mode 100644 index 0000000..dd7b3ad Binary files /dev/null and b/graphics/chroma-neon/64_earth_shadow.png differ diff --git a/graphics/chroma-neon/64_earth_x.png b/graphics/chroma-neon/64_earth_x.png new file mode 100644 index 0000000..55c9e72 Binary files /dev/null and b/graphics/chroma-neon/64_earth_x.png differ diff --git a/graphics/chroma-neon/64_earth_x_shadow.png b/graphics/chroma-neon/64_earth_x_shadow.png new file mode 100644 index 0000000..8b3559e Binary files /dev/null and b/graphics/chroma-neon/64_earth_x_shadow.png differ diff --git a/graphics/chroma-neon/64_earth_y.png b/graphics/chroma-neon/64_earth_y.png new file mode 100644 index 0000000..9b85f50 Binary files /dev/null and b/graphics/chroma-neon/64_earth_y.png differ diff --git a/graphics/chroma-neon/64_earth_y_shadow.png b/graphics/chroma-neon/64_earth_y_shadow.png new file mode 100644 index 0000000..4f63968 Binary files /dev/null and b/graphics/chroma-neon/64_earth_y_shadow.png differ diff --git a/graphics/chroma-neon/64_map_bottom_left.png b/graphics/chroma-neon/64_map_bottom_left.png new file mode 100644 index 0000000..e6eebf3 Binary files /dev/null and b/graphics/chroma-neon/64_map_bottom_left.png differ diff --git a/graphics/chroma-neon/64_map_bottom_left_shadow.png b/graphics/chroma-neon/64_map_bottom_left_shadow.png new file mode 100644 index 0000000..66ae813 Binary files /dev/null and b/graphics/chroma-neon/64_map_bottom_left_shadow.png differ diff --git a/graphics/chroma-neon/64_map_bottom_right.png b/graphics/chroma-neon/64_map_bottom_right.png new file mode 100644 index 0000000..817df8b Binary files /dev/null and b/graphics/chroma-neon/64_map_bottom_right.png differ diff --git a/graphics/chroma-neon/64_map_bottom_right_shadow.png b/graphics/chroma-neon/64_map_bottom_right_shadow.png new file mode 100644 index 0000000..885d98b Binary files /dev/null and b/graphics/chroma-neon/64_map_bottom_right_shadow.png differ diff --git a/graphics/chroma-neon/64_map_top_left.png b/graphics/chroma-neon/64_map_top_left.png new file mode 100644 index 0000000..f92a2db Binary files /dev/null and b/graphics/chroma-neon/64_map_top_left.png differ diff --git a/graphics/chroma-neon/64_map_top_left_shadow.png b/graphics/chroma-neon/64_map_top_left_shadow.png new file mode 100644 index 0000000..f298ef5 Binary files /dev/null and b/graphics/chroma-neon/64_map_top_left_shadow.png differ diff --git a/graphics/chroma-neon/64_map_top_right.png b/graphics/chroma-neon/64_map_top_right.png new file mode 100644 index 0000000..7702e12 Binary files /dev/null and b/graphics/chroma-neon/64_map_top_right.png differ diff --git a/graphics/chroma-neon/64_map_top_right_shadow.png b/graphics/chroma-neon/64_map_top_right_shadow.png new file mode 100644 index 0000000..1c81238 Binary files /dev/null and b/graphics/chroma-neon/64_map_top_right_shadow.png differ diff --git a/graphics/chroma-neon/64_player_one.png b/graphics/chroma-neon/64_player_one.png new file mode 100644 index 0000000..79e0ea3 Binary files /dev/null and b/graphics/chroma-neon/64_player_one.png differ diff --git a/graphics/chroma-neon/64_player_one_shadow.png b/graphics/chroma-neon/64_player_one_shadow.png new file mode 100644 index 0000000..4155443 Binary files /dev/null and b/graphics/chroma-neon/64_player_one_shadow.png differ diff --git a/graphics/chroma-neon/64_player_one_swapped.png b/graphics/chroma-neon/64_player_one_swapped.png new file mode 100644 index 0000000..270dcd1 Binary files /dev/null and b/graphics/chroma-neon/64_player_one_swapped.png differ diff --git a/graphics/chroma-neon/64_player_one_swapped_shadow.png b/graphics/chroma-neon/64_player_one_swapped_shadow.png new file mode 100644 index 0000000..5dec74e Binary files /dev/null and b/graphics/chroma-neon/64_player_one_swapped_shadow.png differ diff --git a/graphics/chroma-neon/64_player_two.png b/graphics/chroma-neon/64_player_two.png new file mode 100644 index 0000000..9c79015 Binary files /dev/null and b/graphics/chroma-neon/64_player_two.png differ diff --git a/graphics/chroma-neon/64_player_two_shadow.png b/graphics/chroma-neon/64_player_two_shadow.png new file mode 100644 index 0000000..1a80520 Binary files /dev/null and b/graphics/chroma-neon/64_player_two_shadow.png differ diff --git a/graphics/chroma-neon/64_player_two_swapped.png b/graphics/chroma-neon/64_player_two_swapped.png new file mode 100644 index 0000000..bc85e40 Binary files /dev/null and b/graphics/chroma-neon/64_player_two_swapped.png differ diff --git a/graphics/chroma-neon/64_player_two_swapped_shadow.png b/graphics/chroma-neon/64_player_two_swapped_shadow.png new file mode 100644 index 0000000..b8e4520 Binary files /dev/null and b/graphics/chroma-neon/64_player_two_swapped_shadow.png differ diff --git a/graphics/chroma-neon/64_star.png b/graphics/chroma-neon/64_star.png new file mode 100644 index 0000000..a28fa59 Binary files /dev/null and b/graphics/chroma-neon/64_star.png differ diff --git a/graphics/chroma-neon/64_star_shadow.png b/graphics/chroma-neon/64_star_shadow.png new file mode 100644 index 0000000..7f0eb2b Binary files /dev/null and b/graphics/chroma-neon/64_star_shadow.png differ diff --git a/graphics/chroma-neon/64_switch.png b/graphics/chroma-neon/64_switch.png new file mode 100644 index 0000000..8784bd6 Binary files /dev/null and b/graphics/chroma-neon/64_switch.png differ diff --git a/graphics/chroma-neon/64_switch_shadow.png b/graphics/chroma-neon/64_switch_shadow.png new file mode 100644 index 0000000..fb9c425 Binary files /dev/null and b/graphics/chroma-neon/64_switch_shadow.png differ diff --git a/graphics/chroma-neon/64_teleport.png b/graphics/chroma-neon/64_teleport.png new file mode 100644 index 0000000..c5fe5ad Binary files /dev/null and b/graphics/chroma-neon/64_teleport.png differ diff --git a/graphics/chroma-neon/64_teleport_shadow.png b/graphics/chroma-neon/64_teleport_shadow.png new file mode 100644 index 0000000..b06be5f Binary files /dev/null and b/graphics/chroma-neon/64_teleport_shadow.png differ diff --git a/graphics/chroma-neon/64_wall.png b/graphics/chroma-neon/64_wall.png new file mode 100644 index 0000000..6b006f7 Binary files /dev/null and b/graphics/chroma-neon/64_wall.png differ diff --git a/graphics/chroma-neon/64_wall_inside.png b/graphics/chroma-neon/64_wall_inside.png new file mode 100644 index 0000000..34fd0a0 Binary files /dev/null and b/graphics/chroma-neon/64_wall_inside.png differ diff --git a/graphics/chroma-neon/64_wall_outside.png b/graphics/chroma-neon/64_wall_outside.png new file mode 100644 index 0000000..88a9172 Binary files /dev/null and b/graphics/chroma-neon/64_wall_outside.png differ diff --git a/graphics/chroma-neon/64_wall_shadow.png b/graphics/chroma-neon/64_wall_shadow.png new file mode 100644 index 0000000..55a5895 Binary files /dev/null and b/graphics/chroma-neon/64_wall_shadow.png differ diff --git a/graphics/chroma-neon/64_wall_x.png b/graphics/chroma-neon/64_wall_x.png new file mode 100644 index 0000000..9c827e1 Binary files /dev/null and b/graphics/chroma-neon/64_wall_x.png differ diff --git a/graphics/chroma-neon/64_wall_y.png b/graphics/chroma-neon/64_wall_y.png new file mode 100644 index 0000000..276a1a3 Binary files /dev/null and b/graphics/chroma-neon/64_wall_y.png differ diff --git a/graphics/chroma-zen.chroma b/graphics/chroma-zen.chroma new file mode 100644 index 0000000..d33f36e --- /dev/null +++ b/graphics/chroma-zen.chroma @@ -0,0 +1,270 @@ + + + + + +Chroma Zen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/graphics/chroma-zen/16_arrow_blue_down.png b/graphics/chroma-zen/16_arrow_blue_down.png new file mode 100644 index 0000000..122c8d3 Binary files /dev/null and b/graphics/chroma-zen/16_arrow_blue_down.png differ diff --git a/graphics/chroma-zen/16_arrow_blue_left.png b/graphics/chroma-zen/16_arrow_blue_left.png new file mode 100644 index 0000000..b884b7f Binary files /dev/null and b/graphics/chroma-zen/16_arrow_blue_left.png differ diff --git a/graphics/chroma-zen/16_arrow_blue_right.png b/graphics/chroma-zen/16_arrow_blue_right.png new file mode 100644 index 0000000..03af23c Binary files /dev/null and b/graphics/chroma-zen/16_arrow_blue_right.png differ diff --git a/graphics/chroma-zen/16_arrow_blue_up.png b/graphics/chroma-zen/16_arrow_blue_up.png new file mode 100644 index 0000000..539fdee Binary files /dev/null and b/graphics/chroma-zen/16_arrow_blue_up.png differ diff --git a/graphics/chroma-zen/16_arrow_green_down.png b/graphics/chroma-zen/16_arrow_green_down.png new file mode 100644 index 0000000..a04c0eb Binary files /dev/null and b/graphics/chroma-zen/16_arrow_green_down.png differ diff --git a/graphics/chroma-zen/16_arrow_green_left.png b/graphics/chroma-zen/16_arrow_green_left.png new file mode 100644 index 0000000..b10eb66 Binary files /dev/null and b/graphics/chroma-zen/16_arrow_green_left.png differ diff --git a/graphics/chroma-zen/16_arrow_green_right.png b/graphics/chroma-zen/16_arrow_green_right.png new file mode 100644 index 0000000..2d003b8 Binary files /dev/null and b/graphics/chroma-zen/16_arrow_green_right.png differ diff --git a/graphics/chroma-zen/16_arrow_green_up.png b/graphics/chroma-zen/16_arrow_green_up.png new file mode 100644 index 0000000..37a4ac7 Binary files /dev/null and b/graphics/chroma-zen/16_arrow_green_up.png differ diff --git a/graphics/chroma-zen/16_arrow_red_down.png b/graphics/chroma-zen/16_arrow_red_down.png new file mode 100644 index 0000000..e62de9d Binary files /dev/null and b/graphics/chroma-zen/16_arrow_red_down.png differ diff --git a/graphics/chroma-zen/16_arrow_red_left.png b/graphics/chroma-zen/16_arrow_red_left.png new file mode 100644 index 0000000..ad899f6 Binary files /dev/null and b/graphics/chroma-zen/16_arrow_red_left.png differ diff --git a/graphics/chroma-zen/16_arrow_red_right.png b/graphics/chroma-zen/16_arrow_red_right.png new file mode 100644 index 0000000..3973bfe Binary files /dev/null and b/graphics/chroma-zen/16_arrow_red_right.png differ diff --git a/graphics/chroma-zen/16_arrow_red_up.png b/graphics/chroma-zen/16_arrow_red_up.png new file mode 100644 index 0000000..56e3759 Binary files /dev/null and b/graphics/chroma-zen/16_arrow_red_up.png differ diff --git a/graphics/chroma-zen/16_bomb_blue_down.png b/graphics/chroma-zen/16_bomb_blue_down.png new file mode 100644 index 0000000..4955205 Binary files /dev/null and b/graphics/chroma-zen/16_bomb_blue_down.png differ diff --git a/graphics/chroma-zen/16_bomb_blue_left.png b/graphics/chroma-zen/16_bomb_blue_left.png new file mode 100644 index 0000000..7a6c642 Binary files /dev/null and b/graphics/chroma-zen/16_bomb_blue_left.png differ diff --git a/graphics/chroma-zen/16_bomb_blue_right.png b/graphics/chroma-zen/16_bomb_blue_right.png new file mode 100644 index 0000000..5c3add8 Binary files /dev/null and b/graphics/chroma-zen/16_bomb_blue_right.png differ diff --git a/graphics/chroma-zen/16_bomb_blue_up.png b/graphics/chroma-zen/16_bomb_blue_up.png new file mode 100644 index 0000000..f8b95d2 Binary files /dev/null and b/graphics/chroma-zen/16_bomb_blue_up.png differ diff --git a/graphics/chroma-zen/16_bomb_green_down.png b/graphics/chroma-zen/16_bomb_green_down.png new file mode 100644 index 0000000..9604734 Binary files /dev/null and b/graphics/chroma-zen/16_bomb_green_down.png differ diff --git a/graphics/chroma-zen/16_bomb_green_left.png b/graphics/chroma-zen/16_bomb_green_left.png new file mode 100644 index 0000000..ea1e99f Binary files /dev/null and b/graphics/chroma-zen/16_bomb_green_left.png differ diff --git a/graphics/chroma-zen/16_bomb_green_right.png b/graphics/chroma-zen/16_bomb_green_right.png new file mode 100644 index 0000000..704a3fb Binary files /dev/null and b/graphics/chroma-zen/16_bomb_green_right.png differ diff --git a/graphics/chroma-zen/16_bomb_green_up.png b/graphics/chroma-zen/16_bomb_green_up.png new file mode 100644 index 0000000..16cc696 Binary files /dev/null and b/graphics/chroma-zen/16_bomb_green_up.png differ diff --git a/graphics/chroma-zen/16_bomb_red_down.png b/graphics/chroma-zen/16_bomb_red_down.png new file mode 100644 index 0000000..63e0cb5 Binary files /dev/null and b/graphics/chroma-zen/16_bomb_red_down.png differ diff --git a/graphics/chroma-zen/16_bomb_red_left.png b/graphics/chroma-zen/16_bomb_red_left.png new file mode 100644 index 0000000..ec4a065 Binary files /dev/null and b/graphics/chroma-zen/16_bomb_red_left.png differ diff --git a/graphics/chroma-zen/16_bomb_red_right.png b/graphics/chroma-zen/16_bomb_red_right.png new file mode 100644 index 0000000..bdae9eb Binary files /dev/null and b/graphics/chroma-zen/16_bomb_red_right.png differ diff --git a/graphics/chroma-zen/16_bomb_red_up.png b/graphics/chroma-zen/16_bomb_red_up.png new file mode 100644 index 0000000..7ac7a6d Binary files /dev/null and b/graphics/chroma-zen/16_bomb_red_up.png differ diff --git a/graphics/chroma-zen/16_circle.png b/graphics/chroma-zen/16_circle.png new file mode 100644 index 0000000..a94a2d9 Binary files /dev/null and b/graphics/chroma-zen/16_circle.png differ diff --git a/graphics/chroma-zen/16_circle_double.png b/graphics/chroma-zen/16_circle_double.png new file mode 100644 index 0000000..e940782 Binary files /dev/null and b/graphics/chroma-zen/16_circle_double.png differ diff --git a/graphics/chroma-zen/16_door.png b/graphics/chroma-zen/16_door.png new file mode 100644 index 0000000..dff10b5 Binary files /dev/null and b/graphics/chroma-zen/16_door.png differ diff --git a/graphics/chroma-zen/16_dots.png b/graphics/chroma-zen/16_dots.png new file mode 100644 index 0000000..97e02ca Binary files /dev/null and b/graphics/chroma-zen/16_dots.png differ diff --git a/graphics/chroma-zen/16_dots_double.png b/graphics/chroma-zen/16_dots_double.png new file mode 100644 index 0000000..77e802d Binary files /dev/null and b/graphics/chroma-zen/16_dots_double.png differ diff --git a/graphics/chroma-zen/16_dots_x.png b/graphics/chroma-zen/16_dots_x.png new file mode 100644 index 0000000..82d1f5b Binary files /dev/null and b/graphics/chroma-zen/16_dots_x.png differ diff --git a/graphics/chroma-zen/16_dots_y.png b/graphics/chroma-zen/16_dots_y.png new file mode 100644 index 0000000..b9808e5 Binary files /dev/null and b/graphics/chroma-zen/16_dots_y.png differ diff --git a/graphics/chroma-zen/16_earth.png b/graphics/chroma-zen/16_earth.png new file mode 100644 index 0000000..4e9153f Binary files /dev/null and b/graphics/chroma-zen/16_earth.png differ diff --git a/graphics/chroma-zen/16_earth_double.png b/graphics/chroma-zen/16_earth_double.png new file mode 100644 index 0000000..1cb99c6 Binary files /dev/null and b/graphics/chroma-zen/16_earth_double.png differ diff --git a/graphics/chroma-zen/16_earth_x.png b/graphics/chroma-zen/16_earth_x.png new file mode 100644 index 0000000..b1c6ed0 Binary files /dev/null and b/graphics/chroma-zen/16_earth_x.png differ diff --git a/graphics/chroma-zen/16_earth_y.png b/graphics/chroma-zen/16_earth_y.png new file mode 100644 index 0000000..27bb1c6 Binary files /dev/null and b/graphics/chroma-zen/16_earth_y.png differ diff --git a/graphics/chroma-zen/16_map_bottom_left.png b/graphics/chroma-zen/16_map_bottom_left.png new file mode 100644 index 0000000..045cdf0 Binary files /dev/null and b/graphics/chroma-zen/16_map_bottom_left.png differ diff --git a/graphics/chroma-zen/16_map_bottom_right.png b/graphics/chroma-zen/16_map_bottom_right.png new file mode 100644 index 0000000..83a2e0c Binary files /dev/null and b/graphics/chroma-zen/16_map_bottom_right.png differ diff --git a/graphics/chroma-zen/16_map_top_left.png b/graphics/chroma-zen/16_map_top_left.png new file mode 100644 index 0000000..73b8aa0 Binary files /dev/null and b/graphics/chroma-zen/16_map_top_left.png differ diff --git a/graphics/chroma-zen/16_map_top_right.png b/graphics/chroma-zen/16_map_top_right.png new file mode 100644 index 0000000..743736c Binary files /dev/null and b/graphics/chroma-zen/16_map_top_right.png differ diff --git a/graphics/chroma-zen/16_player_one.png b/graphics/chroma-zen/16_player_one.png new file mode 100644 index 0000000..50239dc Binary files /dev/null and b/graphics/chroma-zen/16_player_one.png differ diff --git a/graphics/chroma-zen/16_player_one_swapped.png b/graphics/chroma-zen/16_player_one_swapped.png new file mode 100644 index 0000000..0d29eba Binary files /dev/null and b/graphics/chroma-zen/16_player_one_swapped.png differ diff --git a/graphics/chroma-zen/16_player_two.png b/graphics/chroma-zen/16_player_two.png new file mode 100644 index 0000000..4cb916c Binary files /dev/null and b/graphics/chroma-zen/16_player_two.png differ diff --git a/graphics/chroma-zen/16_player_two_swapped.png b/graphics/chroma-zen/16_player_two_swapped.png new file mode 100644 index 0000000..d7e3e85 Binary files /dev/null and b/graphics/chroma-zen/16_player_two_swapped.png differ diff --git a/graphics/chroma-zen/16_star.png b/graphics/chroma-zen/16_star.png new file mode 100644 index 0000000..a507c7e Binary files /dev/null and b/graphics/chroma-zen/16_star.png differ diff --git a/graphics/chroma-zen/16_switch.png b/graphics/chroma-zen/16_switch.png new file mode 100644 index 0000000..90dda00 Binary files /dev/null and b/graphics/chroma-zen/16_switch.png differ diff --git a/graphics/chroma-zen/16_teleport.png b/graphics/chroma-zen/16_teleport.png new file mode 100644 index 0000000..965be03 Binary files /dev/null and b/graphics/chroma-zen/16_teleport.png differ diff --git a/graphics/chroma-zen/16_wall_inside.png b/graphics/chroma-zen/16_wall_inside.png new file mode 100644 index 0000000..3c0e6e2 Binary files /dev/null and b/graphics/chroma-zen/16_wall_inside.png differ diff --git a/graphics/chroma-zen/16_wall_outside.png b/graphics/chroma-zen/16_wall_outside.png new file mode 100644 index 0000000..ebeaa3c Binary files /dev/null and b/graphics/chroma-zen/16_wall_outside.png differ diff --git a/graphics/chroma-zen/16_wall_x.png b/graphics/chroma-zen/16_wall_x.png new file mode 100644 index 0000000..601463f Binary files /dev/null and b/graphics/chroma-zen/16_wall_x.png differ diff --git a/graphics/chroma-zen/16_wall_y.png b/graphics/chroma-zen/16_wall_y.png new file mode 100644 index 0000000..26245e7 Binary files /dev/null and b/graphics/chroma-zen/16_wall_y.png differ diff --git a/graphics/chroma-zen/20_arrow_blue_down.png b/graphics/chroma-zen/20_arrow_blue_down.png new file mode 100644 index 0000000..029d3c6 Binary files /dev/null and b/graphics/chroma-zen/20_arrow_blue_down.png differ diff --git a/graphics/chroma-zen/20_arrow_blue_left.png b/graphics/chroma-zen/20_arrow_blue_left.png new file mode 100644 index 0000000..c32d0a0 Binary files /dev/null and b/graphics/chroma-zen/20_arrow_blue_left.png differ diff --git a/graphics/chroma-zen/20_arrow_blue_right.png b/graphics/chroma-zen/20_arrow_blue_right.png new file mode 100644 index 0000000..4f940aa Binary files /dev/null and b/graphics/chroma-zen/20_arrow_blue_right.png differ diff --git a/graphics/chroma-zen/20_arrow_blue_up.png b/graphics/chroma-zen/20_arrow_blue_up.png new file mode 100644 index 0000000..78b1688 Binary files /dev/null and b/graphics/chroma-zen/20_arrow_blue_up.png differ diff --git a/graphics/chroma-zen/20_arrow_green_down.png b/graphics/chroma-zen/20_arrow_green_down.png new file mode 100644 index 0000000..8894086 Binary files /dev/null and b/graphics/chroma-zen/20_arrow_green_down.png differ diff --git a/graphics/chroma-zen/20_arrow_green_left.png b/graphics/chroma-zen/20_arrow_green_left.png new file mode 100644 index 0000000..8cfd487 Binary files /dev/null and b/graphics/chroma-zen/20_arrow_green_left.png differ diff --git a/graphics/chroma-zen/20_arrow_green_right.png b/graphics/chroma-zen/20_arrow_green_right.png new file mode 100644 index 0000000..efdd37e Binary files /dev/null and b/graphics/chroma-zen/20_arrow_green_right.png differ diff --git a/graphics/chroma-zen/20_arrow_green_up.png b/graphics/chroma-zen/20_arrow_green_up.png new file mode 100644 index 0000000..a3907a7 Binary files /dev/null and b/graphics/chroma-zen/20_arrow_green_up.png differ diff --git a/graphics/chroma-zen/20_arrow_red_down.png b/graphics/chroma-zen/20_arrow_red_down.png new file mode 100644 index 0000000..823ebf3 Binary files /dev/null and b/graphics/chroma-zen/20_arrow_red_down.png differ diff --git a/graphics/chroma-zen/20_arrow_red_left.png b/graphics/chroma-zen/20_arrow_red_left.png new file mode 100644 index 0000000..97238b7 Binary files /dev/null and b/graphics/chroma-zen/20_arrow_red_left.png differ diff --git a/graphics/chroma-zen/20_arrow_red_right.png b/graphics/chroma-zen/20_arrow_red_right.png new file mode 100644 index 0000000..77f0e19 Binary files /dev/null and b/graphics/chroma-zen/20_arrow_red_right.png differ diff --git a/graphics/chroma-zen/20_arrow_red_up.png b/graphics/chroma-zen/20_arrow_red_up.png new file mode 100644 index 0000000..50b2c0c Binary files /dev/null and b/graphics/chroma-zen/20_arrow_red_up.png differ diff --git a/graphics/chroma-zen/20_bomb_blue_down.png b/graphics/chroma-zen/20_bomb_blue_down.png new file mode 100644 index 0000000..c76c31f Binary files /dev/null and b/graphics/chroma-zen/20_bomb_blue_down.png differ diff --git a/graphics/chroma-zen/20_bomb_blue_left.png b/graphics/chroma-zen/20_bomb_blue_left.png new file mode 100644 index 0000000..545b715 Binary files /dev/null and b/graphics/chroma-zen/20_bomb_blue_left.png differ diff --git a/graphics/chroma-zen/20_bomb_blue_right.png b/graphics/chroma-zen/20_bomb_blue_right.png new file mode 100644 index 0000000..d7af73c Binary files /dev/null and b/graphics/chroma-zen/20_bomb_blue_right.png differ diff --git a/graphics/chroma-zen/20_bomb_blue_up.png b/graphics/chroma-zen/20_bomb_blue_up.png new file mode 100644 index 0000000..9bb4f1b Binary files /dev/null and b/graphics/chroma-zen/20_bomb_blue_up.png differ diff --git a/graphics/chroma-zen/20_bomb_green_down.png b/graphics/chroma-zen/20_bomb_green_down.png new file mode 100644 index 0000000..f92ee43 Binary files /dev/null and b/graphics/chroma-zen/20_bomb_green_down.png differ diff --git a/graphics/chroma-zen/20_bomb_green_left.png b/graphics/chroma-zen/20_bomb_green_left.png new file mode 100644 index 0000000..bf571de Binary files /dev/null and b/graphics/chroma-zen/20_bomb_green_left.png differ diff --git a/graphics/chroma-zen/20_bomb_green_right.png b/graphics/chroma-zen/20_bomb_green_right.png new file mode 100644 index 0000000..16fc5ac Binary files /dev/null and b/graphics/chroma-zen/20_bomb_green_right.png differ diff --git a/graphics/chroma-zen/20_bomb_green_up.png b/graphics/chroma-zen/20_bomb_green_up.png new file mode 100644 index 0000000..6c35184 Binary files /dev/null and b/graphics/chroma-zen/20_bomb_green_up.png differ diff --git a/graphics/chroma-zen/20_bomb_red_down.png b/graphics/chroma-zen/20_bomb_red_down.png new file mode 100644 index 0000000..4779df9 Binary files /dev/null and b/graphics/chroma-zen/20_bomb_red_down.png differ diff --git a/graphics/chroma-zen/20_bomb_red_left.png b/graphics/chroma-zen/20_bomb_red_left.png new file mode 100644 index 0000000..0930525 Binary files /dev/null and b/graphics/chroma-zen/20_bomb_red_left.png differ diff --git a/graphics/chroma-zen/20_bomb_red_right.png b/graphics/chroma-zen/20_bomb_red_right.png new file mode 100644 index 0000000..9fb9860 Binary files /dev/null and b/graphics/chroma-zen/20_bomb_red_right.png differ diff --git a/graphics/chroma-zen/20_bomb_red_up.png b/graphics/chroma-zen/20_bomb_red_up.png new file mode 100644 index 0000000..71e4167 Binary files /dev/null and b/graphics/chroma-zen/20_bomb_red_up.png differ diff --git a/graphics/chroma-zen/20_circle.png b/graphics/chroma-zen/20_circle.png new file mode 100644 index 0000000..b0376cd Binary files /dev/null and b/graphics/chroma-zen/20_circle.png differ diff --git a/graphics/chroma-zen/20_circle_double.png b/graphics/chroma-zen/20_circle_double.png new file mode 100644 index 0000000..f12bbb3 Binary files /dev/null and b/graphics/chroma-zen/20_circle_double.png differ diff --git a/graphics/chroma-zen/20_door.png b/graphics/chroma-zen/20_door.png new file mode 100644 index 0000000..9cbe313 Binary files /dev/null and b/graphics/chroma-zen/20_door.png differ diff --git a/graphics/chroma-zen/20_dots.png b/graphics/chroma-zen/20_dots.png new file mode 100644 index 0000000..ad6856a Binary files /dev/null and b/graphics/chroma-zen/20_dots.png differ diff --git a/graphics/chroma-zen/20_dots_double.png b/graphics/chroma-zen/20_dots_double.png new file mode 100644 index 0000000..fbc9952 Binary files /dev/null and b/graphics/chroma-zen/20_dots_double.png differ diff --git a/graphics/chroma-zen/20_dots_x.png b/graphics/chroma-zen/20_dots_x.png new file mode 100644 index 0000000..ee3f9cf Binary files /dev/null and b/graphics/chroma-zen/20_dots_x.png differ diff --git a/graphics/chroma-zen/20_dots_y.png b/graphics/chroma-zen/20_dots_y.png new file mode 100644 index 0000000..e6c4358 Binary files /dev/null and b/graphics/chroma-zen/20_dots_y.png differ diff --git a/graphics/chroma-zen/20_earth.png b/graphics/chroma-zen/20_earth.png new file mode 100644 index 0000000..7080ee7 Binary files /dev/null and b/graphics/chroma-zen/20_earth.png differ diff --git a/graphics/chroma-zen/20_earth_double.png b/graphics/chroma-zen/20_earth_double.png new file mode 100644 index 0000000..a4e30a7 Binary files /dev/null and b/graphics/chroma-zen/20_earth_double.png differ diff --git a/graphics/chroma-zen/20_earth_x.png b/graphics/chroma-zen/20_earth_x.png new file mode 100644 index 0000000..bcd345a Binary files /dev/null and b/graphics/chroma-zen/20_earth_x.png differ diff --git a/graphics/chroma-zen/20_earth_y.png b/graphics/chroma-zen/20_earth_y.png new file mode 100644 index 0000000..61cc90b Binary files /dev/null and b/graphics/chroma-zen/20_earth_y.png differ diff --git a/graphics/chroma-zen/20_map_bottom_left.png b/graphics/chroma-zen/20_map_bottom_left.png new file mode 100644 index 0000000..a20741b Binary files /dev/null and b/graphics/chroma-zen/20_map_bottom_left.png differ diff --git a/graphics/chroma-zen/20_map_bottom_right.png b/graphics/chroma-zen/20_map_bottom_right.png new file mode 100644 index 0000000..84ff5a9 Binary files /dev/null and b/graphics/chroma-zen/20_map_bottom_right.png differ diff --git a/graphics/chroma-zen/20_map_top_left.png b/graphics/chroma-zen/20_map_top_left.png new file mode 100644 index 0000000..34fa8f7 Binary files /dev/null and b/graphics/chroma-zen/20_map_top_left.png differ diff --git a/graphics/chroma-zen/20_map_top_right.png b/graphics/chroma-zen/20_map_top_right.png new file mode 100644 index 0000000..39692cd Binary files /dev/null and b/graphics/chroma-zen/20_map_top_right.png differ diff --git a/graphics/chroma-zen/20_player_one.png b/graphics/chroma-zen/20_player_one.png new file mode 100644 index 0000000..82544ca Binary files /dev/null and b/graphics/chroma-zen/20_player_one.png differ diff --git a/graphics/chroma-zen/20_player_one_swapped.png b/graphics/chroma-zen/20_player_one_swapped.png new file mode 100644 index 0000000..c9168f3 Binary files /dev/null and b/graphics/chroma-zen/20_player_one_swapped.png differ diff --git a/graphics/chroma-zen/20_player_two.png b/graphics/chroma-zen/20_player_two.png new file mode 100644 index 0000000..a5882f1 Binary files /dev/null and b/graphics/chroma-zen/20_player_two.png differ diff --git a/graphics/chroma-zen/20_player_two_swapped.png b/graphics/chroma-zen/20_player_two_swapped.png new file mode 100644 index 0000000..f0aa671 Binary files /dev/null and b/graphics/chroma-zen/20_player_two_swapped.png differ diff --git a/graphics/chroma-zen/20_star.png b/graphics/chroma-zen/20_star.png new file mode 100644 index 0000000..671491f Binary files /dev/null and b/graphics/chroma-zen/20_star.png differ diff --git a/graphics/chroma-zen/20_switch.png b/graphics/chroma-zen/20_switch.png new file mode 100644 index 0000000..470aec9 Binary files /dev/null and b/graphics/chroma-zen/20_switch.png differ diff --git a/graphics/chroma-zen/20_teleport.png b/graphics/chroma-zen/20_teleport.png new file mode 100644 index 0000000..6aae5ac Binary files /dev/null and b/graphics/chroma-zen/20_teleport.png differ diff --git a/graphics/chroma-zen/20_wall_inside.png b/graphics/chroma-zen/20_wall_inside.png new file mode 100644 index 0000000..e66ceff Binary files /dev/null and b/graphics/chroma-zen/20_wall_inside.png differ diff --git a/graphics/chroma-zen/20_wall_outside.png b/graphics/chroma-zen/20_wall_outside.png new file mode 100644 index 0000000..2323153 Binary files /dev/null and b/graphics/chroma-zen/20_wall_outside.png differ diff --git a/graphics/chroma-zen/20_wall_x.png b/graphics/chroma-zen/20_wall_x.png new file mode 100644 index 0000000..4640bf2 Binary files /dev/null and b/graphics/chroma-zen/20_wall_x.png differ diff --git a/graphics/chroma-zen/20_wall_y.png b/graphics/chroma-zen/20_wall_y.png new file mode 100644 index 0000000..9b555d9 Binary files /dev/null and b/graphics/chroma-zen/20_wall_y.png differ diff --git a/graphics/chroma-zen/24_arrow_blue_down.png b/graphics/chroma-zen/24_arrow_blue_down.png new file mode 100644 index 0000000..67c56c8 Binary files /dev/null and b/graphics/chroma-zen/24_arrow_blue_down.png differ diff --git a/graphics/chroma-zen/24_arrow_blue_left.png b/graphics/chroma-zen/24_arrow_blue_left.png new file mode 100644 index 0000000..aed64f4 Binary files /dev/null and b/graphics/chroma-zen/24_arrow_blue_left.png differ diff --git a/graphics/chroma-zen/24_arrow_blue_right.png b/graphics/chroma-zen/24_arrow_blue_right.png new file mode 100644 index 0000000..e5fd98b Binary files /dev/null and b/graphics/chroma-zen/24_arrow_blue_right.png differ diff --git a/graphics/chroma-zen/24_arrow_blue_up.png b/graphics/chroma-zen/24_arrow_blue_up.png new file mode 100644 index 0000000..f788bef Binary files /dev/null and b/graphics/chroma-zen/24_arrow_blue_up.png differ diff --git a/graphics/chroma-zen/24_arrow_green_down.png b/graphics/chroma-zen/24_arrow_green_down.png new file mode 100644 index 0000000..01d5e40 Binary files /dev/null and b/graphics/chroma-zen/24_arrow_green_down.png differ diff --git a/graphics/chroma-zen/24_arrow_green_left.png b/graphics/chroma-zen/24_arrow_green_left.png new file mode 100644 index 0000000..bba42cb Binary files /dev/null and b/graphics/chroma-zen/24_arrow_green_left.png differ diff --git a/graphics/chroma-zen/24_arrow_green_right.png b/graphics/chroma-zen/24_arrow_green_right.png new file mode 100644 index 0000000..f181ed0 Binary files /dev/null and b/graphics/chroma-zen/24_arrow_green_right.png differ diff --git a/graphics/chroma-zen/24_arrow_green_up.png b/graphics/chroma-zen/24_arrow_green_up.png new file mode 100644 index 0000000..35e07d8 Binary files /dev/null and b/graphics/chroma-zen/24_arrow_green_up.png differ diff --git a/graphics/chroma-zen/24_arrow_red_down.png b/graphics/chroma-zen/24_arrow_red_down.png new file mode 100644 index 0000000..1793a4d Binary files /dev/null and b/graphics/chroma-zen/24_arrow_red_down.png differ diff --git a/graphics/chroma-zen/24_arrow_red_left.png b/graphics/chroma-zen/24_arrow_red_left.png new file mode 100644 index 0000000..9b3456c Binary files /dev/null and b/graphics/chroma-zen/24_arrow_red_left.png differ diff --git a/graphics/chroma-zen/24_arrow_red_right.png b/graphics/chroma-zen/24_arrow_red_right.png new file mode 100644 index 0000000..16305c0 Binary files /dev/null and b/graphics/chroma-zen/24_arrow_red_right.png differ diff --git a/graphics/chroma-zen/24_arrow_red_up.png b/graphics/chroma-zen/24_arrow_red_up.png new file mode 100644 index 0000000..ead8834 Binary files /dev/null and b/graphics/chroma-zen/24_arrow_red_up.png differ diff --git a/graphics/chroma-zen/24_bomb_blue_down.png b/graphics/chroma-zen/24_bomb_blue_down.png new file mode 100644 index 0000000..c057642 Binary files /dev/null and b/graphics/chroma-zen/24_bomb_blue_down.png differ diff --git a/graphics/chroma-zen/24_bomb_blue_left.png b/graphics/chroma-zen/24_bomb_blue_left.png new file mode 100644 index 0000000..1bd80cb Binary files /dev/null and b/graphics/chroma-zen/24_bomb_blue_left.png differ diff --git a/graphics/chroma-zen/24_bomb_blue_right.png b/graphics/chroma-zen/24_bomb_blue_right.png new file mode 100644 index 0000000..641c84e Binary files /dev/null and b/graphics/chroma-zen/24_bomb_blue_right.png differ diff --git a/graphics/chroma-zen/24_bomb_blue_up.png b/graphics/chroma-zen/24_bomb_blue_up.png new file mode 100644 index 0000000..fed7d03 Binary files /dev/null and b/graphics/chroma-zen/24_bomb_blue_up.png differ diff --git a/graphics/chroma-zen/24_bomb_green_down.png b/graphics/chroma-zen/24_bomb_green_down.png new file mode 100644 index 0000000..d89a106 Binary files /dev/null and b/graphics/chroma-zen/24_bomb_green_down.png differ diff --git a/graphics/chroma-zen/24_bomb_green_left.png b/graphics/chroma-zen/24_bomb_green_left.png new file mode 100644 index 0000000..bdfec6e Binary files /dev/null and b/graphics/chroma-zen/24_bomb_green_left.png differ diff --git a/graphics/chroma-zen/24_bomb_green_right.png b/graphics/chroma-zen/24_bomb_green_right.png new file mode 100644 index 0000000..b2e2ef3 Binary files /dev/null and b/graphics/chroma-zen/24_bomb_green_right.png differ diff --git a/graphics/chroma-zen/24_bomb_green_up.png b/graphics/chroma-zen/24_bomb_green_up.png new file mode 100644 index 0000000..f81e6c8 Binary files /dev/null and b/graphics/chroma-zen/24_bomb_green_up.png differ diff --git a/graphics/chroma-zen/24_bomb_red_down.png b/graphics/chroma-zen/24_bomb_red_down.png new file mode 100644 index 0000000..4f6c9b0 Binary files /dev/null and b/graphics/chroma-zen/24_bomb_red_down.png differ diff --git a/graphics/chroma-zen/24_bomb_red_left.png b/graphics/chroma-zen/24_bomb_red_left.png new file mode 100644 index 0000000..63f21e7 Binary files /dev/null and b/graphics/chroma-zen/24_bomb_red_left.png differ diff --git a/graphics/chroma-zen/24_bomb_red_right.png b/graphics/chroma-zen/24_bomb_red_right.png new file mode 100644 index 0000000..a881ab1 Binary files /dev/null and b/graphics/chroma-zen/24_bomb_red_right.png differ diff --git a/graphics/chroma-zen/24_bomb_red_up.png b/graphics/chroma-zen/24_bomb_red_up.png new file mode 100644 index 0000000..14e80b7 Binary files /dev/null and b/graphics/chroma-zen/24_bomb_red_up.png differ diff --git a/graphics/chroma-zen/24_circle.png b/graphics/chroma-zen/24_circle.png new file mode 100644 index 0000000..4135abb Binary files /dev/null and b/graphics/chroma-zen/24_circle.png differ diff --git a/graphics/chroma-zen/24_circle_double.png b/graphics/chroma-zen/24_circle_double.png new file mode 100644 index 0000000..e404daf Binary files /dev/null and b/graphics/chroma-zen/24_circle_double.png differ diff --git a/graphics/chroma-zen/24_door.png b/graphics/chroma-zen/24_door.png new file mode 100644 index 0000000..253c02a Binary files /dev/null and b/graphics/chroma-zen/24_door.png differ diff --git a/graphics/chroma-zen/24_dots.png b/graphics/chroma-zen/24_dots.png new file mode 100644 index 0000000..00fd965 Binary files /dev/null and b/graphics/chroma-zen/24_dots.png differ diff --git a/graphics/chroma-zen/24_dots_double.png b/graphics/chroma-zen/24_dots_double.png new file mode 100644 index 0000000..e1503cc Binary files /dev/null and b/graphics/chroma-zen/24_dots_double.png differ diff --git a/graphics/chroma-zen/24_dots_x.png b/graphics/chroma-zen/24_dots_x.png new file mode 100644 index 0000000..c43bfdd Binary files /dev/null and b/graphics/chroma-zen/24_dots_x.png differ diff --git a/graphics/chroma-zen/24_dots_y.png b/graphics/chroma-zen/24_dots_y.png new file mode 100644 index 0000000..b9662ef Binary files /dev/null and b/graphics/chroma-zen/24_dots_y.png differ diff --git a/graphics/chroma-zen/24_earth.png b/graphics/chroma-zen/24_earth.png new file mode 100644 index 0000000..b140d17 Binary files /dev/null and b/graphics/chroma-zen/24_earth.png differ diff --git a/graphics/chroma-zen/24_earth_double.png b/graphics/chroma-zen/24_earth_double.png new file mode 100644 index 0000000..3f9ed06 Binary files /dev/null and b/graphics/chroma-zen/24_earth_double.png differ diff --git a/graphics/chroma-zen/24_earth_x.png b/graphics/chroma-zen/24_earth_x.png new file mode 100644 index 0000000..7cd7d68 Binary files /dev/null and b/graphics/chroma-zen/24_earth_x.png differ diff --git a/graphics/chroma-zen/24_earth_y.png b/graphics/chroma-zen/24_earth_y.png new file mode 100644 index 0000000..2f94895 Binary files /dev/null and b/graphics/chroma-zen/24_earth_y.png differ diff --git a/graphics/chroma-zen/24_map_bottom_left.png b/graphics/chroma-zen/24_map_bottom_left.png new file mode 100644 index 0000000..4dec861 Binary files /dev/null and b/graphics/chroma-zen/24_map_bottom_left.png differ diff --git a/graphics/chroma-zen/24_map_bottom_right.png b/graphics/chroma-zen/24_map_bottom_right.png new file mode 100644 index 0000000..313cd6a Binary files /dev/null and b/graphics/chroma-zen/24_map_bottom_right.png differ diff --git a/graphics/chroma-zen/24_map_top_left.png b/graphics/chroma-zen/24_map_top_left.png new file mode 100644 index 0000000..e3c5e73 Binary files /dev/null and b/graphics/chroma-zen/24_map_top_left.png differ diff --git a/graphics/chroma-zen/24_map_top_right.png b/graphics/chroma-zen/24_map_top_right.png new file mode 100644 index 0000000..3830d21 Binary files /dev/null and b/graphics/chroma-zen/24_map_top_right.png differ diff --git a/graphics/chroma-zen/24_player_one.png b/graphics/chroma-zen/24_player_one.png new file mode 100644 index 0000000..1251542 Binary files /dev/null and b/graphics/chroma-zen/24_player_one.png differ diff --git a/graphics/chroma-zen/24_player_one_swapped.png b/graphics/chroma-zen/24_player_one_swapped.png new file mode 100644 index 0000000..a4b59af Binary files /dev/null and b/graphics/chroma-zen/24_player_one_swapped.png differ diff --git a/graphics/chroma-zen/24_player_two.png b/graphics/chroma-zen/24_player_two.png new file mode 100644 index 0000000..65f00c3 Binary files /dev/null and b/graphics/chroma-zen/24_player_two.png differ diff --git a/graphics/chroma-zen/24_player_two_swapped.png b/graphics/chroma-zen/24_player_two_swapped.png new file mode 100644 index 0000000..8783d52 Binary files /dev/null and b/graphics/chroma-zen/24_player_two_swapped.png differ diff --git a/graphics/chroma-zen/24_star.png b/graphics/chroma-zen/24_star.png new file mode 100644 index 0000000..c7ee46a Binary files /dev/null and b/graphics/chroma-zen/24_star.png differ diff --git a/graphics/chroma-zen/24_switch.png b/graphics/chroma-zen/24_switch.png new file mode 100644 index 0000000..d097146 Binary files /dev/null and b/graphics/chroma-zen/24_switch.png differ diff --git a/graphics/chroma-zen/24_teleport.png b/graphics/chroma-zen/24_teleport.png new file mode 100644 index 0000000..c376a49 Binary files /dev/null and b/graphics/chroma-zen/24_teleport.png differ diff --git a/graphics/chroma-zen/24_wall_inside.png b/graphics/chroma-zen/24_wall_inside.png new file mode 100644 index 0000000..795b9db Binary files /dev/null and b/graphics/chroma-zen/24_wall_inside.png differ diff --git a/graphics/chroma-zen/24_wall_outside.png b/graphics/chroma-zen/24_wall_outside.png new file mode 100644 index 0000000..bba8db1 Binary files /dev/null and b/graphics/chroma-zen/24_wall_outside.png differ diff --git a/graphics/chroma-zen/24_wall_x.png b/graphics/chroma-zen/24_wall_x.png new file mode 100644 index 0000000..33f22a9 Binary files /dev/null and b/graphics/chroma-zen/24_wall_x.png differ diff --git a/graphics/chroma-zen/24_wall_y.png b/graphics/chroma-zen/24_wall_y.png new file mode 100644 index 0000000..0bc8cea Binary files /dev/null and b/graphics/chroma-zen/24_wall_y.png differ diff --git a/graphics/chroma-zen/32_arrow_blue_down.png b/graphics/chroma-zen/32_arrow_blue_down.png new file mode 100644 index 0000000..a2eadf6 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_blue_down.png differ diff --git a/graphics/chroma-zen/32_arrow_blue_left.png b/graphics/chroma-zen/32_arrow_blue_left.png new file mode 100644 index 0000000..1a15739 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_blue_left.png differ diff --git a/graphics/chroma-zen/32_arrow_blue_right.png b/graphics/chroma-zen/32_arrow_blue_right.png new file mode 100644 index 0000000..344940e Binary files /dev/null and b/graphics/chroma-zen/32_arrow_blue_right.png differ diff --git a/graphics/chroma-zen/32_arrow_blue_up.png b/graphics/chroma-zen/32_arrow_blue_up.png new file mode 100644 index 0000000..d789b85 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_blue_up.png differ diff --git a/graphics/chroma-zen/32_arrow_green_down.png b/graphics/chroma-zen/32_arrow_green_down.png new file mode 100644 index 0000000..07878d9 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_green_down.png differ diff --git a/graphics/chroma-zen/32_arrow_green_left.png b/graphics/chroma-zen/32_arrow_green_left.png new file mode 100644 index 0000000..e3fda83 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_green_left.png differ diff --git a/graphics/chroma-zen/32_arrow_green_right.png b/graphics/chroma-zen/32_arrow_green_right.png new file mode 100644 index 0000000..44ffc48 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_green_right.png differ diff --git a/graphics/chroma-zen/32_arrow_green_up.png b/graphics/chroma-zen/32_arrow_green_up.png new file mode 100644 index 0000000..9aeff08 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_green_up.png differ diff --git a/graphics/chroma-zen/32_arrow_red_down.png b/graphics/chroma-zen/32_arrow_red_down.png new file mode 100644 index 0000000..fd0a4c3 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_red_down.png differ diff --git a/graphics/chroma-zen/32_arrow_red_left.png b/graphics/chroma-zen/32_arrow_red_left.png new file mode 100644 index 0000000..1ea8339 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_red_left.png differ diff --git a/graphics/chroma-zen/32_arrow_red_right.png b/graphics/chroma-zen/32_arrow_red_right.png new file mode 100644 index 0000000..d2767d4 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_red_right.png differ diff --git a/graphics/chroma-zen/32_arrow_red_up.png b/graphics/chroma-zen/32_arrow_red_up.png new file mode 100644 index 0000000..77250a0 Binary files /dev/null and b/graphics/chroma-zen/32_arrow_red_up.png differ diff --git a/graphics/chroma-zen/32_bomb_blue_down.png b/graphics/chroma-zen/32_bomb_blue_down.png new file mode 100644 index 0000000..4694ab3 Binary files /dev/null and b/graphics/chroma-zen/32_bomb_blue_down.png differ diff --git a/graphics/chroma-zen/32_bomb_blue_left.png b/graphics/chroma-zen/32_bomb_blue_left.png new file mode 100644 index 0000000..f7886f7 Binary files /dev/null and b/graphics/chroma-zen/32_bomb_blue_left.png differ diff --git a/graphics/chroma-zen/32_bomb_blue_right.png b/graphics/chroma-zen/32_bomb_blue_right.png new file mode 100644 index 0000000..fd44c51 Binary files /dev/null and b/graphics/chroma-zen/32_bomb_blue_right.png differ diff --git a/graphics/chroma-zen/32_bomb_blue_up.png b/graphics/chroma-zen/32_bomb_blue_up.png new file mode 100644 index 0000000..3ae9d0e Binary files /dev/null and b/graphics/chroma-zen/32_bomb_blue_up.png differ diff --git a/graphics/chroma-zen/32_bomb_green_down.png b/graphics/chroma-zen/32_bomb_green_down.png new file mode 100644 index 0000000..0a5a7c7 Binary files /dev/null and b/graphics/chroma-zen/32_bomb_green_down.png differ diff --git a/graphics/chroma-zen/32_bomb_green_left.png b/graphics/chroma-zen/32_bomb_green_left.png new file mode 100644 index 0000000..6f9e98c Binary files /dev/null and b/graphics/chroma-zen/32_bomb_green_left.png differ diff --git a/graphics/chroma-zen/32_bomb_green_right.png b/graphics/chroma-zen/32_bomb_green_right.png new file mode 100644 index 0000000..835e1fc Binary files /dev/null and b/graphics/chroma-zen/32_bomb_green_right.png differ diff --git a/graphics/chroma-zen/32_bomb_green_up.png b/graphics/chroma-zen/32_bomb_green_up.png new file mode 100644 index 0000000..896fa8d Binary files /dev/null and b/graphics/chroma-zen/32_bomb_green_up.png differ diff --git a/graphics/chroma-zen/32_bomb_red_down.png b/graphics/chroma-zen/32_bomb_red_down.png new file mode 100644 index 0000000..e19f4f1 Binary files /dev/null and b/graphics/chroma-zen/32_bomb_red_down.png differ diff --git a/graphics/chroma-zen/32_bomb_red_left.png b/graphics/chroma-zen/32_bomb_red_left.png new file mode 100644 index 0000000..7bd443c Binary files /dev/null and b/graphics/chroma-zen/32_bomb_red_left.png differ diff --git a/graphics/chroma-zen/32_bomb_red_right.png b/graphics/chroma-zen/32_bomb_red_right.png new file mode 100644 index 0000000..789c2ad Binary files /dev/null and b/graphics/chroma-zen/32_bomb_red_right.png differ diff --git a/graphics/chroma-zen/32_bomb_red_up.png b/graphics/chroma-zen/32_bomb_red_up.png new file mode 100644 index 0000000..9453f56 Binary files /dev/null and b/graphics/chroma-zen/32_bomb_red_up.png differ diff --git a/graphics/chroma-zen/32_circle.png b/graphics/chroma-zen/32_circle.png new file mode 100644 index 0000000..05316de Binary files /dev/null and b/graphics/chroma-zen/32_circle.png differ diff --git a/graphics/chroma-zen/32_circle_double.png b/graphics/chroma-zen/32_circle_double.png new file mode 100644 index 0000000..9a5504c Binary files /dev/null and b/graphics/chroma-zen/32_circle_double.png differ diff --git a/graphics/chroma-zen/32_door.png b/graphics/chroma-zen/32_door.png new file mode 100644 index 0000000..9ef7b4b Binary files /dev/null and b/graphics/chroma-zen/32_door.png differ diff --git a/graphics/chroma-zen/32_dots.png b/graphics/chroma-zen/32_dots.png new file mode 100644 index 0000000..a9b1dc6 Binary files /dev/null and b/graphics/chroma-zen/32_dots.png differ diff --git a/graphics/chroma-zen/32_dots_double.png b/graphics/chroma-zen/32_dots_double.png new file mode 100644 index 0000000..e4d83e3 Binary files /dev/null and b/graphics/chroma-zen/32_dots_double.png differ diff --git a/graphics/chroma-zen/32_dots_x.png b/graphics/chroma-zen/32_dots_x.png new file mode 100644 index 0000000..f433ad7 Binary files /dev/null and b/graphics/chroma-zen/32_dots_x.png differ diff --git a/graphics/chroma-zen/32_dots_y.png b/graphics/chroma-zen/32_dots_y.png new file mode 100644 index 0000000..dd872d2 Binary files /dev/null and b/graphics/chroma-zen/32_dots_y.png differ diff --git a/graphics/chroma-zen/32_earth.png b/graphics/chroma-zen/32_earth.png new file mode 100644 index 0000000..59a467f Binary files /dev/null and b/graphics/chroma-zen/32_earth.png differ diff --git a/graphics/chroma-zen/32_earth_double.png b/graphics/chroma-zen/32_earth_double.png new file mode 100644 index 0000000..ec55f6c Binary files /dev/null and b/graphics/chroma-zen/32_earth_double.png differ diff --git a/graphics/chroma-zen/32_earth_x.png b/graphics/chroma-zen/32_earth_x.png new file mode 100644 index 0000000..a1cfcf9 Binary files /dev/null and b/graphics/chroma-zen/32_earth_x.png differ diff --git a/graphics/chroma-zen/32_earth_y.png b/graphics/chroma-zen/32_earth_y.png new file mode 100644 index 0000000..a144488 Binary files /dev/null and b/graphics/chroma-zen/32_earth_y.png differ diff --git a/graphics/chroma-zen/32_map_bottom_left.png b/graphics/chroma-zen/32_map_bottom_left.png new file mode 100644 index 0000000..d55a02a Binary files /dev/null and b/graphics/chroma-zen/32_map_bottom_left.png differ diff --git a/graphics/chroma-zen/32_map_bottom_right.png b/graphics/chroma-zen/32_map_bottom_right.png new file mode 100644 index 0000000..92668d0 Binary files /dev/null and b/graphics/chroma-zen/32_map_bottom_right.png differ diff --git a/graphics/chroma-zen/32_map_top_left.png b/graphics/chroma-zen/32_map_top_left.png new file mode 100644 index 0000000..8749d26 Binary files /dev/null and b/graphics/chroma-zen/32_map_top_left.png differ diff --git a/graphics/chroma-zen/32_map_top_right.png b/graphics/chroma-zen/32_map_top_right.png new file mode 100644 index 0000000..652fd14 Binary files /dev/null and b/graphics/chroma-zen/32_map_top_right.png differ diff --git a/graphics/chroma-zen/32_player_one.png b/graphics/chroma-zen/32_player_one.png new file mode 100644 index 0000000..52fefdd Binary files /dev/null and b/graphics/chroma-zen/32_player_one.png differ diff --git a/graphics/chroma-zen/32_player_one_swapped.png b/graphics/chroma-zen/32_player_one_swapped.png new file mode 100644 index 0000000..a4633cb Binary files /dev/null and b/graphics/chroma-zen/32_player_one_swapped.png differ diff --git a/graphics/chroma-zen/32_player_two.png b/graphics/chroma-zen/32_player_two.png new file mode 100644 index 0000000..b8d24cc Binary files /dev/null and b/graphics/chroma-zen/32_player_two.png differ diff --git a/graphics/chroma-zen/32_player_two_swapped.png b/graphics/chroma-zen/32_player_two_swapped.png new file mode 100644 index 0000000..860c771 Binary files /dev/null and b/graphics/chroma-zen/32_player_two_swapped.png differ diff --git a/graphics/chroma-zen/32_star.png b/graphics/chroma-zen/32_star.png new file mode 100644 index 0000000..878a545 Binary files /dev/null and b/graphics/chroma-zen/32_star.png differ diff --git a/graphics/chroma-zen/32_switch.png b/graphics/chroma-zen/32_switch.png new file mode 100644 index 0000000..d734204 Binary files /dev/null and b/graphics/chroma-zen/32_switch.png differ diff --git a/graphics/chroma-zen/32_teleport.png b/graphics/chroma-zen/32_teleport.png new file mode 100644 index 0000000..e84ee8f Binary files /dev/null and b/graphics/chroma-zen/32_teleport.png differ diff --git a/graphics/chroma-zen/32_wall_inside.png b/graphics/chroma-zen/32_wall_inside.png new file mode 100644 index 0000000..a879afb Binary files /dev/null and b/graphics/chroma-zen/32_wall_inside.png differ diff --git a/graphics/chroma-zen/32_wall_outside.png b/graphics/chroma-zen/32_wall_outside.png new file mode 100644 index 0000000..e840c9e Binary files /dev/null and b/graphics/chroma-zen/32_wall_outside.png differ diff --git a/graphics/chroma-zen/32_wall_x.png b/graphics/chroma-zen/32_wall_x.png new file mode 100644 index 0000000..3d67363 Binary files /dev/null and b/graphics/chroma-zen/32_wall_x.png differ diff --git a/graphics/chroma-zen/32_wall_y.png b/graphics/chroma-zen/32_wall_y.png new file mode 100644 index 0000000..c70d8db Binary files /dev/null and b/graphics/chroma-zen/32_wall_y.png differ diff --git a/graphics/chroma-zen/40_arrow_blue_down.png b/graphics/chroma-zen/40_arrow_blue_down.png new file mode 100644 index 0000000..c3dc8e2 Binary files /dev/null and b/graphics/chroma-zen/40_arrow_blue_down.png differ diff --git a/graphics/chroma-zen/40_arrow_blue_left.png b/graphics/chroma-zen/40_arrow_blue_left.png new file mode 100644 index 0000000..2bee92b Binary files /dev/null and b/graphics/chroma-zen/40_arrow_blue_left.png differ diff --git a/graphics/chroma-zen/40_arrow_blue_right.png b/graphics/chroma-zen/40_arrow_blue_right.png new file mode 100644 index 0000000..87ffde7 Binary files /dev/null and b/graphics/chroma-zen/40_arrow_blue_right.png differ diff --git a/graphics/chroma-zen/40_arrow_blue_up.png b/graphics/chroma-zen/40_arrow_blue_up.png new file mode 100644 index 0000000..34f1aa3 Binary files /dev/null and b/graphics/chroma-zen/40_arrow_blue_up.png differ diff --git a/graphics/chroma-zen/40_arrow_green_down.png b/graphics/chroma-zen/40_arrow_green_down.png new file mode 100644 index 0000000..37a9886 Binary files /dev/null and b/graphics/chroma-zen/40_arrow_green_down.png differ diff --git a/graphics/chroma-zen/40_arrow_green_left.png b/graphics/chroma-zen/40_arrow_green_left.png new file mode 100644 index 0000000..326a6fd Binary files /dev/null and b/graphics/chroma-zen/40_arrow_green_left.png differ diff --git a/graphics/chroma-zen/40_arrow_green_right.png b/graphics/chroma-zen/40_arrow_green_right.png new file mode 100644 index 0000000..caa8022 Binary files /dev/null and b/graphics/chroma-zen/40_arrow_green_right.png differ diff --git a/graphics/chroma-zen/40_arrow_green_up.png b/graphics/chroma-zen/40_arrow_green_up.png new file mode 100644 index 0000000..fb75a10 Binary files /dev/null and b/graphics/chroma-zen/40_arrow_green_up.png differ diff --git a/graphics/chroma-zen/40_arrow_red_down.png b/graphics/chroma-zen/40_arrow_red_down.png new file mode 100644 index 0000000..995b170 Binary files /dev/null and b/graphics/chroma-zen/40_arrow_red_down.png differ diff --git a/graphics/chroma-zen/40_arrow_red_left.png b/graphics/chroma-zen/40_arrow_red_left.png new file mode 100644 index 0000000..297ffa2 Binary files /dev/null and b/graphics/chroma-zen/40_arrow_red_left.png differ diff --git a/graphics/chroma-zen/40_arrow_red_right.png b/graphics/chroma-zen/40_arrow_red_right.png new file mode 100644 index 0000000..ac5e2d4 Binary files /dev/null and b/graphics/chroma-zen/40_arrow_red_right.png differ diff --git a/graphics/chroma-zen/40_arrow_red_up.png b/graphics/chroma-zen/40_arrow_red_up.png new file mode 100644 index 0000000..a39a531 Binary files /dev/null and b/graphics/chroma-zen/40_arrow_red_up.png differ diff --git a/graphics/chroma-zen/40_bomb_blue_down.png b/graphics/chroma-zen/40_bomb_blue_down.png new file mode 100644 index 0000000..27e2282 Binary files /dev/null and b/graphics/chroma-zen/40_bomb_blue_down.png differ diff --git a/graphics/chroma-zen/40_bomb_blue_left.png b/graphics/chroma-zen/40_bomb_blue_left.png new file mode 100644 index 0000000..807cfeb Binary files /dev/null and b/graphics/chroma-zen/40_bomb_blue_left.png differ diff --git a/graphics/chroma-zen/40_bomb_blue_right.png b/graphics/chroma-zen/40_bomb_blue_right.png new file mode 100644 index 0000000..341a27b Binary files /dev/null and b/graphics/chroma-zen/40_bomb_blue_right.png differ diff --git a/graphics/chroma-zen/40_bomb_blue_up.png b/graphics/chroma-zen/40_bomb_blue_up.png new file mode 100644 index 0000000..8f9d27e Binary files /dev/null and b/graphics/chroma-zen/40_bomb_blue_up.png differ diff --git a/graphics/chroma-zen/40_bomb_green_down.png b/graphics/chroma-zen/40_bomb_green_down.png new file mode 100644 index 0000000..a6bcf18 Binary files /dev/null and b/graphics/chroma-zen/40_bomb_green_down.png differ diff --git a/graphics/chroma-zen/40_bomb_green_left.png b/graphics/chroma-zen/40_bomb_green_left.png new file mode 100644 index 0000000..9ac8e0c Binary files /dev/null and b/graphics/chroma-zen/40_bomb_green_left.png differ diff --git a/graphics/chroma-zen/40_bomb_green_right.png b/graphics/chroma-zen/40_bomb_green_right.png new file mode 100644 index 0000000..9fb56d5 Binary files /dev/null and b/graphics/chroma-zen/40_bomb_green_right.png differ diff --git a/graphics/chroma-zen/40_bomb_green_up.png b/graphics/chroma-zen/40_bomb_green_up.png new file mode 100644 index 0000000..ac50cdd Binary files /dev/null and b/graphics/chroma-zen/40_bomb_green_up.png differ diff --git a/graphics/chroma-zen/40_bomb_red_down.png b/graphics/chroma-zen/40_bomb_red_down.png new file mode 100644 index 0000000..f3ca1d0 Binary files /dev/null and b/graphics/chroma-zen/40_bomb_red_down.png differ diff --git a/graphics/chroma-zen/40_bomb_red_left.png b/graphics/chroma-zen/40_bomb_red_left.png new file mode 100644 index 0000000..86a63bd Binary files /dev/null and b/graphics/chroma-zen/40_bomb_red_left.png differ diff --git a/graphics/chroma-zen/40_bomb_red_right.png b/graphics/chroma-zen/40_bomb_red_right.png new file mode 100644 index 0000000..d5bde18 Binary files /dev/null and b/graphics/chroma-zen/40_bomb_red_right.png differ diff --git a/graphics/chroma-zen/40_bomb_red_up.png b/graphics/chroma-zen/40_bomb_red_up.png new file mode 100644 index 0000000..e165197 Binary files /dev/null and b/graphics/chroma-zen/40_bomb_red_up.png differ diff --git a/graphics/chroma-zen/40_circle.png b/graphics/chroma-zen/40_circle.png new file mode 100644 index 0000000..9b70891 Binary files /dev/null and b/graphics/chroma-zen/40_circle.png differ diff --git a/graphics/chroma-zen/40_circle_double.png b/graphics/chroma-zen/40_circle_double.png new file mode 100644 index 0000000..d97ff28 Binary files /dev/null and b/graphics/chroma-zen/40_circle_double.png differ diff --git a/graphics/chroma-zen/40_door.png b/graphics/chroma-zen/40_door.png new file mode 100644 index 0000000..94487c5 Binary files /dev/null and b/graphics/chroma-zen/40_door.png differ diff --git a/graphics/chroma-zen/40_dots.png b/graphics/chroma-zen/40_dots.png new file mode 100644 index 0000000..487ceed Binary files /dev/null and b/graphics/chroma-zen/40_dots.png differ diff --git a/graphics/chroma-zen/40_dots_double.png b/graphics/chroma-zen/40_dots_double.png new file mode 100644 index 0000000..5b19381 Binary files /dev/null and b/graphics/chroma-zen/40_dots_double.png differ diff --git a/graphics/chroma-zen/40_dots_x.png b/graphics/chroma-zen/40_dots_x.png new file mode 100644 index 0000000..65acae1 Binary files /dev/null and b/graphics/chroma-zen/40_dots_x.png differ diff --git a/graphics/chroma-zen/40_dots_y.png b/graphics/chroma-zen/40_dots_y.png new file mode 100644 index 0000000..fcf0c55 Binary files /dev/null and b/graphics/chroma-zen/40_dots_y.png differ diff --git a/graphics/chroma-zen/40_earth.png b/graphics/chroma-zen/40_earth.png new file mode 100644 index 0000000..c9e62e2 Binary files /dev/null and b/graphics/chroma-zen/40_earth.png differ diff --git a/graphics/chroma-zen/40_earth_double.png b/graphics/chroma-zen/40_earth_double.png new file mode 100644 index 0000000..e941140 Binary files /dev/null and b/graphics/chroma-zen/40_earth_double.png differ diff --git a/graphics/chroma-zen/40_earth_x.png b/graphics/chroma-zen/40_earth_x.png new file mode 100644 index 0000000..0ca96a5 Binary files /dev/null and b/graphics/chroma-zen/40_earth_x.png differ diff --git a/graphics/chroma-zen/40_earth_y.png b/graphics/chroma-zen/40_earth_y.png new file mode 100644 index 0000000..d17dad5 Binary files /dev/null and b/graphics/chroma-zen/40_earth_y.png differ diff --git a/graphics/chroma-zen/40_map_bottom_left.png b/graphics/chroma-zen/40_map_bottom_left.png new file mode 100644 index 0000000..c4c6195 Binary files /dev/null and b/graphics/chroma-zen/40_map_bottom_left.png differ diff --git a/graphics/chroma-zen/40_map_bottom_right.png b/graphics/chroma-zen/40_map_bottom_right.png new file mode 100644 index 0000000..5845ace Binary files /dev/null and b/graphics/chroma-zen/40_map_bottom_right.png differ diff --git a/graphics/chroma-zen/40_map_top_left.png b/graphics/chroma-zen/40_map_top_left.png new file mode 100644 index 0000000..0e41f6f Binary files /dev/null and b/graphics/chroma-zen/40_map_top_left.png differ diff --git a/graphics/chroma-zen/40_map_top_right.png b/graphics/chroma-zen/40_map_top_right.png new file mode 100644 index 0000000..95d019d Binary files /dev/null and b/graphics/chroma-zen/40_map_top_right.png differ diff --git a/graphics/chroma-zen/40_player_one.png b/graphics/chroma-zen/40_player_one.png new file mode 100644 index 0000000..b832d91 Binary files /dev/null and b/graphics/chroma-zen/40_player_one.png differ diff --git a/graphics/chroma-zen/40_player_one_swapped.png b/graphics/chroma-zen/40_player_one_swapped.png new file mode 100644 index 0000000..c403a13 Binary files /dev/null and b/graphics/chroma-zen/40_player_one_swapped.png differ diff --git a/graphics/chroma-zen/40_player_two.png b/graphics/chroma-zen/40_player_two.png new file mode 100644 index 0000000..0e98d2a Binary files /dev/null and b/graphics/chroma-zen/40_player_two.png differ diff --git a/graphics/chroma-zen/40_player_two_swapped.png b/graphics/chroma-zen/40_player_two_swapped.png new file mode 100644 index 0000000..1c626a4 Binary files /dev/null and b/graphics/chroma-zen/40_player_two_swapped.png differ diff --git a/graphics/chroma-zen/40_star.png b/graphics/chroma-zen/40_star.png new file mode 100644 index 0000000..37494cc Binary files /dev/null and b/graphics/chroma-zen/40_star.png differ diff --git a/graphics/chroma-zen/40_switch.png b/graphics/chroma-zen/40_switch.png new file mode 100644 index 0000000..1f48a1c Binary files /dev/null and b/graphics/chroma-zen/40_switch.png differ diff --git a/graphics/chroma-zen/40_teleport.png b/graphics/chroma-zen/40_teleport.png new file mode 100644 index 0000000..a13df31 Binary files /dev/null and b/graphics/chroma-zen/40_teleport.png differ diff --git a/graphics/chroma-zen/40_wall_inside.png b/graphics/chroma-zen/40_wall_inside.png new file mode 100644 index 0000000..5dd5e43 Binary files /dev/null and b/graphics/chroma-zen/40_wall_inside.png differ diff --git a/graphics/chroma-zen/40_wall_outside.png b/graphics/chroma-zen/40_wall_outside.png new file mode 100644 index 0000000..aec8a5f Binary files /dev/null and b/graphics/chroma-zen/40_wall_outside.png differ diff --git a/graphics/chroma-zen/40_wall_x.png b/graphics/chroma-zen/40_wall_x.png new file mode 100644 index 0000000..839e1e7 Binary files /dev/null and b/graphics/chroma-zen/40_wall_x.png differ diff --git a/graphics/chroma-zen/40_wall_y.png b/graphics/chroma-zen/40_wall_y.png new file mode 100644 index 0000000..0bcd4de Binary files /dev/null and b/graphics/chroma-zen/40_wall_y.png differ diff --git a/graphics/chroma-zen/64_arrow_blue_down.png b/graphics/chroma-zen/64_arrow_blue_down.png new file mode 100644 index 0000000..5ad1b13 Binary files /dev/null and b/graphics/chroma-zen/64_arrow_blue_down.png differ diff --git a/graphics/chroma-zen/64_arrow_blue_left.png b/graphics/chroma-zen/64_arrow_blue_left.png new file mode 100644 index 0000000..a88af6e Binary files /dev/null and b/graphics/chroma-zen/64_arrow_blue_left.png differ diff --git a/graphics/chroma-zen/64_arrow_blue_right.png b/graphics/chroma-zen/64_arrow_blue_right.png new file mode 100644 index 0000000..15a61e8 Binary files /dev/null and b/graphics/chroma-zen/64_arrow_blue_right.png differ diff --git a/graphics/chroma-zen/64_arrow_blue_up.png b/graphics/chroma-zen/64_arrow_blue_up.png new file mode 100644 index 0000000..c520e06 Binary files /dev/null and b/graphics/chroma-zen/64_arrow_blue_up.png differ diff --git a/graphics/chroma-zen/64_arrow_green_down.png b/graphics/chroma-zen/64_arrow_green_down.png new file mode 100644 index 0000000..ed7b167 Binary files /dev/null and b/graphics/chroma-zen/64_arrow_green_down.png differ diff --git a/graphics/chroma-zen/64_arrow_green_left.png b/graphics/chroma-zen/64_arrow_green_left.png new file mode 100644 index 0000000..a16694f Binary files /dev/null and b/graphics/chroma-zen/64_arrow_green_left.png differ diff --git a/graphics/chroma-zen/64_arrow_green_right.png b/graphics/chroma-zen/64_arrow_green_right.png new file mode 100644 index 0000000..55a60f8 Binary files /dev/null and b/graphics/chroma-zen/64_arrow_green_right.png differ diff --git a/graphics/chroma-zen/64_arrow_green_up.png b/graphics/chroma-zen/64_arrow_green_up.png new file mode 100644 index 0000000..04df9d8 Binary files /dev/null and b/graphics/chroma-zen/64_arrow_green_up.png differ diff --git a/graphics/chroma-zen/64_arrow_red_down.png b/graphics/chroma-zen/64_arrow_red_down.png new file mode 100644 index 0000000..27b1857 Binary files /dev/null and b/graphics/chroma-zen/64_arrow_red_down.png differ diff --git a/graphics/chroma-zen/64_arrow_red_left.png b/graphics/chroma-zen/64_arrow_red_left.png new file mode 100644 index 0000000..1d5325e Binary files /dev/null and b/graphics/chroma-zen/64_arrow_red_left.png differ diff --git a/graphics/chroma-zen/64_arrow_red_right.png b/graphics/chroma-zen/64_arrow_red_right.png new file mode 100644 index 0000000..dcff7a6 Binary files /dev/null and b/graphics/chroma-zen/64_arrow_red_right.png differ diff --git a/graphics/chroma-zen/64_arrow_red_up.png b/graphics/chroma-zen/64_arrow_red_up.png new file mode 100644 index 0000000..5d8303b Binary files /dev/null and b/graphics/chroma-zen/64_arrow_red_up.png differ diff --git a/graphics/chroma-zen/64_bomb_blue_down.png b/graphics/chroma-zen/64_bomb_blue_down.png new file mode 100644 index 0000000..265c481 Binary files /dev/null and b/graphics/chroma-zen/64_bomb_blue_down.png differ diff --git a/graphics/chroma-zen/64_bomb_blue_left.png b/graphics/chroma-zen/64_bomb_blue_left.png new file mode 100644 index 0000000..e218f74 Binary files /dev/null and b/graphics/chroma-zen/64_bomb_blue_left.png differ diff --git a/graphics/chroma-zen/64_bomb_blue_right.png b/graphics/chroma-zen/64_bomb_blue_right.png new file mode 100644 index 0000000..4dcf0ad Binary files /dev/null and b/graphics/chroma-zen/64_bomb_blue_right.png differ diff --git a/graphics/chroma-zen/64_bomb_blue_up.png b/graphics/chroma-zen/64_bomb_blue_up.png new file mode 100644 index 0000000..1bc5234 Binary files /dev/null and b/graphics/chroma-zen/64_bomb_blue_up.png differ diff --git a/graphics/chroma-zen/64_bomb_green_down.png b/graphics/chroma-zen/64_bomb_green_down.png new file mode 100644 index 0000000..f4d5f1e Binary files /dev/null and b/graphics/chroma-zen/64_bomb_green_down.png differ diff --git a/graphics/chroma-zen/64_bomb_green_left.png b/graphics/chroma-zen/64_bomb_green_left.png new file mode 100644 index 0000000..ecbec98 Binary files /dev/null and b/graphics/chroma-zen/64_bomb_green_left.png differ diff --git a/graphics/chroma-zen/64_bomb_green_right.png b/graphics/chroma-zen/64_bomb_green_right.png new file mode 100644 index 0000000..5c2e7a9 Binary files /dev/null and b/graphics/chroma-zen/64_bomb_green_right.png differ diff --git a/graphics/chroma-zen/64_bomb_green_up.png b/graphics/chroma-zen/64_bomb_green_up.png new file mode 100644 index 0000000..f4738dd Binary files /dev/null and b/graphics/chroma-zen/64_bomb_green_up.png differ diff --git a/graphics/chroma-zen/64_bomb_red_down.png b/graphics/chroma-zen/64_bomb_red_down.png new file mode 100644 index 0000000..de71359 Binary files /dev/null and b/graphics/chroma-zen/64_bomb_red_down.png differ diff --git a/graphics/chroma-zen/64_bomb_red_left.png b/graphics/chroma-zen/64_bomb_red_left.png new file mode 100644 index 0000000..4fece78 Binary files /dev/null and b/graphics/chroma-zen/64_bomb_red_left.png differ diff --git a/graphics/chroma-zen/64_bomb_red_right.png b/graphics/chroma-zen/64_bomb_red_right.png new file mode 100644 index 0000000..ed139cb Binary files /dev/null and b/graphics/chroma-zen/64_bomb_red_right.png differ diff --git a/graphics/chroma-zen/64_bomb_red_up.png b/graphics/chroma-zen/64_bomb_red_up.png new file mode 100644 index 0000000..e86fbae Binary files /dev/null and b/graphics/chroma-zen/64_bomb_red_up.png differ diff --git a/graphics/chroma-zen/64_circle.png b/graphics/chroma-zen/64_circle.png new file mode 100644 index 0000000..2a09d35 Binary files /dev/null and b/graphics/chroma-zen/64_circle.png differ diff --git a/graphics/chroma-zen/64_circle_double.png b/graphics/chroma-zen/64_circle_double.png new file mode 100644 index 0000000..72acf7b Binary files /dev/null and b/graphics/chroma-zen/64_circle_double.png differ diff --git a/graphics/chroma-zen/64_door.png b/graphics/chroma-zen/64_door.png new file mode 100644 index 0000000..4288bda Binary files /dev/null and b/graphics/chroma-zen/64_door.png differ diff --git a/graphics/chroma-zen/64_dots.png b/graphics/chroma-zen/64_dots.png new file mode 100644 index 0000000..2d4c86b Binary files /dev/null and b/graphics/chroma-zen/64_dots.png differ diff --git a/graphics/chroma-zen/64_dots_double.png b/graphics/chroma-zen/64_dots_double.png new file mode 100644 index 0000000..acb9225 Binary files /dev/null and b/graphics/chroma-zen/64_dots_double.png differ diff --git a/graphics/chroma-zen/64_dots_x.png b/graphics/chroma-zen/64_dots_x.png new file mode 100644 index 0000000..fdb50fe Binary files /dev/null and b/graphics/chroma-zen/64_dots_x.png differ diff --git a/graphics/chroma-zen/64_dots_y.png b/graphics/chroma-zen/64_dots_y.png new file mode 100644 index 0000000..704a632 Binary files /dev/null and b/graphics/chroma-zen/64_dots_y.png differ diff --git a/graphics/chroma-zen/64_earth.png b/graphics/chroma-zen/64_earth.png new file mode 100644 index 0000000..d107194 Binary files /dev/null and b/graphics/chroma-zen/64_earth.png differ diff --git a/graphics/chroma-zen/64_earth_double.png b/graphics/chroma-zen/64_earth_double.png new file mode 100644 index 0000000..fec5afd Binary files /dev/null and b/graphics/chroma-zen/64_earth_double.png differ diff --git a/graphics/chroma-zen/64_earth_x.png b/graphics/chroma-zen/64_earth_x.png new file mode 100644 index 0000000..1ee677c Binary files /dev/null and b/graphics/chroma-zen/64_earth_x.png differ diff --git a/graphics/chroma-zen/64_earth_y.png b/graphics/chroma-zen/64_earth_y.png new file mode 100644 index 0000000..05fe597 Binary files /dev/null and b/graphics/chroma-zen/64_earth_y.png differ diff --git a/graphics/chroma-zen/64_map_bottom_left.png b/graphics/chroma-zen/64_map_bottom_left.png new file mode 100644 index 0000000..cc430bc Binary files /dev/null and b/graphics/chroma-zen/64_map_bottom_left.png differ diff --git a/graphics/chroma-zen/64_map_bottom_right.png b/graphics/chroma-zen/64_map_bottom_right.png new file mode 100644 index 0000000..418d95e Binary files /dev/null and b/graphics/chroma-zen/64_map_bottom_right.png differ diff --git a/graphics/chroma-zen/64_map_top_left.png b/graphics/chroma-zen/64_map_top_left.png new file mode 100644 index 0000000..afb1c7c Binary files /dev/null and b/graphics/chroma-zen/64_map_top_left.png differ diff --git a/graphics/chroma-zen/64_map_top_right.png b/graphics/chroma-zen/64_map_top_right.png new file mode 100644 index 0000000..7b5c1a4 Binary files /dev/null and b/graphics/chroma-zen/64_map_top_right.png differ diff --git a/graphics/chroma-zen/64_player_one.png b/graphics/chroma-zen/64_player_one.png new file mode 100644 index 0000000..fdc5d6b Binary files /dev/null and b/graphics/chroma-zen/64_player_one.png differ diff --git a/graphics/chroma-zen/64_player_one_swapped.png b/graphics/chroma-zen/64_player_one_swapped.png new file mode 100644 index 0000000..4956424 Binary files /dev/null and b/graphics/chroma-zen/64_player_one_swapped.png differ diff --git a/graphics/chroma-zen/64_player_two.png b/graphics/chroma-zen/64_player_two.png new file mode 100644 index 0000000..b3b79ba Binary files /dev/null and b/graphics/chroma-zen/64_player_two.png differ diff --git a/graphics/chroma-zen/64_player_two_swapped.png b/graphics/chroma-zen/64_player_two_swapped.png new file mode 100644 index 0000000..c5ba319 Binary files /dev/null and b/graphics/chroma-zen/64_player_two_swapped.png differ diff --git a/graphics/chroma-zen/64_star.png b/graphics/chroma-zen/64_star.png new file mode 100644 index 0000000..7a4aa5b Binary files /dev/null and b/graphics/chroma-zen/64_star.png differ diff --git a/graphics/chroma-zen/64_switch.png b/graphics/chroma-zen/64_switch.png new file mode 100644 index 0000000..23143c9 Binary files /dev/null and b/graphics/chroma-zen/64_switch.png differ diff --git a/graphics/chroma-zen/64_teleport.png b/graphics/chroma-zen/64_teleport.png new file mode 100644 index 0000000..6cb2126 Binary files /dev/null and b/graphics/chroma-zen/64_teleport.png differ diff --git a/graphics/chroma-zen/64_wall_inside.png b/graphics/chroma-zen/64_wall_inside.png new file mode 100644 index 0000000..e8b6354 Binary files /dev/null and b/graphics/chroma-zen/64_wall_inside.png differ diff --git a/graphics/chroma-zen/64_wall_outside.png b/graphics/chroma-zen/64_wall_outside.png new file mode 100644 index 0000000..e55436a Binary files /dev/null and b/graphics/chroma-zen/64_wall_outside.png differ diff --git a/graphics/chroma-zen/64_wall_x.png b/graphics/chroma-zen/64_wall_x.png new file mode 100644 index 0000000..0a60b27 Binary files /dev/null and b/graphics/chroma-zen/64_wall_x.png differ diff --git a/graphics/chroma-zen/64_wall_y.png b/graphics/chroma-zen/64_wall_y.png new file mode 100644 index 0000000..84dd7af Binary files /dev/null and b/graphics/chroma-zen/64_wall_y.png differ diff --git a/graphics/curses.chroma b/graphics/curses.chroma new file mode 100644 index 0000000..2a45b97 --- /dev/null +++ b/graphics/curses.chroma @@ -0,0 +1,18 @@ + + + +Curses Emulation + + + + + + + + + + + + + + diff --git a/graphics/fallback.chroma b/graphics/fallback.chroma new file mode 100644 index 0000000..a369c20 --- /dev/null +++ b/graphics/fallback.chroma @@ -0,0 +1,17 @@ + + diff --git a/graphics/font.ttf b/graphics/font.ttf new file mode 100644 index 0000000..e0699fe Binary files /dev/null and b/graphics/font.ttf differ diff --git a/graphics/font.txt b/graphics/font.txt new file mode 100644 index 0000000..254e2cc --- /dev/null +++ b/graphics/font.txt @@ -0,0 +1,99 @@ +Fonts are (c) Bitstream (see below). DejaVu changes are in public domain. +Glyphs imported from Arev fonts are (c) Tavmjong Bah (see below) + +Bitstream Vera Fonts Copyright +------------------------------ + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is +a trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated +documentation files (the "Font Software"), to reproduce and distribute the +Font Software, including without limitation the rights to use, copy, merge, +publish, distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to the +following conditions: + +The above copyright and trademark notices and this permission notice shall +be included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may be modified and +additional glyphs or characters may be added to the Fonts, only if the fonts +are renamed to names not containing either the words "Bitstream" or the word +"Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream +Vera" names. + +The Font Software may be sold as part of a larger software package but no +copy of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME +FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING +ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF +THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE +FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome +Foundation, and Bitstream Inc., shall not be used in advertising or +otherwise to promote the sale, use or other dealings in this Font Software +without prior written authorization from the Gnome Foundation or Bitstream +Inc., respectively. For further information, contact: fonts at gnome dot +org. + +Arev Fonts Copyright +------------------------------ + +Copyright (c) 2006 by Tavmjong Bah. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of the fonts accompanying this license ("Fonts") and +associated documentation files (the "Font Software"), to reproduce +and distribute the modifications to the Bitstream Vera Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit +persons to whom the Font Software is furnished to do so, subject to +the following conditions: + +The above copyright and trademark notices and this permission notice +shall be included in all copies of one or more of the Font Software +typefaces. + +The Font Software may be modified, altered, or added to, and in +particular the designs of glyphs or characters in the Fonts may be +modified and additional glyphs or characters may be added to the +Fonts, only if the fonts are renamed to names not containing either +the words "Tavmjong Bah" or the word "Arev". + +This License becomes null and void to the extent applicable to Fonts +or Font Software that has been modified and is distributed under the +"Tavmjong Bah Arev" names. + +The Font Software may be sold as part of a larger software package but +no copy of one or more of the Font Software typefaces may be sold by +itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL +TAVMJONG BAH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the name of Tavmjong Bah shall not +be used in advertising or otherwise to promote the sale, use or other +dealings in this Font Software without prior written authorization +from Tavmjong Bah. For further information, contact: tavmjong @ free +. fr. + +$Id: LICENSE 2133 2007-11-28 02:46:28Z lechimp $ diff --git a/graphics/icon.png b/graphics/icon.png new file mode 100644 index 0000000..265f84c Binary files /dev/null and b/graphics/icon.png differ diff --git a/help/README b/help/README new file mode 100644 index 0000000..947bd21 --- /dev/null +++ b/help/README @@ -0,0 +1,98 @@ +Chroma is an abstract puzzle game. A variety of colourful shapes are arranged +in a series of increasingly complex patterns, forming fiendish traps that must +be disarmed and mysterious puzzles that must be manipulated in order to give +up their subtle secrets. Initially so straightforward that anyone can pick it +up and begin to play, yet gradually becoming difficult enough to tax even the +brightest of minds. Have you got what it takes to solve Chroma? + +Levels +====== +There are twenty one levels, split into two sets - nine intended for beginners, +providing a step-by-step introduction to the mechanics of Chroma's building +blocks, and a further twelve for those in search of a real challenge. You can +play them in any order, but you'll probably find it useful to build up +experience on the earlier levels before tacking the later ones. + +Objective +========= +In each level, the goal is to use your two player pieces to collect all of the +stars before leaving through the door. Other pieces such as circles, squares, +triangles and dots serve to help or hinder you in this quest. Part of the +challenge of Chroma is understanding exactly how these pieces interact with +one another - you'll need to experiment until you discover how their differing +properties can best be used to your advantage. To this end, the full range of +pieces is introduced over the first six levels of each set. + +Controlling your pieces +======================= +There are two octagonal player pieces, of which one is active, and may be +moved using the arrow keys. To swap control to the other player piece, press +[SPACE] or [ENTER] - its colour will change to reflect this. Initially, many of +the puzzles can be solved using only one of the player pieces, but as the +levels get harder, you'll find it necessary to carefully co-ordinate the moves +of both of them in order to achieve your objective. + +Undoing moves +============= +If you make a mistake, you can press [DELETE] to undo as many moves as you +wish, allowing you to move in a different way or press [INSERT] to redo moves +that have been previously undone. Once a move has been made, however, you must +wait for its full consequences to take effect before you can move again. In the +graphical version, holding [SHIFT] down will speed things up, whereas [CTRL] +will slow things down, allowing you to observe the changes in more detail. +[F] will bring the pieces to their ultimate state of rest immediately. + +Saving and loading positions +============================ +Pressing [ESCAPE] will present you with a menu, from which you can save your +position, load a previous position, or return to the level selection menu, as +well as allowing you to revert to the last position loaded. At the start of a +level, you can also replay the moves from a previously saved position. When +doing so, [LEFT] reverses the replay, [UP] or [DOWN] pauses it, and [RIGHT] +continues. Should you wish to stop the replay and start making moves again, +return to the menu with [ESCAPE], then press [T]. + +Changing the display +==================== +The Display Options menu allows you to change the graphics used, as well as +the size of the screen and the speed of the game. You can also change the keys +used and how the mouse works, and save these changes for future use if desired. + +Designing your own levels +========================= +Selecting [E] from the title screen allows you to design your own levels. To +start with a blank level, press [L] and then [C]. You can now press [Q] to +enter the level editor itself. Use the arrow keys to move the cursor, and +[PAGE-UP] and [PAGE-DOWN] to change the currently selected piece. Pressing +[SPACE] or [ENTER] will place a piece under the cursor, and pressing [Q] will +return you to the editing menu, from which you can save your work, test the +level, or verify it to ensure that it contains no errors. The Level Options +menu allows you to give your level a title, change its size and rotate it. + +Website +======= +Visit the Chroma website at http://level7.org.uk/chroma/ + +Comments and suggestions regarding Chroma are always welcome! Email: + + chroma (at) level7 (dot) org (dot) uk + +Include the word "chroma" in your subject to get past the spam filter. + +Copyright and Licence +===================== +Chroma is Copyright (C) 2010-2019 Amf + +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 diff --git a/iconcurses.ico b/iconcurses.ico new file mode 100644 index 0000000..1478637 Binary files /dev/null and b/iconcurses.ico differ diff --git a/iconcurses.rc b/iconcurses.rc new file mode 100644 index 0000000..723e3ec --- /dev/null +++ b/iconcurses.rc @@ -0,0 +1 @@ +AppIcon ICON "iconcurses.ico" diff --git a/iconsdl.ico b/iconsdl.ico new file mode 100644 index 0000000..6cc817d Binary files /dev/null and b/iconsdl.ico differ diff --git a/iconsdl.rc b/iconsdl.rc new file mode 100644 index 0000000..2f127ea --- /dev/null +++ b/iconsdl.rc @@ -0,0 +1,18 @@ +/* Microsoft say: + +We recommend that your icon contains these three sizes: + + * 48 x 48 pixels + * 32 x 32 pixels + * 16 x 16 pixels + +Each Windows XP icon should contain these three color depths to support +different monitor display settings: + + * 24-bit with 8-bit alpha (32-bit) + * 8-bit (256 colors) with 1-bit transparency + * 4-bit (16 colors) with 1-bit transparency + +*/ + +AppIcon ICON "iconsdl.ico" diff --git a/install-sh b/install-sh new file mode 100755 index 0000000..6ce63b9 --- /dev/null +++ b/install-sh @@ -0,0 +1,294 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd=$cpprog + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd=$stripprog + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "$0: no input file specified" >&2 + exit 1 +else + : +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d "$dst" ]; then + instcmd=: + chmodcmd="" + else + instcmd=$mkdirprog + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f "$src" ] || [ -d "$src" ] + then + : + else + echo "$0: $src does not exist" >&2 + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "$0: no destination specified" >&2 + exit 1 + else + : + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d "$dst" ] + then + dst=$dst/`basename "$src"` + else + : + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo "$dst" | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' + ' +IFS="${IFS-$defaultIFS}" + +oIFS=$IFS +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS=$oIFS + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp=$pathcomp$1 + shift + + if [ ! -d "$pathcomp" ] ; + then + $mkdirprog "$pathcomp" + else + : + fi + + pathcomp=$pathcomp/ +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd "$dst" && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dst"; else : ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dst"; else : ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dst"; else : ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dst"; else : ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename "$dst"` + else + dstfile=`basename "$dst" $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename "$dst"` + else + : + fi + +# Make a couple of temp file names in the proper directory. + + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + +# Trap to clean up temp files at exit. + + trap 'status=$?; rm -f "$dsttmp" "$rmtmp" && exit $status' 0 + trap '(exit $?); exit' 1 2 13 15 + +# Move or copy the file name to the temp name + + $doit $instcmd "$src" "$dsttmp" && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$dsttmp"; else :;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$dsttmp"; else :;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd "$dsttmp"; else :;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd "$dsttmp"; else :;fi && + +# Now remove or move aside any old file at destination location. We try this +# two ways since rm can't unlink itself on some systems and the destination +# file might be busy for other reasons. In this case, the final cleanup +# might fail but the new file should still install successfully. + +{ + if [ -f "$dstdir/$dstfile" ] + then + $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null || + $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null || + { + echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 + (exit 1); exit + } + else + : + fi +} && + +# Now rename the file to the real destination. + + $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" + +fi && + +# The final little trick to "correctly" pass the exit status to the exit trap. + +{ + (exit 0); exit +} diff --git a/level.c b/level.c new file mode 100644 index 0000000..d76afd0 --- /dev/null +++ b/level.c @@ -0,0 +1,1515 @@ +/* + level.c + + Copyright (C) 2010-2019 Amf + + 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 +#include +#include +#include +#include +#include +#include +#include + +#include "chroma.h" +#include "level.h" +#include "util.h" + +extern char *piece_name[]; + +char piecetochar(int piece) +{ + switch(piece) + { + case PIECE_SPACE: + return ' '; + case PIECE_WALL: + return '%'; + case PIECE_PLAYER_ONE: + return '1'; + case PIECE_PLAYER_TWO: + return '2'; + case PIECE_DOTS: + return '.'; + case PIECE_ARROW_RED_LEFT: + return 'a'; + case PIECE_ARROW_RED_UP: + return 'b'; + case PIECE_ARROW_RED_RIGHT: + return 'c'; + case PIECE_ARROW_RED_DOWN: + return 'd'; + case PIECE_BOMB_RED_LEFT: + return 'A'; + case PIECE_BOMB_RED_UP: + return 'B'; + case PIECE_BOMB_RED_RIGHT: + return 'C'; + case PIECE_BOMB_RED_DOWN: + return 'D'; + case PIECE_ARROW_GREEN_LEFT: + return 'e'; + case PIECE_ARROW_GREEN_UP: + return 'f'; + case PIECE_ARROW_GREEN_RIGHT: + return 'g'; + case PIECE_ARROW_GREEN_DOWN: + return 'h'; + case PIECE_BOMB_GREEN_LEFT: + return 'E'; + case PIECE_BOMB_GREEN_UP: + return 'F'; + case PIECE_BOMB_GREEN_RIGHT: + return 'G'; + case PIECE_BOMB_GREEN_DOWN: + return 'H'; + case PIECE_ARROW_BLUE_LEFT: + return 'i'; + case PIECE_ARROW_BLUE_UP: + return 'j'; + case PIECE_ARROW_BLUE_RIGHT: + return 'k'; + case PIECE_ARROW_BLUE_DOWN: + return 'l'; + case PIECE_BOMB_BLUE_LEFT: + return 'I'; + case PIECE_BOMB_BLUE_UP: + return 'J'; + case PIECE_BOMB_BLUE_RIGHT: + return 'K'; + case PIECE_BOMB_BLUE_DOWN: + return 'L'; + case PIECE_CIRCLE: + return 'o'; + case PIECE_STAR: + return '*'; + case PIECE_DOOR: + return '/'; +#ifdef ENIGMA_COMPATIBILITY + case PIECE_DOTS_DOUBLE: + return ':'; + case PIECE_CIRCLE_DOUBLE: + return '8'; +#endif +#ifdef XOR_COMPATIBILITY + case PIECE_DOTS_X: + return '-'; + case PIECE_DOTS_Y: + return '|'; + case PIECE_SWITCH: + return 'S'; + case PIECE_TELEPORT: + return 'T'; + case PIECE_MAP_TOP_LEFT: + return 'M'; + case PIECE_MAP_TOP_RIGHT: + return 'm'; + case PIECE_MAP_BOTTOM_LEFT: + return 'N'; + case PIECE_MAP_BOTTOM_RIGHT: + return 'n'; +#endif + case PIECE_GONE: + return '!'; + case PIECE_EXPLOSION_RED_LEFT: + return 'p'; + case PIECE_EXPLOSION_RED_HORIZONTAL: + return 'q'; + case PIECE_EXPLOSION_RED_RIGHT: + return 'r'; + case PIECE_EXPLOSION_RED_TOP: + return 'P'; + case PIECE_EXPLOSION_RED_VERTICAL: + return 'Q'; + case PIECE_EXPLOSION_RED_BOTTOM: + return 'R'; + case PIECE_EXPLOSION_GREEN_LEFT: + return 'u'; + case PIECE_EXPLOSION_GREEN_HORIZONTAL: + return 'v'; + case PIECE_EXPLOSION_GREEN_RIGHT: + return 'w'; + case PIECE_EXPLOSION_GREEN_TOP: + return 'U'; + case PIECE_EXPLOSION_GREEN_VERTICAL: + return 'V'; + case PIECE_EXPLOSION_GREEN_BOTTOM: + return 'W'; + case PIECE_EXPLOSION_BLUE_LEFT: + return 'x'; + case PIECE_EXPLOSION_BLUE_HORIZONTAL: + return 'y'; + case PIECE_EXPLOSION_BLUE_RIGHT: + return 'z'; + case PIECE_EXPLOSION_BLUE_TOP: + return 'X'; + case PIECE_EXPLOSION_BLUE_VERTICAL: + return 'Y'; + case PIECE_EXPLOSION_BLUE_BOTTOM: + return 'Z'; + + default: + return '?'; + } +} + +int chartopiece(char c) +{ + switch(c) + { + case ' ': + return PIECE_SPACE; + case '%': + return PIECE_WALL; + case '1': + return PIECE_PLAYER_ONE; + case '2': + return PIECE_PLAYER_TWO; + case '.': + return PIECE_DOTS; + case 'a': + return PIECE_ARROW_RED_LEFT; + case 'b': + return PIECE_ARROW_RED_UP; + case 'c': + return PIECE_ARROW_RED_RIGHT; + case 'd': + return PIECE_ARROW_RED_DOWN; + case 'A': + return PIECE_BOMB_RED_LEFT; + case 'B': + return PIECE_BOMB_RED_UP; + case 'C': + return PIECE_BOMB_RED_RIGHT; + case 'D': + return PIECE_BOMB_RED_DOWN; + case 'e': + return PIECE_ARROW_GREEN_LEFT; + case 'f': + return PIECE_ARROW_GREEN_UP; + case 'g': + return PIECE_ARROW_GREEN_RIGHT; + case 'h': + return PIECE_ARROW_GREEN_DOWN; + case 'E': + return PIECE_BOMB_GREEN_LEFT; + case 'F': + return PIECE_BOMB_GREEN_UP; + case 'G': + return PIECE_BOMB_GREEN_RIGHT; + case 'H': + return PIECE_BOMB_GREEN_DOWN; + case 'i': + return PIECE_ARROW_BLUE_LEFT; + case 'j': + return PIECE_ARROW_BLUE_UP; + case 'k': + return PIECE_ARROW_BLUE_RIGHT; + case 'l': + return PIECE_ARROW_BLUE_DOWN; + case 'I': + return PIECE_BOMB_BLUE_LEFT; + case 'J': + return PIECE_BOMB_BLUE_UP; + case 'K': + return PIECE_BOMB_BLUE_RIGHT; + case 'L': + return PIECE_BOMB_BLUE_DOWN; + case 'o': + return PIECE_CIRCLE; + case '*': + return PIECE_STAR; + case '/': + return PIECE_DOOR; +#ifdef ENIGMA_COMPATIBILITY + case '8': + return PIECE_CIRCLE_DOUBLE; + case ':': + return PIECE_DOTS_DOUBLE; +#endif +#ifdef XOR_COMPATIBILITY + case '-': + return PIECE_DOTS_X; + case '|': + return PIECE_DOTS_Y; + case 'S': + return PIECE_SWITCH; + case 'T': + return PIECE_TELEPORT; + case 'M': + return PIECE_MAP_TOP_LEFT; + case 'm': + return PIECE_MAP_TOP_RIGHT; + case 'N': + return PIECE_MAP_BOTTOM_LEFT; + case 'n': + return PIECE_MAP_BOTTOM_RIGHT; +#endif + case '!': + return PIECE_GONE; + case 'p': + return PIECE_EXPLOSION_RED_LEFT; + case 'q': + return PIECE_EXPLOSION_RED_HORIZONTAL; + case 'r': + return PIECE_EXPLOSION_RED_RIGHT; + case 'P': + return PIECE_EXPLOSION_RED_TOP; + case 'Q': + return PIECE_EXPLOSION_RED_VERTICAL; + case 'R': + return PIECE_EXPLOSION_RED_BOTTOM; + case 'u': + return PIECE_EXPLOSION_GREEN_LEFT; + case 'v': + return PIECE_EXPLOSION_GREEN_HORIZONTAL; + case 'w': + return PIECE_EXPLOSION_GREEN_RIGHT; + case 'U': + return PIECE_EXPLOSION_GREEN_TOP; + case 'V': + return PIECE_EXPLOSION_GREEN_VERTICAL; + case 'W': + return PIECE_EXPLOSION_GREEN_BOTTOM; + case 'x': + return PIECE_EXPLOSION_BLUE_LEFT; + case 'y': + return PIECE_EXPLOSION_BLUE_HORIZONTAL; + case 'z': + return PIECE_EXPLOSION_BLUE_RIGHT; + case 'X': + return PIECE_EXPLOSION_BLUE_TOP; + case 'Y': + return PIECE_EXPLOSION_BLUE_VERTICAL; + case 'Z': + return PIECE_EXPLOSION_BLUE_BOTTOM; + default: + return PIECE_UNKNOWN; + } +} + +char directiontochar(int direction) +{ + switch(direction) + { + case MOVE_LEFT: + return 'l'; + case MOVE_UP: + return 'u'; + case MOVE_RIGHT: + return 'r'; + case MOVE_DOWN: + return 'd'; + case MOVE_SWAP: + return 's'; + case MOVE_SWAPPED: + return 'w'; + case MOVE_NONE: + return 'n'; + default: + return '?'; + } +} + +int chartodirection(char c) +{ + switch(tolower(c)) + { + case 'l': + return MOVE_LEFT; + case 'u': + return MOVE_UP; + case 'r': + return MOVE_RIGHT; + case 'd': + return MOVE_DOWN; + case 's': + return MOVE_SWAP; + case 'w': + return MOVE_SWAPPED; + case 'n': + return MOVE_NONE; + default: + return MOVE_UNKNOWN; + } +} + +struct level* level_new() +{ + struct level* plevel; + int i; + + plevel = (struct level*)malloc(sizeof(struct level)); + + if(plevel == NULL) + fatal("Out of memory in level_new()"); + + plevel->size_x = 0; + plevel->size_y = 0; + + plevel->player = 0; + + plevel->data_pieces = NULL; + plevel->data_moving = NULL; + plevel->data_previous = NULL; + plevel->data_previousmoving = NULL; + plevel->data_detonator = NULL; + plevel->data_detonatormoving = NULL; + plevel->data_data = NULL; + + plevel->move_first = NULL; + plevel->move_last = NULL; + plevel->move_current = NULL; + + plevel->mover_first = NULL; + plevel->mover_last = NULL; + + plevel->stack_first = NULL; + plevel->stack_last = NULL; + + plevel->stars_caught = 0; + plevel->stars_exploded = 0; + plevel->stars_total = 0; + + plevel->moves = 0; + + plevel->flags = 0; + +#ifdef XOR_COMPATIBILITY + plevel->switched = 0; + plevel->mapped = 0; +#endif + + plevel->mode = MODE_CHROMA; + + plevel->level = 0; + + plevel->title = NULL; + + for(i = 0; i < 2; i++) + { + plevel->alive[i] = 0; + plevel->teleport_x[0] = -1; + plevel->teleport_y[0] = -1; + plevel->view_teleport_x[0] = 0; + plevel->view_teleport_y[0] = 0; + } + + for(i = 0; i < 3; i++) + { + plevel->player_x[i] = 0; + plevel->player_y[i] = 0; + plevel->view_x[i] = 0; + plevel->view_y[i] = 0; + } + + return plevel; +} + +struct level* level_create(int size_x, int size_y) +{ + struct level *pnew; + int x, y; + + pnew = level_new(); + + pnew->size_x = size_x; + pnew->size_y = size_y; + + pnew->data_pieces = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_moving = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_previous = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_previousmoving = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_detonator = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_detonatormoving = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_data = (unsigned int *)malloc(sizeof(unsigned int) * pnew->size_x * pnew->size_y); + + if(pnew->data_pieces == NULL || pnew->data_moving == NULL || + pnew->data_previous == NULL || pnew->data_previousmoving == NULL || + pnew->data_detonator == NULL || pnew->data_detonatormoving == NULL || + pnew->data_data == NULL ) + fatal("Out of memory in level_create()"); + + for(y = 0; y < pnew->size_y; y++) + { + for(x = 0; x < pnew->size_x; x++) + { + level_setpiece(pnew, x, y, PIECE_WALL); + level_setmoving(pnew, x, y, MOVE_NONE); + level_setprevious(pnew, x, y, PIECE_SPACE); + level_setpreviousmoving(pnew, x, y, MOVE_NONE); + level_setdetonator(pnew, x, y, PIECE_SPACE); + level_setdetonatormoving(pnew, x, y, MOVE_NONE); + level_setdata(pnew, x, y, 0); + } + } + + for(y = 1; y < pnew->size_y - 1; y++) + { + for(x = 1; x < pnew->size_x - 1; x++) + { + level_setpiece(pnew, x, y, PIECE_SPACE); + } + } + + return pnew; +} + +void level_delete(struct level* plevel) +{ + struct mover *pmover; + struct mover *ptmp; + struct move *pmove; + struct move *pmovetmp; + + if(plevel == NULL) + return; + + if(plevel->title != NULL) + free(plevel->title); + + if(plevel->data_pieces != NULL) + free(plevel->data_pieces); + if(plevel->data_moving != NULL) + free(plevel->data_moving); + if(plevel->data_previous != NULL) + free(plevel->data_previous); + if(plevel->data_previousmoving != NULL) + free(plevel->data_previousmoving); + if(plevel->data_detonator != NULL) + free(plevel->data_detonator); + if(plevel->data_detonatormoving != NULL) + free(plevel->data_detonatormoving); + if(plevel->data_data != NULL) + free(plevel->data_data); + + pmover = plevel->mover_first; + while(pmover != NULL) + { + ptmp = pmover; + pmover = pmover->next; + free(ptmp); + } + + pmover = plevel->stack_first; + while(pmover != NULL) + { + ptmp = pmover; + pmover = pmover->next; + free(ptmp); + } + + pmove = plevel->move_first; + while(pmove != NULL) + { + pmover = pmove->mover_first; + while(pmover != NULL) + { + ptmp = pmover; + pmover = pmover->next; + free(ptmp); + } + + pmovetmp = pmove; + pmove = pmove->next; + free(pmovetmp); + } + + free(plevel); +} + +char level_piece(struct level* plevel, int x, int y) +{ + if(plevel == NULL || plevel->data_pieces == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return PIECE_WALL; + + return *(plevel->data_pieces + x + y * plevel->size_x); +} + +void level_setpiece(struct level* plevel, int x, int y, char piece) +{ + if(plevel == NULL || plevel->data_pieces == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return; + + *(plevel->data_pieces + x + y * plevel->size_x) = piece; +} + +char level_moving(struct level* plevel, int x, int y) +{ + if(plevel == NULL || plevel->data_moving == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return MOVE_NONE; + + return *(plevel->data_moving + x + y * plevel->size_x); +} + +void level_setmoving(struct level* plevel, int x, int y, char moving) +{ + if(plevel == NULL || plevel->data_moving == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return; + + *(plevel->data_moving + x + y * plevel->size_x) = moving; +} + +char level_previous(struct level* plevel, int x, int y) +{ + if(plevel == NULL || plevel->data_previous == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return PIECE_WALL; + + return *(plevel->data_previous + x + y * plevel->size_x); +} + +void level_setprevious(struct level* plevel, int x, int y, char previous) +{ + if(plevel == NULL || plevel->data_previous == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return; + + *(plevel->data_previous + x + y * plevel->size_x) = previous; +} + +char level_previousmoving(struct level* plevel, int x, int y) +{ + if(plevel == NULL || plevel->data_previousmoving == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return MOVE_NONE; + + return *(plevel->data_previousmoving + x + y * plevel->size_x); +} + +void level_setpreviousmoving(struct level* plevel, int x, int y, char previousmoving) +{ + if(plevel == NULL || plevel->data_previousmoving == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return; + + *(plevel->data_previousmoving + x + y * plevel->size_x) = previousmoving; +} + +char level_detonator(struct level* plevel, int x, int y) +{ + if(plevel == NULL || plevel->data_detonator == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return PIECE_SPACE; + + return *(plevel->data_detonator + x + y * plevel->size_x); +} + +void level_setdetonator(struct level* plevel, int x, int y, char detonator) +{ + if(plevel == NULL || plevel->data_detonator == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return; + + *(plevel->data_detonator + x + y * plevel->size_x) = detonator; +} + +char level_detonatormoving(struct level* plevel, int x, int y) +{ + if(plevel == NULL || plevel->data_detonatormoving == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return MOVE_NONE; + + return *(plevel->data_detonatormoving + x + y * plevel->size_x); +} + +void level_setdetonatormoving(struct level* plevel, int x, int y, char moving) +{ + if(plevel == NULL || plevel->data_detonator == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return; + + *(plevel->data_detonatormoving + x + y * plevel->size_x) = moving; +} + +unsigned int level_data(struct level* plevel, int x, int y) +{ + if(plevel == NULL || plevel->data_pieces == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return 0; + + return *(plevel->data_data + x + y * plevel->size_x); +} + +void level_setdata(struct level* plevel, int x, int y, unsigned int data) +{ + if(plevel == NULL || plevel->data_pieces == NULL || + x < 0 || x >= plevel->size_x || y < 0 || y >= plevel->size_y) + return; + + *(plevel->data_data + x + y * plevel->size_x) = data; +} + +struct level* level_copy(struct level* pold) +{ + struct level* pnew; + struct move* pmove; + struct mover* pmover; + int x, y; + int i; + + pnew = level_new(); + + pnew->size_x = pold->size_x; + pnew->size_y = pold->size_y; + + pnew->player = pold->player; + + pnew->data_pieces = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_moving = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_previous = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_previousmoving = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_detonator = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_detonatormoving = malloc(sizeof(char) * pnew->size_x * pnew->size_y); + pnew->data_data = (unsigned int *)malloc(sizeof(unsigned int) * pnew->size_x * pnew->size_y); + + if(pnew->data_pieces == NULL || pnew->data_moving == NULL || + pnew->data_previous == NULL || pnew->data_previousmoving == NULL || + pnew->data_detonator == NULL || pnew->data_detonatormoving == NULL || + pnew->data_data == NULL ) + fatal("Out of memory in level_copy"); + + pnew->mover_first = NULL; + pnew->mover_last = NULL; + + pnew->stack_first = NULL; + pnew->stack_last = NULL; + + pnew->stars_caught = pold->stars_caught; + pnew->stars_exploded = pold->stars_exploded; + pnew->stars_total = pold->stars_total; + + pnew->moves = pold->moves; + + pnew->flags = pold->flags; + +#ifdef XOR_COMPATIBILITY + pnew->switched = pold->switched; + pnew->mapped = pold->mapped; +#endif + + pnew->mode = pold->mode; + + pnew->level = pold->level; + + level_settitle(pnew, pold->title); + + for(i = 0; i < 2; i ++) + { + pnew->alive[i] = pold->alive[i]; + pnew->teleport_x[i] = pold->teleport_x[i]; + pnew->teleport_y[i] = pold->teleport_y[i]; + pnew->view_teleport_x[i] = pold->view_teleport_x[i]; + pnew->view_teleport_y[i] = pold->view_teleport_y[i]; + pnew->player_x[i] = pold->player_x[i]; + pnew->player_y[i] = pold->player_y[i]; + pnew->view_x[i] = pold->view_x[i]; + pnew->view_y[i] = pold->view_y[i]; + } + + for(y = 0; y < pnew->size_y; y++) + { + for(x = 0; x < pnew->size_x; x++) + { + level_setpiece(pnew, x, y, level_piece(pold, x, y)); + level_setmoving(pnew, x, y, MOVE_NONE); + level_setprevious(pnew, x, y, PIECE_SPACE); + level_setpreviousmoving(pnew, x, y, MOVE_NONE); + level_setdetonator(pnew, x, y, PIECE_SPACE); + level_setdetonatormoving(pnew, x, y, MOVE_NONE); + level_setdata(pnew, x, y, level_data(pold, x, y)); + } + } + + /* Copy moves and undo data */ + pmove = pold->move_first; + while(pmove != NULL) + { + level_addmove(pnew, pmove->direction); + + pnew->move_current = pnew->move_last; + + pmover = pmove->mover_first; + while(pmover != NULL) + { + mover_newundo(pnew, pmover->x, pmover->y, pmover->direction, pmover->piece, pmover->piece_previous, MOVER_STORE | (pmover->fast ? MOVER_FAST : 0)); + pmover = pmover->next; + } + pmove = pmove->next; + } + + pnew->move_current = pnew->move_last; + + return pnew; +} + +struct level* level_load(char *filename, int partial) +{ + struct level* plevel; + FILE *level; + char buffer[4096]; + int state; + int x, y, z; +#ifdef XOR_COMPATIBILITY + int w; +#endif + int i; + char c; + int piece, previous, direction; + int teleport; + int move; + int loop; + + if(!isfile(filename)) + return NULL; + + level = fopen(filename, "r"); + if(level == NULL) + return NULL; + + plevel = level_new(); + + state = 0; + while(!feof(level)) + { + file_readline(level, buffer, 4096); + + /* Ignore comments and blank lines */ + if(buffer[0] == '#' || buffer[0] == 0) + continue; + + /* and everything before the "chroma level" line */ + if(strncmp(buffer, "chroma level", 12) == 0) + state = 1; + + if(state == 1) + { + if(strncmp(buffer, "mode: ", 6) == 0) + { + plevel->mode = MODE_MAX; +#ifdef XOR_COMPATIBILITY + if(strncmp(buffer, "mode: xor", 9) == 0) + plevel->mode = MODE_XOR; +#endif +#ifdef ENIGMA_COMPATIBILITY + if(strncmp(buffer, "mode: enigma", 12) == 0) + plevel->mode = MODE_ENIGMA; +#endif + /* Unrecognised mode */ + if(plevel->mode == MODE_MAX) + { + level_delete(plevel); + return NULL; + } + } + + /* Level data comes after level options */ + if(strncmp(buffer, "data:", 5) == 0) + { + state = 2; + break; + } + + /* Read level size */ + if(strncmp(buffer, "size:", 5) == 0) + { + i = sscanf(buffer, "size: %d %d", &x, &y); + if(i == 2) + { + plevel->size_x = x; + plevel->size_y = y; + } + } + + /* Read star totals */ + if(strncmp(buffer,"stars:",6)==0) + { + i = sscanf(buffer, "stars: %d %d %d", &x, &y, &z); + if(i == 3) + { + plevel->stars_caught = x; + plevel->stars_exploded = y; + plevel->stars_total = z; + } + } + + /* Read move total */ + if(strncmp(buffer,"moves:",6)==0) + { + i = sscanf(buffer, "moves: %d", &x); + if(i == 1) + plevel->moves = x; + } + + /* Read player */ + if(strncmp(buffer,"player:",7)==0) + { + i = sscanf(buffer, "player: %d", &x); + if(i == 1 && (x == 1 || x == 2)) + plevel->player = x - 1; + } + + /* Read level number */ + if(strncmp(buffer,"level:",6)==0) + { + i = sscanf(buffer, "level: %d", &x); + if(i == 1) + plevel->level = x; + } + + /* Read title */ + if(strncmp(buffer,"title: ",7)==0) + level_settitle(plevel, buffer + 7); + + if(strcmp(buffer, "solved: 1") == 0) + plevel->flags |= LEVELFLAG_SOLVED; + + if(strcmp(buffer, "failed: 1") == 0) + plevel->flags |= LEVELFLAG_FAILED; + +#ifdef XOR_COMPATIBILITY + /* Read switched */ + if(strncmp(buffer,"switched:",9)==0) + { + i = sscanf(buffer, "switched: %d", &x); + if(i == 1) + plevel->switched = x; + } + /* Read viewpoints */ + if(strncmp(buffer,"view1: ",7)==0) + { + i = sscanf(buffer, "view1: %d %d", &x, &y); + if(i == 2) + { + plevel->view_x[0] = x; + plevel->view_y[0] = y; + } + } + if(strncmp(buffer,"view2: ",7)==0) + { + i = sscanf(buffer, "view2: %d %d", &x, &y); + if(i == 2) + { + plevel->view_x[1] = x; + plevel->view_y[1] = y; + } + } + if(strncmp(buffer,"viewteleport1: ",15)==0) + { + i = sscanf(buffer, "viewteleport1: %d %d (%d %d)", &x, &y, &z, &w); + if(i == 4) + { + plevel->teleport_x[0] = z; + plevel->teleport_y[0] = w; + plevel->view_teleport_x[0] = x; + plevel->view_teleport_y[0] = y; + teleport ++; + + } + } + if(strncmp(buffer,"viewteleport2: ",15)==0) + { + i = sscanf(buffer, "viewteleport2: %d %d (%d %d)", &x, &y, &z, &w); + if(i == 4) + { + plevel->teleport_x[1] = z; + plevel->teleport_y[1] = w; + plevel->view_teleport_x[1] = x; + plevel->view_teleport_y[1] = y; + teleport ++; + } + } + if(strncmp(buffer, "mapped: ", 8) == 0) + { + if(strstr(buffer, "top_left") != NULL) + plevel->mapped |= MAPPED_TOP_LEFT; + if(strstr(buffer, "top_right") != NULL) + plevel->mapped |= MAPPED_TOP_RIGHT; + if(strstr(buffer, "bottom_left") != NULL) + plevel->mapped |= MAPPED_BOTTOM_LEFT; + if(strstr(buffer, "bottom_right") != NULL) + plevel->mapped |= MAPPED_BOTTOM_RIGHT; + } +#endif + } + } + + /* If the file ended before the level data started, it's no good */ + if(state != 2) + { + fclose(level); + level_delete(plevel); + return NULL; + } + + /* Don't load level or move data if we're indexing for a menu */ + if(partial) + { + fclose(level); + return plevel; + } + + plevel->data_pieces = malloc(sizeof(char) * plevel->size_x * plevel->size_y); + plevel->data_moving = malloc(sizeof(char) * plevel->size_x * plevel->size_y); + plevel->data_previous = malloc(sizeof(char) * plevel->size_x * plevel->size_y); + plevel->data_previousmoving = malloc(sizeof(char) * plevel->size_x * plevel->size_y); + plevel->data_detonator = malloc(sizeof(char) * plevel->size_x * plevel->size_y); + plevel->data_detonatormoving = malloc(sizeof(char) * plevel->size_x * plevel->size_y); + plevel->data_data = malloc(sizeof(int) * plevel->size_x * plevel->size_y); + + if(plevel->data_pieces == NULL || plevel->data_moving == NULL || + plevel->data_previous == NULL || plevel->data_previousmoving == NULL || + plevel->data_detonator == NULL || plevel->data_detonatormoving == NULL || + plevel->data_data == NULL ) + fatal("Out of memory in level_load"); + + /* Seed random number generator based on level title */ + x = 7; + if(plevel->title != NULL) + { + for(i = 0; i < strlen(plevel->title); i ++) + x = x ^ (plevel->title[i] << (i % 24)); + } + srand(x); + + for(y = 0; y < plevel->size_y; y++) + { + for(x = 0; x < plevel->size_x; x++) + { + level_setpiece(plevel, x, y, PIECE_WALL); + level_setmoving(plevel, x, y, MOVE_NONE); + level_setprevious(plevel, x, y, PIECE_SPACE); + level_setpreviousmoving(plevel, x, y, MOVE_NONE); + level_setdetonator(plevel, x, y, PIECE_SPACE); + level_setdetonatormoving(plevel, x, y, MOVE_NONE); + level_setdata(plevel, x, y, rand() % 0xffff); + } + } + + /* Recalculate stars_total - use the saved value in partial loads only */ + plevel->stars_total = plevel->stars_caught + plevel->stars_exploded; + + teleport = 0; + + x = 0; y = 0; + while(!feof(level) && y <= plevel->size_y) + { + c = fgetc(level); + if(feof(level)) + break; + if(c == 10 || c == 13 || c == 0 || c == -1) + continue; + + piece = chartopiece(c); + + switch(piece) + { + case PIECE_PLAYER_ONE: + plevel->player_x[0] = x; + plevel->player_y[0] = y; + plevel->alive[0] = 1; + break; + + case PIECE_PLAYER_TWO: + plevel->player_x[1] = x; + plevel->player_y[1] = y; + plevel->alive[1] = 1; + break; + + case PIECE_STAR: + plevel->stars_total ++; + break; + +#ifdef XOR_COMPATIBILITY + case PIECE_TELEPORT: + if(teleport < 2) + { + plevel->teleport_x[teleport] = x; + plevel->teleport_y[teleport] = y; + teleport ++; + } + break; +#endif + case PIECE_UNKNOWN: + piece = PIECE_SPACE; + break; + + default: + break; + } + + level_setpiece(plevel, x, y, piece); + + x++; + if(x == plevel->size_x) + { + x = 0; + y ++; + } + if(y == plevel->size_y) + break; + } + + /* Search for move data */ + state = 0; + while(!feof(level)) + { + file_readline(level, buffer, 4096); + if(strncmp(buffer,"movedata:",9)==0) + { + state = 1; + break; + } + } + /* and if we find it, read it */ + if(state == 1) + { + i = 0; + + while(i < plevel->moves && !feof(level)) + { + move = chartodirection(fgetc(level)); + if(move != MOVE_NONE && move != MOVE_UNKNOWN) + { + level_addmove(plevel, move); + i ++; + } + } + } + + /* Search for undo data */ + state = 0; + while(!feof(level)) + { + file_readline(level, buffer, 4096); + if(strncmp(buffer,"undodata:",9)==0) + { + state = 1; + break; + } + } + /* and if we find it, read it */ + if(state == 1) + { + plevel->move_current = plevel->move_first; + + state = 0; + + x = 0; + y = 0; + piece = PIECE_UNKNOWN; + previous = PIECE_UNKNOWN; + direction = MOVE_UNKNOWN; + + while(plevel->move_current != NULL && !feof(level)) + { + c = fgetc(level); + + if(c == 13 || c == 10) + continue; + + /* Undo data is read by means of a state machine. */ + /* [x]:[y][direction][piece][previous piece][state of next move] */ + loop = 1; + while(loop) + { + loop = 0; + switch(state) + { + /* Read x */ + case 0: + if(c >= '0' && c <='9') + { + x = x * 10 + (c - '0'); + } + else + { + state = 1; loop = 1; + } + break; + + /* Read : */ + case 1: + if(c == ':') + state = 2; + break; + + /* Read y */ + case 2: + if(c >= '0' && c <='9') + { + y = y * 10 + (c - '0'); + } + else + { + state = 3; loop = 1; + } + break; + + /* Read direction */ + case 3: + if(chartodirection(c) != MOVE_UNKNOWN) + { + direction = chartodirection(c); + state = 4; + } + break; + + /* Read piece */ + case 4: + if(chartopiece(c) != PIECE_UNKNOWN) + { + piece = chartopiece(c); + state = 5; + } + break; + + /* Read previous piece */ + case 5: + if(chartopiece(c) != PIECE_UNKNOWN) + { + previous = chartopiece(c); + state = 6; + } + break; + + /* Read state of next move */ + case 6: + if(c == ',' || c == ';' || c == '.') + { + /* Add mover to current move */ + mover_newundo(plevel, x, y, direction, piece, previous, MOVER_STORE | (c == ',' ? MOVER_FAST : 0)); + /* Next move if this is the last mover for this one */ + if(c == '.') + plevel->move_current = plevel->move_current->next; + + /* Reset state machine for next mover */ + state = 0; + x = 0; + y = 0; + piece = PIECE_UNKNOWN; + previous = PIECE_UNKNOWN; + direction = MOVE_UNKNOWN; + } + break; + + default: + break; + } + } + } + + plevel->move_current = plevel->move_last; + } + + fclose(level); + + return plevel; +} + +int level_save(struct level* plevel, char *filename, int partial) +{ + FILE *level; + char c; + int x, y; + int i, j; + char buffer[256]; + struct move* pmove; + struct mover* pmover; + + level = fopen(filename, "w"); + if(level == NULL) + return errno; + + fprintf(level, "chroma level\n\n"); + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + fprintf(level, "mode: xor\n\n"); +#endif +#ifdef ENIGMA_COMPATIBILITY + if(plevel->mode == MODE_ENIGMA) + fprintf(level, "mode: enigma\n\n"); +#endif + + if(plevel->title != NULL && strcmp(plevel->title, "") != 0) + fprintf(level, "title: %s\n", plevel->title); + if(plevel->level != 0) + fprintf(level, "level: %d\n", plevel->level); + fprintf(level, "size: %d %d\n", plevel->size_x, plevel->size_y); + + if(!partial || plevel->flags & LEVELFLAG_SOLVED) + { + fprintf(level, "player: %d\n", plevel->player + 1); + fprintf(level, "moves: %d\n", plevel->moves); + fprintf(level, "stars: %d %d %d\n", plevel->stars_caught, plevel->stars_exploded, plevel->stars_total); + if(plevel->flags & LEVELFLAG_SOLVED) + fprintf(level, "solved: 1\n"); + if(plevel->flags & LEVELFLAG_FAILED) + fprintf(level, "failed: 1\n"); + } + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + { + if(plevel->switched) + fprintf(level, "switched: %d\n", plevel->switched); + fprintf(level, "view1: %d %d\n", plevel->view_x[0], plevel->view_y[0]); + fprintf(level, "view2: %d %d\n", plevel->view_x[1], plevel->view_y[1]); + if(plevel->teleport_x[0] != -1) + { + fprintf(level, "viewteleport1: %d %d (%d %d)\n", plevel->view_teleport_x[0], plevel->view_teleport_y[0], plevel->teleport_x[0], plevel->teleport_y[0]); + fprintf(level, "viewteleport2: %d %d (%d %d)\n", plevel->view_teleport_x[1], plevel->view_teleport_y[1], plevel->teleport_x[1], plevel->teleport_y[1]); + } + if(plevel->mapped) + { + fprintf(level, "mapped:"); + if(plevel->mapped & MAPPED_TOP_LEFT) + fprintf(level, " top_left"); + if(plevel->mapped & MAPPED_TOP_RIGHT) + fprintf(level, " top_right"); + if(plevel->mapped & MAPPED_BOTTOM_LEFT) + fprintf(level, " bottom_left"); + if(plevel->mapped & MAPPED_BOTTOM_RIGHT) + fprintf(level, " bottom_right"); + fprintf(level, "\n"); + } + + } +#endif + + fprintf(level, "\ndata:\n"); + + for(y = 0; y < plevel->size_y; y ++) + { + for(x = 0; x < plevel->size_x; x ++) + { + fputc(piecetochar(level_piece(plevel, x, y)), level); + } + fputc('\n', level); + } + fputc('\n', level); + + if(plevel->move_first != NULL && plevel->moves != 0) + { + fprintf(level, "movedata:\n"); + + i = 0; + pmove = plevel->move_first; + while(pmove != NULL && i < plevel->moves) + { + fputc(directiontochar(pmove->direction), level); + i ++; + + if(i % 78 == 77 && pmove->next != NULL) + fputc('\n', level); + + pmove = pmove->next; + } + + fprintf(level, "\n\n"); + + if(!partial) + { + fprintf(level, "undodata:\n"); + + i = 0; j = 0; + pmove = plevel->move_first; + while(pmove != NULL && j < plevel->moves) + { + pmover = pmove->mover_first; + while(pmover != NULL) + { + c = ','; + if(pmover->fast == 0) + c = ';'; + if(pmover->next == NULL) + c = '.'; + + sprintf(buffer, "%02d:%02d%c%c%c%c", pmover->x, pmover->y, directiontochar(pmover->direction), piecetochar(pmover->piece), piecetochar(pmover->piece_previous), c); + if(i + strlen(buffer) > 78) + { + fprintf(level, "\n"); + i = 0; + } + + fprintf(level, "%s", buffer); + i += strlen(buffer); + pmover = pmover->next; + } + j ++; + pmove = pmove->next; + } + + fprintf(level, "\n\n"); + } + } + + fclose(level); + + return 0; +} + +void level_addmove(struct level* plevel, int move) +{ + struct move* pmove; + struct move* ptmp; + struct mover* pmover; + struct mover* pmovertmp; + + /* If we are making a move after undoing some moves */ + if(plevel->move_current != plevel->move_last) + { + + /* Find the first undone move */ + if(plevel->move_current != NULL) + pmove = plevel->move_current->next; + else + pmove = plevel->move_first; + + /* Delete all moves that follow it */ + while(pmove != NULL) + { + ptmp = pmove->next; + + /* Delete movers associated with deleted move */ + pmover = pmove->mover_first; + while(pmover != NULL) + { + pmovertmp = pmover->next; + free(pmover); + pmover = pmovertmp; + } + + free(pmove); + pmove = ptmp; + } + + /* Fix up this move so that it appears to be the last */ + if(plevel->move_current != NULL) + plevel->move_current->next = NULL; + else + plevel->move_first = NULL; + + plevel->move_last = plevel->move_current; + } + + /* Create the new move */ + pmove = (struct move*)malloc(sizeof(struct move)); + if(pmove == NULL) + fatal("Out of memory in level_addmove()"); + + pmove->direction = move; + pmove->previous = plevel->move_last; + pmove->next = NULL; + pmove->mover_first = NULL; + pmove->mover_last = NULL; + + if(plevel->move_first == NULL) + plevel->move_first = pmove; + + if(plevel->move_last != NULL) + { + plevel->move_last->next = pmove; + pmove->count = plevel->move_last->count + 1; + } + else + pmove->count = 1; + + plevel->move_last = pmove; + plevel->move_current = pmove; + +} + +void level_fix(struct level *plevel) +{ + int i, j; + int teleport; + + for(i = 0; i < 2; i++) + { + plevel->alive[i] = 0; + plevel->teleport_x[i] = -1; + plevel->teleport_y[i] = -1; + } + + plevel->stars_caught = 0; + plevel->stars_exploded = 0; + plevel->stars_total = 0; + + teleport = 0; + + for(j = 0; j < plevel->size_y; j ++) + { + for(i = 0; i < plevel->size_x; i ++) + { + switch(level_piece(plevel, i, j)) + { + case PIECE_PLAYER_ONE: + plevel->alive[0] = 1; + plevel->player_x[0] = i; + plevel->player_y[0] = j; + break; + + case PIECE_PLAYER_TWO: + plevel->alive[1] = 1; + plevel->player_x[1] = i; + plevel->player_y[1] = j; + break; + + case PIECE_STAR: + plevel->stars_total ++; + break; + +#ifdef XOR_COMPATIBILITY + case PIECE_TELEPORT: + if(teleport < 2) + { + plevel->teleport_x[teleport] = i; + plevel->teleport_y[teleport] = j; + teleport ++; + } + break; +#endif + } + } + } +} + +void level_settitle(struct level* plevel, char *title) +{ + if(plevel->title != NULL) + free(plevel->title); + + if(title == NULL) + { + plevel->title = NULL; + return; + } + + plevel->title = malloc(strlen(title) + 1); + + if(plevel->title != NULL) + strcpy(plevel->title, title); +} + diff --git a/level.h b/level.h new file mode 100644 index 0000000..07d2514 --- /dev/null +++ b/level.h @@ -0,0 +1,286 @@ +/* + level.h + + Copyright (C) 2010-2019 Amf + + 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 MOVE_LEFT 0 +#define MOVE_UP 1 +#define MOVE_RIGHT 2 +#define MOVE_DOWN 3 +#define MOVE_NONE 4 +#define MOVE_SWAP 5 +#define MOVE_SWAPPED 6 +#define MOVE_UNKNOWN 7 +#define MOVE_REDO 8 + +#define MOVER_FAST 1 +#define MOVER_UNDO 2 +#define MOVER_STORE 4 + +#define LEVELFLAG_MOVES 1 +#define LEVELFLAG_STARS 2 +#define LEVELFLAG_SWITCH 4 +#define LEVELFLAG_EXIT 8 +#define LEVELFLAG_SOLVED 16 +#define LEVELFLAG_FAILED 32 +#define LEVELFLAG_PAUSED 64 +#define LEVELFLAG_UNDO 128 +#define LEVELFLAG_TESTING 256 +#define LEVELFLAG_MAP 512 +#define LEVELFLAG_NOUNDO 1024 + +#ifdef XOR_COMPATIBILITY +#define MAPPED_TOP_LEFT 1 +#define MAPPED_TOP_RIGHT 2 +#define MAPPED_BOTTOM_LEFT 4 +#define MAPPED_BOTTOM_RIGHT 8 +#endif + +enum { + PIECE_SPACE = 0, + PIECE_WALL = 1, + PIECE_PLAYER_ONE = 2, + PIECE_PLAYER_TWO = 3, + PIECE_STAR = 4, + PIECE_DOTS = 5, + PIECE_DOOR = 6, + PIECE_CIRCLE = 7, + PIECE_ARROW_RED_LEFT = 8, /* PIECE_ARROW_RED_LEFT % 4 must = 0 */ + PIECE_ARROW_RED_UP = 9, + PIECE_ARROW_RED_RIGHT = 10, + PIECE_ARROW_RED_DOWN = 11, + PIECE_BOMB_RED_LEFT = 12, + PIECE_BOMB_RED_UP = 13, + PIECE_BOMB_RED_RIGHT = 14, + PIECE_BOMB_RED_DOWN = 15, + PIECE_ARROW_GREEN_LEFT = 16, + PIECE_ARROW_GREEN_UP = 17, + PIECE_ARROW_GREEN_RIGHT = 18, + PIECE_ARROW_GREEN_DOWN = 19, + PIECE_BOMB_GREEN_LEFT = 20, + PIECE_BOMB_GREEN_UP = 21, + PIECE_BOMB_GREEN_RIGHT = 22, + PIECE_BOMB_GREEN_DOWN = 23, + PIECE_ARROW_BLUE_LEFT = 24, + PIECE_ARROW_BLUE_UP = 25, + PIECE_ARROW_BLUE_RIGHT = 26, + PIECE_ARROW_BLUE_DOWN = 27, + PIECE_BOMB_BLUE_LEFT = 28, + PIECE_BOMB_BLUE_UP = 29, + PIECE_BOMB_BLUE_RIGHT = 30, + PIECE_BOMB_BLUE_DOWN = 31, + +#ifdef ENIGMA_COMPATIBILITY + PIECE_CIRCLE_DOUBLE, + PIECE_DOTS_DOUBLE, +#endif + +#ifdef XOR_COMPATIBILITY + PIECE_DOTS_X, + PIECE_DOTS_Y, + PIECE_SWITCH, + PIECE_TELEPORT, + PIECE_MAP_TOP_LEFT, + PIECE_MAP_TOP_RIGHT, + PIECE_MAP_BOTTOM_LEFT, + PIECE_MAP_BOTTOM_RIGHT, + PIECE_DARKNESS, +#endif + + PIECE_EXPLOSION_RED_LEFT, + PIECE_EXPLOSION_RED_HORIZONTAL, + PIECE_EXPLOSION_RED_RIGHT, + PIECE_EXPLOSION_RED_TOP, + PIECE_EXPLOSION_RED_VERTICAL, + PIECE_EXPLOSION_RED_BOTTOM, + PIECE_EXPLOSION_GREEN_LEFT, + PIECE_EXPLOSION_GREEN_HORIZONTAL, + PIECE_EXPLOSION_GREEN_RIGHT, + PIECE_EXPLOSION_GREEN_TOP, + PIECE_EXPLOSION_GREEN_VERTICAL, + PIECE_EXPLOSION_GREEN_BOTTOM, + PIECE_EXPLOSION_BLUE_LEFT, + PIECE_EXPLOSION_BLUE_HORIZONTAL, + PIECE_EXPLOSION_BLUE_RIGHT, + PIECE_EXPLOSION_BLUE_TOP, + PIECE_EXPLOSION_BLUE_VERTICAL, + PIECE_EXPLOSION_BLUE_BOTTOM, + + PIECE_EXPLOSION_NEW_RED_LEFT, + PIECE_EXPLOSION_NEW_RED_HORIZONTAL, + PIECE_EXPLOSION_NEW_RED_RIGHT, + PIECE_EXPLOSION_NEW_RED_TOP, + PIECE_EXPLOSION_NEW_RED_VERTICAL, + PIECE_EXPLOSION_NEW_RED_BOTTOM, + PIECE_EXPLOSION_NEW_GREEN_LEFT, + PIECE_EXPLOSION_NEW_GREEN_HORIZONTAL, + PIECE_EXPLOSION_NEW_GREEN_RIGHT, + PIECE_EXPLOSION_NEW_GREEN_TOP, + PIECE_EXPLOSION_NEW_GREEN_VERTICAL, + PIECE_EXPLOSION_NEW_GREEN_BOTTOM, + PIECE_EXPLOSION_NEW_BLUE_LEFT, + PIECE_EXPLOSION_NEW_BLUE_HORIZONTAL, + PIECE_EXPLOSION_NEW_BLUE_RIGHT, + PIECE_EXPLOSION_NEW_BLUE_TOP, + PIECE_EXPLOSION_NEW_BLUE_VERTICAL, + PIECE_EXPLOSION_NEW_BLUE_BOTTOM, + + PIECE_CURSOR, + PIECE_GONE, + PIECE_UNKNOWN +}; + +#define PIECE_EXPLOSION_FIRST PIECE_EXPLOSION_RED_LEFT +#define PIECE_EXPLOSION_LAST PIECE_EXPLOSION_BLUE_BOTTOM +#define PIECE_EXPLOSION_NEW_FIRST PIECE_EXPLOSION_NEW_RED_LEFT +#define PIECE_EXPLOSION_NEW_LAST PIECE_EXPLOSION_NEW_BLUE_BOTTOM +#define PIECE_EXPLOSION_NEW_OFFSET (PIECE_EXPLOSION_NEW_FIRST - PIECE_EXPLOSION_FIRST) +#define PIECE_MOVERS_FIRST PIECE_ARROW_RED_LEFT +#define PIECE_MOVERS_LAST PIECE_BOMB_BLUE_DOWN +#define PIECE_MAX PIECE_GONE + +#define isexplosion(x) (x >= PIECE_EXPLOSION_FIRST && x<= PIECE_EXPLOSION_LAST) +#define isnewexplosion(x) (x >= PIECE_EXPLOSION_NEW_FIRST && x <= PIECE_EXPLOSION_NEW_LAST) + +enum { + MODE_CHROMA, +#ifdef XOR_COMPATIBILITY + MODE_XOR, +#endif +#ifdef ENIGMA_COMPATIBILITY + MODE_ENIGMA, +#endif + MODE_MAX +}; + +struct mover +{ + int x; + int y; + int direction; + int piece; + int piece_previous; + int fast; + struct mover* next; + struct mover* previous; +}; + +struct move +{ + int count; + int direction; + struct move* previous; + struct move* next; + struct mover* mover_first; + struct mover* mover_last; +}; + +struct level +{ + int size_x; + int size_y; + + char *data_pieces; + char *data_moving; + char *data_previous; + char *data_previousmoving; + char *data_detonator; + char *data_detonatormoving; + unsigned int *data_data; + + struct move* move_first; + struct move* move_last; + struct move* move_current; + + struct mover* mover_first; + struct mover* mover_last; + + struct mover* stack_first; + struct mover* stack_last; + + int player; + int player_x[3]; + int player_y[3]; + int view_x[3]; + int view_y[3]; + int alive[2]; + + int moves; + + int stars_caught; + int stars_exploded; + int stars_total; + + char *title; + + int flags; + +#ifdef XOR_COMPATIBILITY + int switched; + int mapped; +#endif + + int mode; + int level; + + int teleport_x[2]; + int teleport_y[2]; + int view_teleport_x[2]; + int view_teleport_y[2]; +}; + +/* level.c */ +char piecetochar(int piece); +int chartopiece(char c); +char directiontochar(int direction); +int chartodirection(char c); + +struct level* level_new(); +struct level* level_load(char *filename, int partial); +int level_save(struct level* plevel, char *filename, int partial); +struct level* level_copy(struct level*); +void level_addmove(struct level*, int); +void level_fix(struct level*); +struct level* level_create(int, int); +void level_delete(struct level* plevel); + +char level_piece(struct level*, int, int); +void level_setpiece(struct level*, int, int, char); +char level_moving(struct level*, int, int); +void level_setmoving(struct level*, int, int, char); +char level_previous(struct level*, int, int); +void level_setprevious(struct level*, int, int, char); +char level_detonator(struct level*, int, int); +void level_setdetonator(struct level*, int, int, char); +char level_detonatormoving(struct level*, int, int); +void level_setdetonatormoving(struct level*, int, int, char); +char level_previousmoving(struct level*, int, int); +void level_setpreviousmoving(struct level*, int, int, char); +unsigned int level_data(struct level*, int, int); +void level_setdata(struct level*, int, int, unsigned int); +void level_settitle(struct level* plevel, char *title); + +/* engine.c */ +int level_move(struct level*, int); +int level_evolve(struct level*); +int canfall(int p, int into, int d); +struct mover* mover_new(struct level* plevel, int x, int y, int d, int piece, int fast); +struct mover* mover_addtostack(struct level* plevel, int x, int y, int move); +void level_storemovers(struct level*); +int level_undo(struct level*); +struct mover* mover_newundo(struct level* plevel, int x, int y, int d, int piece, int previous, int flags); diff --git a/levels/chroma-1/chroma-1-01.chroma b/levels/chroma-1/chroma-1-01.chroma new file mode 100644 index 0000000..1a385e0 --- /dev/null +++ b/levels/chroma-1/chroma-1-01.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 1.01 : invitation +level: 1 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%lll%h %ll%% d%* . % *.* * % +%*l*%* h%*ll%dd%/%j * .bb*%%f%%% +%%l%% *% ll *d *%j% b %f. % +% * h % .. %%d%%%% %%%%* %ff*% +% % % *.%%%%d%d.%. . %*%b %fff% +%l l% %hh%d d%%f*f*.% %% %%%%% +%.l.% % %h*%d . %.%fff% * %* *% +% .*% %* .*% %f * % j%%% . % +%%%%%% %%h %*%% % *%%%% *..% b.% +%* *%d d%. % %*f%* jjj b% +%hhh%* *%%%%%%l%%%%% %%%%%%%%%%% +%*hh% 1 l l*.%***% * %.* %. *% +% ..%*d %l. l %...%.* b . f f% +% %%%%% %.%*%. %fff% b % *b%f *% +% %%%%%% % %%%%% .f% +% llll% %h hhh % %%% % b b f % +% ***.% %* .h*h%*..j*%%%.%%%%%%% +%%%%%%% % * . .%jjjjj% * %* *% +%ddd%d % %%%%%%%%%%%% . 2 %j j% +%.d*%* % %ddd % .f.f*f* * * % +%*. *% ...*%%*f ff%f%f% j % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-1/chroma-1-02.chroma b/levels/chroma-1/chroma-1-02.chroma new file mode 100644 index 0000000..ca65150 --- /dev/null +++ b/levels/chroma-1/chroma-1-02.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 1.02 : illustration +level: 2 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% h *%*l% %*%c* %*g* *%*% +% .* he% .il % 2 % gf f g. % +% * *e%%%* .i % c% *% f % +% % .ee% % % b b%g.% g*% *% +% %%%%.%%% %%%%%%% *%gf %gf% +%* da%%% *i%%%%% . f f % +% da%d%% %%h% * %%k.%%%%% %%% +%* d * %*/*%cb%kkj*% % +% * %% %% h %b%bb%*%j %* cc*% % +%%% %% %eee%%%%%%%%%%% b% % +%*%%% li% *%g*.* . %*. cb *%%% +% *i %%%%% f % %%b %b % +% %%%%%%%%l l%%%%f%% %%%%%% % % +% h %d. %li.i% %%% k* %g. . % +% *e%*aa%* % % %% * % * f % +%1 % %% % %c. *%k*j. %fgg*% +%% %% %%% h % b%%%%%% %%%b%%% +% % h*e%% %%%%g.*% % c. % +% da%li% h*e % .*. %g.*% %c. *% +%*a %. % *e %%j.j %% f %%c* %% +% d%* % jk. f %cb *% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-1/chroma-1-03.chroma b/levels/chroma-1/chroma-1-03.chroma new file mode 100644 index 0000000..3561b5a --- /dev/null +++ b/levels/chroma-1/chroma-1-03.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 1.03 : elaboration +level: 3 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%hgg*%g.%ll % %*a % h % +%gf g. .. *ee% ba *aa 1*ee% +% %% %%k* %gg* *d b b% % f % +% d %j .i% %c. cb %%%%%% +% d %% %%%%%%%%%%%%%% %d%*d% +%cc*aa% . *a d% *.l%*/*%d*% +% b %kj % .%cd *%kk.j*%b% %. % +% b %*%*%*a% d b% j %%% .% +% %% %%%%%%%%%*ccb%%%*% *he %*b% +%.eg.% l li%d%%%%%%h%%%% *fe%b*% +% fe%k* . %*. *a%h*h%* gf %%%% +%*% * *% .%%. .%% *%% %li% +%%% %%% . %%. % %k*% +%dc. % ji%c* .*%g. .e%cda% 2% +%cb *%*%*%%%%%b% * * % d %% %%% +%%%%%%%%%%%*c.%%%%% %%% b % % +%**% * %**%% d %*%* *%%%%%g. *% +%ggg. .eee%c.* %i%k. % hf% +%ff ff%% % . . li % gf% +% . . ..a%%j%*j% kl ..e% +%g* f*f *e%cb %%kj *. % f *% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-1/chroma-1-04.chroma b/levels/chroma-1/chroma-1-04.chroma new file mode 100644 index 0000000..2a41719 --- /dev/null +++ b/levels/chroma-1/chroma-1-04.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 1.04 : detonation +level: 4 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% G*% *% %l%gF.*e% .*i*i*i% +% Gf.% gF%c*%*/*%%%%% % . % +%* %B% F % D %j% .*AA%%%%%%%J*% +%%%%*%%%%% b %*%d * % %%%% +%1d% Hl%%%%%% %c* . %LLL*i% % +% .%g* .%%k*. % b %...% %g.% +%*D% b *K% . *%%%H%%%%** %*%. % +%%%%%%%%%%* J j%* . *e%%%%%E*Ee% +%*Ee%l %%%%%%%% d % % +% %*cC*% h %g.* G% * %%%%%% +%g* % %%%gG* . %%%%%*% k. % +% f %L %*% H*% l %%%C.A%kK.*% +%%%%%%%%h%%%%%%%% l *% * % kK.% +% .%.*%.% d% . %%%%%%% % +%Cdb%Jl% %c*A.aD%%K.%* %%%%%% +% d %*.%H% .*%*K%%% *a%G*.E% +% * %j %%%%%%%%%%% *%*% b %d *% +% . % L% . *%%%%%%%%%%%%%%% +%%%%%%%%%%f%g* G% l %h h %I *i% +%*%*%L l %gGf%gg%% L %* H % % +%f%D%* *i%*gf .*%*.k% * %*D 2% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-1/chroma-1-05.chroma b/levels/chroma-1/chroma-1-05.chroma new file mode 100644 index 0000000..6c83ccb --- /dev/null +++ b/levels/chroma-1/chroma-1-05.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 1.05 : complication +level: 5 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% %B 2 D% %l% %d l % +%.Iaei%Fc*iH% l d %.e *Aa %*1* % +% %J L% .h. % * %H .e% +%%%%%%%%%%%%% * % %%%.%%%%%% +% l h d %*l*%%A%K%%I %*%L% h d% +% . . . %ji%%%%%%%%%%%% %%% . .% +%* %%%%l *%*%* *% d % K% +%%%%%%%E%GA%h %%%b dj% l % % +% %%% %d % l % * % k* % +% dlh % * %.*Aa % hA% % C% +%*... f % % . %KCK%%%%%% +%.EEe % b.i%*%%%%% %%%%%%%%% *% +%%%%%%% %I%* D%%% %c* *% Dj% +%c* *%%%%%%%%E . *.ei%%%% % gD% +%%%%%%% d%c.*%* B% b *%D% % *% +%*l%L %*a%%h%%%%%%%%% %%* %% %% +% .%* . *% H %H %k*i% +%%%%D %e %% %d% H .I %* L % % +%c*%. % *%k% . * % * %DDH% +%%/%* %.i% %%A% .AA%HDL%%...% +%g*%H j % *%L %fbja%***% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-1/chroma-1-06.chroma b/levels/chroma-1/chroma-1-06.chroma new file mode 100644 index 0000000..2c132b1 --- /dev/null +++ b/levels/chroma-1/chroma-1-06.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 1.06 : transportation +level: 6 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% *e% .% *% *%*% %B *% .*h % +% /J *i f% %.% %go o % *o% +% *a% .% %% % % % o % +% %%% %oooo% oa% . G%o* % +% k*% *a % % % %%% % +%%%%%%%%%%%%%%%%%% %%% * %*%%% % +%Dk. *L % % *a %h%%%%%%%. *% +%* % o %%% % *% o %oa%% +% %c.* %G%%%%% % o *% +%*.go %* %%% %kL o %% %% +%B o%f %cc. %%% % % +%%%%%%%A%%%%%% oo Da% . *i%ooo% +% % % o %*% % 1 % +% o Hoo o g% * %%%%%%%%%% %% +% % * %%%f %* .e% * % +% g* %%%%b%%%%K%%%%%%%c.C*% %%%% +% *%%% . %* *% %%% l % +%%%%%%d%% *% .o. %e . % +% . % o % o*o *%% c% +% o 2 *% . o % .o. % di%* % +% D% j %* *%*ie%%f * % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-1/chroma-1-07.chroma b/levels/chroma-1/chroma-1-07.chroma new file mode 100644 index 0000000..48104af --- /dev/null +++ b/levels/chroma-1/chroma-1-07.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 1.07 : collaboration +level: 7 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% J%*%*%B F%*% d %h*% +% C. %%%%% * * % o . %%%% +% jC. % % % % % %%%. K.*% +% h * % b %k%B % +%%%%%%%%f %%%%f%%%%%% . *%%%%% +%* .a.a%i1% *. lli%*%H %%%%% Da% +%%%* B % %kjj .*%% %%%%* %* *%% +% %*G%%%%%%%% % .%f %% +%*%%g* %%%% * %c. l c. . o % +% %% % .ji% *%%cc%h %% +%oo % %cc* % jkj%* D * %. *%% +% %% %% j %%%%%%%%%%%%%%%%% Ba% +%*%% %%j % k.* Fa%lll % %%% +%%%g.%.e%%%% g. %*%kD. % %h% +%A% *b* %2 % %k% . *a%*/*% +% %%%%%%%*i%.a *% % L% %j% % +% %J j b %%%%%%%%%%%%%% +%%* d %%%%%%%%%%% l % * C% +%gb h *a F %* oa % f h% +%%% L %% * . %%%. % b * *% +%*% . *i f %*%L g* H% j % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-1/chroma-1-08.chroma b/levels/chroma-1/chroma-1-08.chroma new file mode 100644 index 0000000..d086017 --- /dev/null +++ b/levels/chroma-1/chroma-1-08.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 1.08 : preparation +level: 8 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*% .a% d . %*j %k* *% +% * % h o % D*f % o %%%%% D .% +% be% .e% *%2.%%%%e %IEA% H. % +%%* % c* % D* % *a% % D* % +%*f % . *%%%% % %%%%% *%% . % +% ja% j %%%% %d*e% b %% %%% +%%%%%%%%%* d oooo %hl f %K.Il% +% . . . . .% o o %la % j %j k*% +%* . . . . o o %*1 %%%%%%%%%% +%A%%%%%%%%%% oooo %c. % f % +%%% %e% % d * k% +%l%c*c*c*C*%%%%%%%%%%%%%% % % % +%.% %e%*%* D%*a% . .% g% +% %* *%%%%%%%% g. .%%/%% o % +%I%G.E%d% J % . % *a% d % +%%%%*%%. k.K% c. .Ho%%%%%%%%%C% +% J %*% %* %%%* b% +% g. %%%%% *%%%%%%%d%% L H D %% +% % dh% j%he%D .%H . . .*a% +% k* C%dahe c%gh%* %* . . . %% +% b %* . * . %L%F . *% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-1/chroma-1-09.chroma b/levels/chroma-1/chroma-1-09.chroma new file mode 100644 index 0000000..37af1b8 --- /dev/null +++ b/levels/chroma-1/chroma-1-09.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 1.09 : application +level: 9 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% c* %h le%* % *e*%. *%*a% +% h c*%. d %b . da gco %/%% +%K. % . % %biEe%* B .%*e% +% * %E* %%%.%%%%%%%% F %%%%%%% +%. .*%kc. l% % d%%%%% % +%*i G% %l*% % H * . % D2d % +%%%%%%%%%%.%% % % % %aei% G* *E% +%I h C% . %l%1 .i %l % +%* . *% *%%%%%%%%%G%* %*% % +%% cie %* . % %%%%%%%%%% +%l*af %f % %%%%%%% B .ab % +%G%%%%%% * %%% Lh %E o.e kh % +% %C* *A% *. % * K*% +% * % %%% . b% d %%%%% %%%%%%% +% % %%f%%%%gg. %H*l% ha*% +% o . . d%L% %%%* .e.%%% o %% +% . . .*%%%g.Ha% *% %*%. % +%C%%%%% %%ka k*%%%%%%%%%% %***% +%%% *% %%Ik* .II% d %GGG% +% g.c. D %%%%% %%%% . *Aa%%%%% +%* j % f* *%*% *a *%*D %*%k*i% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-1/set.chroma b/levels/chroma-1/set.chroma new file mode 100644 index 0000000..5ec7cb3 --- /dev/null +++ b/levels/chroma-1/set.chroma @@ -0,0 +1,7 @@ + + + +chroma 1 : initiation +for beginners + + diff --git a/levels/chroma-2/chroma-2-01.chroma b/levels/chroma-2/chroma-2-01.chroma new file mode 100644 index 0000000..65ad1ce --- /dev/null +++ b/levels/chroma-2/chroma-2-01.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.01 : inauguration +level: 1 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%h h l%l d% ld% *.f.* %.*...*.% +%. *d*%*h *%h.*%*bj. j %fbfjfbf% +%* l. % d %.d % ..b.f %.j.2.j.% +% d.h %.*..%l*.%* fjfb.% % +% . ..% hd.h %%%%%%%j%%%%% %%% +%*l l .. * % .b *%*% +%%%%%%%%%%%%%%d%.fj %%%%%%%%b% % +%*dhdh%l.d%dh .%*.f %*.f..*%j % +%l.d.l%*h*%ldl % b% %.j.b.j%f% % +%dhldh%h.l%h.h%%% % %f.j...%bj.% +%l.h.d%.d.%d%. */*% %.b.f.b%f%f% +%. . . * * %%%f%.%%%%%j%%%% % +%%%%% % %%%% %%d%j% b f.% +% d1%h d %l *%%%%%%%%%f% b% +%l.h.l%.l..%.%l %* *%*%*%j%* *j% +%*d.h.% h. %h%. %...%.%.%f%j.f.% +%h.l.*%*.*d%l%d %jfb.f.j.b% . % +%%%%%%% %%%%d%h % j.b. *%*b* % +%* l d h . %.* .j.f j%f.j*% +%dhlhd%.%% %*%% %bj *. *b%j*bf% +%...*.% %* *%*f f jf%bjfj% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-02.chroma b/levels/chroma-2/chroma-2-02.chroma new file mode 100644 index 0000000..11c6990 --- /dev/null +++ b/levels/chroma-2/chroma-2-02.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.02 : manipulation +level: 2 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% f %* .% *g. %* h %.* l% +%g* b %jcg. f%cj *% d la %hlae% +% *j %gk.j .% kb% . *.e%dh%*% +%c*j. * %fb j *f%%h%i *aiea% +%%%%%%%%%%%2%%%g%%% . . .i% +%%c*% k.* *% .*%*%%%%%%%%%%%% +%gj.* g*.% fkb% kb% l ha% hd*% +%* . j%c.f % f%%% . *i % .le% +%%%%%j% %%% %%%.%%*d %.%%e% *a % +%gc* % f %* f*% . *% +%kf % %*g.k. c.%1%%%%%%%% %%%% +%ck. .%j b*j%k. % *%h d d.i% +%* *j%%%%%%%%%%%%%aie%*ah l.e % +% . b . .% *a * . % l .a *% +%g.% % % j.b%ahle%%%% %%*%%%%%%% +%j c* *% gbf%*dea% l %d hi de*% +%c.k.%j% bj*% . *.e *a%..a *h % +%g*.f%%%%%%%%%%l%% %% %l .e l.% +% k. %k* %d%* . %.* %% d.% +% .g.%c. .%*/*% * lea%%%d% *i% +%* b j *.f% .ai*%* . *e*% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-03.chroma b/levels/chroma-2/chroma-2-03.chroma new file mode 100644 index 0000000..06f897b --- /dev/null +++ b/levels/chroma-2/chroma-2-03.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.03 : edification +level: 3 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*d *k* d . . % d h %gl% +% hide% .. hajgj % g..* *i %la% +%gl kb% g. * *%%%*% ck. . % +% * *%cl k%%%l%%%* .e.a% *% +%%%.%%% .*ha% .le%%%% %%%%%%%%% +% gj*%* *fi %gc.. %* l *%h *l*% +% %*%%%d%%%%%%* %*% .d. %c. . % +%c* .lh l*%kd.% % kc*ai *...e% +% . .b.d .h%jg.* % % .b1 %kfb % +% f j *.* .%c. % %.%* j *%%%%%%% +%%% %%% %%%%* %%% %%% %%%h*.*a% +%*f.l*%.i*%*kg*% c. %.a. * k. % +%k.b.g%.e %l% %cf..i% fj% ..bh% +%.a2c. %b*/*%.a%* f *%cjb%lb .% +%e.d.i%%%j% %%%%%%%j * . *e*% +%*j.h*%*%%%%%%%%*l h %%%%%%%%% % +%%% %%% . l %.. *e%*h* d % +%lc.h %%%je .*.%f j %%.b k.*hi% +%*e l. %aj d %*a%.*%cl .f .*f% +% .a% * .e..*i .ib % . * l .a% +%*%.* %.% b *a% .e% b .d % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-04.chroma b/levels/chroma-2/chroma-2-04.chroma new file mode 100644 index 0000000..7ed9787 --- /dev/null +++ b/levels/chroma-2/chroma-2-04.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.04 : disintegration +level: 4 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% l *%*%kK* *%F* h .B D*% +% Kl %%% L . kK*%%% . %A.c.C% +% .Ll %k. j jiK%*%.%g%E% b2d % +%%%.L * %*j %%%*h % %A.a.C% +%*% .*j %%%%%K.i * %f. %*%*B D.% +%%%%%%% %* %%K.ij*%%% %%%%%%% % +%*.e gG*% h %%L.i %*% . % +%.egG...%%.E %%%%%%%% L l % +% 1* %* g. % HG..e% K*I k*i % +%...Aac.% .e % h % J j %% +%*Aa c.*%*% % . .eG*e%. .% +% %%%%%%%E%%%%% * %%%%%%%k*.*i%% +% h %fee%h%*g. g* %%j%j%%% +%%. .*eE%%%*/*%%%%%%%%%%%%%%%%*% +%%h %*%f% g. %*%*%g*F.e% K% +% .*e. %%%%%%%%%%%% % * %.i*% +%*H G%A* d% h.eF. %. j% +% %%%%%%%%% *cC*%d% % F %j % +% %*%*%*.Aa B*% H * % +%%kLi %%%%%b .Aa%b %%%g.H.e%*Ji% +%K*. *L% * %*%*H*eF%Ji % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-05.chroma b/levels/chroma-2/chroma-2-05.chroma new file mode 100644 index 0000000..06f5467 --- /dev/null +++ b/levels/chroma-2/chroma-2-05.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.05 : triplication +level: 5 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% l l %*% 1 %*% d %* H d % +%k. . %%% l d %%% % % %l% . D % +% J gd % .h. % . . %. f .I% +%%% G*% % D.L %C% %e% % c.* %%% +%*% D %h% .H. % . . % %*% +%%%%%%%%.% . % % % % %*g*%%%%% +% %.g.E% %%%*%%% j F %kb %d%l% +% *j % %*%%%%%%%%%%%%%*/*% +% %a%%% %%%%%%%%* c* J%*g.e % % +%*LHD % %* .a% d % %*%%% %%% % +% ... % %% %% .i %%%%% % % % % +%%jfb %a% %* h L%c. . . .*% +% % % . k. .%*f L %%% +%C.*.a%%%*%%C.a lg.E%%%lc*. .*% +%%%%%%%*% %%*%k*%*%%*%. F Bi% +%l%*%*%%%.%%%%%%%%%%%%%*.i j % +%*d %lg.E D %ch*%E%%%%%%%%%% +% l.Di%*d L . %%%%% h % +%he . % . k. *% * * .AI.IA2% +%*. %%% c. *.e%%%%% f % +% g*E%*% b*%kF*%*g.E G.e*% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-06.chroma b/levels/chroma-2/chroma-2-06.chroma new file mode 100644 index 0000000..28f19d4 --- /dev/null +++ b/levels/chroma-2/chroma-2-06.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.06 : orchestration +level: 6 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*a h. %*% %J %DH d .*% +%bo oi.a%%%DgoE %%Dd.i .*% o .% +%*l .I.%cC. b %*.. %b% o % +% . % %%% goG%%%.1 oe% +%%%%%%%%% l .Ii%*. %*%*. % +%* j G% GoeJ%%%%%k.o %%%%%A% +% o % %*%*% L%*%*. la% +%A o %% %%%%%%%%%%%%%%%. . % +% 2 o % . *% h %d% % . % +% l o %c.%%oL %co.i%*/*% . % +% f %k*e% .*% *Da%j% o % +%%%%%%%%%%%A%%%%%%%%%%%%%% b .I% +%*% .o. %%h* l* .*% h *% +% %.o o.%*. .*.*. .*% .a%%%%%%% +%. o o o *b%%%% %%*%g*E% +%%%.o o.%%%%%%%%%G%% % d*l % +%*% .o. % .* .d.L o o % .o. % +%%%%%%%%% .o %%%% o o % o o % +% h *A%c* h .a*% o o %. o .% +% o.o.i%% o . %%% o o %I%.%C% +% b %D* %*% o o %f*f*f% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-07.chroma b/levels/chroma-2/chroma-2-07.chroma new file mode 100644 index 0000000..732706e --- /dev/null +++ b/levels/chroma-2/chroma-2-07.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.07 : augmentation +level: 7 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*%*% D %*Ad %.%1 % 2%* %F%*% +%%%%%goH%%%k*L%*% l o d %co%%%%% +% %* .%.% %%a% D L %kK. . % +%C*A%%%%%*%* *%.% . . % . .% +% . % H % %%%%%%% * * % fDd j% +% b % . .*% . %% %%% %% c* j% +% b % h %a%%% %G.ehG.e%%%%%%C% +%G.E% *. % * .% %h% % l % +% * % %J% %%o B %%%%%%%%a . %.% +% f % b *%c. j %. Ha% *%K% +%%%%%%%%%%%%%%%%% * *ae%%%%%%%%% +% * %J%*l %*f . Fa% d % *.% +% d % C.a%H%.%%% %%%%%.K.%o%b% +% . h %%f %%L% *a% %. *% * * % +% D . H%% .%%/%% % o %.k.%%%%% +% . B .*% %%J%c* .L% .% f %G.e% +% o .f%%oe%F%%%%%D%kK*%%%%%kBa% +% L f % . %. % .* % l*% .i% +%k% l %c* %j . %%B%%% %h.a% b % +% % . *.i *%H b o J % . . %%b%% +%*b*%* %g*.%*e c*%%*%*%kL* *% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-08.chroma b/levels/chroma-2/chroma-2-08.chroma new file mode 100644 index 0000000..3c0755f --- /dev/null +++ b/levels/chroma-2/chroma-2-08.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.08 : conflagration +level: 8 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*B.D.B*% l .*%*Bla* % H*%. L .% +%A.C.B.C% * .%%kgc. % *A% L1 % +%.A.b.D.%%%e. % d %c. %KK*II% +%C.a2c.A* o * .% .*.E%.o % J % +%.B.d.C.%%%*EE %* *%f *%. J .% +%A.D.A.C% f %fLe%%%%%%%%%%%%% +%*D.B.D*%*II%%l%%%*%E%*%I%*a *% +%%%%*%%%%%%%%*.*a%%%. D%%%cgoeG% +% % % %h h%BH %% h* . %. D .% +%kL%oii*%gH*%B. %c.j *% %%%%%%% +% * *. j% . % .%%% . . .*.*% +% k* %% .a% %%J% %%% f h% +%%%%%%%%%%%%I* %*i% j*%*%*D .a% +%. J .%*%d*%%%%%%%%%%%%% %%%%%%% +% g*i %%%.h%*.ae * c* .% * *i% +% B %* .%% %oC% L%h %f%I.i/%% +%h H % .i %*h% % .di %b%% *i% +%* %%% %d.k. %I * %%% d.%%% +%FD %E % %%* j h l%el % +%%L.*. la %%% g* %%%* *%dhae % +%*%b%f*a D*%D%H. %H%.aH%*.* L% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-09.chroma b/levels/chroma-2/chroma-2-09.chroma new file mode 100644 index 0000000..3584587 --- /dev/null +++ b/levels/chroma-2/chroma-2-09.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.09 : restoration +level: 9 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%*h.aL% *i l k* % H %d* .%*%*d% +% * k.% H l H %gKoi%kh B%%%je% +% *% de%%%gD % .a%*. *%* % +%g.* % * . . * % D *%%% o % *% +%jc. *%. % % .%*D%%%* J B% +%%%%%%%%%%% %%%%%%%%*%%%.a H.%%% +%d .J%*%*%.*2 1E %%%G%b Jj%*% +%k. .C% %f%c%DDDD% . %f*%%%%%% +%Ag. %o%%% %....% L %%%% *d % +%* b * * .%*.%****% *a%*%* % % +%%% H .%%%%%%%%%%%% f %%%% H.e% +%*%* .ab%dl%*%C*.*A% . % *%%%% % +%.%%%%%%%kd%%%%kFi%%%%%% %%ck* % +%*a*% % *%c*%% . d .*%I%gkb. % +%.o .e* . %. .fcJ %%%%%%%%% +%b. %k* %%C%c.i%C%%%%%%%*% l . % +%I*.%% *%.% * %c* %D%.% d b % +%%%%%E c.%%% . %%%e%*jI%L* o f % +% %d%*cl %*%%*E%* .% .*%.% * J % +%*/*% L.%%%A .ai%*ji%*% j % +%j% %D . b*%D %L * %Bj.% h . f % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-10.chroma b/levels/chroma-2/chroma-2-10.chroma new file mode 100644 index 0000000..389bf35 --- /dev/null +++ b/levels/chroma-2/chroma-2-10.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.10 : perturbation +level: 10 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%c*1D%*.* h % .*a % . %hd le% +%%%%%%%%g*%*% % .%*% %D%.%*. . % +%. %g. J %gk. C*A %%%%%%% +% K* K% *i%* .%.%B% % .a%*% +% .fEk*%a.Ad %%%c*% . %o* %%% +%c*f j% * *%.%*%%%%%% %%%%l*%C% +% .2 %*%%%%%%gG.%c.%c* *a%*b %.% +%%%%*%j%Gg. g* %%%%%. .%%%%%%G% +% *%%%E%.*g. j *%*B*%B*B% %*%%% +%co% %%% f * b% %.% F %ih *C% +% %%l%%%%%f% bf% f % %. % +% . *i%kg.B%C.ja.%G% J % %%K% % +% * .a%.a %* be %*% j % D% b % +% .F %glGkD . % %%%%% *% .*% +%.f l %jg*.%.%%%%%*k.%L % *G% +%f . %%%%b%*/*% %%%%%%%K*%ej.% +%I%%%%%% %%%b%j%ld c.G*% B%k*b% +%ch%*D %%%Laa*gj %%%%%%%% +%.i%c. . g*%he f K.% . .*a% +% .Ee *i .o d %H% *i%%B.f. % +%* %* J f . %*%D* j %* b f % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-11.chroma b/levels/chroma-2/chroma-2-11.chroma new file mode 100644 index 0000000..dff514d --- /dev/null +++ b/levels/chroma-2/chroma-2-11.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.11 : bifurcation +level: 11 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%l%H d . %* h%% h h .%D *% +%*%. . B j %. L lk.*a. B%*g. %% +% o D%%* % *. * % *aK% +%g. * %b%%% b*H Ge %L.i *% +% .* .aG%%%%%%%%%%%%%%%%%%%%%% +%a j %%%k%G. . %l %%%* . K*% +% .%I%%%*%%%* f%%B.a%h ga%%% +%k.f% %h%%% B. g. . G%. . g.A% +%d%%%*/*%k% . % b %%* %% +%*%cgbA %%%. b. %%% %%%%%. . Hi% +%%%%% G.eh%f. % d C%*f f o%% +%*B %%* %l% * *a%ck*e *%%A.a % +% .*d%b*%d% B f % g.* H%*%%%%*% +% bFK%%gb.%l% %%%%%%%%%%%%%*.%%% +%* .e % %.% .i *%h%d%* l .% +%.a * % %%g. Fiaei%..fl C% +% . .K%c% %%%%%% %%H% %% *a % +% c.f %L% % *% . %. % +% d * %%% %%B% * .e%BL *i% +%.I%H% .j D%oh%c* o %D%%%.2.I% +%*%j*f C. .% *%I%H*e bi%1%f b% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/chroma-2-12.chroma b/levels/chroma-2/chroma-2-12.chroma new file mode 100644 index 0000000..d0df83c --- /dev/null +++ b/levels/chroma-2/chroma-2-12.chroma @@ -0,0 +1,33 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 2.12 : culmination +level: 12 +size: 32 23 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%***e%*% .%d%d%* Ji% % +%CCC%%H%kk* * %*/*% %I*i% *a.e% +%b .% .% d. J % %.% d %% % +%% %II%%cDFae % % %%% o.e%.k.*% +% %* .f j % l . *E% b % +%k. *% %k. *%%% h.j %%%*a % +%c. %%%%%%%%%%f%*% HcC* .%* b % +% K. o%B %%%%%%%%%l%%%F%%%%% +% *. *.e *%.d %kkd%%% % +% b *k% H %% o %***% *a% +%%%%%%%%%%%.e* % L %%%%% d % +%i % %%*k. dI% *.l % +% * .* d %....d%j . jA%* * % +%. l *a%jjbf*%%%%%%%%%% k*ee% +% %% h %%%%%%%%%* D%A%BK% dF % +% g% .AA% l% 2ec.B%%%%%%%% 1L%% +% * % * o % * %*. .a % +% % %%ji% h Lci% H K%f%. % % +% l %%%% %%%.% . *% D %%% *e % +%K. o%g*k. .%J% * %%%*i *%%%%%% +%j % %.L b .I%*% .iae%*% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/chroma-2/set.chroma b/levels/chroma-2/set.chroma new file mode 100644 index 0000000..bf04b93 --- /dev/null +++ b/levels/chroma-2/set.chroma @@ -0,0 +1,7 @@ + + + +chroma 2 : coronation +for experts + + diff --git a/levels/regression/chroma-pieces.chroma b/levels/regression/chroma-pieces.chroma new file mode 100644 index 0000000..bf3eb8a --- /dev/null +++ b/levels/regression/chroma-pieces.chroma @@ -0,0 +1,30 @@ +# Copyright (C) 2010 Amf + +chroma level + +title: chroma 0.00 : pieces +size: 17 21 + +data: +%%%%%%%%%%%%%%%%% +% % +% 1 2 . a b c d % +% % +% o * / A B C D % +% % +% - | % e f g h % +% % +% S M m E F G H % +% % +% T N n i j k l % +% % +% : 8 % I J K L % +% % +% %%% % % % % % +% % %% %% % +% %%% % % % +% %%% %% %% % +% %%% % % % % % +% % +%%%%%%%%%%%%%%%%% + diff --git a/levels/regression/chroma-regression.chroma b/levels/regression/chroma-regression.chroma new file mode 100644 index 0000000..64de721 --- /dev/null +++ b/levels/regression/chroma-regression.chroma @@ -0,0 +1,65 @@ +# Copyright (C) 2010 Amf +# +# Regression tests for Chroma's game engine +# +# This level tests a number of subtleties in Chroma's game engine. The stars +# indicate where the player should move to trigger each test. After triggering, +# in the top row of tests, pairs of red arrows should fall below the centre +# line, whereas pairs of green arrows should fall above, and pairs of blue +# arrows depend on how they were triggered - falling below if from the left, +# and above if from the right. +# +# In the middle and bottom rows, the precedence of moving bombs is tested. +# After triggering each the first four tests on each row, the green bombs +# should detonate each other, exploding on the positions indicated by the dots. +# The blue bombs should not detonate, but should instead stop on the dots. +# +# In the next two tests in the middle row, only the green arrows should be +# destroyed. The final two tests in the middle row examine explosions - the +# circle in the left hand chamber should be destroyed by the new explosion, +# whereas the circle in the right hand chamber should pass through the dying +# explosion and stop at the wall. +# +# Finally, the stack of bombs to the right of the bottom row is a minimal +# example of a problematic arrangement of bombs - some care is required to +# ensure there are no display glitches when undoing moves. + +chroma level + +title: chroma 0.01 : regression tests +size: 50 32 + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%1 %/% +% D %%% +% . d D d h H % +% cd C. * * * * * % +% d .d.d d d d.d d h h.h h.h dD hh l % +%%c*D*a%c*C..%%.D.%.b.%K.D.i%.F.%.F.%.* *.%k*.*i%% +% b .b.b b.b b b b % f f f f f bb Ff j % +% cb C. % +% . % +% b % d %o%%%o%%% +% % . * %.a %.a % +% d% . Kd ..% Kd .% cgGc.%% b % b % +% * Gd . cd% cd% ccgk.%% b % b % +%Gd .... d . c. c. % b % b % +% dDb cc. % %A.*a %C.*a %%%%%%% b % b % +% %%baa %A *a %aa %aa dd % b % b % +% F %aa % baaa % baaa hd %EbE% b % +% F J J Hh % %EbE% +% % % dl %% % % +%2 c*.. % % o % +% %%%%%%%%%%%%% +% % +% % % % %%% %%% %%% % +% d d d % % % % % % %%%%% +% * %% *.%% * %% %%% %% %%%.%% %%% %% %DD % +% g.D..% K.D..% K.D. % g.B..% K.B..% K.B. % %DD % +% %b%% %b%% %b%% *b%% *b%% *b%% %hD % +% F j b bF bj bb %HD % +% J J *. % +% %ooo% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/levels/regression/enigma-regression.chroma b/levels/regression/enigma-regression.chroma new file mode 100644 index 0000000..a385766 --- /dev/null +++ b/levels/regression/enigma-regression.chroma @@ -0,0 +1,68 @@ +# Copyright (C) 2010 Amf +# +# Regression tests for Enigma +# +# Expected result: +# +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# % % +# % v v % +# % >v< >v< >v^v< >v^v< % +# % >^< >^< ^ ^ ^ ^ % +# % >< >< % +# % % +# % % +# % >< >< % +# % >v< >v< % +# % >< >< E % +# % ^ ^ % +# % % +# % >vvv< >vvv< % +# % >v< >v< ^^^ ^^^ % +# % >< >< % +# % >< >< % +# % ^ ^ v v % +# % v>v< v>v< % +# % ^^^ ^^^ % +# % >v< >v< % +# % >< >< v v % +# % >< >< >vv + diff --git a/levels/regression/xor-regression.chroma b/levels/regression/xor-regression.chroma new file mode 100644 index 0000000..7b4363c --- /dev/null +++ b/levels/regression/xor-regression.chroma @@ -0,0 +1,134 @@ +# Copyright (C) 2010 Amf +# +# Regression tests for XOR +# +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# % (9) % (7) %%% +# %HHHHHH% % F$ |VC% +# %HHHHHH% % FT$ %%% +# %HHHHHH% % -$C %%% +# %HHHHHH% F (8) % $T$ %%% +# %HHHHHH% $% % %$ |VC% +# %HHHHHH% %E$C % %% %%%%% +# %HHHHHH% %% (6) F % +# %HHHHHH% F H H F % +# %HHHHHH% F F %$V $C $V $ % +# %HHHHHH%%C %$C % F F % +# %HHHHHH% (1) %F%F %H%C % +# %HHHHHH% F %C%%C %%%% % +# %HHHHHH%FC $C %C%V $CC FFFC % +# %HHHHHH%% % %C%%C (3) %%%% % +# %HHHHHH% % +# %HHHHHH% MMMM %F FFF F % +# %HHHHHH% (2) %F -H-$CC F % +# %HHHHHH%-H$CC % %$ %%% (4) $ % +# %HHHHHH%%%%%% % %V F %FC%|C % +# %HHHHHH%C %F%- FFC %C %VC % +# %HHHHHH%%%%%% %%%% %%% %C %|C % +# %HHHHHH% % +# %HHHHHH% %F %FF F FFF % +# %HHHHHH% %$ %V-$C $ -H-$C% +# %HHHHHH% C%|C %%%%% %C%|C %%% % +# %HHHHHH% %HC % F %C%VC FFF % +# %HHHHHH%%%%%% %%%%% %C%|C %%% % +# %HHHHHH (5) (5) % +# %HHHHHH$C % +# %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +# +# Key: +# F Fish H H-Bomb - Dots $ Mask T Teleport +# C Chicken V V-Bomb | Waves M Map % Wall +# +# XOR has some subtleties that are easily overlooked. In particular: +# +# (1) Precedence depends on which way the player leaves the space. +# (approximate engine ok; exact engine ok) +# +# (2) When a stream of pieces hits a bomb, only the first should be destroyed. +# (approximate engine ok; exact engine ok) +# +# (3) Precendence after an explosion depends on the bomb that produced it. +# (approximate engine ok; exact engine ok) +# +# (4) Spaces vacated by explosions are added to the end of the move stack. +# (approximate engine fails; exact engine ok) +# +# (5) When a fish detonates an H-bomb, a chicken may erroneously be left +# hanging in mid-air. The other combinations of detonation are as expected. +# (approximate engine fails; exact engine ok) +# +# This omission does not seem to affect any of the original levels. +# +# (6) If a space in the move stack has a bomb and a detonator that can both +# fall into it, the bomb will be detonated, contrary to expectations. If +# two bombs are involved, the bomb that moves first detonates; this +# depends on how the space was vacated. +# (approximate engine fails; exact engine ok) +# +# This phenomenon may be seen at the start of "Patience Pending", and +# may be exploited to good effect near its end. +# +# (7) When considering how to exit a teleport, the spaces around it are +# considered in the following order: right, up, left, down. If the only +# exit from a teleport is the square the player is currently on, no move +# is made. If the player attempts to enter a teleport when its companion +# has been destroyed, the teleport is converted into a wall. +# (approximate engine fails to convert the teleport to a wall, but is +# otherwise fine; exact engine ok) +# +# (8) It is sufficient for a player to enter the door to finish the level - +# evolution of the level stops at that point, even if the player would +# otherwise be killed. +# (approximate engine marks the level as solved, but continues to +# evolve it; exact engine ok) +# +# (9) It is possible to overflow the move stack if it contains more than 127 +# entries, causing it to behave unpredictably. A wraparound effect occurs +# when there are 256 entries, causing all motion to cease. +# (neither engine attempts to handle such a pathological case!) + +chroma level + +mode: xor + +title: XOR regression tests +size: 32 32 +view1: 7 15 +view2: 9 15 +viewteleport1: 22 0 (25 3) +viewteleport2: 22 0 (25 5) + +data: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% % %%% +%DDDDDD% % d* |Aa% +%DDDDDD% % dT* %%% +%DDDDDD% % -*a %%% +%DDDDDD% d % *T* %%% +%DDDDDD% *% % %* |Aa% +%DDDDDD% %/*a % %% %%%%% +%DDDDDD% %% d % +%DDDDDD% d D D d % +%DDDDDD% d d %*A *a *A * % +%DDDDDD%%a %*a % d d % +%DDDDDD% %d%d %D%a % +%DDDDDD% d %a%%a %%%% % +%DDDDDD%da *a %a%A *aa ddda % +%DDDDDD%% % %a%%a %%%% % +%DDDDDD% % +%DDDDDD% 1MmNn2 %d ddd d % +%DDDDDD% %d -D-*aa d % +%DDDDDD%-D*aa % %* %%% * % +%DDDDDD%%%%%% % %A d %da%|a % +%DDDDDD%a %d%- dda %a %Aa % +%DDDDDD%%%%%% %%%% %%% %a %|a % +%DDDDDD% % +%DDDDDD% %d %dd d ddd % +%DDDDDD% %* %A-*a * -D-*a% +%DDDDDD% a%|a %%%%% %a%|a %%% % +%DDDDDD% %Da % d %a%Aa ddd % +%DDDDDD%%%%%% %%%%% %a%|a %%% % +%DDDDDD % +%DDDDDD*a % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/locale/en_US/LC_MESSAGES/chroma.mo b/locale/en_US/LC_MESSAGES/chroma.mo new file mode 100644 index 0000000..30e0239 Binary files /dev/null and b/locale/en_US/LC_MESSAGES/chroma.mo differ diff --git a/main.c b/main.c new file mode 100644 index 0000000..c5577da --- /dev/null +++ b/main.c @@ -0,0 +1,527 @@ +/* + main.c + + Copyright (C) 2010-2019 Amf + + 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 +*/ + +#ifdef __WIN32__ +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chroma.h" +#include "level.h" +#include "menu.h" +#include "display.h" +#include "colours.h" +#include "util.h" + +void editor(); +void help(); +void export(struct level*, int); + +extern int options_xor_mode; +extern int options_xor_display; +struct level* plevelcurrent = NULL; + +#ifdef __WIN32__ +int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) +{ + main(0, NULL); +} +#endif + +int main(int argc, char **argv) +{ + struct menu* pmenu; + struct menuentry* pentryplay; + int result; + int ok; + char directory[FILENAME_MAX]; + + getfilename("locale", directory, 0, LOCATION_SYSTEM); + setlocale(LC_ALL, ""); + bindtextdomain("chroma", directory); + textdomain("chroma"); + + display_init(); + + pmenu = menu_new(gettext("Chroma")); + pmenu->logo = 1; + + pentryplay = menuentry_new(pmenu, gettext("Press any key to play"), MENU_KEY_ANY, MENU_CENTRE); + menuentry_new(pmenu, "", 0, MENU_SPACE); + menuentry_new(pmenu, gettext("How to Play"), 'H', 0); + menuentry_new(pmenu, gettext("Editor"), 'E', 0); + menuentry_new(pmenu, gettext("Display Options"), 'D', 0); + menuentry_new(pmenu, gettext("Quit"), 'Q', 0); + + ok = 0; + while(!ok) + { + pmenu->entry_selected = pentryplay; + result = menu_process(pmenu); + switch(result) + { + case MENU_SELECT: + switch(pmenu->entry_selected->key) + { + case MENU_KEY_ANY: + while(menu_levelselector(NULL, NULL, gettext("Choose a level"), LEVELMENU_MAIN | LEVELMENU_SAVED | LEVELMENU_SOLVED | LEVELMENU_GAME) != MENU_QUIT); + break; + + case 'H': + help(); + break; + + case 'E': + editor(); + break; + + case 'D': + display_options(); + break; + + case 'Q': + ok = 1; + break; + } + break; + + case MENU_QUIT: + ok = 1; + break; + + default: + break; + } + } + + exit(0); +} + +void level_play(struct level* plevelgame) +{ + struct menu* pmenu; + + struct menuentry* pentry; + struct level* plevelrevert; + struct level* plevelload; + struct level *plevelreplay; + + int result; + int quit; + int ok; + + char filename[FILENAME_MAX]; + char directory[FILENAME_MAX]; + char menutitle[256]; + + plevelrevert = level_copy(plevelgame); + plevelreplay = NULL; + + plevelcurrent = plevelgame; + + quit = 0; + + while(!quit) + { + display_play(plevelgame, plevelreplay); + + /* Has the replay finished? */ + if(plevelreplay != NULL && plevelreplay->move_current == NULL) + { + level_delete(plevelreplay); + plevelreplay = NULL; + } + + ok = 0; + while(!ok) + { + pmenu = menu_new(gettext("Game Options")); + + menuentry_new(pmenu, gettext("Return to Level"), 'Q', 0); + menuentry_new(pmenu, gettext("Abort Level and Return to Selection"), 'A', 0); + + if(plevelrevert->moves != plevelgame->moves) + menuentry_new(pmenu, gettext("Revert to Original Position"), 'V', 0); + else + { + pentry = menuentry_new(pmenu, gettext("Revert to Original Position"), 'V', MENU_GREY); + menuentry_extratext(pentry, gettext("(only after changes)"), NULL, NULL); + } + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + menuentry_new(pmenu, gettext("Load Position"), 'L', 0); + + if(plevelgame->mover_first == NULL) + { + + menuentry_new(pmenu, gettext("Save Position"), 'S', 0); + +/* + if(plevelgame->flags & LEVELFLAG_SOLVED) + menuentry_new(pmenu, gettext("Export Solution"), 'E', 0); +*/ + } + else + { + pentry = menuentry_new(pmenu, gettext("Save Position"), 'S', MENU_GREY); + menuentry_extratext(pentry, gettext("(not while pieces in motion)"), NULL, NULL); +/* + if(plevelgame->flags & LEVELFLAG_SOLVED) + { + pentry = menuentry_new(pmenu, gettext("Export Solution"), 'E', MENU_GREY); + menuentry_extratext(pentry, gettext("(not while pieces in motion)"), NULL, NULL); + } +*/ + } + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + if(plevelreplay == NULL) + { + if(plevelgame->moves == 0) + { + menuentry_new(pmenu, gettext("Replay Saved Position"), 'R', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + } + else + { + pentry = menuentry_new(pmenu, gettext("Replay Saved Position"), 'R', MENU_GREY); + menuentry_extratext(pentry, gettext("(only at start of a level)"), NULL, NULL); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + } + } + else + { + menuentry_new(pmenu, gettext("Stop Replaying Position"), 'T', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + } + + menuentry_new(pmenu, gettext("Display Options"), 'D', 0); + + menuentry_new(pmenu, gettext("Currently playing:"), 0, MENU_NOTE); + if(plevelgame->title == NULL || strcmp(plevelgame->title, "") == 0) + menuentry_new(pmenu, gettext("[untitled level]"), 0, MENU_NOTE | MENU_RIGHT); + else + menuentry_new(pmenu, gettext(plevelgame->title), 0, MENU_NOTE | MENU_RIGHT); + + result = menu_process(pmenu); + + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'Q': + ok =1; + break; + + case 'A': + ok = 1; quit = 1; + break; + + case 'S': + /* Are there pieces still in motion? */ + if(plevelgame->mover_first != NULL) + break; + + if(plevelgame->flags & LEVELFLAG_SOLVED && !(plevelgame->flags & LEVELFLAG_FAILED)) + { + getfilename("solved", directory, 1, LOCATION_LOCAL); + strcpy(menutitle, gettext("Save Solution")); + } + else + { + getfilename("saved", directory, 1, LOCATION_LOCAL); + strcpy(menutitle, gettext("Save Position")); + } + + if(menu_levelselector(directory, filename, menutitle, LEVELMENU_RETURN | LEVELMENU_NEW | LEVELMENU_DELETE | LEVELMENU_MOVES | LEVELMENU_FILTER) == MENU_SELECT) + { + if(strcmp(filename, "") == 0) + sprintf(filename, "%s/%x.chroma", directory, (int)time(NULL)); + level_save(plevelgame, filename, 0); + + level_delete(plevelrevert); + plevelrevert = level_copy(plevelgame); + ok = 1; + } + break; + + case 'L': + getfilename("saved", directory, 0, LOCATION_LOCAL); + if(menu_levelselector(directory, filename, gettext("Load Position"), LEVELMENU_RETURN | LEVELMENU_DELETE | LEVELMENU_MOVES | LEVELMENU_FILTER) == MENU_SELECT) + { + plevelload = level_load(filename, 0); + if(plevelload != NULL) + { + if(plevelreplay != NULL) + { + level_delete(plevelreplay); + plevelreplay = NULL; + } + level_delete(plevelgame); + level_delete(plevelrevert); + + plevelrevert = plevelload; + plevelgame = level_copy(plevelrevert); + plevelcurrent = plevelgame; + ok = 1; + } + } + break; + + case 'E': + /* Are there pieces still in motion? */ + if(plevelgame->mover_first != NULL) + break; + export(plevelgame, 1); + break; + + case 'V': + if(plevelreplay != NULL) + { + level_delete(plevelreplay); + plevelreplay = NULL; + } + level_delete(plevelgame); + plevelgame = level_copy(plevelrevert); + plevelcurrent = plevelgame; + ok = 1; + break; + + case 'R': + getfilename("saved", directory, 0, LOCATION_LOCAL); + if(menu_levelselector(directory, filename, gettext("Replay Saved Position"), LEVELMENU_RETURN | LEVELMENU_DELETE | LEVELMENU_MOVES | LEVELMENU_SOLVED | LEVELMENU_FILTER) == MENU_SELECT) + { + plevelreplay = level_load(filename, 0); + plevelreplay->move_current = plevelreplay->move_first; + ok = 1; + } + break; + + case 'T': + level_delete(plevelreplay); + plevelreplay = NULL; + break; + + case 'D': + display_options(); + break; + } + } + } + + menu_delete(pmenu); + } + + if(plevelrevert != NULL) + level_delete(plevelrevert); + if(plevelreplay != NULL) + level_delete(plevelreplay); + if(plevelgame != NULL) + level_delete(plevelgame); + + plevelcurrent = NULL; +} + +void help() +{ + struct menu* pmenu; + char directory[FILENAME_MAX]; + char filename[FILENAME_MAX]; + char buffer[FILENAME_MAX]; + char *locale; + int ok; + int i; + + pmenu = menu_new(gettext("How to Play")); + + menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(pmenu, gettext("Use [UP] and [DOWN] to scroll"), 0, MENU_NOTE | MENU_CENTRE); + menuentry_new(pmenu, "", 0, MENU_TEXT); + + getfilename("help/README", directory, 0, LOCATION_SYSTEM); + + locale = setlocale(LC_MESSAGES, NULL); + + /* Given a locale of, say, en_GB.UTF-8, try help/README.en_GB.UTF-8, then + help/README.en_GB and finally help/README.en before defaulting to just + help/README - if we can't get even that, generate an error. */ + ok = 0; + if(locale != NULL) + { + i = 0; + while(locale[i] != 0 && locale[i] != '/') + { + buffer[i] = locale[i]; i ++; + } + buffer[i] = 0; + sprintf(filename, "%s.%s", directory, buffer); + + if(menu_addfile(pmenu, filename)) + ok = 1; + } + else + ok = 2; + if(ok == 0) + { + i = 0; + while(locale[i] != 0 && locale[i] != '/' && locale[i] != '.') + { + buffer[i] = locale[i]; i ++; + } + buffer[i] = 0; + sprintf(filename, "%s.%s", directory, buffer); + + if(menu_addfile(pmenu, filename)) + ok = 1; + } + if(ok == 0) + { + i = 0; + while(locale[i] != 0 && locale[i] != '/' && locale[i] != '.' && locale[i] != '_') + { + buffer[i] = locale[i]; i ++; + } + buffer[i] = 0; + sprintf(filename, "%s.%s", directory, buffer); + + if(menu_addfile(pmenu, filename)) + ok = 1; + } + if(ok != 1) + { + strcpy(filename, directory); + if(!menu_addfile(pmenu, filename)) + menuentry_new(pmenu, "Unable to read help file!", 0, MENU_GREY | MENU_CENTRE); + } + + menu_process(pmenu); + +} + +void export(struct level* plevel, int solution) +{ + struct menu *pmenu; + struct menuentry *pentry_filename; + char filename[FILENAME_MAX]; + int ok, result; + int i, j; + + if(!solution) + pmenu = menu_new(gettext("Export Level")); + else + pmenu = menu_new(gettext("Export Solution")); + + menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentry_filename = menuentry_new(pmenu, gettext("Filename"), 'I', MENU_DOUBLE | MENU_EDITABLE); + if(solution) + { + if(plevel->title != NULL && sscanf(plevel->title, "chroma %d.%d", &i, &j) == 2) + sprintf(filename, "solution-%d-%02d", i, j); + else + strcpy(filename, "solution"); + } + else + { + if(plevel->title != NULL) + strcpy(filename, plevel->title); + else + strcpy(filename, "level"); + } + + menuentry_extratext(pentry_filename, NULL, NULL, filename); + + if(!solution) + menuentry_new(pmenu, gettext("Export level"), 'E', 0); + else + menuentry_new(pmenu, gettext("Export solution"), 'E', 0); + +#ifdef __WIN32__ + if(!solution) + menuentry_new(pmenu, gettext("Exported levels are saved in \"My Documents\""), 0, MENU_NOTE | MENU_CENTRE); + else + menuentry_new(pmenu, gettext("Exported solutions are saved in \"My Documents\""), 0, MENU_NOTE | MENU_CENTRE); +#else + if(!solution) + menuentry_new(pmenu, gettext("Exported levels are saved in your home directory"), 0, MENU_NOTE | MENU_CENTRE); + else + menuentry_new(pmenu, gettext("Exported solutions are saved in your home directory"), 0, MENU_NOTE | MENU_CENTRE); +#endif + + ok = 0; + while(!ok) + { + result = menu_process(pmenu); + + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'E': + getfilename("", filename, 0, LOCATION_DOCUMENTS); + i = 0; + j = strlen(filename); + while(pentry_filename->text4[i] != 0) + { + if(pentry_filename->text4[i] != '/' && pentry_filename->text4[i] != '\\') + filename[j ++] = pentry_filename->text4[i ++]; + } + filename[j ++] = 0; + if(!(strlen(filename) > 7 && strcmp(filename + strlen(filename) - 7, ".chroma") == 0)) + strcat(filename, ".chroma"); + + level_save(plevel, filename, 1); +#ifndef __WIN32__ + if(solution) + chmod(filename, 00600); +#endif + + ok = 1; + break; + + case 'Q': + ok = 1; + break; + } + } + } + + menu_delete(pmenu); +} diff --git a/menu.c b/menu.c new file mode 100644 index 0000000..cb491f5 --- /dev/null +++ b/menu.c @@ -0,0 +1,808 @@ +/* + menu.c + + Copyright (C) 2010-2019 Amf + + 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chroma.h" +#include "menu.h" +#include "level.h" +#include "util.h" +#include "xmlparser.h" + +int menu_levelentries(struct menu* pmenu, char *directory, int flags); +void level_play(struct level* plevelgame); + +extern struct level* plevelcurrent; + +extern int options_debug; +#ifdef XOR_COMPATIBILITY +extern int options_xor_options; +#endif +#ifdef ENIGMA_COMPATIBILITY +extern int options_enigma_options; +#endif + +struct menu *menu_new(char *title) +{ + struct menu* pmenu; + + pmenu = (struct menu*)malloc(sizeof(struct menu)); + + if(pmenu == NULL) + fatal(gettext("Out of memory in menu_new()")); + + pmenu->title = (char *)malloc(strlen(title) + 1); + + if(pmenu->title == NULL) + fatal(gettext("Out of memory in menu_new()")); + + strcpy(pmenu->title, title); + + pmenu->entry_first = NULL; + pmenu->entry_last = NULL; + pmenu->entry_selected = NULL; + pmenu->display_first = NULL; + pmenu->display_last = NULL; + pmenu->offset = 0; + pmenu->redraw = MENUREDRAW_ALL; + pmenu->logo = 0; + + return pmenu; +} + +void menu_delete(struct menu *pmenu) +{ + struct menuentry *pentry; + struct menuentry *pentrytmp; + + pentry = pmenu->entry_first; + + while(pentry != NULL) + { + pentrytmp = pentry; + pentry = pentry->next; + + if(pentrytmp->text != NULL) + free(pentrytmp->text); + if(pentrytmp->text2 != NULL) + free(pentrytmp->text2); + if(pentrytmp->text3 != NULL) + free(pentrytmp->text3); + if(pentrytmp->text4 != NULL) + free(pentrytmp->text4); + if(pentrytmp->value != NULL) + free(pentrytmp->value); + + free(pentrytmp); + } + + if(pmenu->title != NULL) + free(pmenu->title); + + free(pmenu); +} + +void menu_unsort(struct menu *pmenu) +{ + struct menuentry* pentry; + + if(pmenu == NULL) + return; + + pentry = pmenu->entry_first; + while(pentry != NULL) + { + pentry->flags &= ~(MENU_SORT | MENU_TOPSORT); + pentry = pentry->next; + } +} + +void menu_assignletters(struct menu *pmenu) +{ + struct menuentry* pentry; + struct menuentry* pentry_before; + char c; + + if(pmenu == NULL) + return; + + c = '1'; + + pentry = pmenu->entry_first; + while(pentry != NULL) + { + if(pentry->key == 0 && !(pentry->flags & (MENU_GREY | MENU_NOTE | MENU_SPACE))) + { + pentry_before = pmenu->entry_first; + while(pentry_before != NULL && pentry_before != pentry) + { + if(pentry_before->key == c) + { + c ++; + + /* Valid keys are 1-9 A-P R-Z. Q is deliberately omitted. */ + if(c == '9' + 1) + c = 'A'; + if(c == 'Q') + c ++; + if(c == 'Z' + 1) + return; + + pentry_before = pmenu->entry_first; + } + else + pentry_before = pentry_before ->next; + } + pentry->key = c; + } + pentry = pentry->next; + } +} + +struct menuentry* menuentry_new(struct menu *pmenu, char *text, char key, int flags) +{ + return menuentry_newwithvalue(pmenu, text, key, flags, NULL); +} + +struct menuentry* menuentry_newwithvalue(struct menu *pmenu, char *text, char key, int flags, char *value) +{ + struct menuentry* pentry; + struct menuentry* pentry_before; + + pentry = (struct menuentry*)malloc(sizeof(struct menuentry)); + + if(pentry == NULL) + fatal(gettext("Out of memory in menuentry_newwithvalue()")); + + if(flags & MENU_SORT) + { + pentry_before = pmenu->entry_first; + while(pentry_before != NULL) + { + if((pentry_before->flags & MENU_SORT) && (!(pentry_before->flags & MENU_TOPSORT)) && pentry_before->value != NULL) + { + if(strcmp(pentry_before->value, value) > 0) + break; + } + pentry_before = pentry_before->next; + } + } + else if(flags & MENU_TOPSORT) + { + pentry_before = pmenu->entry_first; + while(pentry_before != NULL) + { + if((pentry_before->flags & MENU_TOPSORT) && pentry_before->value != NULL) + { + if(strcmp(pentry_before->value, value) > 0) + break; + } + + if(pentry_before->flags & MENU_SORT && !(pentry_before->flags & MENU_TOPSORT)) + break; + + pentry_before = pentry_before->next; + } + } + else + pentry_before = NULL; + + /* If pentry_before is NULL, we add to the bottom of the list. + Otherwise, we add before pentry_before. + */ + if(pentry_before == NULL) + { + if(pmenu->entry_first == NULL) + pmenu->entry_first = pentry; + + pentry->previous = pmenu->entry_last; + pentry->next = NULL; + + if(pmenu->entry_last != NULL) + pmenu->entry_last->next = pentry; + + pmenu->entry_last = pentry; + } + else + { + if(pentry_before == pmenu->entry_first) + pmenu->entry_first = pentry; + pentry->previous = pentry_before->previous; + pentry->next = pentry_before; + if(pentry_before->previous != NULL) + pentry_before->previous->next = pentry; + pentry_before->previous = pentry; + } + + pentry->text = (char *)malloc(strlen(text) + 1); + + if(pentry->text == NULL) + fatal(gettext("Out of memory in menuentry_newwithvalue()")); + + strcpy(pentry->text, text); + + pentry->redraw = 0; + + pentry->flags = flags; + + pentry->key = key; + + pentry->value = NULL; + if(value != NULL) + { + pentry->value = (char *)malloc(strlen(value) + 1); + + if(pentry->value == NULL) + fatal(gettext("Out of memory in menuentry_newwithvalue()")); + + strcpy(pentry->value, value); + } + + pentry->text2 = NULL; + pentry->text3 = NULL; + pentry->text4 = NULL; + + return pentry; +} + +void menuentry_value(struct menuentry* pentry, char *value) +{ + if(pentry->value != NULL) + free(pentry->value); + + pentry->value = (char *)malloc(strlen(value) + 1); + + if(pentry->value == NULL) + fatal(gettext("Out of memory in menuentry_value()")); + + strcpy(pentry->value, value); +} + +void menuentry_text(struct menuentry* pentry, char *text) +{ + if(pentry->text != NULL) + free(pentry->text); + + pentry->text = (char *)malloc(strlen(text) + 1); + + if(pentry->text == NULL) + fatal(gettext("Out of memory in menuentry_text()")); + + strcpy(pentry->text, text); +} + +void menuentry_extratext(struct menuentry* pentry, char *text2, char *text3, char *text4) +{ + if(pentry->text2 != NULL) + free(pentry->text2); + if(pentry->text3 != NULL) + free(pentry->text3); + if(pentry->text4 != NULL) + free(pentry->text4); + + if(text2 != NULL) + { + pentry->text2 = (char *)malloc(strlen(text2) + 1); + if(pentry->text2 == NULL) + fatal(gettext("Out of memory in menuentry_extratext()")); + + strcpy(pentry->text2, text2); + } + else + pentry->text2 = NULL; + + if(text3 != NULL) + { + pentry->text3 = (char *)malloc(strlen(text3) + 1); + if(pentry->text3 == NULL) + fatal(gettext("Out of memory in menuentry_extratext()")); + + strcpy(pentry->text3, text3); + } + else + pentry->text3 = NULL; + + if(text4 != NULL) + { + pentry->text4 = (char *)malloc(strlen(text4) + 1); + if(pentry->text4 == NULL) + fatal(gettext("Out of memory in menuentry_extratext()")); + + strcpy(pentry->text4, text4); + } + else + pentry->text4 = NULL; +} + +void menuentry_delete(struct menu* pmenu, struct menuentry* pentry) +{ + struct menuentry* pentry_replace; + + pentry_replace = pentry->next; + if(pentry_replace == NULL) + pentry_replace = pentry->previous; + + if(pmenu->entry_first == pentry) + pmenu->entry_first = pentry_replace; + if(pmenu->display_first == pentry) + pmenu->display_first = pentry_replace; + if(pmenu->entry_last == pentry) + pmenu->entry_last = pentry_replace; + if(pmenu->entry_selected == pentry) + pmenu->entry_selected = pentry_replace; + if(pentry->previous != NULL) + pentry->previous->next = pentry->next; + if(pentry->next != NULL) + pentry->next->previous = pentry->previous; + + if(pentry->text != NULL) + free(pentry->text); + if(pentry->text2 != NULL) + free(pentry->text2); + if(pentry->text3 != NULL) + free(pentry->text3); + if(pentry->text4 != NULL) + free(pentry->text4); + if(pentry->value != NULL) + free(pentry->value); + + free(pentry); +} + +int menu_levelselector(char *directory_levels, char *chosen, char *title, int flags) +{ + struct menu* pmenu; + struct level* plevel; + int flags_child; + int result; + char directory[FILENAME_MAX]; + + pmenu = menu_new(title); + + if(flags & LEVELMENU_RETURN) + menuentry_new(pmenu, gettext("Return to previous menu"), 'Q', 0); + + if(flags & LEVELMENU_NEW) + menuentry_new(pmenu, gettext("Save as new position"), 'S', 0); + + if(flags & LEVELMENU_CREATE) + menuentry_new(pmenu, gettext("Create new level"), 'C', 0); + + if(flags & LEVELMENU_IMPORT) + { + getfilename("", directory, 0, LOCATION_DOCUMENTS); + if(isdirectory(directory)) + menuentry_newwithvalue(pmenu, gettext("Import a position"), 'I', 0, directory); + } + + if(flags & LEVELMENU_SAVED) + { + getfilename("saved", directory, 0, LOCATION_LOCAL); + if(isdirectory(directory)) + menuentry_newwithvalue(pmenu, gettext("Saved Positions"), 'S', MENU_BOLD, directory); + } + + if(flags & LEVELMENU_SOLVED) + { + getfilename("solved", directory, 0, LOCATION_LOCAL); + if(isdirectory(directory)) + menuentry_newwithvalue(pmenu, gettext("Solved Positions"), 'O', MENU_BOLD, directory); + } + + if(flags & LEVELMENU_MAIN) + { + getfilename("construct", directory, 0, LOCATION_LOCAL); + if(isdirectory(directory)) + menuentry_newwithvalue(pmenu, gettext("Levels under Construction"), 'C', MENU_BOLD, directory); + } + + /* Separator only if needed */ + if(pmenu->entry_first != NULL) + menuentry_new(pmenu, "", 0, MENU_TOPSORT | MENU_SPACE); + + if(flags & LEVELMENU_DELETE) + menuentry_new(pmenu, gettext("[DELETE] to delete a position"), 0, MENU_NOTE | MENU_CENTRE); + + if(flags & LEVELMENU_MAIN) + { + getfilename("levels", directory, 0, LOCATION_SYSTEM); + if(menu_levelentries(pmenu, directory, flags)) + menuentry_newwithvalue(pmenu, "", 0, MENU_SORT | MENU_SPACE, ""); + + menu_unsort(pmenu); + + /* Separator only if needed */ + if(pmenu->entry_last != NULL && !(pmenu->entry_last->flags & MENU_SPACE)) + menuentry_newwithvalue(pmenu, "", 0, MENU_SPACE, ""); + + getfilename("levels", directory, 0, LOCATION_LOCAL); + if(menu_levelentries(pmenu, directory, flags)) + menuentry_newwithvalue(pmenu, "", 0, MENU_SORT | MENU_SPACE, ""); + } + else + { + if(menu_levelentries(pmenu, directory_levels, flags)) + menuentry_newwithvalue(pmenu, "", 0, MENU_SORT | MENU_SPACE, ""); + } + + menu_assignletters(pmenu); + + while(1) + { + result = menu_process(pmenu); + + if(result == MENU_QUIT) + { + if(chosen != NULL) + strcpy(chosen, ""); + break; + } + + if(result == MENU_SELECT) + { + if(pmenu->entry_selected->key == '+' && flags & LEVELMENU_FILTER) + { + result = menu_levelselector(directory_levels, chosen, title, flags & ~LEVELMENU_FILTER); + if(result == MENU_SELECT) + break; + } + else if(pmenu->entry_selected->value != NULL) + { + if(isfile(pmenu->entry_selected->value)) + { + if(flags & LEVELMENU_GAME) + { + plevel = level_load(pmenu->entry_selected->value, 0); + if(plevel != NULL) + level_play(plevel); + /* plevel is deleted by level_play */ + } + else + { + if(chosen != NULL) + strcpy(chosen, pmenu->entry_selected->value); + break; + } + } + else if(isdirectory(pmenu->entry_selected->value)) + { + flags_child = flags & (LEVELMENU_NEW | LEVELMENU_DELETE | LEVELMENU_FILENAMES | LEVELMENU_MOVES | LEVELMENU_GAME | LEVELMENU_FILTER); + flags_child |= LEVELMENU_RETURN; + + /* Fix flags for "saved", "solved" and "construct" */ + if(pmenu->entry_selected->key == 'S') + flags_child |= LEVELMENU_MOVES | LEVELMENU_DELETE; + if(pmenu->entry_selected->key == 'C') + flags_child |= LEVELMENU_MOVES | LEVELMENU_DELETE; + if(pmenu->entry_selected->key == 'O') + flags_child |= LEVELMENU_MOVES | LEVELMENU_DELETE; + + result = menu_levelselector(pmenu->entry_selected->value, chosen, pmenu->entry_selected->text, flags_child); + + if(result == MENU_SELECT) + break; + + result = MENU_NULL; + } + } + else + { + if(chosen != NULL) + strcpy(chosen, ""); + + if(pmenu->entry_selected->key == 'Q') + result = MENU_QUIT; + + break; + } + } + + if(result == MENU_DELETE) + { + if(pmenu->entry_selected->value != NULL) + unlink(pmenu->entry_selected->value); + menuentry_delete(pmenu, pmenu->entry_selected); + } + } + + menu_delete(pmenu); + + return result; +} + +int menu_levelentries(struct menu* pmenu, char *directory, int flags) +{ + DIR *pdir; + struct dirent *dentry; + struct menuentry* pentry; + struct level* plevel; + struct stat filestat; + int flags_child; + int submenus; + int subfiles; + int state; + int hidden; + int filtered; + + char text_date[256]; + char text_moves[256]; + char text_stars[256]; + char *text_title; + char *text_subtitle; + + char filename[FILENAME_MAX]; + char titlefilename[FILENAME_MAX]; + + struct parser* pparser; + + submenus = 0; + subfiles = 0; + filtered = 0; + + pdir = opendir(directory); + + if(pdir == NULL) + return 0; + + while((dentry = readdir(pdir)) != NULL) + { + if(strcmp(dentry->d_name, ".") == 0) + continue; + if(strcmp(dentry->d_name, "..") == 0) + continue; + + if(dentry->d_name[0] == '.') + continue; + + sprintf(filename, "%s%s%s", directory, "/", dentry->d_name); + + if(isfile(filename) && strlen(filename) > 7 && strcmp(filename + strlen(filename) - 7, ".chroma") == 0) + { + plevel = level_load(filename, 1); + + if(plevel != NULL) + { + flags_child = MENU_SORT; + if(flags & (LEVELMENU_MOVES | LEVELMENU_FILENAMES)) + flags_child |= MENU_DOUBLE; + if(flags & LEVELMENU_DELETE) + flags_child |= MENU_DELETABLE; + + if(plevel->title == NULL || strcmp(plevel->title, "") == 0) + pentry = menuentry_newwithvalue(pmenu, gettext("[untitled level]"), 0, flags_child, filename); + else + { + if(strncmp(plevel->title, "chroma", 6) == 0) + pentry = menuentry_newwithvalue(pmenu, gettext(plevel->title), 0, flags_child, filename); + else + pentry = menuentry_newwithvalue(pmenu, plevel->title, 0, flags_child, filename); + } + + if(plevel->stars_exploded) + sprintf(text_stars, gettext("%d lost"), plevel->stars_exploded); + else + sprintf(text_stars, "%d / %d", plevel->stars_caught, plevel->stars_total); + if(plevel->flags & LEVELFLAG_SOLVED && !(plevel->flags & LEVELFLAG_FAILED)) + sprintf(text_stars, gettext("solved")); + + if(plevel->flags & LEVELFLAG_FAILED) + sprintf(text_moves, gettext("failed")); + else + sprintf(text_moves, gettext("%d moves"), plevel->moves); + + if(!stat(filename, &filestat)) + { + sprintf(text_date, "%s", ctime(&filestat.st_mtime)); + if(strlen(text_date) > 0) + text_date[strlen(text_date) - 1] = 0; + } + else + strcpy(text_date, ""); + + if(flags & LEVELMENU_FILENAMES) + menuentry_extratext(pentry, NULL, text_date, dentry->d_name); + else if(flags & LEVELMENU_MOVES) + menuentry_extratext(pentry, text_stars, text_date, text_moves); + else + { + /* Not really needed except for development */ + if(plevel->flags & LEVELFLAG_SOLVED && !(plevel->flags & LEVELFLAG_FAILED)) + menuentry_extratext(pentry, gettext("solved"), NULL, NULL); + } + + if((flags & LEVELMENU_FILTER) && plevelcurrent != NULL) + { + if((plevelcurrent->title != NULL && strcmp(plevelcurrent->title, pentry->text) != 0) + || (plevelcurrent->title == NULL && plevel->title != NULL)) + { + filtered ++; + menuentry_delete(pmenu, pentry); + continue; + } + } + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + options_xor_options = 1; +#endif +#ifdef ENIGMA_COMPATIBILITY + if(plevel->mode == MODE_ENIGMA) + options_enigma_options = 1; +#endif + subfiles ++; + } + + level_delete(plevel); + } + else if(isdirectory(filename)) + { + flags_child = MENU_TOPSORT | MENU_BOLD; + if(flags & (LEVELMENU_MOVES | LEVELMENU_FILENAMES)) + flags_child |= MENU_DOUBLE; + + /* Read the title information from set.chroma, if it exists */ + snprintf(titlefilename, FILENAME_MAX, "%s/%s", filename, "set.chroma"); + text_title = NULL; + text_subtitle = NULL; + + hidden = 0; + + pparser = parser_new(titlefilename); + + enum { + LEVELSETPARSER_END, + LEVELSETPARSER_OUTSIDE, + LEVELSETPARSER_CHROMA + }; + + state = LEVELSETPARSER_OUTSIDE; + + while(state != LEVELSETPARSER_END) + { + switch(parser_parse(pparser)) + { + case PARSER_END: + state = LEVELSETPARSER_END; + break; + + case PARSER_ELEMENT_START: + break; + + case PARSER_ELEMENT_END: + switch(state) + { + case LEVELSETPARSER_CHROMA: + /* We only read the file's header here */ + if(parser_match(pparser, 0, "head")) + state = LEVELSETPARSER_END; + break; + } + break; + + case PARSER_CONTENT: + switch(state) + { + case LEVELSETPARSER_CHROMA: + if(parser_match(pparser, 1, "title")) + { + text_title = malloc(strlen(parser_text(pparser, 0)) + 1); + if(text_title == NULL) + fatal(gettext("Out of memory in menu_levelentries()")); + strcpy(text_title, parser_text(pparser, 0)); + } + if(parser_match(pparser, 1, "subtitle")) + { + text_subtitle = malloc(strlen(parser_text(pparser, 0)) + 1); + if(text_title == NULL) + fatal(gettext("Out of memory in menu_levelentries()")); + strcpy(text_subtitle, parser_text(pparser, 0)); + } + break; + } + break; + + case PARSER_ATTRIBUTE: + switch(state) + { + case LEVELSETPARSER_OUTSIDE: + if(parser_match(pparser, 2, "chroma") && parser_match(pparser, 1, "type")) + { + if(parser_match(pparser, 0, "set")) + state = LEVELSETPARSER_CHROMA; + } + break; + + case LEVELSETPARSER_CHROMA: + if(parser_match(pparser, 2, "chroma") && parser_match(pparser, 1, "hidden")) + { + if(parser_match(pparser, 0, "yes")) + hidden = 1; + } + break; + } + break; + + case PARSER_ERROR: + state = LEVELSETPARSER_END; + break; + } + } + + parser_delete(pparser); + + if(!hidden || options_debug & DEBUG_HIDDEN) + { + if(text_title != NULL) + { + if(strncmp(text_title, "chroma", 6) == 0) + pentry = menuentry_newwithvalue(pmenu, gettext(text_title), 0, flags_child | (text_subtitle != NULL ? MENU_DOUBLE : 0), filename); + else + pentry = menuentry_newwithvalue(pmenu, text_title, 0, flags_child | (text_subtitle != NULL ? MENU_DOUBLE : 0), filename); + + } + else + pentry = menuentry_newwithvalue(pmenu, dentry->d_name, 0, flags_child, filename); + + if(flags & LEVELMENU_FILENAMES) + menuentry_extratext(pentry, NULL, NULL, dentry->d_name); + else + { + if(text_title != NULL && strncmp(text_title, "chroma", 6) == 0) + menuentry_extratext(pentry, NULL, NULL, gettext(text_subtitle)); + else + menuentry_extratext(pentry, NULL, NULL, text_subtitle); + } + if(text_title != NULL) + free(text_title); + if(text_subtitle != NULL) + free(text_subtitle); + + submenus ++; + } + } + } + + closedir(pdir); + + if(filtered != 0) + { + if(submenus != 0 || subfiles != 0) + menuentry_new(pmenu, "", 0, MENU_SPACE); + pentry = menuentry_new(pmenu, gettext("Show positions for other levels"), '+', 0); + sprintf(text_date, filtered == 1 ? gettext("(%d other)") : gettext("(%d others)"), filtered); + menuentry_extratext(pentry, text_date, NULL, NULL); + } + + if(submenus !=0 && subfiles != 0) + return 1; + else + return 0; + +} + diff --git a/menu.h b/menu.h new file mode 100644 index 0000000..81ab4f6 --- /dev/null +++ b/menu.h @@ -0,0 +1,110 @@ +/* + menu.h + + Copyright (C) 2010-2019 Amf + + 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 MENU_GREY 1 +#define MENU_NOTE 2 +#define MENU_RIGHT 4 +#define MENU_CENTRE 8 +#define MENU_DOUBLE 16 +#define MENU_SORT 32 +#define MENU_TOPSORT 64 +#define MENU_DELETABLE 128 +#define MENU_BOLD 256 +#define MENU_INVISIBLE 512 +#define MENU_SCROLLABLE 1024 +#define MENU_EDITABLE 2048 +#define MENU_EDITING 4096 +#define MENU_SPACE 8192 +#define MENU_TEXT 16384 + +#define MENU_NULL 0 +#define MENU_QUIT 1 +#define MENU_SELECT 2 +#define MENU_DELETE 3 +#define MENU_SCROLLLEFT 4 +#define MENU_SCROLLRIGHT 5 +#define MENU_RESIZE 6 + +#define LEVELMENU_RETURN 1 +#define LEVELMENU_NEW 2 +#define LEVELMENU_FILENAMES 4 +#define LEVELMENU_DELETE 8 +#define LEVELMENU_MAIN 16 +#define LEVELMENU_MOVES 32 +#define LEVELMENU_SAVED 64 +#define LEVELMENU_SOLVED 128 +#define LEVELMENU_CREATE 256 +#define LEVELMENU_GAME 512 +#define LEVELMENU_IMPORT 1024 +#define LEVELMENU_FILTER 2048 + +#define MENU_KEY_ANY 1 + +enum { + MENUREDRAW_NONE, + MENUREDRAW_CHANGED, + MENUREDRAW_ENTRIES, + MENUREDRAW_ALL, +}; + +struct menuentry +{ + struct menuentry *next; + struct menuentry *previous; + char *text; + char *text2; + char *text3; + char *text4; + char *value; + int redraw; + int flags; + char key; +}; + +struct menu +{ + char *title; + struct menuentry *entry_first; + struct menuentry *entry_last; + struct menuentry *entry_selected; + struct menuentry *display_first; + struct menuentry *display_last; + int offset; + int redraw; + int logo; +}; + +/* menu.c */ +struct menu *menu_new(char *); +struct menuentry *menuentry_new(struct menu *, char *, char, int); +struct menuentry *menuentry_newwithvalue(struct menu *, char *, char, int, char *); +void menu_delete(struct menu *); +void menu_unsort(struct menu *); +void menu_assignletters(struct menu *); +void menuentry_text(struct menuentry* pentry, char *text); +void menuentry_value(struct menuentry* pentry, char *value); +void menuentry_extratext(struct menuentry* pentry, char *text2, char *text3, char *text4); +int menu_levelselector(char *directory, char *chosen, char *title, int flags); +int menu_colourselector(char *directory, char *chosen, char *title, int flags); + +/* $DISPLAYmenudisplay.c */ +void menu_display(struct menu *, int); +int menu_process(struct menu *); +int menu_addfile(struct menu *, char *); diff --git a/names.c b/names.c new file mode 100644 index 0000000..df32603 --- /dev/null +++ b/names.c @@ -0,0 +1,161 @@ +/* + names.c + + Copyright (C) 2010-2019 Amf + + 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 "chroma.h" + +char* piece_name[] = { + "SPACE", + "WALL", + "PLAYER_ONE", + "PLAYER_TWO", + "STAR", + "DOTS", + "DOOR", + "CIRCLE", + "ARROW_RED_LEFT", + "ARROW_RED_UP", + "ARROW_RED_RIGHT", + "ARROW_RED_DOWN", + "BOMB_RED_LEFT", + "BOMB_RED_UP", + "BOMB_RED_RIGHT", + "BOMB_RED_DOWN", + "ARROW_GREEN_LEFT", + "ARROW_GREEN_UP", + "ARROW_GREEN_RIGHT", + "ARROW_GREEN_DOWN", + "BOMB_GREEN_LEFT", + "BOMB_GREEN_UP", + "BOMB_GREEN_RIGHT", + "BOMB_GREEN_DOWN", + "ARROW_BLUE_LEFT", + "ARROW_BLUE_UP", + "ARROW_BLUE_RIGHT", + "ARROW_BLUE_DOWN", + "BOMB_BLUE_LEFT", + "BOMB_BLUE_UP", + "BOMB_BLUE_RIGHT", + "BOMB_BLUE_DOWN", + +#ifdef ENIGMA_COMPATIBILITY + "CIRCLE_DOUBLE", + "DOTS_DOUBLE", +#endif + +#ifdef XOR_COMPATIBILITY + "DOTS_X", + "DOTS_Y", + "SWITCH", + "TELEPORT", + "MAP_TOP_LEFT", + "MAP_TOP_RIGHT", + "MAP_BOTTOM_LEFT", + "MAP_BOTTOM_RIGHT", + "DARKNESS", +#endif + + "EXPLOSION_RED_LEFT", + "EXPLOSION_RED_HORIZONTAL", + "EXPLOSION_RED_RIGHT", + "EXPLOSION_RED_TOP", + "EXPLOSION_RED_VERTICAL", + "EXPLOSION_RED_BOTTOM", + "EXPLOSION_GREEN_LEFT", + "EXPLOSION_GREEN_HORIZONTAL", + "EXPLOSION_GREEN_RIGHT", + "EXPLOSION_GREEN_TOP", + "EXPLOSION_GREEN_VERTICAL", + "EXPLOSION_GREEN_BOTTOM", + "EXPLOSION_BLUE_LEFT", + "EXPLOSION_BLUE_HORIZONTAL", + "EXPLOSION_BLUE_RIGHT", + "EXPLOSION_BLUE_TOP", + "EXPLOSION_BLUE_VERTICAL", + "EXPLOSION_BLUE_BOTTOM", + "EXPLOSION_NEW_RED_LEFT", + "EXPLOSION_NEW_RED_HORIZONTAL", + "EXPLOSION_NEW_RED_RIGHT", + "EXPLOSION_NEW_RED_TOP", + "EXPLOSION_NEW_RED_VERTICAL", + "EXPLOSION_NEW_RED_BOTTOM", + "EXPLOSION_NEW_GREEN_LEFT", + "EXPLOSION_NEW_GREEN_HORIZONTAL", + "EXPLOSION_NEW_GREEN_RIGHT", + "EXPLOSION_NEW_GREEN_TOP", + "EXPLOSION_NEW_GREEN_VERTICAL", + "EXPLOSION_NEW_GREEN_BOTTOM", + "EXPLOSION_NEW_BLUE_LEFT", + "EXPLOSION_NEW_BLUE_HORIZONTAL", + "EXPLOSION_NEW_BLUE_RIGHT", + "EXPLOSION_NEW_BLUE_TOP", + "EXPLOSION_NEW_BLUE_VERTICAL", + "EXPLOSION_NEW_BLUE_BOTTOM", + "CURSOR", + "GONE", + "" }; + +char *action_name[] = { + "Do nothing", + "Quit", + "Redraw screen", + "Fast", + "Move left", + "Move right", + "Move up", + "Move down", + "Swap players / Select", + "Undo move / Delete", + "Redo move", + "Piece left / Page up", + "Piece right / Page down", + "Hide screen", + "Pause", + "Faster", + "Slower", + + "Mouse click", + "Mouse drag", + "Mouse drag or click" +}; + +char *action_shortname[] = { + "none", + "quit", + "redraw", + "fast", + "left", + "right", + "up", + "down", + "swap", + "undo", + "redo", + "piece-left", + "piece-right", + "hide", + "pause", + "faster", + "slower", + + "mouse-click", + "mouse-drag", + "mouse-drag-or-click", +}; + diff --git a/po/README b/po/README new file mode 100644 index 0000000..ca47616 --- /dev/null +++ b/po/README @@ -0,0 +1,19 @@ +Internationalisation +==================== +To initialise the template (only if the source code has changed): + + xgettext -d chroma -s -o chroma.pot ../*.c + +but remember to add the level titles, action names and scheme names. + +To create a new language (eg en_US): + + msginit -l en_US -o en_US.po -i chroma.pot + mkdir ../locale/en_US/ + mkdir ../locale/en_US/LC_MESSAGES/ + +To update the translations: + + msgfmt -c -v -o ../locale/en_US/LC_MESSAGES/chroma.mo en_US.po + +More translations always welcomed! diff --git a/po/chroma.pot b/po/chroma.pot new file mode 100644 index 0000000..9095a9c --- /dev/null +++ b/po/chroma.pot @@ -0,0 +1,1030 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-03-07 11:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" + +#: ../editor.c:792 +#, c-format +msgid "%d degrees" +msgstr "" + +#: ../editor.c:546 +#, c-format +msgid "%d error found" +msgstr "" + +#: ../editor.c:548 +#, c-format +msgid "%d errors found" +msgstr "" + +#: ../cursesdisplay.c:309 ../menu.c:610 ../sdldisplay.c:914 +#, c-format +msgid "%d lost" +msgstr "" + +#: ../sdldisplay.c:2507 ../sdldisplay.c:2510 ../sdldisplay.c:2513 +#: ../sdldisplay.c:2516 +#, c-format +msgid "%d milliseconds" +msgstr "" + +#: ../menu.c:619 +#, c-format +msgid "%d moves" +msgstr "" + +#: ../sdldisplay.c:2841 +#, c-format +msgid "%d x %d (%d bits per pixel)" +msgstr "" + +#: ../cursesdisplay.c:1104 ../cursesdisplay.c:1118 +#, c-format +msgid "%d00 milliseconds" +msgstr "" + +#: ../graphics.c:1536 ../graphics.c:1545 ../graphics.c:1555 +#, c-format +msgid "%s bevelling requires five images" +msgstr "" + +#: ../validate.c:95 +#, c-format +msgid "%s: insufficient arguments\n" +msgstr "" + +#: ../validate.c:89 +#, c-format +msgid "%s: too many arguments\n" +msgstr "" + +#: ../menu.c:800 +#, c-format +msgid "(%d other)" +msgstr "" + +#: ../menu.c:800 +#, c-format +msgid "(%d others)" +msgstr "" + +#: ../cursesdisplay.c:1372 ../sdldisplay.c:2971 +msgid "(fixed)" +msgstr "" + +#: ../sdldisplay.c:2895 +msgid "(none)" +msgstr "" + +#: ../main.c:193 ../main.c:197 +msgid "(not while pieces in motion)" +msgstr "" + +#: ../main.c:175 +msgid "(only after changes)" +msgstr "" + +#: ../main.c:213 +msgid "(only at start of a level)" +msgstr "" + +#: ../editor.c:796 +msgid "(only for Chroma levels)" +msgstr "" + +#: ../editor.c:198 +msgid "** NO LEVEL LOADED **" +msgstr "" + +#: ../colours.c:353 ../cursesdisplay.c:1087 ../graphics.c:366 +#: ../sdldisplay.c:2546 ../sdldisplay.c:2564 ../sdldisplay.c:3258 +msgid "** NONE **" +msgstr "" + +#: ../editor.c:171 +msgid "Abort Editor and Return to Main Menu" +msgstr "" + +#: ../main.c:168 +msgid "Abort Level and Return to Selection" +msgstr "" + +#: ../sdldisplay.c:2500 ../sdldisplay.c:2522 +#, c-format +msgid "Auto (%d x %d)" +msgstr "" + +#: ../sdldisplay.c:2541 +#, c-format +msgid "Auto (%d)" +msgstr "" + +#: ../sdldisplay.c:3252 +#, c-format +msgid "Automatic (%d x %d)" +msgstr "" + +#: ../sdldisplay.c:2758 ../sdldisplay.c:3260 +msgid "Automatic sizing" +msgstr "" + +#: ../xmlparser.c:287 +#, c-format +msgid "Badly nested tags on line %d (expecting '/%s', found '%s')" +msgstr "" + +#: ../sdldisplay.c:3140 +#, c-format +msgid "Button %d" +msgstr "" + +#: ../cursesdisplay.c:1060 ../sdldisplay.c:2472 +msgid "Change Keys" +msgstr "" + +#: ../sdldisplay.c:2473 +msgid "Change Mouse" +msgstr "" + +#: ../main.c:94 +msgid "Choose a level" +msgstr "" + +#: ../editor.c:724 ../main.c:73 +msgid "Chroma" +msgstr "" + +#: ../graphics.c:956 +msgid "Clone loop" +msgstr "" + +#: ../cursesdisplay.c:1053 ../sdldisplay.c:2456 +msgid "Colour Scheme" +msgstr "" + +#: ../colours.c:345 +msgid "Colour Schemes" +msgstr "" + +#: ../editor.c:230 +msgid "Confirm Save" +msgstr "" + +#: ../menu.c:395 +msgid "Create new level" +msgstr "" + +#: ../sdldisplay.c:3197 +msgid "Current action is:" +msgstr "" + +#: ../colours.c:350 +msgid "Current colour scheme:" +msgstr "" + +#: ../graphics.c:363 +msgid "Current graphics scheme:" +msgstr "" + +#: ../sdldisplay.c:3248 +msgid "Current graphics size:" +msgstr "" + +#: ../sdldisplay.c:2840 +msgid "Current screen size:" +msgstr "" + +#: ../editor.c:188 +msgid "Currently editing:" +msgstr "" + +#: ../main.c:226 +msgid "Currently playing:" +msgstr "" + +#: ../sdldisplay.c:2832 +#, c-format +msgid "Custom (%d x %d)" +msgstr "" + +#: ../cursesdisplay.c:1080 ../cursesdisplay.c:1418 ../sdldisplay.c:2493 +#: ../sdldisplay.c:3307 +msgid "Debug Options" +msgstr "" + +#: ../cursesdisplay.c:1045 ../editor.c:186 ../main.c:80 ../main.c:224 +#: ../sdldisplay.c:2446 +msgid "Display Options" +msgstr "" + +#: ../cursesdisplay.c:1424 ../sdldisplay.c:3313 +msgid "Display order of movers" +msgstr "" + +#: ../editor.c:232 +msgid "Do you wish to overwrite:" +msgstr "" + +#: ../editor.c:164 +msgid "Editing Menu" +msgstr "" + +#: ../main.c:79 +msgid "Editor" +msgstr "" + +#: ../editor.c:755 +msgid "Enigma" +msgstr "" + +#: ../cursesdisplay.c:1491 ../sdldisplay.c:3392 +msgid "Enigma Engine" +msgstr "" + +#: ../editor.c:177 ../main.c:434 +msgid "Export Level" +msgstr "" + +#: ../main.c:188 ../main.c:196 ../main.c:436 +msgid "Export Solution" +msgstr "" + +#: ../main.c:460 +msgid "Export level" +msgstr "" + +#: ../main.c:462 +msgid "Export solution" +msgstr "" + +#: ../main.c:466 +msgid "Exported levels are saved in \"My Documents\"" +msgstr "" + +#: ../main.c:471 +msgid "Exported levels are saved in your home directory" +msgstr "" + +#: ../main.c:468 +msgid "Exported solutions are saved in \"My Documents\"" +msgstr "" + +#: ../main.c:473 +msgid "Exported solutions are saved in your home directory" +msgstr "" + +#: ../main.c:441 +msgid "Filename" +msgstr "" + +#: ../sdldisplay.c:2461 +msgid "Fullscreen" +msgstr "" + +#: ../main.c:165 +msgid "Game Options" +msgstr "" + +#: ../graphics.c:443 +msgid "Graphics Errors" +msgstr "" + +#: ../sdldisplay.c:2455 +msgid "Graphics Level" +msgstr "" + +#: ../sdldisplay.c:2453 +msgid "Graphics Scheme" +msgstr "" + +#: ../graphics.c:358 +msgid "Graphics Schemes" +msgstr "" + +#: ../sdldisplay.c:2454 ../sdldisplay.c:3243 +msgid "Graphics Size" +msgstr "" + +#: ../main.c:78 ../main.c:359 +msgid "How to Play" +msgstr "" + +#: ../menu.c:401 +msgid "Import a position" +msgstr "" + +#: ../graphics.c:454 +#, c-format +msgid "In file '%s':\n" +msgstr "" + +#: ../graphics.c:1259 +msgid "Invalid bevel type" +msgstr "" + +#: ../graphics.c:1209 ../graphics.c:1325 ../graphics.c:1402 +msgid "Invalid colour" +msgstr "" + +#: ../graphics.c:1383 +#, c-format +msgid "Invalid filename '%s'" +msgstr "" + +#: ../editor.c:414 +#, c-format +msgid "Invalid piece %s at (%d,%d)" +msgstr "" + +#: ../graphics.c:959 +msgid "Invalid piece for clone" +msgstr "" + +#: ../graphics.c:1245 +msgid "Invalid piece name" +msgstr "" + +#: ../graphics.c:1126 +msgid "Invalid shadow" +msgstr "" + +#: ../graphics.c:1099 +msgid "Invalid size" +msgstr "" + +#: ../cursesdisplay.c:1320 ../sdldisplay.c:2917 +msgid "Keys" +msgstr "" + +#: ../editor.c:693 +msgid "Level Mode" +msgstr "" + +#: ../editor.c:183 ../editor.c:611 +msgid "Level Options" +msgstr "" + +#: ../editor.c:702 ../editor.c:733 ../editor.c:748 ../editor.c:765 +msgid "Level height" +msgstr "" + +#: ../editor.c:731 +msgid "Level height (Chroma standard is 23)" +msgstr "" + +#: ../editor.c:763 +msgid "Level height (Enigma standard is 20)" +msgstr "" + +#: ../editor.c:746 +msgid "Level height (XOR standard is 32)" +msgstr "" + +#: ../editor.c:697 ../editor.c:728 ../editor.c:743 ../editor.c:760 +msgid "Level width" +msgstr "" + +#: ../editor.c:726 +msgid "Level width (Chroma standard is 32)" +msgstr "" + +#: ../editor.c:758 +msgid "Level width (Enigma standard is 36)" +msgstr "" + +#: ../editor.c:741 +msgid "Level width (XOR standard is 32)" +msgstr "" + +#: ../menu.c:422 +msgid "Levels under Construction" +msgstr "" + +#: ../sdldisplay.c:3314 +msgid "List movers on stderr" +msgstr "" + +#: ../editor.c:175 ../editor.c:273 +msgid "Load Level" +msgstr "" + +#: ../main.c:180 ../main.c:279 +msgid "Load Position" +msgstr "" + +#: ../xmlparser.c:334 ../xmlparser.c:348 +#, c-format +msgid "Malformed attribute on line %d (in '%s')" +msgstr "" + +#: ../sdldisplay.c:3130 +msgid "Mouse" +msgstr "" + +#: ../cursesdisplay.c:1056 ../sdldisplay.c:2466 +msgid "Move Speed" +msgstr "" + +#: ../editor.c:247 ../sdldisplay.c:2505 +msgid "No" +msgstr "" + +#: ../editor.c:440 ../editor.c:451 ../editor.c:461 ../editor.c:493 +#: ../editor.c:503 ../editor.c:513 ../editor.c:523 +#, c-format +msgid "No %s" +msgstr "" + +#: ../sdlscreen.c:64 +msgid "No resolutions available" +msgstr "" + +#: ../graphics.c:889 +msgid "No size specified" +msgstr "" + +#: ../cursesdisplay.c:1074 ../cursesdisplay.c:1477 ../sdldisplay.c:2487 +#: ../sdldisplay.c:3378 +msgid "Other Games Options" +msgstr "" + +#: ../colours.c:213 +msgid "Out of memory in colours_load()" +msgstr "" + +#: ../graphics.c:676 ../graphics.c:1082 ../graphics.c:1110 ../graphics.c:1148 +msgid "Out of memory in graphics_load()" +msgstr "" + +#: ../menu.c:718 ../menu.c:725 +msgid "Out of memory in menu_levelentries()" +msgstr "" + +#: ../menu.c:58 ../menu.c:63 +msgid "Out of memory in menu_new()" +msgstr "" + +#: ../menu.c:313 ../menu.c:324 ../menu.c:335 +msgid "Out of memory in menuentry_extratext()" +msgstr "" + +#: ../menu.c:181 ../menu.c:246 ../menu.c:262 +msgid "Out of memory in menuentry_newwithvalue()" +msgstr "" + +#: ../menu.c:295 +msgid "Out of memory in menuentry_text()" +msgstr "" + +#: ../menu.c:282 +msgid "Out of memory in menuentry_value()" +msgstr "" + +#: ../xmlparser.c:41 ../xmlparser.c:58 +msgid "Out of memory in parser_new()" +msgstr "" + +#: ../xmlparser.c:378 +msgid "Out of memory in parser_parse()" +msgstr "" + +#: ../xmlparser.c:87 +msgid "Out of memory in parser_push()" +msgstr "" + +#: ../editor.c:704 +msgid "Padding on bottom edge" +msgstr "" + +#: ../editor.c:698 +msgid "Padding on left edge" +msgstr "" + +#: ../editor.c:699 +msgid "Padding on right edge" +msgstr "" + +#: ../editor.c:703 +msgid "Padding on top edge" +msgstr "" + +#: ../sdldisplay.c:2465 +msgid "Player Speed" +msgstr "" + +#: ../cursesdisplay.c:1377 ../sdldisplay.c:2975 +msgid "Press a key to add or remove it from this list." +msgstr "" + +#: ../main.c:76 +msgid "Press any key to play" +msgstr "" + +#: ../main.c:81 +msgid "Quit" +msgstr "" + +#: ../colours.c:347 ../cursesdisplay.c:1322 ../cursesdisplay.c:1362 +#: ../graphics.c:360 ../main.c:361 ../main.c:438 ../sdldisplay.c:2755 +#: ../sdldisplay.c:2919 ../sdldisplay.c:2961 ../sdldisplay.c:3132 +#: ../sdldisplay.c:3184 ../sdldisplay.c:3245 +msgid "Quit and return to previous menu" +msgstr "" + +#: ../main.c:207 ../main.c:212 ../main.c:316 +msgid "Replay Saved Position" +msgstr "" + +#: ../cursesdisplay.c:1057 ../sdldisplay.c:2467 +msgid "Replay Speed" +msgstr "" + +#: ../editor.c:170 +msgid "Return to Editor" +msgstr "" + +#: ../main.c:167 +msgid "Return to Level" +msgstr "" + +#: ../editor.c:167 +msgid "Return to Main Menu" +msgstr "" + +#: ../editor.c:363 +msgid "Return to Previous Menu" +msgstr "" + +#: ../cursesdisplay.c:1047 ../cursesdisplay.c:1420 ../cursesdisplay.c:1479 +#: ../editor.c:678 ../graphics.c:445 ../menu.c:389 ../sdldisplay.c:2448 +#: ../sdldisplay.c:3309 ../sdldisplay.c:3380 +msgid "Return to previous menu" +msgstr "" + +#: ../main.c:171 ../main.c:174 +msgid "Revert to Original Position" +msgstr "" + +#: ../editor.c:707 +msgid "Rotate" +msgstr "" + +#: ../editor.c:176 ../editor.c:212 +msgid "Save Level" +msgstr "" + +#: ../cursesdisplay.c:1050 ../sdldisplay.c:2449 +msgid "Save Options" +msgstr "" + +#: ../main.c:185 ../main.c:192 ../main.c:262 +msgid "Save Position" +msgstr "" + +#: ../main.c:257 +msgid "Save Solution" +msgstr "" + +#: ../menu.c:392 +msgid "Save as new position" +msgstr "" + +#: ../menu.c:408 +msgid "Saved Positions" +msgstr "" + +#: ../sdldisplay.c:2753 +msgid "Screen Size" +msgstr "" + +#: ../sdldisplay.c:2460 +msgid "Screen size" +msgstr "" + +#: ../sdldisplay.c:3181 +#, c-format +msgid "Set action for button %d in %s" +msgstr "" + +#: ../cursesdisplay.c:1359 ../sdldisplay.c:2958 +#, c-format +msgid "Set keys for '%s'" +msgstr "" + +#: ../sdldisplay.c:3315 +msgid "Show frames per second" +msgstr "" + +#: ../cursesdisplay.c:1425 ../sdldisplay.c:3316 +msgid "Show hidden items" +msgstr "" + +#: ../menu.c:799 +msgid "Show positions for other levels" +msgstr "" + +#: ../menu.c:415 +msgid "Solved Positions" +msgstr "" + +#: ../xmlparser.c:89 +msgid "Stack overflow in parser_push()" +msgstr "" + +#: ../main.c:220 +msgid "Stop Replaying Position" +msgstr "" + +#: ../editor.c:178 +msgid "Test Level" +msgstr "" + +#: ../editor.c:681 +msgid "Title" +msgstr "" + +#: ../editor.c:468 ../editor.c:475 ../editor.c:485 ../editor.c:495 +#: ../editor.c:505 ../editor.c:515 ../editor.c:525 +#, c-format +msgid "Too many %s" +msgstr "" + +#: ../util.c:100 +#, c-format +msgid "Unable to create directory '%s': %s" +msgstr "" + +#: ../sdlscreen.c:107 +msgid "Unable to create screen in screen_size" +msgstr "" + +#: ../sdlfont.c:157 +msgid "Unable to create stroker" +msgstr "" + +#: ../sdldisplay.c:160 +#, c-format +msgid "Unable to initalise SDL: %s" +msgstr "" + +#: ../sdlfont.c:123 +#, c-format +msgid "Unable to initialise freetype: error=%d" +msgstr "" + +#: ../sdlfont.c:129 +#, c-format +msgid "Unable to load font: error=%d" +msgstr "" + +#: ../sdlfont.c:368 +msgid "Unable to open font" +msgstr "" + +#: ../sdlfont.c:149 +msgid "Unable to set font size" +msgstr "" + +#: ../sdldisplay.c:2468 +msgid "Undo Speed" +msgstr "" + +#: ../editor.c:428 +#, c-format +msgid "Unsupported %s resting on %s at (%d,%d)" +msgstr "" + +#: ../main.c:362 +msgid "Use [UP] and [DOWN] to scroll" +msgstr "" + +#: ../editor.c:179 ../editor.c:361 +msgid "Verify Level" +msgstr "" + +#: ../editor.c:738 +msgid "XOR" +msgstr "" + +#: ../cursesdisplay.c:1485 ../sdldisplay.c:3386 +msgid "XOR Display" +msgstr "" + +#: ../cursesdisplay.c:1484 ../sdldisplay.c:3385 +msgid "XOR Engine" +msgstr "" + +#: ../editor.c:248 ../sdldisplay.c:2505 +msgid "Yes" +msgstr "" + +#: ../menu.c:430 +msgid "[DELETE] to delete a position" +msgstr "" + +#: ../colours.c:355 ../colours.c:384 ../cursesdisplay.c:1089 +#: ../sdldisplay.c:2566 +msgid "[untitled colours]" +msgstr "" + +#: ../graphics.c:368 ../graphics.c:399 ../sdldisplay.c:2529 +#: ../sdldisplay.c:2532 +msgid "[untitled graphics]" +msgstr "" + +#: ../editor.c:193 ../editor.c:235 ../editor.c:241 ../main.c:228 ../menu.c:600 +msgid "[untitled level]" +msgstr "" + +#: ../cursesdisplay.c:1098 ../cursesdisplay.c:1112 +#, c-format +msgid "after a key is pressed" +msgstr "" + +#: ../cursesdisplay.c:1498 ../cursesdisplay.c:1502 ../sdldisplay.c:3399 +#: ../sdldisplay.c:3403 +msgid "approximate" +msgstr "" + +#: ../cursesdisplay.c:1498 ../cursesdisplay.c:1502 ../sdldisplay.c:3399 +#: ../sdldisplay.c:3403 +msgid "exact" +msgstr "" + +#: ../cursesdisplay.c:279 ../menu.c:617 ../sdldisplay.c:855 +#, c-format +msgid "failed" +msgstr "" + +#: ../cursesdisplay.c:1499 ../sdldisplay.c:3400 +msgid "full" +msgstr "" + +#: ../cursesdisplay.c:1101 ../cursesdisplay.c:1115 +#, c-format +msgid "instantaneous" +msgstr "" + +#: ../cursesdisplay.c:1430 ../cursesdisplay.c:1431 ../sdldisplay.c:3321 +#: ../sdldisplay.c:3322 ../sdldisplay.c:3323 ../sdldisplay.c:3324 +msgid "no" +msgstr "" + +#: ../cursesdisplay.c:1499 ../sdldisplay.c:3400 +msgid "partial" +msgstr "" + +#: ../cursesdisplay.c:270 ../cursesdisplay.c:275 ../sdldisplay.c:846 +#: ../sdldisplay.c:851 +msgid "paused " +msgstr "" + +#: ../cursesdisplay.c:271 ../sdldisplay.c:847 +msgid "replay " +msgstr "" + +#: ../cursesdisplay.c:312 ../menu.c:614 ../menu.c:638 ../sdldisplay.c:917 +#, c-format +msgid "solved" +msgstr "" + +#: ../cursesdisplay.c:476 ../cursesdisplay.c:484 ../sdldisplay.c:791 +msgid "testing: " +msgstr "" + +#: ../editor.c:238 +msgid "with:" +msgstr "" + +#: ../cursesdisplay.c:1430 ../cursesdisplay.c:1431 ../sdldisplay.c:3321 +#: ../sdldisplay.c:3322 ../sdldisplay.c:3323 ../sdldisplay.c:3324 +msgid "yes" +msgstr "" + +# translated level titles *must* begin with the English word "chroma" +msgid "chroma 1 : initiation" +msgstr "" + +msgid "for beginners" +msgstr "" + +msgid "chroma 1.01 : invitation" +msgstr "" + +msgid "chroma 1.02 : illustration" +msgstr "" + +msgid "chroma 1.03 : elaboration" +msgstr "" + +msgid "chroma 1.04 : detonation" +msgstr "" + +msgid "chroma 1.05 : complication" +msgstr "" + +msgid "chroma 1.06 : transportation" +msgstr "" + +msgid "chroma 1.07 : collaboration" +msgstr "" + +msgid "chroma 1.08 : preparation" +msgstr "" + +msgid "chroma 1.09 : application" +msgstr "" + +msgid "chroma 2 : coronation" +msgstr "" + +msgid "for experts" +msgstr "" + +msgid "chroma 2.01 : inauguration" +msgstr "" + +msgid "chroma 2.02 : manipulation" +msgstr "" + +msgid "chroma 2.03 : edification" +msgstr "" + +msgid "chroma 2.04 : disintegration" +msgstr "" + +msgid "chroma 2.05 : triplication" +msgstr "" + +msgid "chroma 2.06 : orchestration" +msgstr "" + +msgid "chroma 2.07 : augmentation" +msgstr "" + +msgid "chroma 2.08 : conflagration" +msgstr "" + +msgid "chroma 2.09 : restoration" +msgstr "" + +msgid "chroma 2.10 : perturbation" +msgstr "" + +msgid "chroma 2.11 : bifurcation" +msgstr "" + +msgid "chroma 2.12 : culmination" +msgstr "" + +msgid "chroma 0 : regression" +msgstr "" + +msgid "for hackers" +msgstr "" + +msgid "chroma 0.00 : pieces" +msgstr "" + +msgid "chroma 0.01 : regression tests" +msgstr "" + +# Actions +msgid "Click to move player" +msgstr "" + +msgid "Click to move player, drag to scroll screen" +msgstr "" + +msgid "Click to set piece" +msgstr "" + +msgid "Click to set piece, drag to scroll screen" +msgstr "" + +msgid "Click to swap player" +msgstr "" + +msgid "Do nothing" +msgstr "" + +msgid "Drag to scroll screen" +msgstr "" + +msgid "Fast" +msgstr "" + +msgid "Faster" +msgstr "" + +msgid "Hide screen" +msgstr "" + +msgid "Mouse click" +msgstr "" + +msgid "Mouse drag" +msgstr "" + +msgid "Mouse drag or click" +msgstr "" + +msgid "Move down" +msgstr "" + +msgid "Move left" +msgstr "" + +msgid "Move right" +msgstr "" + +msgid "Move up" +msgstr "" + +msgid "Page down" +msgstr "" + +msgid "Page up" +msgstr "" + +msgid "Pause" +msgstr "" + +msgid "Piece left" +msgstr "" + +msgid "Piece left / Page up" +msgstr "" + +msgid "Piece right" +msgstr "" + +msgid "Piece right / Page down" +msgstr "" + +msgid "Redo move" +msgstr "" + +msgid "Redraw screen" +msgstr "" + +msgid "Select entry" +msgstr "" + +msgid "Slower" +msgstr "" + +msgid "Swap players / Select" +msgstr "" + +msgid "Undo move" +msgstr "" + +msgid "Undo move / Delete" +msgstr "" + +# Graphics schemes +msgid "Chroma Marble" +msgstr "" + +msgid "Chroma Neon" +msgstr "" + +msgid "Chroma Zen" +msgstr "" + +msgid "Curses Emulation" +msgstr "" + +msgid "Default Fallback" +msgstr "" + +# Colour schemes +msgid "Chroma Curses Enhanced" +msgstr "" + +msgid "Chroma Curses Enigma" +msgstr "" + +msgid "Chroma Curses Monochrome" +msgstr "" + +msgid "Chroma Curses Reverse" +msgstr "" + +msgid "Chroma Curses Standard" +msgstr "" diff --git a/po/en_US.po b/po/en_US.po new file mode 100644 index 0000000..c59c952 --- /dev/null +++ b/po/en_US.po @@ -0,0 +1,980 @@ +# English translations for PACKAGE package. +# Copyright (C) 2009 THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# amf, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2009-12-30 15:52+0000\n" +"PO-Revision-Date: 2009-12-30 15:53+0000\n" +"Last-Translator: amf\n" +"Language-Team: English \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=ISO-8859-1\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: ../editor.c:782 +#, c-format +msgid "%d degrees" +msgstr "%d degrees" + +#: ../editor.c:536 +#, c-format +msgid "%d error found" +msgstr "%d error found" + +#: ../editor.c:538 +#, c-format +msgid "%d errors found" +msgstr "%d errors found" + +#: ../cursesdisplay.c:297 ../menu.c:584 ../sdldisplay.c:908 +#, c-format +msgid "%d lost" +msgstr "%d lost" + +#: ../sdldisplay.c:2475 ../sdldisplay.c:2478 ../sdldisplay.c:2481 +#: ../sdldisplay.c:2484 +#, c-format +msgid "%d milliseconds" +msgstr "%d milliseconds" + +#: ../menu.c:593 +#, c-format +msgid "%d moves" +msgstr "%d moves" + +#: ../sdldisplay.c:2761 +#, c-format +msgid "%d x %d (%d bits per pixel)" +msgstr "%d x %d (%d bits per pixel)" + +#: ../cursesdisplay.c:1035 ../cursesdisplay.c:1049 +#, c-format +msgid "%d00 milliseconds" +msgstr "%d00 milliseconds" + +#: ../graphics.c:1538 ../graphics.c:1547 ../graphics.c:1557 +#, c-format +msgid "%s bevelling requires five images" +msgstr "%s bevelling requires five images" + +#: ../validate.c:91 +#, c-format +msgid "%s: insufficient arguments\n" +msgstr "%s: insufficient arguments\n" + +#: ../validate.c:85 +#, c-format +msgid "%s: too many arguments\n" +msgstr "%s: too many arguments\n" + +#: ../cursesdisplay.c:1304 ../sdldisplay.c:2891 +msgid "(fixed)" +msgstr "(fixed)" + +#: ../sdldisplay.c:2815 +msgid "(none)" +msgstr "(none)" + +#: ../main.c:196 +msgid "(not while pieces in motion)" +msgstr "(not while pieces in motion)" + +#: ../main.c:184 +msgid "(only after changes)" +msgstr "(only after changes)" + +#: ../main.c:211 +msgid "(only at start of a level)" +msgstr "(only at start of a level)" + +#: ../editor.c:786 +msgid "(only for Chroma levels)" +msgstr "(only for Chroma levels)" + +#: ../editor.c:192 +msgid "** NO LEVEL LOADED **" +msgstr "** NO LEVEL LOADED **" + +#: ../colours.c:353 ../cursesdisplay.c:1018 ../graphics.c:368 +#: ../sdldisplay.c:2516 ../sdldisplay.c:2534 ../sdldisplay.c:3173 +msgid "** NONE **" +msgstr "** NONE **" + +#: ../editor.c:166 +msgid "Abort Editor and Return to Main Menu" +msgstr "Abort Editor and Return to Main Menu" + +#: ../main.c:177 +msgid "Abort Level and Return to Selection" +msgstr "Abort Level and Return to Selection" + +#: ../sdldisplay.c:2468 ../sdldisplay.c:2492 +#, c-format +msgid "Auto (%d x %d)" +msgstr "Auto (%d x %d)" + +#: ../sdldisplay.c:2511 +#, c-format +msgid "Auto (%d)" +msgstr "Auto (%d)" + +#: ../sdldisplay.c:3167 +#, c-format +msgid "Automatic (%d x %d)" +msgstr "Automatic (%d x %d)" + +#: ../sdldisplay.c:2727 ../sdldisplay.c:3175 +msgid "Automatic sizing" +msgstr "Automatic sizing" + +#: ../xmlparser.c:287 +#, c-format +msgid "Badly nested tags on line %d (expecting '/%s', found '%s')" +msgstr "Badly nested tags on line %d (expecting '/%s', found '%s')" + +#: ../sdldisplay.c:3055 +#, c-format +msgid "Button %d" +msgstr "Button %d" + +#: ../cursesdisplay.c:997 ../sdldisplay.c:2445 +msgid "Change Keys" +msgstr "Change Keys" + +#: ../sdldisplay.c:2446 +msgid "Change Mouse" +msgstr "Change Mouse" + +#: ../main.c:103 +msgid "Choose a level" +msgstr "Choose a level" + +#: ../editor.c:714 ../main.c:73 +msgid "Chroma" +msgstr "Chroma" + +#: ../graphics.c:958 +msgid "Clone loop" +msgstr "Clone loop" + +#: ../cursesdisplay.c:990 ../sdldisplay.c:2429 +msgid "Colour Scheme" +msgstr "Color Scheme" + +#: ../colours.c:345 +msgid "Colour Schemes" +msgstr "Color Schemes" + +#: ../editor.c:224 +msgid "Confirm Save" +msgstr "Confirm Save" + +#: ../menu.c:388 +msgid "Create new level" +msgstr "Create new level" + +#: ../sdldisplay.c:3112 +msgid "Current action is:" +msgstr "Current action is:" + +#: ../colours.c:350 +msgid "Current colour scheme:" +msgstr "Current color scheme:" + +#: ../graphics.c:365 +msgid "Current graphics scheme:" +msgstr "Current graphics scheme:" + +#: ../sdldisplay.c:3163 +msgid "Current graphics size:" +msgstr "Current graphics size:" + +#: ../sdldisplay.c:2760 +msgid "Current screen size:" +msgstr "Current screen size:" + +#: ../editor.c:182 +msgid "Currently editing:" +msgstr "Currently editing:" + +#: ../main.c:224 +msgid "Currently playing:" +msgstr "Currently playing:" + +#: ../sdldisplay.c:2752 +#, c-format +msgid "Custom (%d x %d)" +msgstr "Custom (%d x %d)" + +#: ../cursesdisplay.c:1011 ../cursesdisplay.c:1350 ../sdldisplay.c:2461 +#: ../sdldisplay.c:3222 +msgid "Debug Options" +msgstr "Debug Options" + +#: ../cursesdisplay.c:982 ../editor.c:180 ../main.c:80 ../main.c:222 +#: ../sdldisplay.c:2419 +msgid "Display Options" +msgstr "Display Options" + +#: ../cursesdisplay.c:1356 ../sdldisplay.c:3228 +msgid "Display order of movers" +msgstr "Display order of movers" + +#: ../editor.c:226 +msgid "Do you wish to overwrite:" +msgstr "Do you wish to overwrite:" + +#: ../editor.c:159 +msgid "Editing Menu" +msgstr "Editing Menu" + +#: ../main.c:79 +msgid "Editor" +msgstr "Editor" + +#: ../editor.c:745 +msgid "Enigma" +msgstr "Enigma" + +#: ../sdldisplay.c:2434 +msgid "Fullscreen" +msgstr "Fullscreen" + +#: ../main.c:174 +msgid "Game Options" +msgstr "Game Options" + +#: ../graphics.c:445 +msgid "Graphics Errors" +msgstr "Graphics Errors" + +#: ../sdldisplay.c:2428 +msgid "Graphics Level" +msgstr "Graphics Level" + +#: ../sdldisplay.c:2426 +msgid "Graphics Scheme" +msgstr "Graphics Scheme" + +#: ../graphics.c:360 +msgid "Graphics Schemes" +msgstr "Graphics Schemes" + +#: ../sdldisplay.c:2427 ../sdldisplay.c:3158 +msgid "Graphics Size" +msgstr "Graphics Size" + +#: ../main.c:78 ../main.c:349 +msgid "How to Play" +msgstr "How to Play" + +#: ../graphics.c:456 +#, c-format +msgid "In file '%s':\n" +msgstr "In file '%s':\n" + +#: ../graphics.c:1261 +msgid "Invalid bevel type" +msgstr "Invalid bevel type" + +#: ../graphics.c:1211 ../graphics.c:1327 ../graphics.c:1404 +msgid "Invalid colour" +msgstr "Invalid color" + +#: ../graphics.c:1385 +#, c-format +msgid "Invalid filename '%s'" +msgstr "Invalid filename '%s'" + +#: ../editor.c:404 +#, c-format +msgid "Invalid piece %s at (%d,%d)" +msgstr "Invalid piece %s at (%d,%d)" + +#: ../graphics.c:961 +msgid "Invalid piece for clone" +msgstr "Invalid piece for clone" + +#: ../graphics.c:1247 +msgid "Invalid piece name" +msgstr "Invalid piece name" + +#: ../graphics.c:1128 +msgid "Invalid shadow" +msgstr "Invalid shadow" + +#: ../graphics.c:1101 +msgid "Invalid size" +msgstr "Invalid size" + +#: ../cursesdisplay.c:1253 ../sdldisplay.c:2837 +msgid "Keys" +msgstr "Keys" + +#: ../editor.c:683 +msgid "Level Mode" +msgstr "Level Mode" + +#: ../editor.c:177 ../editor.c:601 +msgid "Level Options" +msgstr "Level Options" + +#: ../editor.c:692 ../editor.c:723 ../editor.c:738 ../editor.c:755 +msgid "Level height" +msgstr "Level height" + +#: ../editor.c:721 +msgid "Level height (Chroma standard is 23)" +msgstr "Level height (Chroma standard is 23)" + +#: ../editor.c:753 +msgid "Level height (Enigma standard is 20)" +msgstr "Level height (Enigma standard is 20)" + +#: ../editor.c:736 +msgid "Level height (XOR standard is 32)" +msgstr "Level height (XOR standard is 32)" + +#: ../editor.c:687 ../editor.c:718 ../editor.c:733 ../editor.c:750 +msgid "Level width" +msgstr "Level width" + +#: ../editor.c:716 +msgid "Level width (Chroma standard is 32)" +msgstr "Level width (Chroma standard is 32)" + +#: ../editor.c:748 +msgid "Level width (Enigma standard is 36)" +msgstr "Level width (Enigma standard is 36)" + +#: ../editor.c:731 +msgid "Level width (XOR standard is 32)" +msgstr "Level width (XOR standard is 32)" + +#: ../menu.c:408 +msgid "Levels under Construction" +msgstr "Levels under Construction" + +#: ../sdldisplay.c:3229 +msgid "List movers on stderr" +msgstr "List movers on stderr" + +#: ../editor.c:170 ../editor.c:267 +msgid "Load Level" +msgstr "Load Level" + +#: ../main.c:189 ../main.c:277 +msgid "Load Position" +msgstr "Load Position" + +#: ../xmlparser.c:334 ../xmlparser.c:348 +#, c-format +msgid "Malformed attribute on line %d (in '%s')" +msgstr "Malformed attribute on line %d (in '%s')" + +#: ../sdldisplay.c:3045 +msgid "Mouse" +msgstr "Mouse" + +#: ../cursesdisplay.c:993 ../sdldisplay.c:2439 +msgid "Move Speed" +msgstr "Move Speed" + +#: ../editor.c:241 ../sdldisplay.c:2473 +msgid "No" +msgstr "No" + +#: ../editor.c:430 ../editor.c:441 ../editor.c:451 ../editor.c:483 +#: ../editor.c:493 ../editor.c:503 ../editor.c:513 +#, c-format +msgid "No %s" +msgstr "No %s" + +#: ../sdlscreen.c:64 +msgid "No resolutions available" +msgstr "No resolutions available" + +#: ../graphics.c:891 +msgid "No size specified" +msgstr "No size specified" + +#: ../colours.c:213 +msgid "Out of memory in colours_load()" +msgstr "Out of memory in colors_load()" + +#: ../graphics.c:678 ../graphics.c:1084 ../graphics.c:1112 ../graphics.c:1150 +msgid "Out of memory in graphics_load()" +msgstr "Out of memory in graphics_load()" + +#: ../menu.c:678 ../menu.c:685 +msgid "Out of memory in menu_levelentries()" +msgstr "Out of memory in menu_levelentries()" + +#: ../menu.c:51 ../menu.c:56 +msgid "Out of memory in menu_new()" +msgstr "Out of memory in menu_new()" + +#: ../menu.c:306 ../menu.c:317 ../menu.c:328 +msgid "Out of memory in menuentry_extratext()" +msgstr "Out of memory in menuentry_extratext()" + +#: ../menu.c:174 ../menu.c:239 ../menu.c:255 +msgid "Out of memory in menuentry_newwithvalue()" +msgstr "Out of memory in menuentry_newwithvalue()" + +#: ../menu.c:288 +msgid "Out of memory in menuentry_text()" +msgstr "Out of memory in menuentry_text()" + +#: ../menu.c:275 +msgid "Out of memory in menuentry_value()" +msgstr "Out of memory in menuentry_value()" + +#: ../xmlparser.c:41 ../xmlparser.c:58 +msgid "Out of memory in parser_new()" +msgstr "Out of memory in parser_new()" + +#: ../xmlparser.c:378 +msgid "Out of memory in parser_parse()" +msgstr "Out of memory in parser_parse()" + +#: ../xmlparser.c:87 +msgid "Out of memory in parser_push()" +msgstr "Out of memory in parser_push()" + +#: ../editor.c:694 +msgid "Padding on bottom edge" +msgstr "Padding on bottom edge" + +#: ../editor.c:688 +msgid "Padding on left edge" +msgstr "Padding on left edge" + +#: ../editor.c:689 +msgid "Padding on right edge" +msgstr "Padding on right edge" + +#: ../editor.c:693 +msgid "Padding on top edge" +msgstr "Padding on top edge" + +#: ../sdldisplay.c:2438 +msgid "Player Speed" +msgstr "Player Speed" + +#: ../cursesdisplay.c:1309 ../sdldisplay.c:2895 +msgid "Press a key to add or remove it from this list." +msgstr "Press a key to add or remove it from this list." + +#: ../main.c:76 +msgid "Press any key to play" +msgstr "Press any key to play" + +#: ../main.c:81 +msgid "Quit" +msgstr "Quit" + +#: ../colours.c:347 ../cursesdisplay.c:1255 ../cursesdisplay.c:1294 +#: ../graphics.c:362 ../main.c:351 ../sdldisplay.c:2724 ../sdldisplay.c:2839 +#: ../sdldisplay.c:2881 ../sdldisplay.c:3047 ../sdldisplay.c:3099 +#: ../sdldisplay.c:3160 +msgid "Quit and return to previous menu" +msgstr "Quit and return to previous menu" + +#: ../main.c:205 ../main.c:210 ../main.c:306 +msgid "Replay Saved Position" +msgstr "Replay Saved Position" + +#: ../cursesdisplay.c:994 ../sdldisplay.c:2440 +msgid "Replay Speed" +msgstr "Replay Speed" + +#: ../editor.c:165 +msgid "Return to Editor" +msgstr "Return to Editor" + +#: ../main.c:176 +msgid "Return to Level" +msgstr "Return to Level" + +#: ../editor.c:162 +msgid "Return to Main Menu" +msgstr "Return to Main Menu" + +#: ../editor.c:353 +msgid "Return to Previous Menu" +msgstr "Return to Previous Menu" + +#: ../cursesdisplay.c:984 ../cursesdisplay.c:1352 ../cursesdisplay.c:1407 +#: ../editor.c:668 ../graphics.c:447 ../menu.c:382 ../sdldisplay.c:2421 +#: ../sdldisplay.c:3224 ../sdldisplay.c:3291 +msgid "Return to previous menu" +msgstr "Return to previous menu" + +#: ../main.c:180 ../main.c:183 +msgid "Revert to Original Position" +msgstr "Revert to Original Position" + +#: ../editor.c:697 +msgid "Rotate" +msgstr "Rotate" + +#: ../editor.c:171 ../editor.c:206 +msgid "Save Level" +msgstr "Save Level" + +#: ../cursesdisplay.c:987 ../sdldisplay.c:2422 +msgid "Save Options" +msgstr "Save Options" + +#: ../main.c:192 ../main.c:195 ../main.c:260 +msgid "Save Position" +msgstr "Save Position" + +#: ../main.c:255 +msgid "Save Solution" +msgstr "Save Solution" + +#: ../menu.c:385 +msgid "Save as new position" +msgstr "Save as new position" + +#: ../menu.c:394 +msgid "Saved Positions" +msgstr "Saved Positions" + +#: ../sdldisplay.c:2722 +msgid "Screen Size" +msgstr "Screen Size" + +#: ../sdldisplay.c:2433 +msgid "Screen size" +msgstr "Screen size" + +#: ../sdldisplay.c:3096 +#, c-format +msgid "Set action for button %d in %s" +msgstr "Set action for button %d in %s" + +#: ../cursesdisplay.c:1291 ../sdldisplay.c:2878 +#, c-format +msgid "Set keys for '%s'" +msgstr "Set keys for '%s'" + +#: ../sdldisplay.c:3230 +msgid "Show frames per second" +msgstr "Show frames per second" + +#: ../cursesdisplay.c:1357 ../sdldisplay.c:3231 +msgid "Show hidden items" +msgstr "Show hidden items" + +#: ../menu.c:401 +msgid "Solved Positions" +msgstr "Solved Positions" + +#: ../xmlparser.c:89 +msgid "Stack overflow in parser_push()" +msgstr "Stack overflow in parser_push()" + +#: ../main.c:218 +msgid "Stop Replaying Position" +msgstr "Stop Replaying Position" + +#: ../editor.c:172 +msgid "Test Level" +msgstr "Test Level" + +#: ../editor.c:671 +msgid "Title" +msgstr "Title" + +#: ../editor.c:458 ../editor.c:465 ../editor.c:475 ../editor.c:485 +#: ../editor.c:495 ../editor.c:505 ../editor.c:515 +#, c-format +msgid "Too many %s" +msgstr "Too many %s" + +#: ../util.c:100 +#, c-format +msgid "Unable to create directory '%s': %s" +msgstr "Unable to create directory '%s': %s" + +#: ../sdlscreen.c:100 +msgid "Unable to create screen in screen_size" +msgstr "Unable to create screen in screen_size" + +#: ../sdlfont.c:156 +msgid "Unable to create stroker" +msgstr "Unable to create stroker" + +#: ../sdldisplay.c:154 +#, c-format +msgid "Unable to initalise SDL: %s" +msgstr "Unable to initalise SDL: %s" + +#: ../sdlfont.c:123 +#, c-format +msgid "Unable to initialise freetype: error=%d" +msgstr "Unable to initialise freetype: error=%d" + +#: ../sdlfont.c:128 +#, c-format +msgid "Unable to load font: error=%d" +msgstr "Unable to load font: error=%d" + +#: ../sdlfont.c:367 +msgid "Unable to open font" +msgstr "Unable to open font" + +#: ../sdlfont.c:148 +msgid "Unable to set font size" +msgstr "Unable to set font size" + +#: ../sdldisplay.c:2441 +msgid "Undo Speed" +msgstr "Undo Speed" + +#: ../editor.c:418 +#, c-format +msgid "Unsupported %s resting on %s at (%d,%d)" +msgstr "Unsupported %s resting on %s at (%d,%d)" + +#: ../main.c:352 +msgid "Use [UP] and [DOWN] to scroll" +msgstr "Use [UP] and [DOWN] to scroll" + +#: ../editor.c:173 ../editor.c:351 +msgid "Verify Level" +msgstr "Verify Level" + +#: ../editor.c:728 +msgid "XOR" +msgstr "XOR" + +#: ../cursesdisplay.c:1412 ../sdldisplay.c:3296 +msgid "XOR Display" +msgstr "XOR Display" + +#: ../cursesdisplay.c:1411 ../sdldisplay.c:3295 +msgid "XOR Engine" +msgstr "XOR Engine" + +#: ../cursesdisplay.c:1004 ../cursesdisplay.c:1405 ../sdldisplay.c:2454 +#: ../sdldisplay.c:3289 +msgid "XOR Options" +msgstr "XOR Options" + +#: ../editor.c:242 ../sdldisplay.c:2473 +msgid "Yes" +msgstr "Yes" + +#: ../menu.c:416 +msgid "[DELETE] to delete a position" +msgstr "[DELETE] to delete a position" + +#: ../colours.c:355 ../colours.c:384 ../cursesdisplay.c:1020 +#: ../sdldisplay.c:2536 +msgid "[untitled colours]" +msgstr "[untitled colors]" + +#: ../graphics.c:370 ../graphics.c:401 ../sdldisplay.c:2499 +#: ../sdldisplay.c:2502 +msgid "[untitled graphics]" +msgstr "[untitled graphics]" + +#: ../editor.c:187 ../editor.c:229 ../editor.c:235 ../main.c:226 ../menu.c:574 +msgid "[untitled level]" +msgstr "[untitled level]" + +#: ../cursesdisplay.c:1029 ../cursesdisplay.c:1043 +#, c-format +msgid "after a key is pressed" +msgstr "after a key is pressed" + +#: ../cursesdisplay.c:1417 ../sdldisplay.c:3301 +msgid "approximate" +msgstr "approximate" + +#: ../sdldisplay.c:2490 +#, c-format +msgid "curses" +msgstr "curses" + +#: ../cursesdisplay.c:1417 ../sdldisplay.c:3301 +msgid "exact" +msgstr "exact" + +#: ../cursesdisplay.c:267 ../menu.c:591 ../sdldisplay.c:849 +#, c-format +msgid "failed" +msgstr "failed" + +#: ../cursesdisplay.c:1418 ../sdldisplay.c:3302 +msgid "full" +msgstr "full" + +#: ../cursesdisplay.c:1032 ../cursesdisplay.c:1046 +#, c-format +msgid "instantaneous" +msgstr "instantaneous" + +#: ../cursesdisplay.c:1362 ../cursesdisplay.c:1363 ../sdldisplay.c:3236 +#: ../sdldisplay.c:3237 ../sdldisplay.c:3238 ../sdldisplay.c:3239 +msgid "no" +msgstr "no" + +#: ../cursesdisplay.c:1418 ../sdldisplay.c:3302 +msgid "partial" +msgstr "partial" + +#: ../cursesdisplay.c:258 ../cursesdisplay.c:263 ../sdldisplay.c:840 +#: ../sdldisplay.c:845 +msgid "paused " +msgstr "paused " + +#: ../cursesdisplay.c:259 ../sdldisplay.c:841 +msgid "replay " +msgstr "replay " + +#: ../cursesdisplay.c:300 ../menu.c:588 ../menu.c:612 ../sdldisplay.c:911 +#, c-format +msgid "solved" +msgstr "solved" + +#: ../cursesdisplay.c:464 ../cursesdisplay.c:472 ../sdldisplay.c:785 +msgid "testing: " +msgstr "testing: " + +#: ../main.c:83 +#, c-format +msgid "version %s" +msgstr "version %s" + +#: ../editor.c:232 +msgid "with:" +msgstr "with:" + +#: ../cursesdisplay.c:1362 ../cursesdisplay.c:1363 ../sdldisplay.c:3236 +#: ../sdldisplay.c:3237 ../sdldisplay.c:3238 ../sdldisplay.c:3239 +msgid "yes" +msgstr "yes" + +# translated level titles *must* begin with the English word "chroma" +msgid "chroma 1 : initiation" +msgstr "chroma 1 : initiation" + +msgid "for beginners" +msgstr "for beginners" + +msgid "chroma 1.01 : invitation" +msgstr "chroma 1.01 : invitation" + +msgid "chroma 1.02 : illustration" +msgstr "chroma 1.02 : illustration" + +msgid "chroma 1.03 : elaboration" +msgstr "chroma 1.03 : elaboration" + +msgid "chroma 1.04 : detonation" +msgstr "chroma 1.04 : detonation" + +msgid "chroma 1.05 : complication" +msgstr "chroma 1.05 : complication" + +msgid "chroma 1.06 : transportation" +msgstr "chroma 1.06 : transportation" + +msgid "chroma 1.07 : collaboration" +msgstr "chroma 1.07 : collaboration" + +msgid "chroma 1.08 : preparation" +msgstr "chroma 1.08 : preparation" + +msgid "chroma 1.09 : application" +msgstr "chroma 1.09 : application" + +msgid "chroma 2 : coronation" +msgstr "chroma 2 : coronation" + +msgid "for experts" +msgstr "for experts" + +msgid "chroma 2.01 : inauguration" +msgstr "chroma 2.01 : inauguration" + +msgid "chroma 2.02 : manipulation" +msgstr "chroma 2.02 : manipulation" + +msgid "chroma 2.03 : edification" +msgstr "chroma 2.03 : edification" + +msgid "chroma 2.04 : disintegration" +msgstr "chroma 2.04 : disintegration" + +msgid "chroma 2.05 : triplication" +msgstr "chroma 2.05 : triplication" + +msgid "chroma 2.06 : orchestration" +msgstr "chroma 2.06 : orchestration" + +msgid "chroma 2.07 : augmentation" +msgstr "chroma 2.07 : augmentation" + +msgid "chroma 2.08 : conflagration" +msgstr "chroma 2.08 : conflagration" + +msgid "chroma 2.09 : restoration" +msgstr "chroma 2.09 : restoration" + +msgid "chroma 2.10 : perturbation" +msgstr "chroma 2.10 : perturbation" + +msgid "chroma 2.11 : bifurcation" +msgstr "chroma 2.11 : bifurcation" + +msgid "chroma 2.12 : culmination" +msgstr "chroma 2.12 : culmination" + +msgid "chroma 0 : regression" +msgstr "chroma 0 : regression" + +msgid "for hackers" +msgstr "for hackers" + +msgid "chroma 0.00 : pieces" +msgstr "chroma 0.00 : pieces" + +msgid "chroma 0.01 : regression tests" +msgstr "chroma 0.01 : regression tests" + +# Actions +msgid "Click to move player" +msgstr "Click to move player" + +msgid "Click to move player, drag to scroll screen" +msgstr "Click to move player, drag to scroll screen" + +msgid "Click to set piece" +msgstr "Click to set piece" + +msgid "Click to set piece, drag to scroll screen" +msgstr "Click to set piece, drag to scroll screen" + +msgid "Click to swap player" +msgstr "Click to swap player" + +msgid "Do nothing" +msgstr "Do nothing" + +msgid "Drag to scroll screen" +msgstr "Drag to scroll screen" + +msgid "Fast" +msgstr "Fast" + +msgid "Faster" +msgstr "Faster" + +msgid "Hide screen" +msgstr "Hide screen" + +msgid "Mouse click" +msgstr "Mouse click" + +msgid "Mouse drag" +msgstr "Mouse drag" + +msgid "Mouse drag or click" +msgstr "Mouse drag or click" + +msgid "Move down" +msgstr "Move down" + +msgid "Move left" +msgstr "Move left" + +msgid "Move right" +msgstr "Move right" + +msgid "Move up" +msgstr "Move up" + +msgid "Page down" +msgstr "Page down" + +msgid "Page up" +msgstr "Page up" + +msgid "Pause" +msgstr "Pause" + +msgid "Piece left" +msgstr "Piece left" + +msgid "Piece left / Page up" +msgstr "Piece left / Page up" + +msgid "Piece right" +msgstr "Piece right" + +msgid "Piece right / Page down" +msgstr "Piece right / Page down" + +msgid "Redo move" +msgstr "Redo move" + +msgid "Redraw screen" +msgstr "Redraw screen" + +msgid "Select entry" +msgstr "Select entry" + +msgid "Slower" +msgstr "Slower" + +msgid "Swap players / Select" +msgstr "Swap players / Select" + +msgid "Undo move" +msgstr "Undo move" + +msgid "Undo move / Delete" +msgstr "Undo move / Delete" + +# Graphics schemes +msgid "Chroma Marble" +msgstr "Chroma Marble" + +msgid "Chroma Neon" +msgstr "Chroma Neon" + +msgid "Chroma Zen" +msgstr "Chroma Zen" + +msgid "Curses Emulation" +msgstr "Curses Emulation" + +msgid "Default Fallback" +msgstr "Default Fallback" + +# Colour schemes +msgid "Chroma Curses Enhanced" +msgstr "Chroma Curses Enhanced" + +msgid "Chroma Curses Enigma" +msgstr "Chroma Curses Enigma" + +msgid "Chroma Curses Monochrome" +msgstr "Chroma Curses Monochrome" + +msgid "Chroma Curses Reverse" +msgstr "Chroma Curses Reverse" + +msgid "Chroma Curses Standard" +msgstr "Chroma Curses Standard" diff --git a/resources/README b/resources/README new file mode 100644 index 0000000..8e6b881 --- /dev/null +++ b/resources/README @@ -0,0 +1,115 @@ +Resources +========= +This directory contains various resources for building the graphics used in +Chroma, as well as a script to allow XOR and Enigma to be played with Chroma. + +Graphics +======== +The graphics in Chroma come from the various SVG files in this directory, +which are automatically converted to PNGs in the required sizes by a number of +perl scripts. The entire process is started by make-graphics.sh, which will +rebuild all of the PNGs in graphics/chroma-*/. It requires the following: + + * Inkscape + http://www.inkscape.org/ + + * ImageMagick + http://www.imagemagick.org + + * Netpbm + http://netpbm.sourceforge.net/ + + * Pngcrush + http://pmt.sourceforge.net/pngcrush/index.html + +XOR +=== +XOR was published by Logotron Longman in 1987. It features fifteen mazes of +increasingly fiendish puzzles built from surreal elements such as chickens, +fish, bombs and dolls. It was released on a variety of platforms, including +the BBC Micro, Amstrad CPC, Commodore 64, ZX Spectrum and Atari ST. A later +release for the Amiga included a second set of fifteen further mazes. + + http://www.danceswithferrets.org/xor/ + +Enigma +====== +Enigma was devised by an anonymous author, and subsequently reimplemented by +Simon Tatham in 2000. It features twelve levels of falling blocks, exploding +bombs, and pushing stuff around - a mixture of Boulderdash, Sokoban and XOR. + + http://www.chiark.greenend.org.uk/~sgtatham/enigma/ + +convert2chroma.pl +================= +convert2chroma.pl is a perl script that allows Chroma to play both XOR and +Enigma. It will convert the levels and graphics from all of aforementioned +versions of XOR, as well as the levels from Enigma. Obviously, you will need +to obtain copies of the original games before convert2chroma.pl can be used! + +For BBC XOR, you'll need a disc image: + + convert2chroma.pl --bbc xor.ssd ~/.chroma + +For BBC XOR Designer, you'll need a disc image: + + convert2chroma.pl --designer xor-designer.ssd ~/.chroma + +For Spectrum XOR, you'll need a .tap tape image: + + convert2chroma.pl --spectrum xor-spectrum.tap ~/.chroma + +For Commodore 64 XOR, you'll need a memory snapshot: + + convert2chroma.pl --c64 c64-1.sta ~/.chroma + + (an emulator such as MESS will allow such a snapshot to be made) + +For Amstrad CPC XOR, you'll need a memory snapshot: + + convert2chroma.pl --cpc cpc464-1.sta ~/.chroma + + (an emulator such as MESS will allow such a snapshot to be made) + +For Atari ST XOR, you'll need a memory snapshot: + + convert2chroma.pl --atari hatari.sav ~/.chroma + + (an emulator such as Hatari will allow such a snapshot to be made) + +For Amiga XOR, you'll need to extract the xor_lib directory from the disc: + + convert2chroma.pl --amiga xor_lib/ ~/.chroma + +For Enigma, you'll need the levels directory from the tarball: + + convert2chroma.pl --enigma enigma-1.04/levels/ ~/.chroma + +A variety of more esoteric conversions may also be performed by +convert2chroma.pl - see the comments inside the script for more details. + +Once Chroma has seen XOR or Enigma levels, an additional menu will be available +from the Display Options menu. This will allow you to choose which game engine +is used to play XOR and Enigma levels, as well as how to display XOR levels: + + * XOR Engine + exact: use an (almost) exact reverse engineering of the original + BBC XOR game engine. This passes all but one of the regression + tests in levels/regression/xor-regression.chroma, but evolves + levels in a rather jerky manner, one piece at a time. + approximate: use the Chroma engine. This fails a number of the + regression tests, but has a smoother feel to it. + + * XOR Display + full: display the entire level. + partial: display an 8x8 scrolling window, as per the original XOR. + + * Enigma Engine + exact: use a reverse engineering of the original Enigma game engine. + This passes all of the regression tests in levels/regression/ + enigma-regression.chroma, but has some subtle display glitches + in graphical mode, such as pieces moving through each other. + + approximate: use the Chroma engine. This fails the regression tests, + but doesn't have the aforementioned display glitches. + diff --git a/resources/browser/graphics-marble.svg b/resources/browser/graphics-marble.svg new file mode 100644 index 0000000..43b74af --- /dev/null +++ b/resources/browser/graphics-marble.svg @@ -0,0 +1,3060 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/browser/graphics-neon.svg b/resources/browser/graphics-neon.svg new file mode 100644 index 0000000..944cd19 --- /dev/null +++ b/resources/browser/graphics-neon.svg @@ -0,0 +1,5657 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/browser/graphics-zen.svg b/resources/browser/graphics-zen.svg new file mode 100644 index 0000000..a3e12d9 --- /dev/null +++ b/resources/browser/graphics-zen.svg @@ -0,0 +1,945 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/browser/preview-marble.svg b/resources/browser/preview-marble.svg new file mode 100644 index 0000000..b704e1b --- /dev/null +++ b/resources/browser/preview-marble.svg @@ -0,0 +1,318 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/browser/preview-neon.svg b/resources/browser/preview-neon.svg new file mode 100644 index 0000000..bd2826a --- /dev/null +++ b/resources/browser/preview-neon.svg @@ -0,0 +1,966 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/browser/preview-zen.svg b/resources/browser/preview-zen.svg new file mode 100644 index 0000000..eedc6ac --- /dev/null +++ b/resources/browser/preview-zen.svg @@ -0,0 +1,129 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/convert2chroma.pl b/resources/convert2chroma.pl new file mode 100755 index 0000000..eb59e14 --- /dev/null +++ b/resources/convert2chroma.pl @@ -0,0 +1,3951 @@ +#! /usr/bin/perl +# +# convert2chroma.pl +# Convert various other games into a format playable by Chroma +# +# The following inputs are recognised: +# +# BBC, BBC Designer - disc image, memory snapshot +# C64 - memory snapshot +# Spectrum - tape image, memory snapshot +# CPC - memory snapshot +# Atari - memory snapshot +# Amiga - xor_lib directory +# +############################################################################### +# +# Copyright (C) 2010-2019 Amf +# +# 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 +# +############################################################################### +# +# BBC levels +# ========== +# The BBC XOR Designer file format is as follows: +# +# in file in memory +# 0x000 - 0x1c1 Map data 0x900 - 0xbff +# 0x1c2 - 0x1c3 Address of top left map piece - 32 0x78 - 0x79 +# 0x1c4 - 0x1c5 Address of top right map piece - 32 0x7a - 0x7b +# 0x1c6 - 0x1c7 Address of bottom left map piece - 32 0x7c - 0x7d +# 0x1c8 - 0x1c9 Address of bottom right map piece - 32 0x7e - 0x7f +# 0x1ca - 0x1cb Address of Player1 - 32 0x80 - 0x81 +# 0x1cc - 0x1cd Offset of Player1 from View1 (x,y) 0x82 - 0x83 +# 0x1ce - 0x1cf View1 (x,y) 0x84 - 0x85 +# 0x1d0 - 0x1d1 Address of View1 0x86 - 0x87 +# 0x1d2 - 0x1d3 Address of Player2 - 32 0x88 - 0x89 +# 0x1d4 - 0x1d5 Offset of Player2 from View2 (x,y) 0x8a - 0x8b +# 0x1d6 - 0x1d7 View2 (x, y) 0x8c - 0x8d +# 0x1d8 - 0x1d9 Address of View2 0x8e - 0x8f +# 0x1da Current player (must be 0x02) 0x90 +# 0x1db Unused - Other player alive (ignored, 0x02) 0x91 +# 0x1dc Masks total 0x92 +# 0x1dd Masks collected (must be 0x00) 0x93 +# 0x1de Unused - List length (must be 0x00) 0x94 +# 0x1df Unused - Explosion number (ignored, 0x00) 0x95 +# 0x1e0 Unused - Switched (ignored, 0x00) 0x96 +# 0x1e1 Unused (0x00) 0x97 +# 0x1e2 - 0x1e3 Address of Teleport1 0x98 - 0x99 +# 0x1e4 - 0x1e5 Offset of Teleport1 from ViewTeleport1 (x,y) 0x9a - 0x9b +# 0x1e6 - 0x1e7 ViewTeleport1 (x,y) 0x9c - 0x9d +# 0x1e8 - 0x1e9 Address of ViewTeleport1 0x9e - 0x9f +# 0x1ea - 0x1eb Address of Teleport2 0xa0 - 0xa1 +# 0x1ec - 0x1ed Offset of Teleport2 from ViewTeleport2 (x,y) 0xa2 - 0xa3 +# 0x1ee - 0x1ef ViewTeleport2 (x,y) 0xa4 - 0xa5 +# 0x1f0 - 0x1f1 Address of ViewTeleport2 0xa6 - 0xa7 +# 0x1f2 - 0x1ff Unused (0x00) +# 0x200 - 0x211 Title +# 0x220 - 0x283 Completion message +# +# For BBC XOR, the level data is split into two chunks, 0x000 - 0x1ff and +# 0x200 - 0x211, located in different parts of the file. There is no +# completion message. +# +# In memory, the map data is stored in a 32 * 32 byte array, starting at 0x900. +# The address for the piece at (x, y) is therefore 0x900 + x + (32 * y). In the +# file, the map data defines only the inner grid from (1,1) to (30,30). It runs +# from left to right, top to bottom, and should be read as nibbles, with the +# least significant nibble coming first. The nibbles translate as follows: +# +# 0x0 Space PIECE_SPACE +# 0x1 Wall % PIECE_WALL +# 0x2 Magus 1 PIECE_PLAYER_ONE +# 0x3 Questor 2 PIECE_PLAYER_TWO +# 0x4 Map MmNn PIECE_MAP_[TOP|BOTTOM]_[LEFT|RIGHT] +# 0x5 Dots - PIECE_DOTS_X +# 0x6 Waves | PIECE_DOTS_Y +# 0x7 Fish d PIECE_ARROW_RED_DOWN +# 0x8 Chicken a PIECE_ARROW_RED_LEFT +# 0x9 H Bomb D PIECE_BOMB_RED_DOWN +# 0xa V Bomb A PIECE_BOMB_RED_LEFT +# 0xb Mask * PIECE_STAR +# 0xc Door / PIECE_DOOR +# 0xd Fat Doll o PIECE_CIRCLE +# 0xe Beam Me Up Scotty T PIECE_TELEPORT +# 0xf Switch S PIECE_SWITCH +# +# The map pieces are stored ambiguously in the map data. To resolve this, the +# address of each map piece is stored separately in 0x1c2 - 0x1c9. Note that +# these addresses, as well as those for the players, are offset by 32 bytes to +# allow for relative addressing - disassembling the code makes this clearer. +# +# Contrary to what the value of 0x1da might suggest, Questor moves first, +# thanks to a call to 0x17b7 when setting up the level - this is a hack. +# +# The completion message is XORed with 0x7e to prevent casual reading. +# +# There are fourteen common levels shared between BBC XOR and BBC XOR Designer: +# +# title differences +# 1: Dots And Waves View2 +# 2: Something Fishy +# 3: Chicken Supreme View1 View2 +# 4: Explosive Mixture View1 +# 5: Henrys Anguish View1 View2 +# 6: The Dolls House View1 View2 +# 7: Dollys Revenge View1 View2 +# 8: Enlightenment View2 +# 9: The Challenge View1 View2 +# 10: Patience Pending View1 View2 ViewTeleport1 ViewTeleport2 +# 11: Razor Edge View2 ViewTeleport1 ViewTeleport2 +# 12: The Happy Hour View2 ViewTeleport1 +# 13: Deja Vu View2 +# 14: Penultimate View1 View2 ViewTeleport1 +# +# BBC XOR has a fifteenth level not present in XOR Designer: +# +# 15: The Decoder +# +# BBC XOR Designer has two hidden levels which aren't directly accessible: +# +# x1: Wheel Of Fortune +# x2: The Hidden Cavern +# +# BBC graphics +# ============ +# The XOR Designer graphics format contains 16 sprites, following the order +# used for map data. Each sprite is stored in 72 bytes, being 12 x 24 pixels +# in standard BBC four colour mode. For XOR, the sprites for the walls are +# stored separately to the sprites for the pieces. There are also two extra +# wall sprites which we add to the end of the standard 16. +# +# Commodore 64 levels and graphics +# ================================ +# The Commodore 64 XOR levels and graphics are stored in an identical format +# to those of the BBC version, and thus may be extracted in a similar way. +# Again, Questor move first. There are no differences between the levels and +# those of the BBC version. +# +# ZX Spectrum levels +# ================== +# The ZX Spectrum version splits the level data into two different chunks - +# the map data itself, and the location data, which takes the following format: +# +# 0x00 - 0x01 Player1 (x, y) +# 0x02 - 0x03 Address of Player1 +# 0x04 - 0x05 Offset of Player1 from View1 (x, y) +# 0x06 - 0x07 Address of View1 +# 0x08 - 0x09 Player2 (x, y) +# 0x0a - 0x0b Address of Player2 +# 0x0c - 0x0d Offset of Player2 from View1 (x, y) +# 0x0e - 0x0f Address of View2 +# 0x10 Masks total (binary packed decimal) +# 0x11 - 0x02 Address of Teleport2 +# 0x13 - 0x14 Teleport1 (x, y) +# 0x15 - 0x16 Address of Teleport1 +# 0x17 - 0x18 Offset of Teleport1 from ViewTeleport1 (x, y) +# 0x19 - 0x1a Address of ViewTeleport1 +# 0x1b - 0x1c Address of Teleport1 +# 0x1d - 0x1e Teleport2 (x, y) +# 0x1f - 0x20 Address of Teleport2 +# 0x21 - 0x22 Offset of Teleport2 from ViewTeleport2 (x, y) +# 0x23 - 0x24 Address of ViewTeleport2 +# 0x25 - 0x26 Address of top left map piece +# 0x25 - 0x26 Address of top right map piece +# 0x25 - 0x26 Address of bottom left map piece +# 0x25 - 0x26 Address of bottom right map piece +# 0x2d - 0x2e Address of map data +# +# The map data is stored as per BBC XOR, and is unpacked to memory at 0xe500. +# The address for the piece at (x, y) is therefore 0xe500 + x + (32 * y). +# Unlike the BBC version, none of the addresses are offset in any way, and +# Magus is the first to move. +# +# title differences from the BBC version +# 1: Dots And Waves View1 View2 +# 2: Something Fishy 1 (extra wall) +# 3: Chicken Supreme +# 4: Explosive Mixture 3 (maps swapped), View1 +# 5: Henrys Anguish +# 6: The Dolls House +# 7: Dollys Revenge +# 8: Enlightenment +# 9: The Challenge View1 View2 +# 10: Patience Pending +# 11: Razor Edge 2 (maps swapped) +# 12: The Happy Hour +# 13: Deja Vu +# 14: Penultimate 2 (players swapped), View1 View2 +# 15: The Decoder +# +# Amstrad CPC levels +# ================== +# The Amstrad CPC XOR levels are stored in a similar format to those of the +# ZX Spectrum version, with the exception that the map data is unpacked to +# memory at 0x3c00, which affects the addresses stored in the location data. +# Again, Magus is the first to move. +# +# title differences from the BBC version +# 1: Dots And Waves View1 View2 +# 2: Something Fishy 1 (extra wall) +# 3: Chicken Supreme +# 4: Explosive Mixture 3 (maps swapped), View1 +# 5: Henrys Anguish +# 6: The Dolls House +# 7: Dollys Revenge +# 8: Enlightenment +# 9: The Challenge View1 View2 +# 10: Patience Pending +# 11: Razor Edge 2 (maps swapped) +# 12: The Happy Hour +# 13: Deja Vu +# 14: Penultimate 2 (players swapped), View1 View2 +# 15: The Decoder 10 (corruption of final line) +# +# title differences from the Spectrum version +# 15: The Decoder 10 (corruption of final line) +# +# Atari ST levels +# =============== +# The Atari ST level format is as follows: +# +# 0x000 - 0x3ff Map data +# 0x400 - 0x401 View1x +# 0x402 - 0x403 View1y +# 0x404 - 0x405 Offset from View1x to Player1x +# 0x406 - 0x407 Offset from View1y to Player1y +# 0x408 - 0x409 0x00 0x11 +# 0x40a - 0x40b View2x +# 0x40c - 0x40d View2y +# 0x40e - 0x40f Offset from View2x to Player2x +# 0x410 - 0x411 Offset from View2y to Player2y +# 0x412 - 0x413 0x00 0x12 +# 0x414 - 0x415 Masks total +# 0x416 - 0x417 ViewTeleport1x +# 0x418 - 0x419 ViewTeleport1y +# 0x41a - 0x41b 0x00 0x00 +# 0x41c - 0x41d Address of Teleport1 +# 0x41e - 0x41f Offset from ViewTeleport1x to Teleport1x +# 0x420 - 0x421 Offset from ViewTeleport1y to Teleport1y +# 0x422 - 0x423 ViewTeleport2x +# 0x424 - 0x425 ViewTeleport2y +# 0x426 - 0x427 0x00 0x00 +# 0x428 - 0x429 Address of Teleport2 +# 0x42a - 0x42b Offset from ViewTeleport2x to Teleport2x +# 0x42c - 0x42d Offset from ViewTeleport2y to Teleport2y +# 0x42e - 0x431 0x1b 0x59 0x21 0x23 +# 0x432 - 0x445 Title +# +# The address for (x,y) is stored as x + (32 * y) - there is no offset. +# The map data defines the whole grid from (0, 0) to (31, 31). It runs from +# left to right, then from top to bottom. It should be read as bytes, which +# are translated as follows: +# +# 0x00 Space PIECE_SPACE +# 0x01 Wall % PIECE_WALL +# 0x02 Magus 1 PIECE_PLAYER_ONE +# 0x03 Questor 2 PIECE_PLAYER_TWO +# 0x04 Map top left M PIECE_MAP_TOP_LEFT +# 0x05 Dots - PIECE_DOTS_X +# 0x06 Waves | PIECE_DOTS_Y +# 0x07 Fish d PIECE_ARROW_RED_DOWN +# 0x08 Chicken a PIECE_ARROW_RED_LEFT +# 0x09 H Bomb D PIECE_BOMB_RED_DOWN +# 0x0a V Bomb A PIECE_BOMB_RED_LEFT +# 0x0b Mask * PIECE_STAR +# 0x0c Door / PIECE_DOOR +# 0x0d Fat Doll o PIECE_CIRCLE +# 0x0e Map top right m PIECE_MAP_TOP_RIGHT +# 0x0f Map bottom left N PIECE_MAP_BOTTOM_LEFT +# 0x10 Map bottom right n PIECE_MAP_BOTTOM_RIGHT +# 0x11 Beam Me Up Scotty T PIECE_TELEPORT +# 0x12 Switch S PIECE_SWITCH +# 0x13 Fish d PIECE_ARROW_RED_DOWN +# 0x14 Chicken a PIECE_ARROW_RED_LEFT +# 0x15 Chicken a PIECE_ARROW_RED_LEFT +# 0x16 Fish d PIECE_ARROW_RED_DOWN +# 0x17 Fish d PIECE_ARROW_RED_DOWN +# 0x18 Chicken a PIECE_ARROW_RED_LEFT +# 0x19 Chicken a PIECE_ARROW_RED_LEFT +# 0x1a Fish d PIECE_ARROW_RED_DOWN +# 0x21 - 0x5c Wall % PIECE_WALL +# 0x61 End piece ? PIECE_UNKNOWN +# 0x62 Wall % PIECE_WALL +# +# Magus moves first. +# +# title differences from the BBC version +# 1: Dots And Waves 1 View1 View2 +# 2: Something Fishy 3 (players swapped) +# 3: Chicken Supreme +# 4: Explosive Mixture +# 5: Henrys Anguish 2 (players swapped) View1 View2 +# 6: The Dolls House +# 7: Dollys Revenge +# 8: Enlightenment +# 9: The Challenge 1 View1 View2 +# 10: Patience Pending ViewTeleport1 ViewTeleport2 +# 11: Razor Edge +# 12: The Happy Hour View2 ViewTeleport1 ViewTeleport2 +# 13: Deja Vu +# 14: Penultimate View1 View2 ViewTeleport1 +# 15: The Decoder Ending ViewTeleport1 ViewTeleport2 +# +# Amiga levels +# ============ +# Amiga .maze files have fifteen levels, sequentially, each with the following +# format: +# +# 0x000 - 0x01e Title +# 0x01f - 0x41e Map Data +# 0x420 - 0x423 View 1 x +# 0x424 - 0x427 View 1 y +# 0x428 - 0x42b Player 1 x +# 0x42c - 0x42f Player 1 y +# 0x430 - 0x433 View 2 x +# 0x434 - 0x437 View 2 y +# 0x438 - 0x43b Player 2 x +# 0x43c - 0x43f Player 2 y +# 0x440 - 0x443 Mask Total +# 0x444 - 0x447 ViewTeleport 1 x +# 0x448 - 0x44b ViewTeleport 1 y +# 0x44c - 0x44f Teleport 1 x +# 0x450 - 0x453 Teleport 1 y +# 0x454 - 0x457 ViewTeleport 1 x +# 0x458 - 0x45b ViewTeleport 1 y +# 0x45c - 0x45f Teleport 1 x +# 0x460 - 0x463 Teleport 1 y +# +# The map data defines the whole grid from (0, 0) to (31, 31). It runs from +# left to right, then from top to bottom. It should be read as bytes; the +# lowest six bits of each byte determine the piece: +# +# 0x00 Space PIECE_SPACE +# 0x01 Magus 1 PIECE_PLAYER_ONE +# 0x02 Questor 2 PIECE_PLAYER_TWO +# 0x03 Fish v PIECE_ARROW_RED_DOWN +# 0x04 Chicken < PIECE_ARROW_RED_LEFT +# 0x05 Fat Doll o PIECE_CIRCLE +# 0x06 Mask * PIECE_STAR +# 0x07 Switch S PIECE_SWITCH +# 0x08 Map TL M PIECE_MAP_TOP_LEFT +# 0x09 Map TR m PIECE_MAP_TOP_RIGHT +# 0x0a Map BL N PIECE_MAP_BOTTOM_LEFT +# 0x0b Map BR n PIECE_MAP_BOTTOM_RIGHT +# 0x0c Beam Me Up Scotty T PIECE_TELEPORT +# 0x0d Waves | PIECE_EARTH_Y +# 0x0e Dots - PIECE_EARTH_X +# 0x0f V Bomb Z PIECE_BOMB_RED_LEFT +# 0x10 H Bomb X PIECE_BOMB_RED_DOWN +# 0x11 Door / PIECE_DOOR +# 0x20 Wall % PIECE_WALL +# +# Questor is the first to move. +# +# There are two sets of fifteen levels: +# +# XOR's Mazes: +# +# Amiga title BBC equivalent differences from BBC version +# 1: Olaf's Warm Up Dots and Waves 2 View1 View2 +# 2: Rocks & Zeppelins Something Fishy 3 (players swapped) +# 3: Something Tricky Chicken Supreme +# 4: Explosive Mixture Explosive Mixture +# 5: Erik's Anguish Henrys Anguish 3 (players swapped) View1 View2 +# 6: The Ball's House The Doll's House +# 7: Rolling Revenge Dollys Revenge +# 8: Enlightenment Enlighenment +# 9: The Challenge The Challenge 1 View1 View2 +# 10: Patience Pending Patience Pending ViewTeleport1 ViewTeleport2 +# 11: Razor Edge Razor Edge 8 (last line corrupted) +# 12: The Happy Hour The Happy Hour View2 ViewTeleport1 ViewTeleport2 +# 13: Deja Vu Deja Vu +# 14: Penultimate Penultimate View1 View ViewTeleport2 +# 15: The Decoder The Decoder Ending ViewTeleport1 ViewTeleport2 +# +# +# Procyon's Mazes: +# +# Amiga title BBC equivalent differences from BBC version +# 1: Taurus +# 2: Andromeda +# 3: Perseus +# 4: Cameloparous +# 5: Ursa Nagor insoluble! +# 6: Draco +# 7: Hercules +# 8: Delphinus +# 9: Aquila +# 10: Ophiuchus Wheel of Fortune 2 View1 View2 ViewTeleport1 ViewTeleport2 +# 11: Corvus +# 12: Canis Maior +# 13: Hydrus +# 14: Vela Carina insoluble! +# 15: Crux The Hidden Cavern View1 View2 ViewTeleport2 +# +# Amiga Graphics +# ============== +# There are fifteen sets of 20 background sprites in the "vimages*" files. The +# format begins with a 32 colour palette, with each entry taking two bytes, of +# the form 0x0R 0xGB. This is followed by a number of 960 byte blocks, with +# each block encoding one bit of colour data for ten sprites. Within each +# block, the first three bytes of a word encode 24 pixels for a sprite. The +# first two blocks encode bit 1 for sprites 0 - 9 and 10 - 19, the next two +# encode bit 2, and so on. +# +# The "cimages" file contains one set of 60 character sprites. It takes a +# similar format to the "vimages*" files, but contains no palette information. +# +# Enigma +# ====== +# Enigma has five different wall pieces, but these are merely cosmetic. We +# merge them all into the single wall piece present in Chroma. Enigma also has +# "certain death" piece, which we also replace with a wall, on the basis that +# in a successful game, the player will interact with this piece in exactly the +# same manner as a wall. +# + +@commands = ( + # Convert XOR levels and graphics + ["bbc", \&convert_bbc_all], + ["designer", \&convert_designer_all], + ["c64", \&convert_c64_all], + ["spectrum", \&convert_spectrum_all], + ["cpc", \&convert_cpc_all], + ["atari", \&convert_atari_all], + ["amiga", \&convert_amiga_all], + + # Convert XOR levels + ["bbc-levels", \&convert_bbc_levels], + ["c64-levels", \&convert_bbc_levels], + ["designer-levels", \&convert_designer_levels], + ["designer-level-file", \&convert_designer_level], + ["spectrum-levels", \&convert_spectrum_levels], + ["cpc-levels", \&convert_spectrum_levels], + ["atari-levels", \&convert_atari_levels], + ["amiga-levels", \&convert_amiga_levels], + + # Convert XOR graphics + ["bbc-graphics", \&convert_bbc_graphics], + ["c64-graphics", \&convert_c64_graphics], + ["designer-graphics", \&convert_bbc_graphics], + ["designer-graphics-file", \&convert_bbc_graphics_file], + ["spectrum-graphics", \&convert_spectrum_graphics], + ["cpc-graphics", \&convert_cpc_graphics], + ["atari-graphics", \&convert_atari_graphics], + ["amiga-graphics", \&convert_amiga_graphics], + ["amiga-graphics-file", \&convert_amiga_graphics_file], + + # Convert BBC XOR music + ["bbc-music", \&convert_bbc_music], + # Patch BBC XOR disc image to show all levels + ["bbc-patch", \&convert_bbc_patch], + # Patch Amiga disc image to avoid manual "copy protection" check + ["amiga-patch", \&convert_amiga_patch], + + # Convert Chroma XOR levels back into 8bit binary files + ["chroma2xor", \&convert_chroma2xor], + + # Convert third party XOR files + ["zanten-file", \&convert_zanten_level], # http://www.rvvz.demon.nl/xor/ + ["ovine-file", \&convert_ovine_level], # http://xor.ovine.net/ + + # Convert Engima level(s) + ["enigma", \&convert_enigma], + ["enigma-file", \&convert_enigma_file], + ["chroma2enigma", \&convert_chroma2enigma] + + ); + +@titles = ( + "Dots and Waves", + "Something Fishy", + "Chicken Supreme", + "Explosive Mixture", + "Henrys Anguish", + "The Dolls House", + "Dollys Revenge", + "Enlightenment", + "The Challenge", + "Patience Pending", + "Razor Edge", + "The Happy Hour", + "Deja Vu", + "Penultimate", + "The Decoder" + ); + +if($#ARGV >= 2) +{ + for($i = 0; $i <= $#commands; $i ++) + { + if($ARGV[0] eq "--".$commands[$i][0]) + { + $command = $commands[$i][1]; + &$command($ARGV[1], $ARGV[2]); + exit(0); + } + } +} + +print STDERR << "EOF"; +Usage: convert2chroma.pl + + convert2chroma.pl --bbc # BBC XOR + convert2chroma.pl --designer # BBC XOR Designer + convert2chroma.pl --c64 # Commodore 64 XOR + convert2chroma.pl --spectrum # Spectrum XOR + convert2chroma.pl --cpc # Amstrad CPC XOR + convert2chroma.pl --amiga # Amiga XOR + convert2chroma.pl --atari # Amiga ST XOR + + convert2chroma.pl --enigma # Enigma + +There are various other options available; see inside the script for details. + +EOF + +exit(0); + +############################################################################### + +sub read_file +{ + my $file = shift(@_); + my $data; + + open(INPUT, $file) || die "Couldn't open file ($file): $!\n"; + binmode INPUT; + undef $/; + $data = ; + close INPUT; + + return $data; +} + +sub locate_string +{ + my $data = shift(@_); + my $string = shift(@_); + my $name = shift(@_); + my $index; + + $index = index($$data, $string); + + if($index != -1 && index($$data, $string, $index + 1) != -1) + { + print "Ambiguous match"; + return -2; + } + + return $index; +} + +sub byte +{ + my $data = shift(@_); + my $offset = shift(@_); + + return ord(substr($$data, $offset, 1)); +} + +sub short +{ + my $data = shift(@_); + my $offset = shift(@_); + + return ord(substr($$data, $offset, 1)) + 256 * ord(substr($$data, $offset + 1, 1)); +} + +sub long +{ + my $data = shift(@_); + my $offset = shift(@_); + + return ord(substr($$data, $offset + 3, 1)) + 256 * ord(substr($$data, $offset + 2, 1)); +} + +sub convert_address +{ + my $address = shift(@_); + my $x = shift(@_); + my $y = shift(@_); + + $$x = $address % 32; + $$y = int($address / 32); +} + +sub make_directory +{ + my $directory = shift(@_); + + if(! -e $directory) + { + mkdir($directory, 0755) || die "Couldn't make directory ($directory): $!\n"; + } +} + +############################################################################### + +sub create_level +{ + my $level = shift(@_); + my $file_output = shift(@_); + + # 12M + $translation = " %???-|daDA*/oTS"; + + print "Creating level '$file_output': "; + + for($j = 0; $j < 32; $j ++) + { + for($i = 0; $i < 32; $i ++) + { + $map[$i][$j] = "%"; + } + } + + $title2number{"Andromeda"} = 2; + $title2number{"Aquila"} = 9; + $title2number{"Cameloparous"} = 4; + $title2number{"Canis Maior"} = 12; + $title2number{"Chicken Supreme"} = 3; + $title2number{"Corvus"} = 11; + $title2number{"Crux"} = 15; + $title2number{"Deja Vu"} = 13; + $title2number{"Delphinus"} = 8; + $title2number{"Dollys Revenge"} = 7; + $title2number{"Dots And Waves"} = 1; + $title2number{"Dots and Waves"} = 1; + $title2number{"Draco"} = 6; + $title2number{"Enlightenment"} = 8; + $title2number{"Erik's Anguish"} = 5; + $title2number{"Explosive Mixture"} = 4; + $title2number{"Henrys Anguish"} = 5; + $title2number{"Hercules"} = 7; + $title2number{"Hydrus"} = 13; + $title2number{"Olaf's Warm Up"} = 1; + $title2number{"Ophiuchus"} = 10; + $title2number{"Patience Pending"} = 10; + $title2number{"Penultimate"} = 14; + $title2number{"Perseus"} = 3; + $title2number{"Razor Edge"} = 11; + $title2number{"Rocks & Zeppelins"} = 2; + $title2number{"Rolling Revenge"} = 7; + $title2number{"Something Fishy"} = 2; + $title2number{"Something Tricky"} = 3; + $title2number{"Taurus"} = 1; + $title2number{"The Ball's House"} = 6; + $title2number{"The Challenge"} = 9; + $title2number{"The Decoder"} = 15; + $title2number{"The Dolls House"} = 6; + $title2number{"The Happy Hour"} = 12; +# $title2number{"The Hidden Cavern"} = 15; + $title2number{"Ursa Nagor"} = 5; + $title2number{"Vela Carina"} = 14; +# $title2number{"Wheel Of Fortune"} = 10; + + # Populate map from data + $teleports = 0; + + # Compressed map - four bits per piece + if($$level{"mode"} eq "8bit") + { + $offset = 0; + for($j = 1; $j < 31; $j ++) + { + for($i = 1; $i < 31; $i += 2) + { + $c = byte(\$$level{"map"}, $offset); + $offset ++; + + $c1 = $c % 16; + $c2 = ($c - %c1) / 16; + + $map[$i][$j] = substr($translation, $c1, 1); + $map[$i + 1][$j] = substr($translation, $c2, 1); + + if($map[$i][$j] eq "T" || $map[$i + 1][$j] eq "T") + { + $teleports ++; + } + } + } + } + + # Uncompressed map - one byte per piece + if($$level{"mode"} eq "amiga") + { + $offset = 0; + for($j = 0; $j < 32; $j ++) + { + for($i = 0; $i < 32; $i ++) + { + $c = byte(\$$level{"map"}, $offset); + $c = $c & 0x3f; # ? + $offset ++; + $m = "?"; + + $m = " " if($c == 0x00); + $m = "1" if($c == 0x01); + $m = "2" if($c == 0x02); + $m = "d" if($c == 0x03); + $m = "a" if($c == 0x04); + $m = "o" if($c == 0x05); + $m = "*" if($c == 0x06); + $m = "S" if($c == 0x07); + $m = "M" if($c == 0x08); + $m = "m" if($c == 0x09); + $m = "N" if($c == 0x0a); + $m = "n" if($c == 0x0b); + $m = "T" if($c == 0x0c); + $m = "|" if($c == 0x0d); + $m = "-" if($c == 0x0e); + $m = "A" if($c == 0x0f); + $m = "D" if($c == 0x10); + $m = "/" if($c == 0x11); + $m = "%" if($c == 0x20); + + if($m eq "T") + { + $teleports ++; + } + + if($m eq "?") + { + print "FAILED\n Unknown map piece 0x".sprintf("%02x", $c)." at ($i, $j)\n"; + return; + } + + $map[$i][$j] = $m; + } + } + } + + if($$level{"mode"} eq "atari") + { + for($j = 0; $j < 32; $j ++) + { + for($i = 0; $i < 32; $i ++) + { + $p = "?"; + $c = byte(\$level_data, $j*32+$i); + + $p = " " if($c == 0x00); + $p = "1" if($c == 0x02); + $p = "2" if($c == 0x03); + $p = "M" if($c == 0x04); + $p = "-" if($c == 0x05); + $p = "|" if($c == 0x06); + $p = "d" if($c == 0x07 || $c == 0x13 || $c == 0x16 || $c == 0x17 || $c == 0x1a); + $p = "a" if($c == 0x08 || $c == 0x14 || $c == 0x15 || $c == 0x18 || $c == 0x19); + $p = "D" if($c == 0x09); + $p = "A" if($c == 0x0a); + $p = "*" if($c == 0x0b); + $p = "/" if($c == 0x0c); + $p = "o" if($c == 0x0d); + $p = "m" if($c == 0x0e); + $p = "N" if($c == 0x0f); + $p = "n" if($c == 0x10); + $p = "T" if($c == 0x11); + $p = "S" if($c == 0x12); + + $p = "%" if($c == 0x55 || $c==0x56 || $c == 0x57 || $c == 0x58); # 1 + $p = "%" if($c == 0x49 || $c==0x4a || $c == 0x4b || $c == 0x4c); # 2 + $p = "%" if($c == 0x4d || $c==0x4e || $c == 0x4f || $c == 0x50); # 3 + $p = "%" if($c == 0x51 || $c==0x52 || $c == 0x53 || $c == 0x54); # 4 + $p = "%" if($c == 0x2d || $c==0x2e || $c == 0x2f || $c == 0x30 || $c == 0x62); # 5 + $p = "%" if($c == 0x31 || $c==0x32 || $c == 0x33 || $c == 0x34); # 6 + $p = "%" if($c == 0x27 || $c==0x28 || $c == 0x29 || $c == 0x2a); # 7 + $p = "%" if($c == 0x25 || $c==0x26 || $c == 0x2b || $c == 0x2c); # 8 + $p = "%" if($c == 0x01 || $c == 0x21 || $c==0x22 || $c == 0x23 || $c == 0x24); # 9 + $p = "%" if($c == 0x35 || $c==0x36 || $c == 0x37 || $c == 0x38); # 10 + $p = "%" if($c == 0x39 || $c==0x3a || $c == 0x3b || $c == 0x3c); # 11 + $p = "%" if($c == 0x3d || $c==0x3e || $c == 0x3f || $c == 0x40); # 12 + $p = "%" if($c == 0x41 || $c==0x42 || $c == 0x43 || $c == 0x44); # 13 + $p = "%" if($c == 0x45 || $c==0x46 || $c == 0x47 || $c == 0x48); # 14 + $p = "%" if($c == 0x59 || $c==0x5a || $c == 0x5b || $c == 0x5c); # 15 + + $p = "?" if($c == 0x61); + + $teleports ++ if($p eq "T"); + + $map[$i][$j] = $p; + } + } + } + + # Populate players + for($i = 1; $i <=2; $i ++) + { + $p = $map[$$level{"player".$i."x"}][$$level{"player".$i."y"}]; + if($p ne $i && $p ne " " && $p ne "?") + { + print "FAILED\n player $i is unmatched (map says '".$map[$$level{"player".$i."x"}][$$level{"player".$i."y"}]."')\n"; + return; + } + $map[$$level{"player".$i."x"}][$$level{"player".$i."y"}] = $i; + } + + # Populate maps + if($$level{"mode"} eq "8bit") + { + foreach $i ("TL", "TR", "BL", "BR") + { + if($map[$$level{"map".$i."x"}][$$level{"map".$i."y"}] ne "?") + { + print "FAILED\n map $i is unmatched (map says '".$map[$$level{"map".$i."x"}][$$level{"map".$i."y"}]."')\n"; + return; + } + } + $map[$$level{"mapTLx"}][$$level{"mapTLy"}] = "M"; + $map[$$level{"mapTRx"}][$$level{"mapTRy"}] = "m"; + $map[$$level{"mapBLx"}][$$level{"mapBLy"}] = "N"; + $map[$$level{"mapBRx"}][$$level{"mapBRy"}] = "n"; + } + + # Sanity check + $failed = 0; + for($j = 1; $j < 31; $j ++) + { + for($i = 1; $i < 31; $i ++) + { + if($map[$i][$j] eq "<" || $map[$i][$j] eq "Z") + { + if($map[$i-1][$j] eq " " || $map[$i-1][$j] eq "-") + { + $failed ++; + } + } + if($map[$i][$j] eq "v" || $map[$i][$j] eq "X") + { + if($map[$i][$j+1] eq " " || $map[$i][$j+1] eq "|") + { + $failed ++; + } + } + } + } + if($failed > 0) + { + print "FAILED\n $failed unsupported pieces\n"; + return; + } + + open(OUTPUT, ">".$file_output) || die "Unable to open file ($file_output) for writing: $!\n"; + + print OUTPUT "chroma level\n"; + print OUTPUT "mode: xor\n\n"; + print OUTPUT "title: XOR: ".$$level{"title"}."\n"; + print OUTPUT "size: 32 32\n"; + print OUTPUT "player: ".$$level{"player"}."\n" if($$level{"player"}); + if($title2number{$$level{"title"}}) + { + print OUTPUT "level: ".$title2number{$$level{"title"}}."\n"; + } + print OUTPUT "view1: ".$$level{"view1x"}." ".$$level{"view1y"}."\n"; + print OUTPUT "view2: ".$$level{"view2x"}." ".$$level{"view2y"}."\n"; + + if($teleports > 0) + { + print OUTPUT "viewteleport1: ".$$level{"viewteleport1x"}." ".$$level{"viewteleport1y"}." (".$$level{"teleport1x"}." ".$$level{"teleport1y"}.")\n"; + print OUTPUT "viewteleport2: ".$$level{"viewteleport2x"}." ".$$level{"viewteleport2y"}." (".$$level{"teleport2x"}." ".$$level{"teleport2y"}.")\n"; + } + + if($message ne "") + { + print OUTPUT "message: $message\n"; + } + + print OUTPUT "\ndata:\n"; + + for($j = 0; $j < 32; $j ++) + { + for($i = 0; $i < 32; $i ++) + { + print OUTPUT $map[$i][$j]; + } + print OUTPUT "\n"; + } + + close(OUTPUT); + + print "OK\n"; +} + +sub create_set +{ + my $file_output = shift(@_); + my $title = shift(@_); + + open(OUTPUT, ">".$file_output) || die "Unable to open file ($file_output) for writing: $!\n"; + + print OUTPUT << "EOF"; + + +$title + + +EOF + close(OUTPUT); +} + +sub create_bmp +{ + my $image = shift(@_); + my $file_output = shift(@_); + my $scale_x = shift(@_); + my $scale_y = shift(@_); + + $bpp = $$image{"colours"} <= 16 ? 4 : 8; + + $size_x = $$image{"x"} * $scale_x; + $size_y = $$image{"y"} * $scale_y; + $offset = 54 + ($$image{"colours"} * 4); + $size_data = $size_x * $size_y * $bpp / 8; + $size_file = $size_data + $offset; + + print "Creating graphic '$file_output'\n"; + + open(BMP, ">".$file_output) || die "Unable to open file ($file_output) for writing: $!\n"; + binmode BMP; + + print BMP "BM"; # header + print BMP pack("L", $size_file); # file length + print BMP pack("S", 0); # reserved + print BMP pack("S", 0); # reserved + print BMP pack("L", $offset); # offset to data + + print BMP pack("L", 0x28); # size of BITMAPINFOHEADER + print BMP pack("L", $size_x); # width + print BMP pack("L", $size_y); # height + print BMP pack("S", 1); # number of planes + print BMP pack("S", $bpp); # bits per pixel + print BMP pack("L", 0); # compression + print BMP pack("L", $size_data); # image size in bytes + print BMP pack("L", 0xb12); # pixels per metre horizontal + print BMP pack("L", 0xb12); # pixels per metre vertical + print BMP pack("L", $$image{"colours"}); # colours used + print BMP pack("L", $$image{"colours"}); # colours important + + for($i = 0; $i < $$image{"colours"}; $i ++) + { + print BMP pack("L", $image{"palette"}[$i]); + } + + for($y = $$image{"y"} - 1; $y >= 0; $y --) + { + for($ys = 0; $ys < $scale_y; $ys ++) + { + $byte = 0; $bits = 0; + for($x = 0; $x < $$image{"x"} ; $x ++ ) + { + for($xs = 0; $xs < $scale_x; $xs ++) + { + $byte = $byte * (2 ** $bits); + $byte += $$image{"pixels"}[$x][$y]; + $bits += $bpp; + + if($bits == 8) + { + print BMP pack("C", $byte); + $byte = 0; + $bits = 0; + } + } + } + if($bits != 0) + { + print BMP pack("C", $byte); + } + } + } + + close BMP; +} + +sub create_graphics_set +{ + my $file_output = shift(@_); + my $stub = shift(@_); + my $title = shift(@_); + my $size = shift(@_); + + open(OUTPUT, ">".$file_output) || die "Unable to open file ($file_output) for writing: $!\n"; + + print OUTPUT << "EOF"; + + + + +$title + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOF + + close(OUTPUT); +} + +############################################################################### + +sub convert_spectrum_levels +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + $data = read_file($file_input); + + # spectrum 0x9748 + $base = 0xe500; # Spectrum + $offset_locations = locate_string(\$data, "\x47\x22\xe5\x12\x01\x32\xe5\x02") - 16; + if($offset_locations < 0) + { + $base = 0x3c00; # CPC + $offset_locations = locate_string(\$data, "\x47\x22\x3c\x12\x01\x32\x3c\x02") - 16; + if($offset_locations < 0) + { + die "Unable to locate locations in input file\n"; + } + } + + # spectrum 0x6400 + $offset_maps= locate_string(\$data, "\x11\x11\x01\x10\x6b\x00\x40\x00") - 27; + if($offset_maps < 0) + { + die "Unable to locate maps in input file\n"; + } + + for($number = 1; $number < 16; $number ++) + { + undef %level; + $level{"map"} = substr($data, $offset_maps + (($number - 1) * 0x1c2), 0x1c2); + $locations = substr($data, $offset_locations + (($number - 1) * 0x2f), 0x2f); + + $level{"player1x"} = byte(\$locations, 0x00); + $level{"player1y"} = byte(\$locations, 0x01); + convert_address(short(\$locations, 0x06) - $base, \$level{"view1x"}, \$level{"view1y"}); + $level{"player2x"} = byte(\$locations, 0x08); + $level{"player2y"} = byte(\$locations, 0x09); + convert_address(short(\$locations, 0x0e) - $base, \$level{"view2x"}, \$level{"view2y"}); + + $level{"teleport1x"} = byte(\$locations, 0x13); + $level{"teleport1y"} = byte(\$locations, 0x14); + convert_address(short(\$locations, 0x19) - $base, \$level{"viewteleport1x"}, \$level{"viewteleport1y"}); + + $level{"teleport2x"} = byte(\$locations, 0x1d); + $level{"teleport2y"} = byte(\$locations, 0x1e); + convert_address(short(\$locations, 0x23) - $base, \$level{"viewteleport2x"}, \$level{"viewteleport2y"}); + + convert_address(short(\$locations, 0x25) - $base, \$level{"mapTLx"}, \$level{"mapTLy"}); + convert_address(short(\$locations, 0x27) - $base, \$level{"mapTRx"}, \$level{"mapTRy"}); + convert_address(short(\$locations, 0x29) - $base, \$level{"mapBLx"}, \$level{"mapBLy"}); + convert_address(short(\$locations, 0x2b) - $base, \$level{"mapBRx"}, \$level{"mapBRy"}); + + $level{"title"} = $titles[$number - 1]; + + $file_output = sprintf("%s%02d%s", $output_prefix, $number, ".chroma"); + + $level{"mode"} = "8bit"; + + create_level(\%level, $file_output); + } +} + +sub convert_bbc_levels +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + $data = read_file($file_input); + + $offset_data = locate_string(\$data, "\xb7\x09\x48\x09\x9d\x0c\x85\x0a") - 0x1c2; + if($offset_data < 0) + { + $offset_data = locate_string(\$data, "\x85\x0b\x81\x0a\xfa\x09\xb6\x0b") - 0x1c2; + } + if($offset_data < 0) + { + die "Unable to locate maps in input file\n"; + } + + $offset_title = locate_string(\$data, " DOTS AND WAVES "); + if($offset_title < 0) + { + $offset_title = locate_string(\$data, " TAURUS "); + } + $offset_title ++; + + for($number = 1; $number < 16; $number ++) + { + $level_data = substr($data, $offset_data, 0x200); + $offset_data -= 0x200; + + if($offset_title != 0) + { + $level_data .= substr($data, $offset_title, 18); + $offset_title += 0x17; + } + else + { + $level_data .= pack("A18", $titles[$number - 1]); + } + + $file_output = sprintf("%s%02d%s", $output_prefix, $number, ".chroma"); + + convert_bbc_level($level_data, $file_output); + } + +} + +sub convert_designer_levels +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + $data = read_file($file_input); + + if($data =~ /(.{512} DOTS AND WAVES .{114})/s) + { + convert_bbc_level($1, $output_prefix."01.chroma"); + } + if($data =~ /(.{512} SOMETHING FISHY .{114})/s) + { + convert_bbc_level($1, $output_prefix."02.chroma"); + } + if($data =~ /(.{512} CHICKEN SUPREME .{114})/s) + { + convert_bbc_level($1, $output_prefix."03.chroma"); + } + if($data =~ /(.{512}EXPLOSIVE MIXTURE .{114})/s) + { + convert_bbc_level($1, $output_prefix."04.chroma"); + } + if($data =~ /(.{512} HENRYS ANGUISH .{114})/s) + { + convert_bbc_level($1, $output_prefix."05.chroma"); + } + if($data =~ /(.{512} THE DOLLS HOUSE .{114})/s) + { + convert_bbc_level($1, $output_prefix."06.chroma"); + } + if($data =~ /(.{512} DOLLYS REVENGE .{114})/s) + { + convert_bbc_level($1, $output_prefix."07.chroma"); + } + if($data =~ /(.{512} ENLIGHTENMENT .{114})/s) + { + convert_bbc_level($1, $output_prefix."08.chroma"); + } + if($data =~ /(.{512} THE CHALLENGE .{114})/s) + { + convert_bbc_level($1, $output_prefix."09.chroma"); + } + if($data =~ /(.{512} PATIENCE PENDING .{114})/s) + { + convert_bbc_level($1, $output_prefix."10.chroma"); + } + if($data =~ /(.{512} RAZOR EDGE .{114})/s) + { + convert_bbc_level($1, $output_prefix."11.chroma"); + } + if($data =~ /(.{512} THE HAPPY HOUR .{114})/s) + { + convert_bbc_level($1, $output_prefix."12.chroma"); + } + if($data =~ /(.{512} DEJA VU .{114})/s) + { + convert_bbc_level($1, $output_prefix."13.chroma"); + } + if($data =~ /(.{512} PENULTIMATE .{114})/s) + { + convert_bbc_level($1, $output_prefix."14.chroma"); + } + if($data =~ /(.{512} WHEEL OF FORTUNE .{114})/s) + { + convert_bbc_level($1, $output_prefix."x1.chroma"); + } + if($data =~ /(.{512}THE HIDDEN CAVERN .{114})/s) + { + convert_bbc_level($1, $output_prefix."x2.chroma"); + } +} + +sub convert_designer_level +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + $data = read_file($file_input); + + convert_bbc_level($data, $file_output); +} + +sub convert_bbc_level +{ + my $level_data = shift(@_); + my $file_output = shift(@_); + + undef %level; + + $level{"map"} = substr($level_data, 0, 0x1c2); + + $base = 0x900; + convert_address(short(\$level_data, 0x1c2) - $base + 32, \$level{"mapTLx"}, \$level{"mapTLy"}); + convert_address(short(\$level_data, 0x1c4) - $base + 32, \$level{"mapTRx"}, \$level{"mapTRy"}); + convert_address(short(\$level_data, 0x1c6) - $base + 32, \$level{"mapBLx"}, \$level{"mapBLy"}); + convert_address(short(\$level_data, 0x1c8) - $base + 32, \$level{"mapBRx"}, \$level{"mapBRy"}); + + convert_address(short(\$level_data, 0x1ca) - $base + 32, \$level{"player1x"}, \$level{"player1y"}); + convert_address(short(\$level_data, 0x1d0) - $base, \$level{"view1x"}, \$level{"view1y"}); + convert_address(short(\$level_data, 0x1d2) - $base + 32, \$level{"player2x"}, \$level{"player2y"}); + convert_address(short(\$level_data, 0x1d8) - $base, \$level{"view2x"}, \$level{"view2y"}); + + convert_address(short(\$level_data, 0x1e2) - $base, \$level{"teleport1x"}, \$level{"teleport1y"}); + convert_address(short(\$level_data, 0x1e8) - $base, \$level{"viewteleport1x"}, \$level{"viewteleport1y"}); + convert_address(short(\$level_data, 0x1ea) - $base, \$level{"teleport2x"}, \$level{"teleport2y"}); + convert_address(short(\$level_data, 0x1f0) - $base, \$level{"viewteleport2x"}, \$level{"viewteleport2y"}); + + $title = substr($level_data, 0x200, 18); + $title = " ".$title." "; + $title = lc($title); + $title =~ s/ (\w)/' '.uc($1)/eg; + $title =~ s/^\s+//; + $title =~ s/\s+$//; + $level{"title"} = $title; + + $cryptedmessage = substr($level_data, 0x220, 100); + $message = ""; + if(ord($cryptedmessage) != 0) + { + for($i = 0; $i < length($cryptedmessage); $i++) + { + $c = byte(\$cryptedmessage, $i); + $c = $c ^ 0x7e; + if($c > 31 && $c <127) + { + $message .= chr($c); + } + else + { + last; + } + } + } + if($message ne "") + { + $level{"message"} = $message; + } + + $level{"mode"} = "8bit"; + + $level{"player"} = 2; + + create_level(\%level, $file_output) +} + +sub convert_amiga_levels +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + $data = read_file($file_input); + + for($number = 1; $number< 16; $number++) + { + $level_data= substr($data, ($number- 1) * 0x464, 0x464); + $file_output = sprintf("%s%02d%s", $output_prefix, $number, ".chroma"); + + convert_amiga_level($level_data, $file_output); + } +} + +sub convert_amiga_level +{ + my $level_data = shift(@_); + my $file_output = shift(@_); + + undef %level; + + $offset = 0; + while(byte(\$level_data, $offset) > 31) + { + $level{"title"} .= substr($level_data, $offset, 1); + $offset ++; + } + + $level{"map"} = substr($level_data, 0x1f, 0x400); + + $level{"view1x"} = long(\$level_data, 0x420); + $level{"view1y"} = long(\$level_data, 0x424); + $level{"player1x"} = long(\$level_data, 0x428); + $level{"player1y"} = long(\$level_data, 0x42c); + $level{"view2x"} = long(\$level_data, 0x430); + $level{"view2y"} = long(\$level_data, 0x434); + $level{"player2x"} = long(\$level_data, 0x438); + $level{"player2y"} = long(\$level_data, 0x43c); + $level{"viewteleport1x"} = long(\$level_data, 0x444); + $level{"viewteleport1y"} = long(\$level_data, 0x448); + $level{"teleport1x"} = long(\$level_data, 0x44c); + $level{"teleport1y"} = long(\$level_data, 0x450); + $level{"viewteleport2x"} = long(\$level_data, 0x454); + $level{"viewteleport2y"} = long(\$level_data, 0x458); + $level{"teleport2x"} = long(\$level_data, 0x45c); + $level{"teleport2y"} = long(\$level_data, 0x460); + $level{"player"} = 2; + + $level{"mode"} = "amiga"; + + create_level(\%level, $file_output); +} + +sub convert_atari_levels +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + $data = read_file($file_input); + + $number = 1; + + foreach $title ( + " DOTS AND WAVES ", + " SOMETHING FISHY ", + " CHICKEN SUPREME ", + " EXPLOSIVE MIXTURE ", + " HENRYS ANGUISH ", + " THE DOLLS HOUSE ", + " DOLLYS REVENGE ", + " ENLIGHTENMENT ", + " THE CHALLENGE ", + " PATIENCE PENDING ", + " RAZOR EDGE ", + " THE HAPPY HOUR ", + " DEJA VU ", + " PENULTIMATE ", + " THE DECODER " + ) + { + + $offset_title = locate_string(\$data, $title); + if($offset_title > 0) + { + $level_data = substr($data, $offset_title - 1074, 1096); + $file_output = sprintf("%s%02d%s", $output_prefix, $number, ".chroma"); + convert_atari_level($level_data, $file_output); + } + + $number ++; + } +} + +sub convert_atari_level +{ + my $level_data = shift(@_); + my $file_output = shift(@_); + + my $title; + + $level{"view1x"} = byte(\$level_data, 0x401); + $level{"view1y"} = byte(\$level_data, 0x403); + $level{"player1x"} = $level{"view1x"} + byte(\$level_data, 0x405); + $level{"player1y"} = $level{"view1y"} + byte(\$level_data, 0x407); + + $level{"view2x"} = byte(\$level_data, 0x40b); + $level{"view2y"} = byte(\$level_data, 0x40d); + $level{"player2x"} = $level{"view2x"} + byte(\$level_data, 0x40f); + $level{"player2y"} = $level{"view2y"} + byte(\$level_data, 0x411); + + $level{"viewteleport1x"} = byte(\$level_data, 0x417); + $level{"viewteleport1y"} = byte(\$level_data, 0x419); + $level{"viewteleport2x"} = byte(\$level_data, 0x423); + $level{"viewteleport2y"} = byte(\$level_data, 0x425); + + $level{"teleport1x"} = $level{"viewteleport1x"} + byte(\$level_data, 0x41f); + $level{"teleport1y"} = $level{"viewteleport1y"} + byte(\$level_data, 0x421); + $level{"teleport2x"} = $level{"viewteleport2x"} + byte(\$level_data, 0x42b); + $level{"teleport2y"} = $level{"viewteleport2y"} + byte(\$level_data, 0x42d); + + $level{"map"} = substr($level_data, 0, 0x400); + + $title = substr($level_data, 0x432, 20); + $title = " ".$title." "; + $title = lc($title); + $title =~ s/ (\w)/' '.uc($1)/eg; + $title =~ s/^\s+//; + $title =~ s/\s+$//; + $level{"title"} = $title; + + $cryptedmessage = substr($level_data, 0x220, 100); + + $level{"mode"} = "atari"; + + create_level(\%level, $file_output); +} + +############################################################################### + +sub convert_bbc_graphics +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + my $mode = shift(@_); + + $data = read_file($file_input); + + if($data =~ /(\x00{72}\x1d\x1d\xdd\x00\x47\x47\x77\x00.{208})/s) + { + $walls = $1; + $walls1 = substr($walls, 0, 144); + $walls2 = substr($walls, 144, 144); + if($walls2 =~ /^\x00\x70\x70\x70/s) + { + $walls2 = ""; + } + } + else + { + die "Unable to locate graphics in input file\n"; + } + + if($data =~ /(\x00\x70\x70\x70\x70\x71\x73\x77\x00\xf0\xf0\xf4\xfe\xff\xfb\xf1.{992})/s) + { + $pieces = $1; + $match = $walls1.$pieces.$walls2; + convert_bbc_graphics_data($match, $output_prefix, "bbc"); + } + else + { + die "Unable to locate graphics in input file\n"; + } + +} + +sub convert_c64_graphics +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + $data = read_file($file_input); + + if($data =~ /(\x53\x53\xf3\x00.{68}\x55\x55\x15\x15.{68}\x00\x1c\x57\x55.{68})/) + { + $walls = substr($1, 72, 144); + } + else + { + $walls = ""; + } + + if($data =~ /(\x00{72}\x53\x53\xf3\x00\x35\x35\x3f\x00.{1072})/s) + { + $pieces = $1.$walls; + convert_bbc_graphics_data($pieces, $output_prefix, "c64"); + } + else + { + die "Unable to locate graphics in input file\n"; + } + +} + +sub convert_bbc_graphics_file +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + $data = read_file($file_input); + + convert_bbc_graphics_data($data, $output_prefix, "bbc"); +} + +sub convert_bbc_graphics_data +{ + my $data = shift(@_); + my $output_prefix = shift(@_); + my $mode = shift(@_); + my $offset; + + $x = 0; + $y = 0; + $j = 0; + $offset = 0; + $number = 0; + + $levels = 1 if($levels < 1); + for($level = 0; $level < $levels; $level ++) + { # 1 2 4 + @colours =( [0x00000000, 0x00ff0000, 0x000000ff, 0x00ffffff], # 1 + [0x00000000, 0x00ff0000, 0x000000ff, 0x00ffffff], # 2 + [0x00000000, 0x00ff0000, 0x000000ff, 0x00ffffff], # 3 + [0x00000000, 0x000000ff, 0x00ff00ff, 0x00ffffff], # 4 + [0x00000000, 0x000000ff, 0x00ff00ff, 0x00ffffff], # 5 + [0x00000000, 0x000000ff, 0x00ff00ff, 0x00ffffff], # 6 + [0x00000000, 0x000000ff, 0x00ff0000, 0x00ffffff], # 7 + [0x00000000, 0x000000ff, 0x00ff0000, 0x00ffffff], # 8 + [0x00000000, 0x000000ff, 0x00ff0000, 0x00ffffff], # 9 + [0x00000000, 0x0000ff00, 0x00ff0000, 0x00ffffff], # 10 + [0x00000000, 0x0000ff00, 0x00ff0000, 0x00ffffff], # 11 + [0x00000000, 0x00ff00ff, 0x000000ff, 0x0000ff00], # 12 + [0x00000000, 0x00ff00ff, 0x000000ff, 0x0000ff00], # 13 + [0x000000ff, 0x00ff0000, 0x00000000, 0x00ffffff], # 14 + [0x000000ff, 0x00ff0000, 0x00000000, 0x00ffffff] # 15 + ); + + $image{"colours"} = 4; # RRGGBB + $image{"palette"}[0] = $colours[$level][0]; + $image{"palette"}[1] = $colours[$level][1]; + $image{"palette"}[2] = $colours[$level][2]; + $image{"palette"}[3] = $colours[$level][3]; + + $image{"x"} = 12; + $image{"y"} = 24; + + $number = 0; + $o = $offset; + while($o < length($data)) + { + $c = ord(substr($data, $o, 1)); + + if($mode eq "bbc") + { + $b3 = ($c & 1 ? 1 : 0) + ($c & 16 ? 2 : 0); + $b2 = ($c & 2 ? 1 : 0) + ($c & 32 ? 2 : 0); + $b1 = ($c & 4 ? 1 : 0) + ($c & 64 ? 2 : 0); + $b0 = ($c & 8 ? 1 : 0) + ($c & 128 ? 2 : 0); + } + if($mode eq "c64") + { + $b3 = ($c & 1 ? 1 : 0) + ($c & 2 ? 2 : 0); + $b2 = ($c & 4 ? 1 : 0) + ($c & 8 ? 2 : 0); + $b1 = ($c & 16 ? 1 : 0) + ($c & 32 ? 2 : 0); + $b0 = ($c & 64 ? 1 : 0) + ($c & 128 ? 2 : 0); + } + + $image{"pixels"}[$x + 0][$y + $j] = $b0; + $image{"pixels"}[$x + 1][$y + $j] = $b1; + $image{"pixels"}[$x + 2][$y + $j] = $b2; + $image{"pixels"}[$x + 3][$y + $j] = $b3; + + $o++; + + $j++; + + if($j == 8) + { + $j = 0; + $x += 4; + } + if($x == 12) + { + $x = 0; + $y += 8; + } + if($y == 24) + { + if($levels > 1) + { + $file_output = sprintf("%s%d_%02d%s", $output_prefix, $level + 1, $number, ".bmp"); + } + else + { + $file_output = sprintf("%s%02d%s", $output_prefix, $number, ".bmp"); + } + create_bmp(\%image, $file_output, 2, 1); + + $y = 0; + $x = 0; + $j = 0; + $number ++; + } + } + } +} + +sub convert_cpc_graphics +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + $data = read_file($file_input); + + if($data =~ /(\xcc{144}\x0c\xc8\x0c\x0c.{2156})/s) + { + convert_cpc_graphics_data($1, $output_prefix); + } + else + { + die "Unable to locate graphics in input file\n"; + } + +} + +sub convert_cpc_graphics_data +{ + my $data = shift(@_); + my $output_prefix = shift(@_); + + my $offset; + + $x = 0; + $y = 0; + $offset = 0; + $number = 0; + + $image{"colours"} = 16; # RRGGBB + $image{"palette"}[0x0] = 0x00000081; + $image{"palette"}[0x1] = 0x00ff8100; + $image{"palette"}[0x2] = 0x00ff0000; + $image{"palette"}[0x3] = 0x00ff0083; + $image{"palette"}[0x4] = 0x008300ff; + $image{"palette"}[0x5] = 0x00830000; + $image{"palette"}[0x6] = 0x00ffff00; + $image{"palette"}[0x7] = 0x00ff81ff; + $image{"palette"}[0x8] = 0x00ffffff; + $image{"palette"}[0x9] = 0x000000ff; + $image{"palette"}[0xa] = 0x00000000; + $image{"palette"}[0xb] = 0x00838183; + $image{"palette"}[0xc] = 0x008381ff; + $image{"palette"}[0xd] = 0x00ff8183; + $image{"palette"}[0xe] = 0x00ffff83; + $image{"palette"}[0xf] = 0x00ffffff; + + $image{"x"} = 12; + $image{"y"} = 24; + + while($offset < length($data)) + { + $c = byte(\$data, $offset); + + $b1 = ($c & 1 ? 1 : 0) + ($c & 4 ? 2 : 0) + ($c & 16 ? 4 : 0) + ($c & 64 ? 8 : 0); + $b0 = ($c & 2 ? 1 : 0) + ($c & 8 ? 2 : 0) + ($c & 32 ? 4 : 0) + ($c & 128 ? 8 : 0); + + $image{"pixels"}[$x + 0][$y] = $b0; + $image{"pixels"}[$x + 1][$y] = $b1; + + $offset ++; + + $x+=2; + + if($x == 12) + { + $x = 0; + $y += 1; + } + if($y == 24) + { + $file_output = sprintf("%s%02d%s", $output_prefix, $number, ".bmp"); + create_bmp(\%image, $file_output, 2, 1); + + $y = 0; + $x = 0; + $number ++; + } + } +} + +sub convert_spectrum_graphics +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + $data = read_file($file_input); + + if($data =~ /(\x00{81}\x00\xc0\x00\x00\xc0\x00.{1209})/s) + { + convert_spectrum_graphics_data($1, $output_prefix); + } + else + { + die "Unable to locate graphics in input file\n"; + } +} + +sub convert_spectrum_graphics_data +{ + my $data = shift(@_); + my $output_prefix = shift(@_); + my $mode = shift(@_); + + my $offset; + + $x = 0; + $y = 0; + $offset = 0; + $number = 0; + + $image{"x"} = 24; + $image{"y"} = 24; + + $image{"colours"} = 16; # RRGGBB + $image{"palette"}[0x0] = 0x00000000; + $image{"palette"}[0x1] = 0x0000007f; + $image{"palette"}[0x2] = 0x007f0000; + $image{"palette"}[0x3] = 0x007f007f; + $image{"palette"}[0x4] = 0x00007f00; + $image{"palette"}[0x5] = 0x00007f7f; + $image{"palette"}[0x6] = 0x007f007f; + $image{"palette"}[0x7] = 0x007f7f7f; + $image{"palette"}[0x8] = 0x00000000; + $image{"palette"}[0x9] = 0x000000ff; + $image{"palette"}[0xa] = 0x00ff0000; + $image{"palette"}[0xb] = 0x00ff00ff; + $image{"palette"}[0xc] = 0x0000ff00; + $image{"palette"}[0xd] = 0x0000ffff; + $image{"palette"}[0xe] = 0x00ffff00; + $image{"palette"}[0xf] = 0x00ffffff; + + while($offset < length($data)) + { + for($y = 0; $y < 24; $y ++) + { + for($x = 0; $x < 3; $x ++) + { + $c = ord(substr($data, $offset + $y * 3 + $x, 1)); + + $px = $x * 8; + if($y % 2 == 1) { $px = 16 - $px; } + + $col = ord(substr($data, $offset + 72 + (int($y / 8)*3) + $x)); + $fg = $col % 8; + $bg = int($col / 8) % 8; + + if($col & 64) + { + $fg +=8; $bg+=8; + } + + $image{"pixels"}[$px + 0][$y] = ($c & 128 ? $fg : $bg); + $image{"pixels"}[$px + 1][$y] = ($c & 64 ? $fg : $bg); + $image{"pixels"}[$px + 2][$y] = ($c & 32 ? $fg : $bg); + $image{"pixels"}[$px + 3][$y] = ($c & 16 ? $fg : $bg); + $image{"pixels"}[$px + 4][$y] = ($c & 8 ? $fg : $bg); + $image{"pixels"}[$px + 5][$y] = ($c & 4 ? $fg : $bg); + $image{"pixels"}[$px + 6][$y] = ($c & 2 ? $fg : $bg); + $image{"pixels"}[$px + 7][$y] = ($c & 1 ? $fg : $bg); + } + } + + $file_output = sprintf("%s%02d%s", $output_prefix, $number, ".bmp"); + create_bmp(\%image, $file_output, 1, 1); + + $offset += 81; + $number++; + } +} + +sub convert_amiga_graphics +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + for($level = 0; $level < 15; $level ++) + { + $file_in = $file_input . "/vimages".$level; + $file_out = sprintf("%s/back_%d_", $output_prefix, $level + 1); + convert_amiga_graphics_file($file_in, $file_out, 0); + } + + $file_in = $file_input . "/cimages"; + $file_out = sprintf("%s/char_", $output_prefix); + convert_amiga_graphics_file($file_in, $file_out, 1); +} + +sub convert_amiga_graphics_file +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + my $mode = shift(@_); + + open(INPUT, $file_input) || die "Couldn't open input file ($file_input): $!\n"; + binmode INPUT; + undef $/; + $data = ; + close INPUT; + + $image{"x"} = 24; + $image{"y"} = 24; + $image{"colours"} = 32; + + # Read palette + if($mode == 0) + { + for($i = 0; $i < 32; $i ++) + { + $p = 256 * ord(substr($data, $i * 2, 1)) + ord(substr($data, $i * 2 + 1, 1)); + + $blue = $p % 16; + $green = (($p - ($p % 16)) / 16) % 16; + $red= (($p - ($p % 256)) / 256) % 16; + + $blue *= 0x11; + $green *= 0x11; + $red *= 0x11; + + $image{"palette"}[$i] = $blue + ($green * 0x100) + ($red * 0x10000); + } + } + + if($mode == 0) + { + $sprites = 20; + } + else + { + $sprites = 60; + } + + for($sprite = 0; $sprite < $sprites; $sprite ++) + { + undef $image{"pixels"}; + + for($colour = 0; $colour < 5; $colour ++) + { + for($row = 0; $row < 24; $row ++) + { + if($mode == 0) + { + $block = ($sprite - ($sprite % 10)) / 10; + $block += 2 * $colour; + $offset = 64 + ($sprite % 10) * 4 + $row * 40 + $block * 960; + } + else + { + $block = ($sprite - ($sprite % 10)) / 10; + $block += 6 * $colour; + $offset = 0 + ($sprite % 10) * 4 + $row * 40 + $block * 960; + } + + for($byte = 0; $byte < 3; $byte ++) + { + $b = ord(substr($data, $offset + $byte, 1)); + for($bit = 0; $bit < 8; $bit ++) + { + if($b & (2 ** (7 - $bit))) + { + $image{"pixels"}[$byte * 8 + $bit][$row] |= 2 ** $colour; + } + } + } + } + } + + $file_output = sprintf("%s%02d%s", $output_prefix, $sprite, ".bmp"); + create_bmp(\%image, $file_output, 1, 1); + } + +} + +sub convert_atari_graphics +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + $data = read_file($file_input); + + $palette = "\x02\x27\x00\x40\x00\x00\x03\x33\x07\x44\x07\x11\x03\x37\x07\x70\x02\x25\x05\x57\x07\x50\x03\x53\x04\x44\x05\x55\x06\x66\x07\x77"; + + $ok = 0; + $offset_palette = 0; + while(!$ok && $offset_palette != -1) + { + $offset_palette = index($data, $palette, $offset_palette); + $offset_palette2 = index($data, $palette, $offset_palette); + + if($offset_palette2 = $offset_palette + 96) + { + $ok = 1; + } + } + if($ok == 0) + { + die "Unable to locate palette data in file"; + } + + $offset_base = $offset_palette - 0x1b6e4; + $offset_pieces = $offset_base + 0x68000; + $offset_backgrounds = $offset_base + 0x60000; + + @graphics_pieces = ( + # ["space", 0, 0, 0], + # ["wall", 2, 0, 0], + # ["player_one", 4, 0, 1] + # ["player_two", 6, 0, 1] + ["map_top_left", 8, 0, 1], + ["dots", 10, 0, 1], + + ["waves", 0, 1, 1], + ["fish", 2, 1, 1], + ["chicken", 4, 1, 1], + ["h_bomb", 6, 1, 1], + ["v_bomb", 8, 1, 1], + ["mask", 10, 1, 1], + + ["door", 0, 2, 1], + ["doll", 2, 2, 1], + ["map_top_right", 4, 2, 1], + ["map_bottom_left", 6, 2, 1], + ["map_bottom_right", 8, 2, 1], + ["teleport", 10, 2, 1], + + ["switch", 0, 3, 1], + ["fish_2", 8, 3, 1], + ["chicken_2", 10, 3, 1], + + ["chicken_3", 0, 4, 1], + ["fish_3", 2, 4, 1], + ["fish_4", 4, 4, 1], + ["chicken_4", 6, 4, 1], + ["chicken_5", 8, 4, 1], + ["fish_5", 10, 4, 1], + + ["explosion_0", 0, 5, 1], + ["explosion_1", 2, 5, 1], + ["explosion_2", 4, 5, 1], + ["explosion_3", 8, 5, 1], + ["explosion_4", 10, 5, 1], + + ["player_one_1", 0, 6, 2], + ["player_two_1", 1, 6, 2], + ["player_one_2", 2, 6, 2], + ["player_two_2", 3, 6, 2], + ["player_one_3", 4, 6, 2], + ["player_two_3", 5, 6, 2], + ["player_one_4", 6, 6, 2], + ["player_two_4", 7, 6, 2], + ["player_one_5", 8, 6, 2], + ["player_two_5", 9, 6, 2], + ["player_one_6", 10, 6, 2], + ["player_two_6", 11, 6, 2], + + ["player_one_7", 0, 7, 2], + ["player_two_7", 1, 7, 2], + ["player_one_8", 2, 7, 2], + ["player_two_8", 3, 7, 2], + ["player_one_9", 4, 7, 2], + ["player_two_9", 5, 7, 2], + ["player_one_10", 6, 7, 2], + ["player_two_10", 7, 7, 2], + ["player_one_11", 8, 7, 2], + ["player_two_11", 9, 7, 2], + ["player_one_12", 10, 7, 2], + ["player_two_12", 11, 7, 2], + + ["player_one_13", 0, 8, 2], + ["player_two_13", 1, 8, 2], + ["player_one_14", 2, 8, 2], + ["player_two_14", 3, 8, 2], + ["player_one_15", 4, 8, 2], + ["player_two_15", 5, 8, 2], + ); + + for($graphic = 0; $graphic <= $#graphics_pieces; $graphic ++) + { + convert_atari_graphic($output_prefix."/".$graphics_pieces[$graphic][0], \$data, $offset_pieces, $graphics_pieces[$graphic][1] * 24, $graphics_pieces[$graphic][2] * 22, 24, 22, $graphics_pieces[$graphic][3]); + } + + @graphics_backgrounds = ( + ["background_1", 0, 0, 0], + ["background_2", 2, 0, 0], + ["background_3", 4, 0, 0], + ["background_4", 6, 0, 0], + ["background_5", 8, 0, 0], + ["background_6", 10, 0, 0], + ["background_7", 0, 2, 0], + ["background_8", 2, 2, 0], + ["background_9", 4, 2, 0], + ["background_10", 6, 2, 0], + ["background_11", 8, 2, 0], + ["background_12", 10, 2, 0], + ["background_13", 6, 4, 0], + ["background_14", 8, 4, 0], + ["background_15", 10, 4, 0], + ); + + for($graphic = 0; $graphic <= $#graphics_backgrounds; $graphic ++) + { + convert_atari_graphic($output_prefix."/".$graphics_backgrounds[$graphic][0], \$data, $offset_backgrounds, $graphics_backgrounds[$graphic][1] * 24, $graphics_backgrounds[$graphic][2] * 22, 48, 44, $graphics_backgrounds[$graphic][3]); + } + + @graphics_walls = ( + ["wall_1_1", 5, 8, 3], + ["wall_1_2", 6, 8, 3], + ["wall_1_3", 7, 8, 3], + ["wall_1_4", 8, 8, 3], + + ["wall_2_1", 7, 6, 3], + ["wall_2_2", 8, 6, 3], + ["wall_2_3", 7, 7, 3], + ["wall_2_4", 8, 7, 3], + + ["wall_3_1", 9, 6, 3], + ["wall_3_2", 10, 6, 3], + ["wall_3_3", 9, 7, 3], + ["wall_3_4", 10, 7, 3], + + ["wall_4_1", 11, 6, 3], + ["wall_4_2", 12, 6, 3], + ["wall_4_3", 11, 7, 3], + ["wall_4_4", 12, 7, 3], + + ["wall_5_1", 12, 0, 4], + ["wall_5_2", 12, 1, 4], + ["wall_5_3", 12, 2, 4], + ["wall_5_4", 12, 3, 4], + ["wall_5_5", 12, 5, 3], + + ["wall_6_1", 12, 4, 4], + ["wall_6_2", 12, 5, 4], + ["wall_6_3", 12, 6, 4], + ["wall_6_4", 12, 7, 4], + + ["wall_7_1", 6, 8, 4], + ["wall_7_2", 7, 8, 4], + ["wall_7_3", 8, 8, 4], + ["wall_7_4", 9, 8, 4], + + ["wall_8_1", 6, 3, 4], + ["wall_8_2", 7, 3, 4], + ["wall_8_3", 10, 8, 4], + ["wall_8_4", 11, 8, 4], + + ["wall_9_1", 2, 3, 4], + ["wall_9_2", 3, 3, 4], + ["wall_9_3", 4, 3, 4], + ["wall_9_4", 5, 3, 4], + + ["wall_10_1", 12, 8, 4], + ["wall_10_2", 2, 8, 3], + ["wall_10_3", 3, 8, 3], + ["wall_10_4", 4, 8, 3], + + ["wall_11_1", 0, 4, 3], + ["wall_11_2", 1, 4, 3], + ["wall_11_3", 0, 5, 3], + ["wall_11_4", 1, 5, 3], + + ["wall_12_1", 2, 4, 3], + ["wall_12_2", 3, 4, 3], + ["wall_12_3", 2, 5, 3], + ["wall_12_4", 3, 5, 3], + + ["wall_13_1", 4, 4, 3], + ["wall_13_2", 5, 4, 3], + ["wall_13_3", 4, 5, 3], + ["wall_13_4", 5, 5, 3], + + ["wall_14_1", 5, 6, 3], + ["wall_14_2", 6, 6, 3], + ["wall_14_3", 5, 7, 3], + ["wall_14_4", 6, 7, 3], + + ["wall_15_1", 9, 8, 3], + ["wall_15_2", 10, 8, 3], + ["wall_15_3", 11, 8, 3], + ["wall_15_4", 12, 8, 3], + + ); + + for($graphic = 0; $graphic <= $#graphics_walls; $graphic ++) + { + $size_x = defined($graphics_walls[$graphic][4]) ? $graphics_walls[$graphic][4] : 1; + $size_y = defined($graphics_walls[$graphic][5]) ? $graphics_walls[$graphic][5] : 1; + + if($graphics_walls[$graphic][3] == 3) + { + convert_atari_graphic($output_prefix."/".$graphics_walls[$graphic][0], \$data, $offset_backgrounds, $graphics_walls[$graphic][1] * 24, $graphics_walls[$graphic][2] * 22, $size_x * 24, $size_y * 22, 0); + } + elsif($graphics_walls[$graphic][3] == 4) + { + convert_atari_graphic($output_prefix."/".$graphics_walls[$graphic][0], \$data, $offset_pieces, $graphics_walls[$graphic][1] * 24, $graphics_walls[$graphic][2] * 22, $size_x * 24, $size_y * 22, 0); + } + } + +} + +sub convert_atari_graphic +{ + my $file_output = shift(@_); + my $data = shift(@_); + my $offset = shift(@_); + my $offset_x = shift(@_); + my $offset_y = shift(@_); + my $size_x = shift(@_); + my $size_y = shift(@_); + my $mask = shift(@_); + + @colour_map = (0, 36, 73, 109, 146, 182, 219, 255); + + $image{"colours"} = 16; + $image{"x"} = $size_x; + $image{"y"} = $size_y; + + # Setup palette + for($i = 0; $i < 16; $i ++) + { + $c = byte(\$palette, $i * 2) * 256 + byte(\$palette, $i * 2 + 1); + $r = $colour_map[int($c / 256) % 8]; + $g = $colour_map[int($c / 16) % 8]; + $b = $colour_map[$c % 8]; + $image{"palette"}[$i] = $r * 0x10000 + $g * 0x100 + $b; + } + + # Transparent colour + if($mask != 0) + { + $image{"colours"} = 17; + $image{"palette"}[16] = 0x00deface; + } + + undef $image{"pixels"}; + + for($y = 0; $y < $size_y; $y ++) + { + for($x = 0; $x < $size_x; $x += 8) + { + $o = $offset + ($y + $offset_y) * 160 + 8 * int(($x + $offset_x) / 16); + $o++ if(($x + $offset_x) % 16 == 8); + + for($colour = 0; $colour < 4; $colour ++) + { + $byte = byte(\$$data, $o + $colour * 2); + for($b = 0; $b < 8; $b ++) + { + if($byte & (2 ** (7 - $b))) + { + $image{"pixels"}[$x + $b][$y] |= 2 ** $colour; + } + } + } + } + } + + if($mask) + { + if($mask == 2) + { + $mask_x = 5 * 24; + $mask_y = 0; + } + else + { + $mask_x = $offset_x + 24; + $mask_y = $offset_y; + } + + for($y = 0; $y < $size_y; $y ++) + { + for($x = 0; $x < $size_x; $x += 8) + { + $o = $offset + ($y + $mask_y) * 160 + 8 * int(($x + $mask_x) / 16); + $o++ if(($x + $mask_x) % 16 == 8); + + $byte = byte(\$$data, $o); + + for($b = 0; $b < 8; $b ++) + { + if($byte & (2 ** (7 - $b))) + { + $image{"pixels"}[$x + $b][$y] = 16; + } + } + } + } + } + + create_bmp(\%image, $file_output.".bmp", 1, 1); +} + +############################################################################### + +sub convert_bbc_music +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + # If debug is set, the notes are displayed on screen + $debug = 0; + + # Translation table for displaying notes on screen + $debug_table[0x00] = "---"; + $debug_table[0x11] = "D#2"; + $debug_table[0x1d] = "F#2"; + $debug_table[0x25] = "G#2"; + $debug_table[0x2d] = "A#2"; + $debug_table[0x35] = "C-3"; + $debug_table[0x39] = "C#3"; + $debug_table[0x41] = "D#3"; + $debug_table[0x49] = "F-3"; + $debug_table[0x4d] = "F#3"; + $debug_table[0x55] = "G#3"; + $debug_table[0x5d] = "A#3"; + $debug_table[0x65] = "C-4"; + $debug_table[0x69] = "C#4"; + $debug_table[0x71] = "D#4"; + $debug_table[0x79] = "F-4"; + $debug_table[0x7d] = "F#4"; + $debug_table[0x85] = "G#4"; + $debug_table[0x8d] = "A#4"; + + # Translation table between BBC SOUND values and note values + $note_table[0x00] = 0; + $note_table[0x11] = 0x1c; + $note_table[0x1d] = 0x1f; + $note_table[0x25] = 0x21; + $note_table[0x2d] = 0x23; + $note_table[0x35] = 0x25; + $note_table[0x39] = 0x26; + $note_table[0x41] = 0x28; + $note_table[0x49] = 0x2a; + $note_table[0x4d] = 0x2b; + $note_table[0x55] = 0x2d; + $note_table[0x5d] = 0x2f; + $note_table[0x65] = 0x31; + $note_table[0x69] = 0x32; + $note_table[0x71] = 0x34; + $note_table[0x79] = 0x36; + $note_table[0x7d] = 0x37; + $note_table[0x85] = 0x39; + $note_table[0x8d] = 0x3b; + + $data = read_file($file_input); + + # Search for various data structures in file + if($data =~ /(\x11\x35\x1d\x35.{75}\x39)/s) + { + $data_channel12barnotes = $1; + } + else + { + print "ERROR: Couldn't locate data in input file (channel12barnotes)\n"; + return; + } + + if($data =~ /(\x00\x00\x46\x0a.{50}\x50)/s) + { + $data_channel12barorder = $1; + } + else + { + print "ERROR: Couldn't locate data in input file (channel12barorder)\n"; + return; + } + + if($data =~ /(\x69\x0c\x65\x0c.{204}\xff)/s) + { + $data_channel3barnotes = $1; + } + else + { + print "ERROR: Couldn't locate data in input file (channel3barnotes)\n"; + return; + } + + if($data =~ /(\x21\x4f\x21\x4f.{47}\x4f)/s) + { + $data_channel3barorder = $1; + } + else + { + print "ERROR: Couldn't locate data in input file (channel3barorder)\n"; + return; + } + + $duration = 648; + $patterns = ($duration / 64) + 1; + + open(OUTPUT, ">".$file_output) || die "Couldn't open file for output: $!\n"; + binmode OUTPUT; + + # Module header + print OUTPUT "Extended Module: "; + print OUTPUT pack("Z20", "XOR Theme"); # Module name + print OUTPUT pack("c", 0x1a); + print OUTPUT pack("Z20", "convert2chroma.pl"); # Tracker name + print OUTPUT pack("v", 0x0104); # Version + print OUTPUT pack("V", 0x114); # Header size + print OUTPUT pack("v", $patterns); # Song length + print OUTPUT pack("v", 0); # Restart position + print OUTPUT pack("v", 4); # Channels + print OUTPUT pack("v", $patterns); # Patterns + print OUTPUT pack("v", 2); # Instruments + print OUTPUT pack("v", 1); # Flags (linear frequency table) + print OUTPUT pack("v", 6); # Default tempo + print OUTPUT pack("v", 125); # Default BPM + + # Pattern table + for($i = 0; $i < 256; $i ++) + { + print OUTPUT pack("c", $i < ($patterns - 1) ? $i : 0); + } + + # Generate patterns from tune + $time = 0; + $time_channel3 = 24; + + $offset_channel12 = 0; + $offset_channel12bar = 0; + $offset_channel3 = 0; + $offset_channel3bar = 0; + + for($time = 0; $time < $duration; $time ++) + { + $play_1 = 0; + $play_2 = 0; + $play_3 = 0; + + if($time % 3 == 0) + { + $note = $offset_channel12 + ($time % 12) / 3; + $play_1 = ord(substr($data_channel12barnotes, $note, 1)); + } + + if($time % 2 == 0) + { + $note = $offset_channel12 + 4 + ($time % 12) / 2; + $play_2 = ord(substr($data_channel12barnotes, $note, 1)); + } + + if($time_channel3 == 0) + { + $play_3 = ord(substr($data_channel3barnotes, $offset_channel3, 1)); + if($play_3 == 255) + { + $offset_channel3 = ord(substr($data_channel3barorder, $offset_channel3bar, 1)); + + $offset_channel3bar += 2; + if($offset_channel3bar > length($data_channel3barorder)) + { + # End of channel 3 bar data + # This should happen just after the end of the tune, so never gets called. + print "ERROR: Premature end of channel 3 bar data\n"; + } + + $play_3 = ord(substr($data_channel3barnotes, $offset_channel3, 1)); + + } + $offset_channel3 ++; + + $time_channel3 = ord(substr($data_channel3barnotes, $offset_channel3, 1)); + $offset_channel3 ++; + + } + + $time_channel3 --; + + if($play_1 != 0) { $pattern[1][$time % 64] = $note_table[$play_1]; } + if($play_2 != 0) { $pattern[2][$time % 64] = $note_table[$play_2]; } + if($play_3 != 0) { $pattern[3][$time % 64] = $note_table[$play_3]; } + + if($debug) + { + printf("%8d%8s%8s%8s\n", $time, $debug_table[$play_1], $debug_table[$play_2], $debug_table[$play_3]); + } + + if($time % 12 == 11) + { + if($debug) + { + # Bar separator + print "\n"; + } + + $offset_channel12bar ++; + $offset_channel12 = ord(substr($data_channel12barorder, $offset_channel12bar, 1)); + if($offset_channel12 == 0x50) + { + # End of channel 1/2 bar data + # This should happen at the very end of the tune. + } + } + + if($time % 64 == 63) + { + dump_pattern(0); + } + } + + # Dump any partial final pattern + if($duration % 64 != 0) + { + dump_pattern(1); + } + + for($instrument =0; $instrument < 2; $instrument ++) + { + # Instrument + print OUTPUT pack("V", 0x107); # Instrument size + print OUTPUT pack("Z22", "Instrument $instrument"); # Instrument name + print OUTPUT pack("c", 0); # Instrument type + print OUTPUT pack("v", 1); # Number of samples + + print OUTPUT pack("V", 40); # Sample header size + print OUTPUT pack("Z96", ""); # Sample number for each note + print OUTPUT pack("Z48", "\x00\x00\x40"); # Points for volume envelope + print OUTPUT pack("Z48", "\x00\x00\x20"); # Points for panning envelope + print OUTPUT pack("c", 1); # Number of volume points + print OUTPUT pack("c", 1); # Number of panning points + print OUTPUT pack("c", 0); # Volume sustain point + print OUTPUT pack("c", 0); # Volume loop start point + print OUTPUT pack("c", 0); # Volume loop end point + print OUTPUT pack("c", 0); # Panning sustain point + print OUTPUT pack("c", 0); # Panning loop start point + print OUTPUT pack("c", 0); # Panning loop end point + print OUTPUT pack("c", 0); # Volume type + print OUTPUT pack("c", 0); # Panning type + print OUTPUT pack("c", 0); # Vibrato type + print OUTPUT pack("c", 0); # Vibrato sweep + print OUTPUT pack("c", 0); # Vibrato depth + print OUTPUT pack("c", 0); # Vibrato rate + print OUTPUT pack("v", 0); # Volume fadeout + print OUTPUT pack("v", 0); # Reserved + print OUTPUT pack("Z20", ""); # ? + + # Sample + if($instrument == 0) + { + # Used for channels 1 and 2 for a backing beat + $sample_length = 2048; + $phase_attack = 0.0; + $phase_decay = 0.0; + $relative_note = 12; + } + else + { + # Used for channel 3 for the melody + $sample_length = 4096; + $phase_attack = 0.05; + $phase_decay = 0.1; + $relative_note = 0; + } + + print OUTPUT pack("V", $sample_length); # Sample length + print OUTPUT pack("V", 0); # Sample loop start + print OUTPUT pack("V", 1); # Sample loop end + print OUTPUT pack("c", 64); # Volume + print OUTPUT pack("c", 0 ); # Finetune + print OUTPUT pack("c", 0); # Type + print OUTPUT pack("c", 128); # Panning + print OUTPUT pack("c", $relative_note); # Relative note number + print OUTPUT pack("c", 0); # Reserved + print OUTPUT pack("Z22", "Sample $instrument"); # Sample name + + # Sample data + $sample = ""; + $previous = 0; + for($i = 0; $i < $sample_length; $i ++) + { + # The XM format documentation gives 8363Hz for C-4. Conversely, xmp's + # output suggests 8287Hz for C-4. C-0 should be 262Hz. Either way, that + # doesn't affect sample generation, as it is independent of C-4s frequency: + # + # $value = sin($PI * ($C4 / 8 ) * ( 2 ** - ($relative_note / 12) * $i / $C4)); + + $value = sin(3.14159265 * (2 ** - ($relative_note / 12)) * $i / 8); + + # Convert to a square wave + $value = $value > 0 ? 1 : -1; + + # Volume envelope + $volume = 124; + + $phase = ($i / $sample_length); + + if($phase < $phase_attack) + { + $value = $volume * $value * $phase / $phase_attack; + } + elsif($phase < $phase_decay) + { + $value = $volume * $value; + } + else + { + $value = $volume * $value * (1 - (($phase - $phase_decay) / (1 - $phase_decay))); + } + + # Convert to delta sample data + $value = int($value); + $delta = $value - $previous; + $previous = $value; + + $sample .= pack("c", $delta); + } + + print OUTPUT $sample; + } + + close(OUTPUT); +} + +sub dump_pattern +{ + my $final = shift(@_); + + $pattern_data = ""; + + for($row = 0; $row < 64; $row ++) + { + for($channel = 1; $channel <=4; $channel ++) + { + if($pattern[$channel][$row] != 0) + { + $pattern_data .= pack("c3", 0x83, $pattern[$channel][$row], $channel == 3 ? 0x2 : 0x1); + } + else + { + if($final && $row == (($duration - 1) % 64) && $channel == 4) + { + # Loop back to pattern 0 at end of tune + $pattern_data .= pack("cc", 0x88, 0xb); + } + else + { + $pattern_data .= pack("c", 0x80); + } + } + } + } + + print OUTPUT pack("V", 9); # Pattern header size + print OUTPUT pack("c", 0); # Packing type + print OUTPUT pack("v", 64); # Number of rows + print OUTPUT pack("v", length($pattern_data)); # Packed pattern size + print OUTPUT $pattern_data; + + undef @pattern; +} + +############################################################################### + +sub convert_bbc_all +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + make_directory($output_prefix); + make_directory($output_prefix."/levels/"); + make_directory($output_prefix."/levels/xor_bbc/"); + make_directory($output_prefix."/graphics/"); + make_directory($output_prefix."/graphics/xor_bbc/"); + + convert_bbc_levels($file_input, $output_prefix."/levels/xor_bbc/xor_bbc_"); + create_set($output_prefix."/levels/xor_bbc/set.chroma", "XOR (BBC)"); + + $levels = 15; + convert_bbc_graphics($file_input, $output_prefix."/graphics/xor_bbc/xor_bbc_"); + + open(FILE, ">".$output_prefix."/graphics/xor_bbc.chroma"); + +print FILE << "EOF"; + + + + +XOR (BBC) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOF + + convert_bbc_music($file_input, $output_prefix."/xor-theme.xm"); +} + +sub convert_designer_all +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + make_directory($output_prefix); + make_directory($output_prefix."/levels/"); + make_directory($output_prefix."/levels/xor_bbc_designer/"); + make_directory($output_prefix."/graphics/"); + make_directory($output_prefix."/graphics/xor_bbc_designer/"); + + convert_designer_levels($file_input, $output_prefix."/levels/xor_bbc_designer/xor_bbc_designer_"); + create_set($output_prefix."/levels/xor_bbc_designer/set.chroma", "XOR (BBC Designer)"); + + convert_bbc_graphics($file_input, $output_prefix."/graphics/xor_bbc_designer/xor_bbc_designer_"); + create_graphics_set($output_prefix."/graphics/xor_bbc_designer.chroma", "xor_bbc_designer", "XOR (BBC Designer)", 24); + + convert_bbc_music($file_input, $output_prefix."/xor-theme.xm"); +} + + +sub convert_c64_all +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + make_directory($output_prefix); + make_directory($output_prefix."/levels/"); + make_directory($output_prefix."/levels/xor_c64/"); + make_directory($output_prefix."/graphics/"); + make_directory($output_prefix."/graphics/xor_c64/"); + + convert_bbc_levels($file_input, $output_prefix."/levels/xor_c64/xor_c64_"); + create_set($output_prefix."/levels/xor_c64/set.chroma", "XOR (C64)"); + + convert_c64_graphics($file_input, $output_prefix."/graphics/xor_c64/xor_c64_"); + create_graphics_set($output_prefix."/graphics/xor_c64.chroma", "xor_c64", "XOR (C64)", 24); +} + +sub convert_spectrum_all +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + make_directory($output_prefix); + make_directory($output_prefix."/levels/"); + make_directory($output_prefix."/levels/xor_spectrum/"); + make_directory($output_prefix."/graphics/"); + make_directory($output_prefix."/graphics/xor_spectrum/"); + + convert_spectrum_levels($file_input, $output_prefix."/levels/xor_spectrum/xor_spectrum_"); + create_set($output_prefix."/levels/xor_spectrum/set.chroma", "XOR (Spectrum)"); + + convert_spectrum_graphics($file_input, $output_prefix."/graphics/xor_spectrum/xor_spectrum_"); + create_graphics_set($output_prefix."/graphics/xor_spectrum.chroma", "xor_spectrum", "XOR (Spectrum)", 24); +} + +sub convert_cpc_all +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + make_directory($output_prefix); + make_directory($output_prefix."/levels/"); + make_directory($output_prefix."/levels/xor_cpc/"); + make_directory($output_prefix."/graphics/"); + make_directory($output_prefix."/graphics/xor_cpc/"); + + convert_spectrum_levels($file_input, $output_prefix."/levels/xor_cpc/xor_cpc_"); + create_set($output_prefix."/levels/xor_cpc/set.chroma", "XOR (CPC)"); + + convert_cpc_graphics($file_input, $output_prefix."/graphics/xor_cpc/xor_cpc_"); + create_graphics_set($output_prefix."/graphics/xor_cpc.chroma", "xor_cpc", "XOR (CPC)", 24); +} + +sub convert_amiga_all +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + make_directory($output_prefix); + + make_directory($output_prefix."/levels/"); + make_directory($output_prefix."/levels/xor_amiga_1/"); + make_directory($output_prefix."/levels/xor_amiga_2/"); + + convert_amiga_levels($file_input."/standard.mazes", $output_prefix."/levels/xor_amiga_1/xor_amiga_1_"); + + convert_amiga_levels($file_input."/standard2.mazes", $output_prefix."/levels/xor_amiga_2/xor_amiga_2_"); + + create_set($output_prefix."/levels/xor_amiga_1/set.chroma", "XOR (Amiga Set 1)"); + create_set($output_prefix."/levels/xor_amiga_2/set.chroma", "XOR (Amiga Set 2)"); + + make_directory($output_prefix."/graphics/"); + make_directory($output_prefix."/graphics/xor_amiga/"); + + convert_amiga_graphics($file_input, $output_prefix."/graphics/xor_amiga"); + + open(FILE, ">".$output_prefix."/graphics/xor_amiga.chroma"); + print FILE << "EOF"; + + + + +XOR (Amiga) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOF + close(FILE); +} + +sub convert_atari_all +{ + my $file_input = shift(@_); + my $output_prefix = shift(@_); + + make_directory($output_prefix); + make_directory($output_prefix."/levels/"); + make_directory($output_prefix."/levels/xor_atari/"); + make_directory($output_prefix."/graphics/"); + make_directory($output_prefix."/graphics/xor_atari/"); + + convert_atari_levels($file_input, $output_prefix."/levels/xor_atari/xor_atari_"); + create_set($output_prefix."/levels/xor_atari/set.chroma", "XOR (Atari ST)"); + + convert_atari_graphics($file_input, $output_prefix."/graphics/xor_atari"); + + open(FILE, ">".$output_prefix."/graphics/xor_atari.chroma"); + +print FILE << "EOF"; + + + + +XOR (Atari ST) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EOF + close(FILE); +} + +############################################################################### + +sub convert_enigma +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + # single file + if(-f $file_input) + { + convert_enigma_file($file_input, $file_output); + return; + } + + if(-d $file_input) + { + opendir(DIR, $file_input) || die "Couldn't open input directory ($file_input): $!\n"; + + $output_prefix = $file_output; + make_directory($output_prefix); + make_directory($output_prefix."/levels/"); + make_directory($output_prefix."/levels/enigma/"); + + create_set($output_prefix."/levels/enigma/set.chroma", "Enigma"); + + while(($entry = readdir(DIR)) ne "") + { + next if($entry eq "." || $entry eq ".."); + next if($entry !~ /.level$/); + + $output = $entry; + $output =~ s/.level$/.chroma/; + + convert_enigma_file($file_input."/".$entry, $file_output."/levels/enigma/".$output); + } + + closedir(DIR); + } + else + { + die "Couldn't open input directory ($file_input)\n"; + } + +} + +############################################################################### + +sub convert_enigma_file +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + print "Converting '$file_input'\n"; + + $title = ""; $height = 0; $width = 0; $map = ""; + + open(INPUT, $file_input) || die "Couldn't open input file ($file_input): $!\n"; + while() + { + if(/^Title: (.*)/) + { + $title = $1; + } + if(/^Height: (\d+)/) + { + $height = $1; + } + if(/^Width: (\d+)/) + { + $width = $1; + } + if(/^Map: (.*)/) + { + $line = $1; + $line =~ tr/-+|&~@E$<^>vYZWX/%%%%%1\/*abcdABCD/; + $map .= $line."\n"; + } + } + + close(INPUT); + + open(OUTPUT, ">".$file_output) || die "Couldn't open output file ($file_output): $!\n"; + print OUTPUT << "EOF"; +chroma level + +title: Enigma: $title +mode: enigma +size: $width $height + +data: +$map +EOF + close(OUTPUT); + +} + +############################################################################### + +sub convert_chroma2enigma +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + open(INPUT, $file_input) || die "Couldn't open input file ($file_input): $!\n"; + + $size_x = 0; + $size_y = 0; + $title = ""; + + $state = 0; + while() + { + $state = 1 if(/^chroma level/); + next if($state == 0); + + if(/^size: (\d+) (\d+)/) + { + $size_x = $1; + $size_y = $2; + } + if(/^title: (.*)/) + { + $title = $1; + } + if(/^data:/) + { + $state = 2; + last; + } + + } + + if($state != 2) + { + die "Unable to locate data in input file"; + } + + $x = 0; + $y = 0; + + while(!eof(INPUT) && $y < $size_y) + { + $c = getc(INPUT); + next if($c eq "\r" || $c eq "\n"); + + $map[$x][$y] = $c; + $x ++; + if($x == $size_x) + { + $x = 0; $y ++; + } + } + + close(INPUT); + + open(OUTPUT, ">".$file_output) || die "Unable to open output file: $!\n"; + print OUTPUT "Title: $title\n"; + print OUTPUT "Height: $size_y\n"; + print OUTPUT "Width: $size_x\n"; + for($y = 0; $y < $size_y; $y ++) + { + print OUTPUT "Map: "; + for($x = 0; $x < $size_x; $x ++) + { + $c = $map[$x][$y]; + $c =~ tr/1\/*abcdABCD/@E$<^>vYZWX/; + print OUTPUT $c; + } + print OUTPUT "\n"; + } + close(OUTPUT); + +} + +############################################################################### +# +# To replace level 1 of the BBC XOR disc image with the XOR regression tests: +# convert2chroma.pl --chroma2xor levels/regression/xor-regression.chroma regression.xor xor-bbc.ssd 1 + +sub convert_chroma2xor +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + open(INPUT, $file_input) || die "Couldn't open input file ($file_input): $!\n"; + + $size_x = 0; + $size_y = 0; + $title = ""; + + $state = 0; + while() + { + $state = 1 if(/^chroma level/); + next if($state == 0); + + if(/^size: (\d+) (\d+)/) + { + $size_x = $1; + $size_y = $2; + } + if(/^title: (.*)/) + { + $title = $1; + } + if(/^view1: (\d+) (\d+)/) + { + $data{"view1x"} = $1; + $data{"view1y"} = $2; + } + if(/^view2: (\d+) (\d+)/) + { + $data{"view2x"} = $1; + $data{"view2y"} = $2; + } + if(/^viewteleport1: (\d+) (\d+) \((\d+) (\d+)\)/) + { + $data{"viewteleport1x"} = $1; + $data{"viewteleport1y"} = $2; + $data{"teleport1x"} = $3; + $data{"teleport1y"} = $4; + $data{"teleports"} ++; + } + if(/^viewteleport2: (\d+) (\d+) \((\d+) (\d+)\)/) + { + $data{"viewteleport2x"} = $1; + $data{"viewteleport2y"} = $2; + $data{"teleport2x"} = $3; + $data{"teleport2y"} = $4; + $data{"teleports"} ++; + } + if(/^data:/) + { + $state = 2; + last; + } + + } + + if($state != 2) + { + die "Unable to locate data in input file"; + } + + $x = 0; + $y = 0; + + $base = 0x900; + + while(!eof(INPUT) && $y < $size_y) + { + $c = getc(INPUT); + next if($c eq "\r" || $c eq "\n"); + + $p = 0x0; + $p = 0x1 if($c eq "%"); + $p = 0x2 if($c eq "1"); + $p = 0x3 if($c eq "2"); + $p = 0x4 if($c eq "M" || $c eq "m" || $c eq "N" || $c eq "n"); + $p = 0x5 if($c eq "-"); + $p = 0x6 if($c eq "|"); + $p = 0x7 if($c eq "d"); + $p = 0x8 if($c eq "a"); + $p = 0x9 if($c eq "D"); + $p = 0xa if($c eq "A"); + $p = 0xb if($c eq "*"); + $p = 0xc if($c eq "/"); + $p = 0xd if($c eq "o"); + $p = 0xe if($c eq "T"); + $p = 0xf if($c eq "S"); + + if($c eq "M") { $data{"mapTLx"} = $x; $data{"mapTLy"} = $y; } + if($c eq "m") { $data{"mapTRx"} = $x; $data{"mapTRy"} = $y; } + if($c eq "N") { $data{"mapBLx"} = $x; $data{"mapBLy"} = $y; } + if($c eq "n") { $data{"mapBRx"} = $x; $data{"mapBRy"} = $y; } + if($c eq "1") { $data{"player1x"} = $x; $data{"player1y"} = $y; } + if($c eq "2") { $data{"player2x"} = $x; $data{"player2y"} = $y; } + if($c eq "*") { $data{"stars"} ++; } + if($c eq "T" && $data{"teleports"} != 2) + { + $data{"teleports"} ++; + $data{"teleport".$data{"teleports"}."x"} = $x; + $data{"teleport".$data{"teleports"}."y"} = $y; + } + + $map[$x][$y] = $p; + $x ++; + if($x == $size_x) + { + $x = 0; $y ++; + } + } + + close(INPUT); + + open(OUTPUT, ">".$file_output) || die "Unable to open output file: $!\n"; + binmode OUTPUT; + + for($y = 1; $y < 31; $y ++) + { + for($x = 1; $x < 31; $x += 2) + { + print OUTPUT chr($map[$x][$y] + 16 * $map[$x + 1][$y]); + } + } + + # Sanitise viewpoints + if(!defined($data{"view1x"})) + { + $data{"view1x"} = $data{"player1x"} - 3; + $data{"view1y"} = $data{"player1y"} - 3; + } + if(!defined($data{"view2x"})) + { + $data{"view2x"} = $data{"player2x"} - 3; + $data{"view2y"} = $data{"player2y"} - 3; + } + if(!defined($data{"viewteleport1x"})) + { + $data{"viewteleport1x"} = $data{"teleport1x"} - 3; + $data{"viewteleport1y"} = $data{"teleport1y"} - 3; + } + if(!defined($data{"viewteleport2x"})) + { + $data{"viewteleport2x"} = $data{"teleport2x"} - 3; + $data{"viewteleport2y"} = $data{"teleport2y"} - 3; + } + + # Ensure viewpoints are not offscreen + foreach $i ("view1x", "view1y", "view2x", "view2y", "viewteleport1x", "viewteleport1y", "viewteleport2x", "viewteleport2y") + { + if($data{$i} < 0) + { + $data{$i} = 0; + } + if($data{$i} > 24) + { + $data{$i} = 24; + } + } + + # Sanitise title + $title =~ s/^XOR: //; + $title =~ tr/a-z/A-Z/; + $title =~ tr/A-Z ?//cd; + $title = substr($title, 0, 19); + if(length($title < 19)) + { + $l = length($title); + $title = " "x((19 - $l)/2).$title." "x((19 - $l)/2); + $title .= " " if(length($title != 19)); + } + $title .= "\r"; + + # Map data + foreach $i ("TL", "TR", "BL", "BR") + { + if(defined($data{"map".$i."x"})) + { + print OUTPUT pack("v", $base + $data{"map".$i."x"} + $data{"map".$i."y"} * 32 - 32); + } + else + { + print OUTPUT pack("v", 0); + } + } + + # Player and view data + for($i = 1; $i <= 2; $i ++) + { + print OUTPUT pack("v", $base + $data{"player".$i."x"} + $data{"player".$i."y"} * 32 - 32); + print OUTPUT pack("c", $data{"player".$i."x"} - $data{"view".$i."x"}); + print OUTPUT pack("c", $data{"player".$i."y"} - $data{"view".$i."y"}); + print OUTPUT pack("c", $data{"view".$i."x"}); + print OUTPUT pack("c", $data{"view".$i."y"}); + print OUTPUT pack("v", $base + $data{"view".$i."x"} + $data{"view".$i."y"} * 32); + } + + # Star count and padding + print OUTPUT pack("c", 0x02); + print OUTPUT pack("c", 0x02); + print OUTPUT pack("c", $data{"stars"}); + print OUTPUT pack("c", 0x00); + print OUTPUT pack("c", 0x00); + print OUTPUT pack("c", 0x00); + print OUTPUT pack("c", 0x00); + print OUTPUT pack("c", 0x00); + + # Teleport data + if($data{"teleports"} != 2 ) + { + print OUTPUT pack("Z30", ""); + } + else + { + for($i = 1; $i <= 2; $i ++) + { + print OUTPUT pack("v", $base + $data{"teleport".$i."x"} + $data{"teleport".$i."y"} * 32); + print OUTPUT pack("c", $data{"teleport".$i."x"} - $data{"viewteleport".$i."x"}); + print OUTPUT pack("c", $data{"teleport".$i."y"} - $data{"viewteleport".$i."y"}); + print OUTPUT pack("c", $data{"viewteleport".$i."x"}); + print OUTPUT pack("c", $data{"viewteleport".$i."y"}); + print OUTPUT pack("v", $base + $data{"viewteleport".$i."x"} + $data{"viewteleport".$i."y"} * 32); + } + + print OUTPUT pack("Z14", ""); + } + + close(OUTPUT); + + # Optionally insert the file into the BBC XOR disc image + if($ARGV[3] ne "") + { + $file_discimage = $ARGV[3]; + + if($ARGV[4] ne "") + { + $level = $ARGV[4]; + } + if($level < 1 || $level >= 15) + { + $level = 1; + } + + $xor = read_file($file_discimage); + $insert = read_file($file_output); + + $index_numbers = locate_string(\$xor, "\x00\x4d\x00\x01\x00\x02\x00\x03\x00\x04\x00\x05\x00\x06\x00\x07\x00\x08\x00\x09\x01\x00\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05"); + + # BBC XOR + if($index_numbers >= 0) + { + $offset = $index_numbers + 0x179 + (15 - $level) * 0x200; + insert(\$xor, \$insert, $offset); + + $offset = $index_numbers + 0x22 + ($level - 1) * 23; + insert(\$xor, \$title, $offset); + + open(OUTPUT, ">".$file_discimage) || die "Unable to open output file: $!\n"; + binmode OUTPUT; + print OUTPUT $xor; + close(OUTPUT); + } + else + { + die "Unable to identify file\n"; + } + } + +} + +sub insert +{ + my $data = shift(@_); + my $string = shift(@_); + my $offset = shift(@_); + + my $tmp = shift(@_); + + $tmp = substr($$data, 0, $offset); + $tmp .= $$string; + $tmp .= substr($$data, $offset + length($$string)); + + $$data = $tmp; +} + + +############################################################################### + +sub convert_bbc_patch +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + $xor = read_file($file_input); + + $index_skip = locate_string(\$xor, "\xad\x6e\x25\xc9\x0b\x30\x06\xee\x6e\x25"); + # BBC XOR + if($index_skip != 0) + { + $xor =~ s/\xad\x6e\x25\xc9\x0b\x30\x06\xee\x6e\x25/\xad\x6e\x25\xc9\x0b\x30\x06\xea\xea\xea/; + $xor =~ s/\xc9\x0b\x30\x07\x29\x01\xf0\x03\xce\x6e\x25/\xc9\x0b\x30\x07\x29\x01\xf0\x03\xea\xea\xea/; + open(OUTPUT, ">".$file_output) || die "Unable to open output file: $!\n"; + binmode OUTPUT; + print OUTPUT $xor; + close(OUTPUT); + } + else + { + die "Unable to identify file\n"; + } +} + + +############################################################################### + +sub convert_amiga_patch +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + open(IN, $file_input) || die "Unable to open input file: $!\n"; + open(OUT,">".$file_output) || die "Unable to open outfile: $!\n"; + binmode IN; + binmode OUT; + while() + { + $line = $_; + # Patch protection routine + if($line =~ /\x00\x00\x00\x06\x8c\xc0\x60\x00\xfc\x84\x4a\xac\x8c\xa8\x6f\x24/) + { + $line =~ s/\x00\x00\x00\x06\x8c\xc0\x60\x00\xfc\x84\x4a\xac\x8c\xa8\x6f\x24/\x00\x00\x00\x06\x8c\xc0\x60\x00\xfc\x84\x4a\xac\x8c\xa8\x60\x24/; + $ok |= 1; + } + # Patch checksum + if($line =~ /\xc0\xf8\x37\xb4/) + { + $line =~ s/\xc0\xf8\x37\xb4/\xc0\xf8\x46\xb4/; + $ok |= 2; + } + print OUT $line; + } + close OUT; + close IN; + + if($ok != 3) + { + die "Unable to identify file\n"; + } +} + +############################################################################### +# +# http://www.rvvz.demon.nl/xor/ +# A JavaScript version by Rob Veldhuyzen van Zanten +# +sub convert_zanten_level +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + print "Converting '$file_input'\n"; + + $title = ""; $height = 0; $width = 0; $map = ""; + + open(INPUT, $file_input) || die "Couldn't open input file ($file_input): $!\n"; + while() + { + if(/^spel='(.*)'/) + { + $title = $1; + } + if(/^'(.*)'/) + { + $line = $1; + $width = length($line); + $line =~ tr/ #UWpqrs\-|".$file_output) || die "Couldn't open output file ($file_output): $!\n"; + print OUTPUT << "EOF"; +chroma level + +title: XOR: $title +mode: xor +size: $width $height + +data: +$map +EOF + close(OUTPUT); + +} + +############################################################################### +# +# http://xor.ovine.net +# Ovine's "remake" has the worst XOR engine I've come across - thoroughly +# broken precedence and bombs that can be pushed against their gravity. Quite +# how well levels written for such an engine will work with Chroma is anyone's +# guess, but converting their level files is simple enough: +# +# 0x000 - 0x3ff Map data (32 * 32, bytes as per BBC XOR except for maps) +# 0x400 - 0x401 Masks total +# 0x402 - 0x411 Title +# 0x412 - 0x437 Unused? + +sub convert_ovine_level +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + print "Converting '$file_input'\n"; + + $level_data = read_file($file_input); + $bad = 1 if(length($level_data) != 0x438); + + $title = ""; $map = ""; + + $o = 0; + for($y = 0; $y < 32; $y ++) + { + for($x = 0; $x < 32; $x ++) + { + $c = byte(\$level_data, $o); + $map .= " " if($c == 0x00); + $map .= "%" if($c == 0x01); + $map .= "1" if($c == 0x02); + $map .= "2" if($c == 0x03); + $map .= "-" if($c == 0x05); + $map .= "|" if($c == 0x06); + $map .= "d" if($c == 0x07); + $map .= "a" if($c == 0x08); + $map .= "D" if($c == 0x09); + $map .= "A" if($c == 0x0a); + $map .= "*" if($c == 0x0b); + $map .= "/" if($c == 0x0c); + $map .= "o" if($c == 0x0d); + $map .= "T" if($c == 0x0e); + $map .= "S" if($c == 0x0f); + $map .= "M" if($c == 0x19); + $map .= "m" if($c == 0x16); + $map .= "N" if($c == 0x18); + $map .= "n" if($c == 0x17); + $bad = 1 if($c >= 0x1a || $c == 0x04); + $o ++; + } + $map .= "\n"; + } + + if($bad) + { + print "ERROR: Couldn't convert file\n"; + return; + } + + $o = 0x402; + while(byte(\$level_data, $o) != 0 && $o < 0x412) + { + $title .= chr(byte(\$level_data, $o)); + $o ++; + } + + open(OUTPUT, ">".$file_output) || die "Couldn't open output file ($file_output): $!\n"; + print OUTPUT << "EOF"; +chroma level + +title: XOR: $title +mode: xor +size: 32 32 + +data: +$map +EOF + close(OUTPUT); + +} diff --git a/resources/crush.pl b/resources/crush.pl new file mode 100755 index 0000000..2394ac6 --- /dev/null +++ b/resources/crush.pl @@ -0,0 +1,42 @@ +#! /usr/bin/perl +# +# crush.pl +# Reduce the size of the graphics files produced by the make-pieces scripts +# +# Copyright (C) 2010-2019 Amf +# +# 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 + +$pngcrush = `which pngcrush`; chop $pngcrush; +die "Unable to locate pngcrush" if(!$pngcrush); + +$directory = $ARGV[0]; +die "Unable to open directory: $!" if(!opendir(DIR, $directory)); + +$file_tmp = "tmp.png"; + +while($entry = readdir(DIR)) +{ + next if($entry eq "." || $entry eq ".."); + next if($entry !~ /.png$/); + + system("$pngcrush $directory/$entry $file_tmp"); + if(-e $file_tmp) + { + system("cp $file_tmp $directory/$entry"); + unlink($file_tmp); + } +} + diff --git a/resources/icons.svg b/resources/icons.svg new file mode 100644 index 0000000..f1a6f58 --- /dev/null +++ b/resources/icons.svg @@ -0,0 +1,135 @@ + + + + + Copyright (C) 2010 Amf + + + + + + + + image/svg+xml + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/logo.svg b/resources/logo.svg new file mode 100644 index 0000000..f609988 --- /dev/null +++ b/resources/logo.svg @@ -0,0 +1,89 @@ + + + + + Copyright (C) 2010 Amf + + + + image/svg+xml + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + diff --git a/resources/make-base-marble.pl b/resources/make-base-marble.pl new file mode 100755 index 0000000..6f4821c --- /dev/null +++ b/resources/make-base-marble.pl @@ -0,0 +1,73 @@ +#! /usr/bin/perl +# +# make-base-marble.pl +# Create the SPACE pieces for the chroma-marble graphics scheme. +# +# Requirements: ImageMagick, Inkscape +# +# Copyright (C) 2010-2019 Amf +# +# 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 + +if($#ARGV != 1) +{ + print STDERR "Usage: make-base-marble.pl \n"; + exit(1); +} + +$file_svg = $ARGV[0]; +$dir_out = $ARGV[1]; + +if(! -e $file_svg) +{ + print STDERR "make-base-marble: couldn't open SVG file\n"; + exit(1); +} +if(! -d $dir_out) +{ + mkdir($dir_out); + if(! -d $dir_out) + { + print STDERR "make-base-marble: couldn't open output directory\n"; + exit(1); + } +} + +make_pieces(16, 0); +make_pieces(20, 0); +make_pieces(24, 0); +make_pieces(32, 0); +make_pieces(40, 0); +make_pieces(64, 0); + +exit(0); + +sub make_pieces +{ + my $size = shift(@_); + my $partial = shift(@_); + + $width = $size; + $height = $size; + + $file_png = sprintf("%s/%d_%s%s.png", $dir_out, $size, "space", $direction); + $width_png = $width * 8; + $height_png = $height * 8; + + $background = ""; + + # Use Inkscape to convert the SVG to a PNG + system("inkscape $background -w $width_png -h $height_png -e $file_png $file_svg"); +} diff --git a/resources/make-graphics.sh b/resources/make-graphics.sh new file mode 100755 index 0000000..7b5a471 --- /dev/null +++ b/resources/make-graphics.sh @@ -0,0 +1,29 @@ +#! /bin/sh +# +# make-graphics.sh +# Make the graphics schemes for Chroma. Run from the resources directory. +# +# Copyright (C) 2010-2019 Amf +# +# 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 +# +./make-pieces-marble.pl pieces-marble.svg ../graphics/chroma-marble/ +./make-base-marble.pl pieces-marble-base.svg ../graphics/chroma-marble/ +./make-wall-marble.pl pieces-marble-wall.svg ../graphics/chroma-marble/ +./crush.pl ../graphics/chroma-marble/ +./make-pieces-neon.pl ../graphics/chroma-neon/ +./crush.pl ../graphics/chroma-neon/ +./make-pieces-zen.pl pieces-zen.svg ../graphics/chroma-zen/ +./crush.pl ../graphics/chroma-zen/ diff --git a/resources/make-pieces-marble.pl b/resources/make-pieces-marble.pl new file mode 100755 index 0000000..a4e3968 --- /dev/null +++ b/resources/make-pieces-marble.pl @@ -0,0 +1,196 @@ +#! /usr/bin/perl +# +# make-base-marble.pl +# Create the pieces for the chroma-marble graphics scheme. +# +# Requirements: ImageMagick, Inkscape, NetPBM +# +# Copyright (C) 2010-2019 Amf +# +# 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 + +if($#ARGV != 1) +{ + print STDERR "Usage: make-pieces-marble.pl \n"; + exit(1); +} + +$file_svg = $ARGV[0]; +$dir_out = $ARGV[1]; + +if(! -e $file_svg) +{ + print STDERR "make-pieces-marble: couldn't open SVG file\n"; + exit(1); +} +if(! -d $dir_out) +{ + mkdir($dir_out); + if(! -d $dir_out) + { + print STDERR "make-pieces-marble: couldn't open output directory\n"; + exit(1); + } +} + +make_pieces(16, 0); +make_pieces(20, 0); +make_pieces(24, 0); +#make_pieces(28, 1); +make_pieces(32, 0); +make_pieces(40, 0); +make_pieces(64, 0); + +exit(0); + +sub make_pieces +{ + my $size = shift(@_); + my $partial = shift(@_); + + $rows = 8; + $columns = 12; + + @pieces = ( + "", "", "", "", "", "", "", "", + "arrow_shadow_left", "arrow_shadow_up", "arrow_shadow_right", "arrow_shadow_down", "bomb_shadow_left", "bomb_shadow_up", "bomb_shadow_right", "bomb_shadow_down", + "arrow_blue_left", "arrow_blue_up", "arrow_blue_right", "arrow_blue_down", "bomb_blue_left", "bomb_blue_up", "bomb_blue_right", "bomb_blue_down", + "arrow_green_left", "arrow_green_up", "arrow_green_right", "arrow_green_down", "bomb_green_left", "bomb_green_up", "bomb_green_right", "bomb_green_down", + "arrow_red_left", "arrow_red_up", "arrow_red_right", "arrow_red_down", "bomb_red_left", "bomb_red_up", "bomb_red_right", "bomb_red_down", + "", "circle", "circle_double", "star*", "dots", "dots_double", "dots_y", "dots_x", + "", "circle_shadow", "circle_double_shadow", "star_shadow", "dots_shadow", "dots_double_shadow", "dots_y_shadow", "dots_x_shadow", + "wall", "teleport", "switch", "door*", "map_top_left", "map_top_right", "map_bottom_left", "map_bottom_right", + "", "teleport_shadow", "switch_shadow", "door_shadow", "map_shadow", "", "", "", + "player_two*", "player_one*", "player_two_swapped", "player_one_swapped", "wall_inside#", "wall_y#", "wall_x#", "wall_outside#", + "player_shadow", "", "", "", "wall_inside_shadow", "wall_y_shadow", "wall_x_shadow", "wall_outside_shadow" + ); + + $width = $size; + $height = $size; + + $file_png = "/tmp/chroma-pieces-$$.png"; + $width_png = $width * ($rows * 2 - 1); + $height_png = $height * ($columns * 2 - 1); + + $background = ""; + $background = "-b \"#000000\"" if($partial); + + # Use Inkscape to convert the SVG to a PNG + system("inkscape $background -w $width_png -h $height_png -e $file_png $file_svg"); + + for($piece = 0; $piece < $rows * $columns; $piece ++) + { + $name = $pieces[$piece]; + + next if($name eq ""); + + next if($partial && $name !~ /\*$/); + + $grey = 0; + $name =~ s/\*$//; + if($name =~ /\#$/) + { + $name =~ s/\#$//; + $grey = 1; + } + + print "$size $name\n"; + + $file_out = sprintf("%s/%d_%s%s.png", $dir_out, $size, $name, $direction); + + $xoff = $width * 2 * ($piece % $rows); + $yoff = $height * 2 * (int($piece / $rows)); + $w = $width; + $h = $height; + + system("convert -quality 100 -crop ".$w."x".$h."+".$xoff."+".$yoff." $file_png $file_out"); + if($grey) + { + grey2alpha($file_out, $file_out); + } + } + + unlink($file_png); +} + +# A poor man's "colour to alpha" to save having to use GIMP by hand! +sub grey2alpha +{ + my $file_input = shift(@_); + my $file_output = shift(@_); + + $file_tmp_pnm = "tmp.pnm"; + $file_tmp_pgm = "tmp.pgm"; + + $grey = 111; + + open(INPUT, "pngtopnm $file_input |") || die "Couldn't open pngtopnm: $!"; + binmode INPUT; + $line = ; + die "Unable to identify pnm: $file_input" if($line !~/^P6$/); + $line = ; + if($line =~ /^(\d+) (\d+)$/) + { + $size_x = $1; $size_y = $2; + } + else + { + die "Unable to identify size from pnm: $file_input"; + } + $line = ; + + $slash = $/; + undef $/; + + $data = ; + + open(TMPCOLOUR, ">".$file_tmp_pnm) || die "Couldn't open tmp_pnm: $!"; + binmode TMPCOLOUR; + print TMPCOLOUR "P6\n$size_x $size_y\n$line"; + open(TMPALPHA, ">".$file_tmp_pgm) || die "Couldn't open tmp_pgm: $!"; + print TMPALPHA "P5\n$size_x $size_y\n$line"; + binmode TMPALPHA; + + for($y = 0; $y < $size_y; $y ++) + { + for($x = 0; $x < $size_x; $x ++) + { + $r = ord(substr($data, ($y * $size_y + $x) * 3)); + if($r <= $grey) + { + $c = 0; + $a = 255 / ($grey - 0) * (111 - $r); + } + else + { + $c = 255; + $a = 255 / (255 - $grey) * ($r - 111); + } + printf TMPCOLOUR "%c%c%c", $c, $c, $c; + printf TMPALPHA "%c", $a; + } + } + + close(INPUT); + + close(TMPCOLOUR); + close(TMPALPHA); + + $/ = $slash; + + system("pnmtopng -alpha $file_tmp_pgm $file_tmp_pnm > $file_output"); + unlink($file_tmp_pgm); + unlink($file_tmp_pnm); +} diff --git a/resources/make-pieces-neon.pl b/resources/make-pieces-neon.pl new file mode 100755 index 0000000..7e8c29e --- /dev/null +++ b/resources/make-pieces-neon.pl @@ -0,0 +1,221 @@ +#! /usr/bin/perl +# +# make-base-neon.pl +# Create the pieces for the chroma-neon graphics scheme. +# +# Requirements: ImageMagick, Inkscape +# +# Copyright (C) 2010-2019 Amf +# +# 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 + +# The colours used are as follows: +# +# black 000000 000000 ffffff +# red 800000 ff0000 ffc0c0 +# green 008000 00ff00 c0ffc0 +# yellow dd0000 e8d912 ffffff +# blue 000080 0000ff c0c0ff +# magenta 400080 8000ff eeddff +# cyan 0000dd 12d9e8 ffffff +# +# Use blur-full for most pieces, blur-half for earth and earth_double, and +# blur-quarter for earth_directional, maps and teleport. + +if($#ARGV != 0) +{ + print STDERR "Usage: make-pieces-neon.pl \n"; + exit(1); +} + +$file_svg_base = "pieces-neon-base.svg"; +$file_svg_overlay = "pieces-neon-overlay.svg"; +$file_svg_overlay_double = "pieces-neon-overlay-double.svg"; +$dir_out = $ARGV[0]; + +if(! -e $file_svg_base || ! -e $file_svg_overlay || ! -e $file_svg_overlay_double) +{ + print STDERR "make-pieces-neon: couldn't open SVG file\n"; + exit(1); +} +if(! -d $dir_out) +{ + mkdir($dir_out); + if(! -d $dir_out) + { + print STDERR "make-pieces-neon: couldn't open output directory\n"; + exit(1); + } +} + +make_pieces(16, 0); +make_pieces(20, 0); +make_pieces(24, 0); +#make_pieces(28, 1); +make_pieces(32, 0); +make_pieces(40, 0); +make_pieces(64, 0); + +exit(0); + +sub make_pieces +{ + my $size = shift(@_); + my $partial = shift(@_); + + $rows = 4; + $columns = 7; + + # Pieces to make: * = create small piece, # = don't make shadow + @pieces = ( + "arrow_red", "arrow_green", "arrow_blue", "circle", + "bomb_red","bomb_green", "bomb_blue", "circle_double", + "earth", "earth_double", "earth_y", "star*", + "wall", "teleport", "switch", "door", + "map_top_left", "map_top_right", "map_bottom_left", "map_bottom_right", + "player_one*", "player_two*", "player_one_swapped", "player_two_swapped", + "wall_x#", "wall_y#", "wall_outside#", "wall_inside#" + ); + + $width = $size; + $height = $size; + + $width_png = $width * ($rows * 2 + 1); + $height_png = $height * ($columns * 2 + 1); + + $file_png_base = "/tmp/chroma-pieces-base-$$.png"; + system("inkscape -w $width_png -h $height_png -e $file_png_base $file_svg_base"); + + $file_png_overlay = "/tmp/chroma-pieces-overlay-$$.png"; + system("inkscape -w $width_png -h $height_png -e $file_png_overlay $file_svg_overlay"); + + $file_png_overlay_double = "/tmp/chroma-pieces-double-$$.png"; + system("inkscape -w $width_png -h $height_png -e $file_png_overlay_double $file_svg_overlay_double"); + + $file_png_partial = "/tmp/chroma-pieces-partial-$$.png"; + system("convert -compose overlay -composite $file_png_base $file_png_overlay $file_png_partial"); + + $file_png_result = "/tmp/chroma-pieces-overlayed-$$.png"; + system("convert -compose overlay -composite $file_png_partial $file_png_overlay_double $file_png_result"); + + $file_png_crop = "/tmp/chroma-pieces-crop-$$.png"; + $xoff = $width * 0.5; + $yoff = $height * 12.5; + system("convert -quality 100 -crop ".($width * 2)."x".($height * 2)."+".$xoff."+".$yoff." $file_png_overlay $file_png_crop"); + + $file_png_back = "/tmp/chroma-pieces-back-$$.png"; + $xoff = $width * 1; + $yoff = $height * 13; + system("convert -quality 100 -crop ".$width."x".$height."+".$xoff."+".$yoff." $file_png_overlay $file_png_back"); + + for($piece = 0; $piece < $rows * $columns; $piece ++) + { + $name = $pieces[$piece]; + + next if($name eq ""); + + next if($partial && $name !~ /\*$/); + + if($name =~ /\#$/) + { + $shadow = 0; + } + else + { + $shadow = 1; + } + + if($partial) + { + $name = "small_$name"; + } + + $name =~ s/\*$//; + $name =~ s/\#$//; + + print "$size $name\n"; + + $direction = ""; + $direction = "_left" if($name =~ /^arrow/ || $name =~ /^bomb/); + + # Make shadow + if(!$partial && $shadow) + { + $file_out = sprintf("%s/%d_%s%s.png", $dir_out, $size, $name, $direction); + $xoff = $width * (0.5 + 2 * ($piece % $rows)); + $yoff = $height * (0.5 + 2 * (int($piece / $rows))); + + system("convert -quality 100 -crop ".($width * 2)."x".($height * 2)."+".$xoff."+".$yoff." $file_png_result $file_out"); + + $file_shadow = $file_out; $file_shadow =~ s/\.png/_shadow\.png/; + system("composite -compose Dst_Out -gravity South $file_png_crop $file_out -matte $file_shadow"); + } + + # Make piece + $file_out = sprintf("%s/%d_%s%s.png", $dir_out, $size, $name, $direction); + $xoff = $width * (1 + 2 * ($piece % $rows)); + $yoff = $height * (1 + 2 * (int($piece / $rows))); + + system("convert -quality 100 -crop ".$width."x".$height."+".$xoff."+".$yoff." $file_png_result $file_out"); + + # Set background if needed + if($partial) + { + system("composite $file_out $file_png_back $file_out"); + } + + + # Make shadow rotations + if($name eq "earth_y") + { + $file_two = sprintf("%s/%d_%s_shadow.png", $dir_out, $width, "earth_x"); + system("convert -quality 100 -rotate 90 $file_shadow $file_two"); + } + if($name =~ /^arrow/ || $name =~ /^bomb/) + { + $file_two = sprintf("%s/%d_%s%s_shadow.png", $dir_out, $width, $name, "_up"); + system("convert -quality 100 -rotate 90 $file_shadow $file_two"); + $file_two = sprintf("%s/%d_%s%s_shadow.png", $dir_out, $width, $name, "_right"); + system("convert -quality 100 -rotate 180 $file_shadow $file_two"); + $file_two = sprintf("%s/%d_%s%s_shadow.png", $dir_out, $width, $name, "_down"); + system("convert -quality 100 -rotate 270 $file_shadow $file_two"); + } + + # Make piece rotations + if($name eq "earth_y") + { + $file_two = sprintf("%s/%d_%s.png", $dir_out, $width, "earth_x"); + system("convert -quality 100 -rotate 90 $file_out $file_two"); + } + if($name =~ /^arrow/ || $name =~ /^bomb/) + { + $file_two = sprintf("%s/%d_%s%s.png", $dir_out, $width, $name, "_up"); + system("convert -quality 100 -rotate 90 $file_out $file_two"); + $file_two = sprintf("%s/%d_%s%s.png", $dir_out, $width, $name, "_right"); + system("convert -quality 100 -rotate 180 $file_out $file_two"); + $file_two = sprintf("%s/%d_%s%s.png", $dir_out, $width, $name, "_down"); + system("convert -quality 100 -rotate 270 $file_out $file_two"); + } + } + + unlink($file_png_base); + unlink($file_png_overlay); + unlink($file_png_overlay_double); + unlink($file_png_partial); + unlink($file_png_result); + unlink($file_png_crop); + unlink($file_png_back); +} + diff --git a/resources/make-pieces-zen.pl b/resources/make-pieces-zen.pl new file mode 100755 index 0000000..95538be --- /dev/null +++ b/resources/make-pieces-zen.pl @@ -0,0 +1,129 @@ +#! /usr/bin/perl +# +# make-base-zen.pl +# Create the pieces for the chroma-zen graphics scheme. +# +# Requirements: ImageMagick, Inkscape +# +# Copyright (C) 2010-2019 Amf +# +# 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 + + +if($#ARGV != 1) +{ + print STDERR "Usage: make-pieces-zen.pl \n"; + exit(1); +} + +$file_svg = $ARGV[0]; +$dir_out = $ARGV[1]; + +if(! -e $file_svg) +{ + print STDERR "make-pieces-zen: couldn't open SVG file\n"; + exit(1); +} +if(! -d $dir_out) +{ + mkdir($dir_out); + if(! -d $dir_out) + { + print STDERR "make-pieces-zen: couldn't open output directory\n"; + exit(1); + } +} + +make_pieces(16, 0); +make_pieces(20, 0); +make_pieces(24, 0); +#make_pieces(28, 1); +make_pieces(32, 0); +make_pieces(40, 0); +make_pieces(64, 0); + +exit(0); + +sub make_pieces +{ + my $size = shift(@_); + my $partial = shift(@_); + + $rows = 4; + $columns = 7; + + @pieces = ( + "arrow_red", "arrow_green", "arrow_blue", "circle", + "bomb_red","bomb_green", "bomb_blue", "circle_double", + "earth", "earth_double", "earth_y", "star*", + "", "teleport", "switch", "door", + "map_top_left", "map_top_right", "map_bottom_left", "map_bottom_right", + "player_one*", "player_two*", "player_one_swapped", "player_two_swapped", + "wall_x", "wall_y", "wall_outside", "wall_inside" + ); + + $width = $size; + $height = $size; + + $file_png = "/tmp/chroma-pieces-$$.png"; + $width_png = $width * ($rows * 2 - 1); + $height_png = $height * ($columns * 2 - 1); + + $background = ""; + $background = "-b \"#000000\"" if($partial); + + # Use Inkscape to convert the SVG to a PNG + system("inkscape $background -w $width_png -h $height_png -e $file_png $file_svg"); + + for($piece = 0; $piece < $rows * $columns; $piece ++) + { + $name = $pieces[$piece]; + + next if($name eq ""); + + next if($partial && $name !~ /\*$/); + + $name =~ s/\*$//; + + print "$size $name\n"; + + $direction = ""; + $direction = "_left" if($name =~ /^arrow/ || $name =~ /^bomb/); + + $file_out = sprintf("%s/%d_%s%s.png", $dir_out, $size, $name, $direction); + + $xoff = $width * 2 * ($piece % $rows); + $yoff = $height * 2 * (int($piece / $rows)); + + system("convert -quality 100 -crop ".$width."x".$height."+".$xoff."+".$yoff." $file_png $file_out"); + + if($name eq "earth_y") + { + $file_two = sprintf("%s/%d_%s.png", $dir_out, $width, "earth_x"); + system("convert -quality 100 -rotate 90 $file_out $file_two"); + } + if($name =~ /^arrow/ || $name =~ /^bomb/) + { + $file_two = sprintf("%s/%d_%s%s.png", $dir_out, $width, $name, "_up"); + system("convert -quality 100 -rotate 90 $file_out $file_two"); + $file_two = sprintf("%s/%d_%s%s.png", $dir_out, $width, $name, "_right"); + system("convert -quality 100 -rotate 180 $file_out $file_two"); + $file_two = sprintf("%s/%d_%s%s.png", $dir_out, $width, $name, "_down"); + system("convert -quality 100 -rotate 270 $file_out $file_two"); + } + } + + unlink($file_png); +} diff --git a/resources/make-wall-marble.pl b/resources/make-wall-marble.pl new file mode 100755 index 0000000..1d39ca6 --- /dev/null +++ b/resources/make-wall-marble.pl @@ -0,0 +1,73 @@ +#! /usr/bin/perl +# +# make-base-marble.pl +# Create the WALL pieces for the chroma-marble graphics scheme. +# +# Requirements: ImageMagick, Inkscape +# +# Copyright (C) 2010-2019 Amf +# +# 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 + +if($#ARGV != 1) +{ + print STDERR "Usage: make-wall-marble.pl \n"; + exit(1); +} + +$file_svg = $ARGV[0]; +$dir_out = $ARGV[1]; + +if(! -e $file_svg) +{ + print STDERR "make-wall-marble: couldn't open SVG file\n"; + exit(1); +} +if(! -d $dir_out) +{ + mkdir($dir_out); + if(! -d $dir_out) + { + print STDERR "make-wall-marble: couldn't open output directory\n"; + exit(1); + } +} + +make_pieces(16, 0); +make_pieces(20, 0); +make_pieces(24, 0); +make_pieces(32, 0); +make_pieces(40, 0); +make_pieces(64, 0); + +exit(0); + +sub make_pieces +{ + my $size = shift(@_); + my $partial = shift(@_); + + $width = $size; + $height = $size; + + $file_png = sprintf("%s/%d_%s%s.png", $dir_out, $size, "wall", $direction); + $width_png = $width * 8; + $height_png = $height * 8; + + $background = ""; + + # Use Inkscape to convert the SVG to a PNG + system("inkscape $background -w $width_png -h $height_png -e $file_png $file_svg"); +} diff --git a/resources/pieces-marble-base.svg b/resources/pieces-marble-base.svg new file mode 100644 index 0000000..7c1ef73 --- /dev/null +++ b/resources/pieces-marble-base.svg @@ -0,0 +1,340 @@ + + + + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + + + + diff --git a/resources/pieces-marble-wall.svg b/resources/pieces-marble-wall.svg new file mode 100644 index 0000000..923ada6 --- /dev/null +++ b/resources/pieces-marble-wall.svg @@ -0,0 +1,340 @@ + + + + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + + + + diff --git a/resources/pieces-marble.svg b/resources/pieces-marble.svg new file mode 100644 index 0000000..da68c09 --- /dev/null +++ b/resources/pieces-marble.svg @@ -0,0 +1,2422 @@ + + + + + + + image/svg+xml + + Chroma Marble + + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/pieces-neon-base.svg b/resources/pieces-neon-base.svg new file mode 100644 index 0000000..3367f52 --- /dev/null +++ b/resources/pieces-neon-base.svg @@ -0,0 +1,4451 @@ + + + + + + + image/svg+xml + + Chroma Neon (base) + + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/pieces-neon-overlay-double.svg b/resources/pieces-neon-overlay-double.svg new file mode 100644 index 0000000..36c73e2 --- /dev/null +++ b/resources/pieces-neon-overlay-double.svg @@ -0,0 +1,115 @@ + + + + + + + image/svg+xml + + Chroma Neon (overlay double) + + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/pieces-neon-overlay.svg b/resources/pieces-neon-overlay.svg new file mode 100644 index 0000000..cb7177e --- /dev/null +++ b/resources/pieces-neon-overlay.svg @@ -0,0 +1,838 @@ + + + + + + + image/svg+xml + + Chroma Neon (overlay) + + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/pieces-zen.svg b/resources/pieces-zen.svg new file mode 100644 index 0000000..c9fbf56 --- /dev/null +++ b/resources/pieces-zen.svg @@ -0,0 +1,960 @@ + + + + + + + image/svg+xml + + Chroma Zen + + + Copyright (C) 2010 Amf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdldisplay.c b/sdldisplay.c new file mode 100644 index 0000000..f95cc54 --- /dev/null +++ b/sdldisplay.c @@ -0,0 +1,3918 @@ +/* + sdldisplay.c + + Copyright (C) 2010-2019 Amf + + 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 +#include +#include +#include +#include +#include +#include + +#include "chroma.h" +#include "menu.h" +#include "level.h" +#include "display.h" +#include "graphics.h" +#include "colours.h" +#include "sdlfont.h" +#include "sdlscreen.h" +#include "util.h" +#include "actions.h" +#include "xmlparser.h" + +#define MOUSE_TIMEOUT_CLICK 200 +#define MOUSE_TIMEOUT_MOVE 1000 + +char options_colours[FILENAME_MAX] = COLOURS_DEFAULT; +char options_graphics[FILENAME_MAX] = GRAPHICS_DEFAULT; +int options_graphic_level = 0; +int options_sdl_fullscreen = 1; +int options_sdl_width = 0; +int options_sdl_height = 0; +int options_sdl_delay = 100; +int options_sdl_player_delay = 200; +int options_sdl_replay_delay = 200; +int options_sdl_undo_delay = 200; +int options_sdl_size_x = 0; +int options_sdl_size_y = 0; +int options_debug = 0; +#ifdef XOR_COMPATIBILITY +int options_xor_options = 0; +int options_xor_mode = 1; +int options_xor_display = 0; + +int xor_map_scale = 4; +int xor_map_x_offset = 0; +int xor_map_y_offset = 0; +#endif + +#ifdef ENIGMA_COMPATIBILITY +int options_enigma_options = 0; +int options_enigma_mode = 1; +#endif + +int actions[SDLK_LAST]; +int actions_mouse[3][MOUSE_BUTTONS_MAX]; + +int display_offset_x; +int display_offset_y; +int display_offset_pixels_x = 0; +int display_offset_pixels_y = 0; +int display_start_x; +int display_start_y; +int display_end_x; +int display_end_y; +int display_pieces_x; +int display_pieces_y; +int display_focus_x; +int display_focus_y; +int display_bar_pixels = 0; +float display_animation; +int display_animation_x; +int display_animation_y; +int display_border_x = 3; +int display_border_y = 3; + +struct SDL_Surface* psurfacelogo = NULL; +struct SDL_Surface* psurfacelogosmall = NULL; + +extern int font_height; + +extern SDL_Surface *screen_surface; + +extern int screen_width; +extern int screen_height; +extern int screen_fullscreen; + +extern int font_height; +extern int font_width; +extern int font_border; +extern int font_padding; + +extern int font_size_game; + +extern char *piece_name[]; +extern char *action_name[]; +extern char *action_shortname[]; + +extern int move_x[]; +extern int move_y[]; + +extern struct graphics* pdisplaygraphics; +extern struct colours* pdisplaycolours; + +extern char options_graphics[]; +extern char options_colours[]; + +extern int *editor_piece_maps[]; + +void display_movers(struct level* plevel, int redraw); +void displayshadowed_movers(struct level* plevel, int redraw); + +void displayshadowed_level(struct level* plevel); + +void display_clip(struct level* plevel, int clip); +void display_screensizemenu(); + +void display_initactions(); +char *display_keyname(SDLKey key); +void display_addkeytomenu(struct menu* pmenu, int action, char *text); +void display_options_keys(); +void display_options_mouse(); +void display_options_size(); +void display_options_debug(); + +#ifdef XOR_COMPATIBILITY +void xor_focus(struct level* plevel); +#endif + +void display_options_othergames(); + +#define SCREENREDRAW_LEVEL 1 +#define SCREENREDRAW_BAR 2 +#define SCREENREDRAW_ALL (SCREENREDRAW_BAR | SCREENREDRAW_LEVEL) + +void display_init() +{ + char buffer[256]; + struct SDL_Surface* psurfaceicon; + + if(SDL_Init(SDL_INIT_VIDEO) < 0) + { + snprintf(buffer, 256, gettext("Unable to initalise SDL: %s"), SDL_GetError()); + fatal(buffer); + } + + display_options_load(); + + atexit(display_quit); + + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + SDL_EnableUNICODE(1); + + psurfaceicon = graphics_loadimage("icon.png"); + if(psurfaceicon != NULL) + SDL_WM_SetIcon(psurfaceicon, NULL); + + screen_size(options_sdl_width, options_sdl_height, options_sdl_fullscreen); + screen_clear(255, 255, 255); + + font_init(); + font_resize(); + colours_init(); + graphics_init(); + +} + +void display_quit() +{ + SDL_Quit(); +} + +void display_piece(struct level* plevel, int p, int x, int y, int d) +{ + SDL_Surface *image; + + SDL_Rect srect; + SDL_Rect drect; + int alpha; + int px, py; + int b; + int bimage[4]; + int i; + int bsizex, bsizey, boffset; + int op; + + int xstart = 0, xend = 0, xsize = 0, xpos = 0; + + if(p < PIECE_SPACE || p >= PIECE_MAX) + return; + +#ifdef XOR_COMPATIBILITY + if(plevel->switched && (p == PIECE_WALL || p == PIECE_SPACE)) + p = PIECE_DARKNESS; +#endif + + op = p; + + px = x * pdisplaygraphics->size_x + display_offset_pixels_x; + py = y * pdisplaygraphics->size_y + display_offset_pixels_y; + if(d != MOVE_NONE + && p != PIECE_SPACE && !isexplosion(p) +#ifdef XOR_COMPATIBILITY + && p != PIECE_TELEPORT +#endif + ) + { + if(d == MOVE_LEFT) + px = px - display_animation_x; + if(d == MOVE_RIGHT) + px = px + display_animation_x; + if(d == MOVE_UP) + py = py - display_animation_y; + if(d == MOVE_DOWN) + py = py + display_animation_y; + } + + if(isexplosion(p) && !(pdisplaygraphics->image_flags[p] & GRAPHICS_KEY)) + { + alpha = 255 * (1 - display_animation); + SDL_SetAlpha(pdisplaygraphics->image[p][IMAGE_PIECE], SDL_SRCALPHA, alpha); + } + if(isnewexplosion(p)) + { + p += PIECE_EXPLOSION_FIRST - PIECE_EXPLOSION_NEW_FIRST; + if(!(pdisplaygraphics->image_flags[p] & GRAPHICS_KEY)) + { + alpha = 255 * display_animation; + SDL_SetAlpha(pdisplaygraphics->image[p][IMAGE_PIECE], SDL_SRCALPHA, alpha); + } + } + + image = pdisplaygraphics->image[p][IMAGE_PIECE]; + + srect.x = 0; + srect.y = 0; + srect.w = pdisplaygraphics->size_x; + srect.h = pdisplaygraphics->size_y; + + if(image->w > pdisplaygraphics->size_x) + { + xstart = 0; + xend = image->w / pdisplaygraphics->size_x; + xsize = 1; + xpos = 0; + + if(pdisplaygraphics->image_flags[p] & GRAPHICS_BEVEL) + xend -= 4; + + if(pdisplaygraphics->image_flags[p] & GRAPHICS_BEVEL16) + xsize = 16; + + if(pdisplaygraphics->image_flags[p] & GRAPHICS_MOVER) + { + xsize = 5; + + if(d == MOVE_LEFT) + xpos += 1; + if(d == MOVE_UP) + xpos += 2; + if(d == MOVE_RIGHT) + xpos += 3; + if(d == MOVE_DOWN) + xpos += 4; + } + + /* If we're plotting the players */ + if(p == PIECE_PLAYER_ONE || p == PIECE_PLAYER_TWO) + { + /* and there's an image for the swapped player */ + if(xend > xstart + xsize) + { + /* then use it if the player is swapped out */ + if(plevel->player != (p & 1) && plevel->player != 2) + xpos += xsize; + } + } + + if(pdisplaygraphics->image_flags[p] & GRAPHICS_BEVEL16) + { + i = 15; + b = level_data(plevel, x, y) & BEVEL_ALL; + + if(b & BEVEL_U) + i -= 1; + if(b & BEVEL_R) + i -= 2; + if(b & BEVEL_D) + i -= 4; + if(b & BEVEL_L) + i -= 8; + + xpos += i; + } + + if(pdisplaygraphics->image_flags[p] & GRAPHICS_ANIMATE) + { + b = (xend - xstart) / xsize; + + if(!isexplosion(p)) + b = b * display_animation; + else + b = b * ((display_animation + (isnewexplosion(op) ? 0 : 1)) * 0.5); + + xpos += b * xsize; + } + else if(pdisplaygraphics->image_flags[p] & GRAPHICS_RANDOM) + { + b = (xend - xstart) / xsize; + + if(p == PIECE_SPACE) + b = (level_data(plevel, x, y) & 0xff) % b; + else + b = ((level_data(plevel, x, y) & 0xff00) / 0x100) % b; + + xpos += b * xsize; + } + else if(pdisplaygraphics->image_flags[p] & GRAPHICS_TILE) + { + b = x % ((xend - xstart) / xsize); + if(b < 0) + b += (xend - xstart) / xsize; + xpos += b * xsize; + + b = y % (image->h / pdisplaygraphics->size_y); + if(b < 0) + b += image->h / pdisplaygraphics->size_y; + srect.y = b * pdisplaygraphics->size_y; + } + + srect.x = (xstart + xpos) * pdisplaygraphics->size_x; + } + + drect.x = px; + drect.y = py; + drect.w = pdisplaygraphics->size_x; + drect.h = pdisplaygraphics->size_y; + + /* Plot piece */ + SDL_BlitSurface(image, &srect, screen_surface, &drect); + + /* Plot bevelling */ + if(pdisplaygraphics->image_flags[p] & GRAPHICS_BEVEL) + { + b = level_data(plevel, x, y) & BEVEL_ALL; + if(b != 0) + { + bsizex = pdisplaygraphics->size_x / 2; + bsizey = pdisplaygraphics->size_y / 2; + boffset = (xend - 1) * pdisplaygraphics->size_x; + + for(i = 0; i < 4; i ++) + bimage[i] = 0; + + if(b & BEVEL_L) + { + if(b & BEVEL_U) + bimage[0] = 3 * pdisplaygraphics->size_x; + else + bimage[0] = 1 * pdisplaygraphics->size_x; + + if(b & BEVEL_D) + bimage[2] = 3 * pdisplaygraphics->size_x; + else + bimage[2] = 1 * pdisplaygraphics->size_x; + } + else + { + if(b & BEVEL_U) + bimage[0] = 2 * pdisplaygraphics->size_x; + if(b & BEVEL_D) + bimage[2] = 2 * pdisplaygraphics->size_x; + } + + if(b & BEVEL_R) + { + if(b & BEVEL_U) + bimage[1] = 3 * pdisplaygraphics->size_x; + else + bimage[1] = 1 * pdisplaygraphics->size_x; + + if(b & BEVEL_D) + bimage[3] = 3 * pdisplaygraphics->size_x; + else + bimage[3] = 1 * pdisplaygraphics->size_x; + } + else + { + if(b & BEVEL_U) + bimage[1] = 2 * pdisplaygraphics->size_x; + if(b & BEVEL_D) + bimage[3] = 2 * pdisplaygraphics->size_x; + } + + if(b & BEVEL_TL) + bimage[0] = 4 * pdisplaygraphics->size_x; + if(b & BEVEL_TR) + bimage[1] = 4 * pdisplaygraphics->size_x; + if(b & BEVEL_BL) + bimage[2] = 4 * pdisplaygraphics->size_x; + if(b & BEVEL_BR) + bimage[3] = 4 * pdisplaygraphics->size_x; + + for(i = 0; i < 4; i ++) + { + if(bimage[i] != 0) + { + srect.x = boffset + bimage[i] + ((i & 1) ? bsizex : 0); + srect.y = (i & 2) ? bsizey : 0; + srect.w = bsizex; + srect.h = bsizey; + + drect.x = px + ((i & 1) ? bsizex : 0); + drect.y = py + ((i & 2) ? bsizey : 0); + drect.w = bsizex; + drect.h = bsizey; + + SDL_BlitSurface(image, &srect, screen_surface, &drect); + } + } + } + } +} + +void display_redrawpiece(int p, int x, int y, int d) +{ + int dx, dy; + + dx = x * pdisplaygraphics->size_x + display_offset_pixels_x; + dy = y * pdisplaygraphics->size_y + display_offset_pixels_y; + if(d != MOVE_NONE && p != PIECE_SPACE && !isexplosion(p)) + { + if(d == MOVE_LEFT) { dx = dx - display_animation_x; } + if(d == MOVE_RIGHT) { dx = dx + display_animation_x; } + if(d == MOVE_UP) { dy = dy - display_animation_y; } + if(d == MOVE_DOWN) { dy = dy + display_animation_y; } + } + + screen_redraw(dx, dy, pdisplaygraphics->size_x, pdisplaygraphics->size_y); +} + +void display_pieceabsolute(int p, int x, int y, int redraw) +{ + SDL_Rect srect; + SDL_Rect drect; + + srect.x = 0; + srect.y = 0; + srect.w = pdisplaygraphics->size_x; + srect.h = pdisplaygraphics->size_y; + + drect.x = x; + drect.y = y; + drect.w = pdisplaygraphics->size_x; + drect.h = pdisplaygraphics->size_y; + + if(p != PIECE_SPACE && p!= PIECE_CURSOR) + SDL_BlitSurface(pdisplaygraphics->image[PIECE_SPACE][IMAGE_PIECE], &srect, screen_surface, &drect); + + SDL_BlitSurface(pdisplaygraphics->image[p][IMAGE_PIECE], &srect, screen_surface, &drect); + + if(redraw) + screen_redraw(x, y, pdisplaygraphics->size_x, pdisplaygraphics->size_y); +} + +int display_focus(struct level* plevel, int refocus) +{ + int ox, oy; + int px, py; + + int maxx, maxy; + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR && options_xor_display) + { + ox = display_offset_pixels_x; + oy = display_offset_pixels_y; + + display_start_x = plevel->view_x[plevel->player]; + display_start_y = plevel->view_y[plevel->player]; + + display_end_x = display_start_x + 8; + display_end_y = display_start_y + 8; + + display_offset_pixels_x = (screen_width - pdisplaygraphics->size_x * 8) / 2; + display_offset_pixels_y = (screen_height - display_bar_pixels - pdisplaygraphics->size_y * 8) / 2; + + display_offset_pixels_x -= display_start_x * pdisplaygraphics->size_x; + display_offset_pixels_y -= display_start_y * pdisplaygraphics->size_y; + + if(display_offset_pixels_x != ox || display_offset_pixels_y != oy) + return 1; + else + return 0; + } +#endif + + px = plevel->player_x[plevel->player] * pdisplaygraphics->size_x; + py = plevel->player_y[plevel->player] * pdisplaygraphics->size_y; + ox = display_offset_pixels_x; + oy = display_offset_pixels_y; + + display_border_x = pdisplaygraphics->size_x * 3; + display_border_y = pdisplaygraphics->size_y * 3; + + maxx = (plevel->size_x * pdisplaygraphics->size_x - screen_width); + maxy = (plevel->size_y * pdisplaygraphics->size_y - screen_height + display_bar_pixels); + + if((plevel->size_x - 1) * pdisplaygraphics->size_x < screen_width) + { + display_offset_pixels_x = (screen_width - (plevel->size_x * pdisplaygraphics->size_x)) / 2; + } + else + { + if(refocus) + { + if(px < -(display_offset_pixels_x - display_border_x)) + display_offset_pixels_x = -(px - display_border_x); + if(px >= -(display_offset_pixels_x - screen_width + display_border_x + pdisplaygraphics->size_x)) + display_offset_pixels_x = -(px - screen_width + display_border_x + pdisplaygraphics->size_x); + } + + if(display_offset_pixels_x > 0) + display_offset_pixels_x = 0; + if(display_offset_pixels_x < -maxx) + display_offset_pixels_x = -maxx; + + } + + if((plevel->size_y - 1) * pdisplaygraphics->size_y < screen_height) + { + display_offset_pixels_y = (screen_height - display_bar_pixels - (plevel->size_y * pdisplaygraphics->size_y)) / 2; + } + else + { + if(refocus) + { + if(py < -(display_offset_pixels_y - display_border_y)) + display_offset_pixels_y = -(py - display_border_y); + if(py >= -(display_offset_pixels_y - screen_height + display_bar_pixels + display_border_y + pdisplaygraphics->size_y)) + display_offset_pixels_y = -(py - screen_height + display_bar_pixels + display_border_y + pdisplaygraphics->size_y); + } + + if(display_offset_pixels_y > 0) + display_offset_pixels_y = 0; + if(display_offset_pixels_y < -maxy) + display_offset_pixels_y = -maxy; + } + + /* Calculate start and end points */ + display_start_x = -display_offset_pixels_x / pdisplaygraphics->size_x; + display_end_x = (-display_offset_pixels_x + screen_width + pdisplaygraphics->size_x - 1) / pdisplaygraphics->size_x; + if(display_offset_pixels_x > 0) + display_start_x --; + + display_start_y = -display_offset_pixels_y / pdisplaygraphics->size_y; + display_end_y = (-display_offset_pixels_y + screen_height + pdisplaygraphics->size_y - display_bar_pixels - 1) / pdisplaygraphics->size_y; + if(display_offset_pixels_y > 0) + display_start_y --; + + if(pdisplaygraphics->flags & GRAPHICS_BACKGROUND) + { + if(display_start_x < 0) + display_start_x = 0; + if(display_end_x > plevel->size_x) + display_end_x = plevel->size_x; + if(display_start_y < 0) + display_start_y = 0; + if(display_end_y > plevel->size_y) + display_end_y = plevel->size_y; + } + + if(display_offset_pixels_x != ox || display_offset_pixels_y != oy) + return 1; + else + return 0; +} + +#ifdef XOR_COMPATIBILITY +void display_map_piece(struct level* plevel, int p, int x, int y, int redraw) +{ + SDL_Rect rect; + + rect.x = xor_map_x_offset + x * xor_map_scale; + rect.y = xor_map_x_offset + y * xor_map_scale; + rect.w = xor_map_scale; + rect.h = xor_map_scale; + + if(plevel->player != 2) + { + if(x < plevel->size_x / 2 && y < plevel->size_y / 2 && !(plevel->mapped & MAPPED_TOP_LEFT)) + p = PIECE_UNKNOWN; + if(x >= plevel->size_x / 2 && y < plevel->size_y / 2 && !(plevel->mapped & MAPPED_TOP_RIGHT)) + p = PIECE_UNKNOWN; + if(x < plevel->size_x / 2 && y >= plevel->size_y / 2 && !(plevel->mapped & MAPPED_BOTTOM_LEFT)) + p = PIECE_UNKNOWN; + if(x >= plevel->size_x / 2 && y >= plevel->size_y / 2 && !(plevel->mapped & MAPPED_BOTTOM_RIGHT)) + p = PIECE_UNKNOWN; + } + + switch(p) + { + case PIECE_UNKNOWN: + SDL_FillRect(screen_surface, &rect, SDL_MapRGB(screen_surface->format, 0x00, 0x00, 0x00)); + break; + + case PIECE_WALL: + SDL_FillRect(screen_surface, &rect, SDL_MapRGB(screen_surface->format, 0x7f, 0x7f, 0x7f)); + break; + + case PIECE_STAR: + SDL_FillRect(screen_surface, &rect, SDL_MapRGB(screen_surface->format, 0xff, 0xa0, 0x00)); + if(xor_map_scale > 2) + { + rect.x ++; + rect.y ++; + rect.w -= 2; + rect.h -= 2; + SDL_FillRect(screen_surface, &rect, SDL_MapRGB(screen_surface->format, 0xff, 0xff, 0x33)); + } + break; + + case PIECE_DOOR: + SDL_FillRect(screen_surface, &rect, SDL_MapRGB(screen_surface->format, 0x00, 0x80, 0xff)); + if(xor_map_scale > 2) + { + rect.x ++; + rect.y ++; + rect.w -= 2; + rect.h -= 2; + SDL_FillRect(screen_surface, &rect, SDL_MapRGB(screen_surface->format, 0x66, 0xb3, 0xff)); + } + break; + + default: + SDL_FillRect(screen_surface, &rect, SDL_MapRGB(screen_surface->format, 0xff, 0xff, 0xff)); + break; + } + + if(redraw) + { + + rect.x = xor_map_x_offset + x * xor_map_scale; + rect.y = xor_map_x_offset + y * xor_map_scale; + rect.w = xor_map_scale; + rect.h = xor_map_scale; + screen_redraw(rect.x, rect.y, rect.w, rect.h); + } +} + +void display_map(struct level* plevel) +{ + int i, j; + + xor_map_scale = screen_width / 256; + if(xor_map_scale < 1) + xor_map_scale = 1; + + display_clip(plevel, 0); + + for(j = 0; j < plevel->size_y; j ++) + { + for(i = 0; i < plevel->size_y; i ++) + { + display_map_piece(plevel, level_piece(plevel, i, j), i, j, 0); + } + } + + /* Redraw map */ + screen_redraw(xor_map_x_offset, xor_map_y_offset, plevel->size_x * xor_map_scale, plevel->size_y * xor_map_scale); +} +#endif + +void display_level(struct level* plevel, int redraw) +{ + int x, y; + int p; + SDL_Rect rect; + + + display_focus(plevel, 0); + + if(redraw == SCREENREDRAW_ALL && ( + (pdisplaygraphics->flags & GRAPHICS_BACKGROUND) +#ifdef XOR_COMPATIBILITY + || (plevel->mode == MODE_XOR && options_xor_display) +#endif + )) + { + rect.x = 0; + rect.y = 0; + rect.w = screen_width; + rect.h = screen_height - display_bar_pixels; + +#ifdef XOR_COMPATIBILITY + if(plevel->switched) + SDL_FillRect(screen_surface, &rect, SDL_MapRGB(screen_surface->format, 0, 0, 0)); + else +#endif + SDL_FillRect(screen_surface, &rect, SDL_MapRGB(screen_surface->format, pdisplaygraphics->background[0], pdisplaygraphics->background[1], pdisplaygraphics->background[2])); + } + + if(pdisplaygraphics->shadows != NULL) + { + displayshadowed_level(plevel); +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR && options_xor_display) + display_map(plevel); +#endif + return; + } + + display_clip(plevel, 1); + + for(y = display_start_y; y < display_end_y; y ++) + { + for(x = display_start_x; x < display_end_x; x ++) + { + p = level_piece(plevel, x, y); + + /* Moving pieces will be redrawn shortly */ + if(level_moving(plevel, x, y) != MOVE_NONE) + p = level_previous(plevel, x, y); + +#ifdef XOR_COMPATIBILITY + if(plevel->switched && (p == PIECE_WALL || p == PIECE_SPACE)) + p = PIECE_DARKNESS; +#endif + + /* If the piece is transparent, plot a background */ + if(pdisplaygraphics->image[p][IMAGE_PIECE]->flags & SDL_SRCALPHA) + { +#ifdef XOR_COMPATIBILITY + if(plevel->switched) + display_piece(plevel, PIECE_DARKNESS, x, y, MOVE_NONE); + else +#endif + display_piece(plevel, PIECE_SPACE, x, y, MOVE_NONE); + } + + /* Plot the piece itself */ + display_piece(plevel, p, x, y, MOVE_NONE); + } + } + + display_clip(plevel, 0); + + if(plevel->mover_first != NULL) + display_movers(plevel, 0); + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR && options_xor_display) + display_map(plevel); +#endif + + screen_redraw(0, 0, screen_width, screen_height); + +} + +void display_title(struct level* plevel) +{ + SDL_Surface *psurface; + SDL_Surface *psurfacetest; + SDL_Rect drect; + int w; + + if(options_debug & DEBUG_SPEED) + return; + + if(plevel->title != NULL) + { + if((strncmp(gettext(plevel->title), "chroma", 6) == 0)) + psurface = font_render(gettext(plevel->title), -8); + else + psurface = font_render(plevel->title, COLOUR_WHITE); + + if(plevel->flags & LEVELFLAG_TESTING) + { + psurfacetest = font_render(gettext("testing: "), COLOUR_CYAN); + w = psurfacetest->w; + + drect.x = (screen_width - psurface->w - w) / 2; + drect.y = screen_height - font_height;; + drect.w = psurfacetest->w;; + drect.h = psurfacetest->h; + SDL_FillRect(screen_surface, &drect, SDL_MapRGB(screen_surface->format, 0, 0, 0)); + SDL_BlitSurface(psurfacetest, NULL, screen_surface, &drect); + SDL_UpdateRects(screen_surface, 1, &drect); + SDL_FreeSurface(psurfacetest); + } + else + w = 0; + + drect.x = ((screen_width - psurface->w - w) / 2) + w; + drect.y = screen_height - font_height; + drect.w = psurface->w; + drect.h = psurface->h; + SDL_FillRect(screen_surface, &drect, SDL_MapRGB(screen_surface->format, 0, 0, 0)); + SDL_BlitSurface(psurface, NULL, screen_surface, &drect); + SDL_UpdateRects(screen_surface, 1, &drect); + SDL_FreeSurface(psurface); + } +} + +void display_moves(struct level* plevel, struct level* plevelreplay) +{ + static int length = 0; + char buffer[256]; + SDL_Surface *psurface; + SDL_Surface *pimage; + SDL_Rect srect, drect; + int w; + int moves, moves2; + + moves = 0; + if(plevel->move_current != NULL) + moves = plevel->move_current->count; + + moves2 = -1; + if(plevelreplay != NULL) + { + moves2 = 0; + if(plevelreplay->move_last != NULL) + moves2 = plevelreplay->move_last->count; + } + else if(plevel->move_current != plevel->move_last) + { + if(plevel->move_last != NULL) + moves2 = plevel->move_last->count; + } + + if(moves2 != -1) + sprintf(buffer, "%s%d/%d", + plevel->flags & LEVELFLAG_PAUSED ? gettext("paused ") : + plevelreplay != NULL ? gettext("replay ") : "", + moves, moves2); + else + sprintf(buffer, "%s%d", + plevel->flags & LEVELFLAG_PAUSED ? gettext("paused ") : "", + moves); + + if(plevel->flags & LEVELFLAG_FAILED) + sprintf(buffer, gettext("failed")); + + psurface = font_render(buffer, COLOUR_CYAN); + + pimage = pdisplaygraphics->image[PIECE_PLAYER_ONE + plevel->player][IMAGE_SMALL]; + if(pimage != NULL) + w = pdisplaygraphics->small_size_x; + else + w = 0; + + drect.w = length > (psurface->w + w) ? length : (psurface->w + w); + drect.h = psurface->h; + drect.x = screen_width - drect.w; + drect.y = screen_height - font_height; + SDL_FillRect(screen_surface, &drect, SDL_MapRGB(screen_surface->format, 0, 0, 0)); + drect.x = screen_width - w - psurface->w; + SDL_BlitSurface(psurface, NULL, screen_surface, &drect); + + if(pimage != NULL) + { + srect.x = 0; + srect.y = 0; + srect.w = pdisplaygraphics->small_size_x; + srect.h = pdisplaygraphics->small_size_y; + + /* If there is a second small image, use it for a dead player */ + if(plevel->alive[plevel->player] == 0 && pimage->w > pdisplaygraphics->small_size_x) + srect.x += pdisplaygraphics->small_size_x; + + drect.x = screen_width - w; + if(pimage->h < font_height) + drect.y += (font_height - pimage->h) / 2; + + SDL_BlitSurface(pimage, &srect, screen_surface, &drect); + } + + drect.w = (length > psurface->w ? length : psurface->w) + w; + drect.h = psurface->h; + drect.x = screen_width - drect.w; + drect.y = screen_height - font_height; + SDL_UpdateRects(screen_surface, 1, &drect); + length = psurface->w + w; + SDL_FreeSurface(psurface); +} + +void display_stars(struct level* plevel) +{ + static int length = 0; + char buffer[256]; + + SDL_Surface *psurface; + SDL_Rect drect; + SDL_Surface *pimage; + int w; + int p; + + sprintf(buffer, "%d/%d", plevel->stars_caught, plevel->stars_total); + + if(plevel->stars_exploded != 0) + sprintf(buffer, gettext("%d lost"), plevel->stars_exploded); + + if(plevel->flags & LEVELFLAG_SOLVED && !(plevel->flags & LEVELFLAG_FAILED)) + sprintf(buffer, gettext("solved")); + + psurface = font_render(buffer, COLOUR_YELLOW); + + /* If solved, and there is a small door, use that */ + if(plevel->flags & LEVELFLAG_SOLVED && !(plevel->flags & LEVELFLAG_FAILED) && pdisplaygraphics->image[PIECE_DOOR][IMAGE_SMALL] != NULL) + p = PIECE_DOOR; + /* otherwise use a small star */ + else + p = PIECE_STAR; + + pimage = pdisplaygraphics->image[p][IMAGE_SMALL]; + + if(pimage != NULL) + w = pdisplaygraphics->small_size_x; + else + w = 0; + + drect.w = length > psurface->w ? length : psurface->w + w; + drect.h = psurface->h; + drect.x = 0; + drect.y = screen_height - font_height; + + SDL_FillRect(screen_surface, &drect, SDL_MapRGB(screen_surface->format, 0, 0, 0)); + drect.x = w; + SDL_BlitSurface(psurface, NULL, screen_surface, &drect); + + if(pimage != NULL) + { + drect.x = 0; + if(pimage->h < font_height) + drect.y += (font_height - pimage->h) / 2; + + SDL_BlitSurface(pimage, NULL, screen_surface, &drect); + } + + drect.w = (length > psurface->w ? length : psurface->w) + w; + drect.h = psurface->h; + drect.x = 0; + drect.y = screen_height - font_height; + SDL_UpdateRects(screen_surface, 1, &drect); + length = psurface->w + w; + SDL_FreeSurface(psurface); +} + +int display_bevelsquare(struct level* plevel, int x, int y) +{ + int bevel; + + bevel = 0; + + if(level_piece(plevel, x, y) == PIECE_WALL) + { + if(level_piece(plevel, x - 1, y) != PIECE_WALL) + bevel |= BEVEL_L; + if(level_piece(plevel, x + 1, y) != PIECE_WALL) + bevel |= BEVEL_R; + if(level_piece(plevel, x, y - 1) != PIECE_WALL) + bevel |= BEVEL_U; + if(level_piece(plevel, x, y + 1) != PIECE_WALL) + bevel |= BEVEL_D; + + if(((bevel & (BEVEL_L | BEVEL_U)) == 0) && level_piece(plevel, x - 1, y - 1) != PIECE_WALL) + bevel |= BEVEL_TL; + if(((bevel & (BEVEL_R | BEVEL_U)) == 0) && level_piece(plevel, x + 1, y - 1) != PIECE_WALL) + bevel |= BEVEL_TR; + if(((bevel & (BEVEL_L | BEVEL_D)) == 0) && level_piece(plevel, x - 1, y + 1) != PIECE_WALL) + bevel |= BEVEL_BL; + if(((bevel & (BEVEL_R | BEVEL_D)) == 0) && level_piece(plevel, x + 1, y + 1) != PIECE_WALL) + bevel |= BEVEL_BR; + } + else + { + if(level_piece(plevel, x - 1, y) == PIECE_WALL) + bevel |= BEVEL_L; + if(level_piece(plevel, x + 1, y) == PIECE_WALL) + bevel |= BEVEL_R; + if(level_piece(plevel, x, y - 1) == PIECE_WALL) + bevel |= BEVEL_U; + if(level_piece(plevel, x, y + 1) == PIECE_WALL) + bevel |= BEVEL_D; + + if(((bevel & (BEVEL_L | BEVEL_U)) == 0) && level_piece(plevel, x - 1, y - 1) == PIECE_WALL) + bevel |= BEVEL_TL; + if(((bevel & (BEVEL_R | BEVEL_U)) == 0) && level_piece(plevel, x + 1, y - 1) == PIECE_WALL) + bevel |= BEVEL_TR; + if(((bevel & (BEVEL_L | BEVEL_D)) == 0) && level_piece(plevel, x - 1, y + 1) == PIECE_WALL) + bevel |= BEVEL_BL; + if(((bevel & (BEVEL_R | BEVEL_D)) == 0) && level_piece(plevel, x + 1, y + 1) == PIECE_WALL) + bevel |= BEVEL_BR; + } + + return bevel; +} + +void display_bevellevel(struct level* plevel) +{ + int x, y; + int bevel; + + for(x = 0; x < plevel->size_x; x ++) + { + for(y = 0; y < plevel->size_y; y ++) + { + bevel = level_data(plevel, x, y) & ~BEVEL_ALL; + bevel = bevel | display_bevelsquare(plevel, x, y); + level_setdata(plevel, x, y, bevel); + } + } +} + + +void display_movers(struct level* plevel, int redraw) +{ + struct mover* pmover; + int x, y, p, pm; + int i, j; + char buffer[16]; + int bevel; + struct SDL_Surface *psurface; + SDL_Rect srect, drect; + + if(pdisplaygraphics->shadows != NULL) + { + displayshadowed_movers(plevel, redraw); + return; + } + + display_clip(plevel, 1); + + display_animation_x = - pdisplaygraphics->size_x + (int)((float) pdisplaygraphics->size_x * display_animation); + display_animation_y = - pdisplaygraphics->size_y + (int)((float) pdisplaygraphics->size_y * display_animation); + + /* First, plot spaces for all moving pieces */ + pmover = plevel->mover_first; + while(pmover != NULL) + { +#ifdef XOR_COMPATIBILITY + if(plevel->switched) + display_piece(plevel, PIECE_DARKNESS, pmover->x, pmover->y, MOVE_NONE); + else +#endif + display_piece(plevel, PIECE_SPACE, pmover->x, pmover->y, MOVE_NONE); + + pmover = pmover->next; + } + + /* Plot moving piece */ + pmover = plevel->mover_first; + while(pmover != NULL) + { + x = pmover->x; + y = pmover->y; + + if(isexplosion(pmover->piece)) + { + /* Plot any piece destroyed by the explosion, or the bomb itself */ + p = level_previous(plevel, x, y); + pm = level_previousmoving(plevel, x, y); + if(p != PIECE_SPACE) + display_piece(plevel, p, x, y, pm); + + /* Plot the detonator */ + p = level_detonator(plevel, x, y); + pm = level_detonatormoving(plevel, x, y); + if(p != PIECE_SPACE) + display_piece(plevel, p, x, y, pm); + } + /* Spaces have already been covered */ + else if(pmover->piece != PIECE_SPACE && pmover->piece != PIECE_GONE) + { + if(display_animation < 1) + { + /* Pieces being collected, earth being eaten */ + p = level_previous(plevel, x, y); + pm = level_previousmoving(plevel, x, y); + if((p != PIECE_SPACE && !isexplosion(p) && pm == MOVE_NONE) +#ifdef XOR_COMPATIBILITY + || pmover->piece == PIECE_TELEPORT +#endif + ) + display_piece(plevel, p, x, y, pm); + } + + display_piece(plevel, pmover->piece, x, y, pmover->direction); + } + + pmover = pmover->next; + } + + /* Plot explosions */ + pmover = plevel->mover_first; + while(pmover != NULL) + { + x = pmover->x; + y = pmover->y; + /* Plot growing explosion */ + if(isexplosion(pmover->piece)) + display_piece(plevel, pmover->piece + PIECE_EXPLOSION_NEW_FIRST - PIECE_EXPLOSION_FIRST, x, y, MOVE_NONE); + + /* Plot dying explosion */ + p = level_previous(plevel, x, y); + if(isexplosion(p) && display_animation < 1) + display_piece(plevel, p, x, y, MOVE_NONE); + + pmover = pmover->next; + } + + /* Plot order of movers if debugging (but not if editing) */ + if(options_debug & DEBUG_ORDER && display_animation < 1 && plevel->player != 2) + { + pmover = plevel->mover_first; + i = 0; + while(pmover != NULL) + { + if(pmover->piece != PIECE_SPACE && pmover->piece != PIECE_GONE) + { + pm = pmover->direction; + if(isexplosion(pmover->piece) || isnewexplosion(pmover->piece)) + pm = MOVE_NONE; + + x = pmover->x * pdisplaygraphics->size_x + display_offset_pixels_x + ((-1 + display_animation) * move_x[pm] * pdisplaygraphics->size_x); + y = pmover->y * pdisplaygraphics->size_y + display_offset_pixels_y + ((-1 + display_animation) * move_y[pm] * pdisplaygraphics->size_y); + + sprintf(buffer, "%X", i++); + switch(pmover->direction) + { + case MOVE_UP: + strcat(buffer, ARROW_UP); + break; + case MOVE_DOWN: + strcat(buffer, ARROW_DOWN); + break; + case MOVE_LEFT: + strcat(buffer, ARROW_LEFT); + break; + case MOVE_RIGHT: + strcat(buffer, ARROW_RIGHT); + break; + default: + break; + } + psurface = font_render(buffer, COLOUR_WHITE | COLOUR_BOLD); + srect.w = psurface->w > pdisplaygraphics->size_x ? pdisplaygraphics->size_x : psurface->w; + srect.h = psurface->h > pdisplaygraphics->size_y ? pdisplaygraphics->size_y : psurface->h; + srect.x = psurface->w - srect.w; + srect.y = 0; + drect.x = x + pdisplaygraphics->size_x - srect.w; + drect.y = y; + SDL_BlitSurface(psurface, &srect, screen_surface, &drect); + SDL_FreeSurface(psurface); + } + else + i ++; + + pmover = pmover->next; + } + } + + if(redraw == 0) + return; + + /* Redraw screen */ + pmover = plevel->mover_first; + + while(pmover != NULL) + { + x = pmover->x; + y = pmover->y; + display_redrawpiece(pmover->piece, x, y, pmover->direction); + + if(isexplosion(pmover->piece)) + { + p = level_previous(plevel, x, y); + pm = level_previousmoving(plevel, x, y); + if(pm != MOVE_NONE && p != PIECE_SPACE) + display_redrawpiece(p, x, y, pm); + + p = level_detonator(plevel, x, y); + pm = level_detonatormoving(plevel, x, y); + if(pm != MOVE_NONE && p != PIECE_SPACE) + display_redrawpiece(p, x, y, pm); + } + + p = level_previous(plevel, x, y); + if(isexplosion(p)) + display_redrawpiece(p, x, y, MOVE_NONE); + + pmover = pmover->next; + } + + /* At the peak of the explosion, rebevel any walls that have been + destroyed. When undoing, rebevel any walls that have been recreated. */ + if(display_animation == 0 || display_animation == 1) + { + /* When undoing, we have to create the wall prior to rebevelling, as it + wouldn't otherwise exist until after the end of the animation. */ + pmover = plevel->mover_first; + while(pmover != NULL) + { + if(pmover->piece == PIECE_WALL) + level_setpiece(plevel, pmover->x, pmover->y, pmover->piece); + pmover = pmover->next; + } + + pmover = plevel->mover_first; + while(pmover != NULL) + { + x = pmover->x; + y = pmover->y; + if(pmover->piece == PIECE_WALL || + (isexplosion(pmover->piece) && display_animation == 1)) + { + for(i = -1; i < 2; i ++) + { + for(j = - 1; j < 2; j ++) + { + bevel = display_bevelsquare(plevel, x + i, y + j); + if(bevel != (level_data(plevel, x + i, y + j) & BEVEL_ALL)) + { + level_setdata(plevel, x + i, y + j, bevel | (level_data(plevel, x + i, y + j) & ~BEVEL_ALL)); + p = level_piece(plevel, x + i, y + j); + if(p == PIECE_WALL) + { +#ifdef XOR_COMPATIBILITY + if(plevel->switched) + display_piece(plevel, PIECE_DARKNESS, x + i, y + j, MOVE_NONE); + else +#endif + display_piece(plevel, PIECE_WALL, x + i, y + j, MOVE_NONE); + } + else + { +#ifdef XOR_COMPATIBILITY + if(plevel->switched) + display_piece(plevel, PIECE_DARKNESS, x + i, y + j, MOVE_NONE); + else +#endif + display_piece(plevel, PIECE_SPACE, x + i, y + j, MOVE_NONE); + /* Moving pieces will be replotted when they next move. */ + if(p != PIECE_SPACE && level_moving(plevel, x + i, y + j) == MOVE_NONE) + display_piece(plevel, p, x + i, y + j, MOVE_NONE); + } + display_redrawpiece(p, x + i, y + j, MOVE_NONE); + } + } + } + } + pmover = pmover->next; + } + } + + display_clip(plevel, 0); +} + +void display_play(struct level* plevel, struct level* plevelreplay) +{ + SDL_Event event; + SDL_Surface *psurface; + SDL_Rect drect; + int quit; + int redraw; + int playermove; + struct mover* pmover; + Uint32 basetime; + Uint32 nowtime; + Uint32 pausetime = 0; + int delay, delayold; + int keymod; + int frames = 0; + int events; + char buffer[256]; + int action; + int fast; + + int mouse_x = 0; + int mouse_y = 0; + int mouse_destination_x = 0; + int mouse_destination_y = 0; + int mouse_button = 0; + int mouse_time; + + int swap = 0; + + graphics_reload(); + + display_bevellevel(plevel); + + /* Force full redraw */ + redraw = SCREENREDRAW_ALL; + + playermove = MOVE_NONE; + action = ACTION_NONE; + delayold = options_sdl_delay; + + mouse_time = SDL_GetTicks(); + + /* Force all animation to end */ + basetime = SDL_GetTicks() - delayold; + + keymod = 0; + fast = 0; + + plevel->flags &= ~LEVELFLAG_PAUSED; + + font_set_size(font_size_game); + display_bar_pixels = font_height; + display_focus(plevel, 1); + + quit = 0; + while(!quit) + { + //////// Screen redraw //////// + + if(redraw & SCREENREDRAW_ALL) + { + font_set_size(font_size_game); + display_bar_pixels = font_height; + } + if(redraw & SCREENREDRAW_BAR) + { + /* Clear bar */ + drect.x = 0; + drect.y = screen_height - display_bar_pixels; + drect.w = screen_width; + drect.h = display_bar_pixels; + SDL_FillRect(screen_surface, &drect, SDL_MapRGB(screen_surface->format, 0, 0, 0)); + + display_title(plevel); + display_stars(plevel); + display_moves(plevel, plevelreplay); + } + if(redraw & SCREENREDRAW_LEVEL) + display_level(plevel, redraw); + + redraw = 0; + + //////// Delay calculation //////// + + /* Calculate what the delay should be, defaulting to the Move Speed. */ + delay = options_sdl_delay; + /* If we're replaying, use the Replay Speed */ + if(plevelreplay != NULL && plevelreplay->moves != -1) + delay = options_sdl_replay_delay; + else + { + /* Otherwise */ + pmover = plevel->mover_first; + while(pmover != NULL) + { + /* Use the Player Speed if the player is still moving */ + if(pmover->piece == PIECE_PLAYER_ONE || pmover->piece == PIECE_PLAYER_TWO) + delay = options_sdl_player_delay; + /* unless there's a piece following in their trail */ + else if(pmover->piece != PIECE_SPACE && pmover->fast == 1) + delay = options_sdl_delay; + + pmover = pmover->next; + } + /* If we're undoing, use the Undo Speed */ + if(plevel->flags & LEVELFLAG_UNDO) + delay = options_sdl_undo_delay; + } + /* If SHIFT is pressed, speed things up. */ + if(keymod & 1) + delay = delay / 10; + /* If CTRL is pressed, slow things down. */ + if(keymod & 2) + delay = delay * 4; + /* If the delay has changed, preserve our position in the animation */ + if(delay != delayold) + { + nowtime = SDL_GetTicks(); + if((plevel->flags & LEVELFLAG_PAUSED)) + nowtime = pausetime; + if(delayold != 0) + basetime = nowtime - (((nowtime - basetime) * delay) / delayold ); + delayold = delay; + } + if(fast && !(plevel->flags & LEVELFLAG_PAUSED)) + basetime = 0; + + //////// Movers //////// + + /* If there are movers, plot and then evolve them */ + if(plevel->mover_first != NULL) + { + nowtime = SDL_GetTicks(); + if((plevel->flags & LEVELFLAG_PAUSED)) + nowtime = pausetime; + display_animation = (float)(nowtime - basetime) / delay; + if(display_animation > 1) + display_animation = 1; + frames ++; + display_movers(plevel, 1); + } + + if(plevel->mover_first != NULL) + { + /* Is it time for the next stage of this move? */ + if(nowtime > basetime + delay && !(plevel->flags & LEVELFLAG_PAUSED)) + { +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR && options_xor_display) + { + pmover = plevel->mover_first; + while(pmover != NULL) + { + display_map_piece(plevel, pmover->piece, pmover->x, pmover->y, 1); + pmover = pmover->next; + } + } +#endif + + /* Evolve movers */ + if(!(plevel->flags & LEVELFLAG_UNDO)) + { + if(level_evolve(plevel)) + redraw |= display_focus(plevel, 1) * SCREENREDRAW_LEVEL; + level_storemovers(plevel); + + if(options_debug & DEBUG_SPEED) + { + sprintf(buffer, " %4dfps (%d frames / %d ms) ", 1000 * frames / (nowtime - basetime), frames, nowtime - basetime); + psurface = font_render(buffer, COLOUR_WHITE); + drect.x = (screen_width - psurface->w) / 2; + drect.y = screen_height - font_height; + drect.w = psurface->w; + drect.h = psurface->h; + SDL_FillRect(screen_surface, &drect, SDL_MapRGB(screen_surface->format, 0, 0, 0)); + SDL_BlitSurface(psurface, NULL, screen_surface, &drect); + SDL_UpdateRects(screen_surface, 1, &drect); + SDL_FreeSurface(psurface); + + printf("%s\n", buffer); + } + frames = 0; + } + else + { + if(level_undo(plevel)) + plevel->flags |= LEVELFLAG_UNDO; + else + plevel->flags &= ~LEVELFLAG_UNDO; + + /* Refocus in case we've moved offscreen */ + redraw |= display_focus(plevel, 1) * SCREENREDRAW_LEVEL; + } + + basetime = SDL_GetTicks(); + + /* Reset animation in case we redraw before it is next calculated */ + display_animation = 0; + } + } + + //////// Events //////// + + /* Hide the mouse if not used whilst in full screen mode */ + if(SDL_GetTicks() > mouse_time + MOUSE_TIMEOUT_MOVE) + screen_cursor(0); + + /* Poll if there are movers, otherwise wait so as to reduce load */ + if(plevel->mover_first != NULL || SDL_GetTicks() < basetime + delay) + events = SDL_PollEvent(&event); + else + events = SDL_WaitEvent(&event); + + while(events) + { + switch(event.type) + { + case SDL_KEYDOWN: + + switch(actions[event.key.keysym.sym]) + { + case ACTION_FASTER: + keymod |= 1; + break; + + case ACTION_SLOWER: + keymod |= 2; + break; + + case ACTION_QUIT: + quit = 1; + break; + + case ACTION_FAST: + fast = 1; + break; + + case ACTION_PAUSE: + if(plevel->flags & LEVELFLAG_PAUSED) + { + plevel->flags &= ~LEVELFLAG_PAUSED; + basetime = SDL_GetTicks() - (pausetime - basetime); + } + else + { + plevel->flags |= LEVELFLAG_PAUSED; + pausetime = SDL_GetTicks(); + } + redraw |= SCREENREDRAW_BAR; + break; + + case ACTION_REDRAW: + redraw |= SCREENREDRAW_ALL; + break; + + case ACTION_HIDE: + SDL_WM_IconifyWindow(); + break; + + case ACTION_UNDO: + if(plevelreplay != NULL) + { + plevelreplay->flags |= LEVELFLAG_UNDO; + plevelreplay->flags &= ~LEVELFLAG_PAUSED; + } + else + action = ACTION_UNDO; + break; + + + case ACTION_REDO: + if(plevelreplay!= NULL) + { + plevelreplay->flags &= ~LEVELFLAG_UNDO; + plevelreplay->flags &= ~LEVELFLAG_PAUSED; + } + else + action = ACTION_REDO; + break; + + case ACTION_LEFT: + if(plevelreplay != NULL) + { + plevelreplay->flags |= LEVELFLAG_UNDO; + plevelreplay->flags &= ~LEVELFLAG_PAUSED; + } + else + action = ACTION_LEFT; + break; + + case ACTION_RIGHT: + if(plevelreplay != NULL) + { + plevelreplay->flags &= ~LEVELFLAG_UNDO; + plevelreplay->flags &= ~LEVELFLAG_PAUSED; + } + else + action = ACTION_RIGHT; + break; + + case ACTION_UP: + if(plevelreplay != NULL) + plevelreplay->flags |= LEVELFLAG_PAUSED; + else + action = ACTION_UP; + break; + + case ACTION_DOWN: + if(plevelreplay != NULL) + plevelreplay->flags |= LEVELFLAG_PAUSED; + else + action = ACTION_DOWN; + break; + + case ACTION_SWAP: + action = ACTION_SWAP; + break; + + default: + break; + } + break; + + case SDL_KEYUP: + switch(actions[event.key.keysym.sym]) + { + case ACTION_SWAP: + swap = 0; + case ACTION_UP: + case ACTION_DOWN: + case ACTION_LEFT: + case ACTION_RIGHT: + case ACTION_UNDO: + case ACTION_REDO: + action = ACTION_NONE; + break; + + case ACTION_FASTER: + keymod &= ~1; + break; + + case ACTION_SLOWER: + keymod &= ~2; + break; + + case ACTION_FAST: + fast = 0; + break; + + default: + break; + } + break; + + case SDL_QUIT: + exit(0); + + case SDL_VIDEORESIZE: + screen_resizeevent(&event); + redraw = SCREENREDRAW_ALL; + break; + + case SDL_ACTIVEEVENT: + if((event.active.state & SDL_APPACTIVE) && event.active.gain == 1) + redraw = SCREENREDRAW_ALL; + break; + + case SDL_MOUSEBUTTONDOWN: + mouse_x = event.button.x; + mouse_y = event.button.y; + mouse_button = event.button.button; + mouse_time = SDL_GetTicks(); + screen_cursor(1); + + if(mouse_button > 0 && mouse_button < MOUSE_BUTTONS_MAX) + action = actions_mouse[ACTIONS_GAME][mouse_button]; + + if(action == ACTION_HIDE) + { + SDL_WM_IconifyWindow(); + action = ACTION_NONE; + } + if(action == ACTION_QUIT) + quit = 1; + break; + + case SDL_MOUSEBUTTONUP: + if(action == ACTION_MOUSE_CLICK || + (action == ACTION_MOUSE_DRAG_OR_CLICK && (SDL_GetTicks() < mouse_time + MOUSE_TIMEOUT_CLICK))) + { + mouse_destination_x = (mouse_x - display_offset_pixels_x) / pdisplaygraphics->size_x; + mouse_destination_y = (mouse_y - display_offset_pixels_y) / pdisplaygraphics->size_y; + if(mouse_destination_x == plevel->player_x[plevel->player]) + { + if(mouse_destination_y < plevel->player_y[plevel->player]) + action = ACTION_UP; + if(mouse_destination_y > plevel->player_y[plevel->player]) + action = ACTION_DOWN; + } + if(mouse_destination_y == plevel->player_y[plevel->player]) + { + if(mouse_destination_x < plevel->player_x[plevel->player]) + action = ACTION_LEFT; + if(mouse_destination_x > plevel->player_x[plevel->player]) + action = ACTION_RIGHT; + } + if(mouse_destination_x == plevel->player_x[1 - plevel->player] && mouse_destination_y == plevel->player_y[1 - plevel->player]) + action = ACTION_SWAP; + } + /* Buttons 4 and 5 can't be held down */ + else if(mouse_button != 4 && mouse_button != 5) + { + mouse_button = 0; + action = ACTION_NONE; + } + break; + case SDL_MOUSEMOTION: + /* Are we dragging? */ + if(action == ACTION_MOUSE_DRAG || action == ACTION_MOUSE_DRAG_OR_CLICK) + { + display_offset_pixels_y -= (mouse_y - event.motion.y); + display_offset_pixels_x -= (mouse_x - event.motion.x); + + mouse_x = event.motion.x; + mouse_y = event.motion.y; + + redraw |= SCREENREDRAW_LEVEL; + } + else + { + mouse_time = SDL_GetTicks(); + screen_cursor(1); + } + break; + + default: + break; + } + events = SDL_PollEvent(&event); + } + + //////// Actions //////// + + /* Are we replaying the level? */ + if(plevelreplay != NULL) + { + /* Prevent the user from moving during the replay */ + playermove = MOVE_NONE; + + /* Is it time for another move? */ + if(plevel->mover_first == NULL && !(plevelreplay->flags & LEVELFLAG_PAUSED)) + { + /* Moving backwards through replay */ + if(plevelreplay->flags & LEVELFLAG_UNDO) + { + if(level_undo(plevel)) + { + plevel->flags |= LEVELFLAG_UNDO; + if(plevelreplay->move_current != NULL) + plevelreplay->move_current = plevelreplay->move_current->previous; + else + plevelreplay->move_current = plevelreplay->move_last; + } + else + plevel->flags &= ~LEVELFLAG_UNDO; + } + /* Moving forwards through replay */ + else + { + if(plevelreplay->move_current != NULL) + { + playermove = plevelreplay->move_current->direction; + plevelreplay->move_current = plevelreplay->move_current->next; + } + } + } + } + /* otherwise, see what action the user has asked for */ + else + { + playermove = MOVE_NONE; + + switch(action) + { + case ACTION_LEFT: + playermove = MOVE_LEFT; + break; + case ACTION_RIGHT: + playermove = MOVE_RIGHT; + break; + case ACTION_UP: + playermove = MOVE_UP; + break; + case ACTION_DOWN: + playermove = MOVE_DOWN; + break; + case ACTION_SWAP: + /* Swap only once per keypress */ + if(plevel->mover_first == NULL && !(plevel->flags & LEVELFLAG_PAUSED) && !swap) + { + playermove = MOVE_SWAP; + swap = 1; + } + break; + case ACTION_UNDO: + if(plevel->mover_first == NULL && !(plevel->flags & LEVELFLAG_UNDO)) + { + if(level_undo(plevel)) + plevel->flags |= LEVELFLAG_UNDO; + else + plevel->flags &= ~LEVELFLAG_UNDO; + playermove = MOVE_NONE; + basetime = SDL_GetTicks(); + + /* Refocus in case we've moved offscreen */ + redraw |= display_focus(plevel, 1) * SCREENREDRAW_LEVEL; + } + break; + case ACTION_REDO: + playermove = MOVE_REDO; + break; + default: + break; + } + } + + if(mouse_button == 4 || mouse_button == 5) + { + action = ACTION_NONE; + mouse_button = 0; + } + + /* Can't move if we've failed or solved the level */ + if(plevel->flags & (LEVELFLAG_FAILED | LEVELFLAG_SOLVED)) + playermove = MOVE_NONE; + + /* If we can move, make the move */ + if(playermove != MOVE_NONE && plevel->mover_first == NULL && !(plevel->flags & LEVELFLAG_PAUSED)) + { + level_move(plevel, playermove); + basetime = SDL_GetTicks(); + redraw |= display_focus(plevel, 1) * SCREENREDRAW_LEVEL; + + if(mouse_destination_x != 0 || mouse_destination_y != 0) + { + /* Have we reached our destination, or been blocked? */ + if((plevel->player_x[plevel->player] == mouse_destination_x && plevel->player_y[plevel->player] == mouse_destination_y) || plevel->mover_first == NULL) + { + action = ACTION_NONE; + mouse_destination_x = 0; + mouse_destination_y = 0; + } + } + } + + //////// Display changes //////// + + if(plevel->flags & LEVELFLAG_MOVES) + { + display_moves(plevel, plevelreplay); + plevel->flags &= ~LEVELFLAG_MOVES; + } + + if(plevel->flags & LEVELFLAG_STARS) + { + display_stars(plevel); + plevel->flags &= ~LEVELFLAG_STARS; + } + +#ifdef XOR_COMPATIBILITY + if(plevel->flags & LEVELFLAG_SWITCH) + { + redraw |= SCREENREDRAW_ALL; + plevel->flags &= ~LEVELFLAG_SWITCH; + } + + if(plevel->flags & LEVELFLAG_MAP) + { + plevel->flags &= ~LEVELFLAG_MAP; + if(plevel->mode == MODE_XOR && options_xor_display) + display_map(plevel); + } +#endif + + + if(!(plevel->flags & LEVELFLAG_SOLVED) && plevel->flags & LEVELFLAG_EXIT) + { + redraw |= SCREENREDRAW_BAR; + plevel->flags |= LEVELFLAG_SOLVED; + } + + if(!(plevel->flags & LEVELFLAG_FAILED) && plevel->alive[0] == 0 && plevel->alive[1] ==0) + { + redraw |= SCREENREDRAW_BAR; + plevel->flags |= LEVELFLAG_FAILED; + } + } + + screen_cursor(1); +} + +void display_edit(struct level* plevel) +{ + int quit; + + struct mover* pmover; + struct mover* pmovertmp; + + static int editor_piece = 0; + int redraw = 0, predraw = 0, moved = 0, pmoved = 0; + int i, j; + int player; + + int ex, ey, ep; + int x, y; + int bevel; + int piece_start = 0; + int piece_end = 0; + int piece_width = 0; + int piece_count = 0; + int action; + int effect; + + SDL_Event event; + SDL_Rect drect; + SDL_Surface *psurface; + + int mouse_x, mouse_y; + int dx, dy; + + int mouse_button; + int mouse_time; + + font_set_size(font_size_game); + graphics_reload(); + + display_bevellevel(plevel); + + piece_count = 0; + while(editor_piece_maps[plevel->mode][piece_count] != PIECE_GONE) + piece_count ++; + + if(editor_piece > piece_count) + editor_piece = 0; + + /* The editor uses player 2, so store the player value */ + player = plevel->player; + + ex = plevel->player_x[2]; + ey = plevel->player_y[2]; + ep = editor_piece; + + mouse_x = 0; + mouse_y = 0; + mouse_button = 0; + mouse_time = SDL_GetTicks(); + action = 0; + effect = 0; + + /* Force a complete redraw */ + redraw = 2; + + display_focus(plevel, 1); + + quit = 0; + while(!quit) + { + plevel->player_x[2] = plevel->player_x[2]; + plevel->player_y[2] = plevel->player_y[2]; + plevel->player = 2; + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR) + xor_focus(plevel); +#endif + + /* Clear screen, and calculate size of bar */ + if(redraw == 2) + { + screen_clear(pdisplaygraphics->background[0], pdisplaygraphics->background[1], pdisplaygraphics->background[2]); + + piece_width = (screen_width - pdisplaygraphics->size_x - 2) / pdisplaygraphics->size_x; + + display_bar_pixels = pdisplaygraphics->size_y + 1; + + if(piece_width < piece_count) + { + if(display_bar_pixels < font_height) + display_bar_pixels = font_height; + piece_width = (screen_width - pdisplaygraphics->size_x - 2) / pdisplaygraphics->size_x; + } + predraw = 2; + } + + if(moved == 1) + redraw |= display_focus(plevel, 1); + + /* Draw level */ + if(redraw) + { + display_level(plevel, SCREENREDRAW_ALL); + + redraw = 0; + moved = 1; + } + + /* Recalculate piece bar */ + if(pmoved || predraw) + { + if(piece_width >= piece_count) + { + piece_start =0; + piece_end = piece_count; + } + else + { + while(editor_piece < piece_start + 3 && piece_start > 0) + { + piece_start --; + piece_end = piece_start + piece_width; + + predraw = 1; + } + + while(editor_piece >= piece_start + piece_width - 3 && piece_end < piece_count) + { + piece_start ++; + piece_end = piece_start + piece_width; + + predraw = 1; + } + + piece_end = piece_start + piece_width; + if(piece_end > piece_count) + piece_end = piece_count; + } + } + + /* Redraw all of piece bar */ + if(predraw) + { + drect.x = 0; + drect.w = screen_width; + drect.y = screen_height - display_bar_pixels; + drect.h = display_bar_pixels; + SDL_FillRect(screen_surface, &drect, SDL_MapRGB(screen_surface->format, 0, 0, 0)); + + drect.x = 0; + drect.w = screen_width - pdisplaygraphics->size_x - 2; + drect.y = screen_height - pdisplaygraphics->size_y; + drect.h = pdisplaygraphics->size_y; + SDL_SetClipRect(screen_surface, &drect); + for(i = piece_start; i < piece_end; i ++) + { + display_pieceabsolute(editor_piece_maps[plevel->mode][i], (i - piece_start) * pdisplaygraphics->size_x, screen_height - pdisplaygraphics->size_y, 0); + } + if(piece_start != 0) + { + psurface = font_render(ARROW_LEFT, COLOUR_WHITE | COLOUR_BOLD); + drect.x = 0; + drect.y = screen_height - (pdisplaygraphics->size_y + font_height) / 2; + SDL_BlitSurface(psurface, NULL, screen_surface, &drect); + SDL_FreeSurface(psurface); + } + if(piece_end != piece_count) + { + psurface = font_render(ARROW_RIGHT, COLOUR_WHITE | COLOUR_BOLD); + drect.x = piece_width * pdisplaygraphics->size_x - 2 - psurface->w; + drect.y = screen_height - (pdisplaygraphics->size_y + font_height) / 2; + SDL_BlitSurface(psurface, NULL, screen_surface, &drect); + SDL_FreeSurface(psurface); + } + SDL_SetClipRect(screen_surface, NULL); + + drect.x = 0; + drect.w = screen_width; + drect.y = screen_height - pdisplaygraphics->size_y; + drect.h = pdisplaygraphics->size_y; + SDL_UpdateRects(screen_surface, 1, &drect); + + pmoved = 1; + } + + /* Redraw piece bar cursor */ + if(pmoved) + { + pmoved = 0; + + /* Remove cursor from previous piece */ + if(!predraw) + display_pieceabsolute(editor_piece_maps[plevel->mode][ep], (ep - piece_start) * pdisplaygraphics->size_x, screen_height - pdisplaygraphics->size_y, 1); + + /* Plot cursor */ + display_pieceabsolute(PIECE_CURSOR, (editor_piece - piece_start) * pdisplaygraphics->size_x, screen_height - pdisplaygraphics->size_y, predraw ? 0 : 1); + + /* Plot current piece in far right corner */ + display_pieceabsolute(editor_piece_maps[plevel->mode][editor_piece], screen_width - pdisplaygraphics->size_x, screen_height - pdisplaygraphics->size_y, predraw ? 0 : 1); + } + + if(predraw) + { + drect.x = 0; + drect.w = screen_width; + drect.y = screen_height - display_bar_pixels; + drect.h = display_bar_pixels; + SDL_UpdateRects(screen_surface, 1, &drect); + predraw = 0; + } + + /* Redraw level cursor */ + if(moved) + { + moved = 0; + + /* Create cosmetic movers */ + level_setprevious(plevel, plevel->player_x[2], plevel->player_y[2], level_piece(plevel, plevel->player_x[2], plevel->player_y[2])); + if(pdisplaygraphics->shadows != NULL) + mover_newundo(plevel, ex, ey, MOVE_NONE, PIECE_SPACE, PIECE_SPACE, MOVER_UNDO); + else + mover_newundo(plevel, ex, ey, MOVE_NONE, level_piece(plevel, ex, ey), PIECE_SPACE, MOVER_UNDO); + mover_newundo(plevel, plevel->player_x[2], plevel->player_y[2], MOVE_NONE, PIECE_CURSOR, PIECE_SPACE, MOVER_UNDO); + display_animation = 0.5; + display_movers(plevel, 1); + level_setmoving(plevel, ex, ey, MOVE_NONE); + level_setmoving(plevel, plevel->player_x[2], plevel->player_y[2], MOVE_NONE); + level_setprevious(plevel, plevel->player_x[2], plevel->player_y[2], PIECE_SPACE); + + /* Delete cosmetic movers */ + pmover = plevel->mover_first; + while(pmover != NULL) + { +#ifdef XOR_COMPATIBILITY + /* Update map if present */ + if(options_xor_display && pmover->piece != PIECE_CURSOR) + display_map_piece(plevel, pmover->piece, pmover->x, pmover->y, 1); +#endif + pmovertmp = pmover; + pmover = pmover->next; + free(pmovertmp); + } + plevel->mover_first = NULL; + plevel->mover_last = NULL; + } + + SDL_WaitEvent(&event); + + /* Hide the mouse if not used whilst in full screen mode */ + if(SDL_GetTicks() > mouse_time + MOUSE_TIMEOUT_MOVE) + screen_cursor(0); + + /* Store previous cursor location for redrawing damaged areas */ + ex = plevel->player_x[2]; + ey = plevel->player_y[2]; + ep = editor_piece; + + switch(event.type) + { + case SDL_KEYDOWN: + switch(actions[event.key.keysym.sym]) + { + case ACTION_QUIT: + quit = 1; + break; + + case ACTION_HIDE: + SDL_WM_IconifyWindow(); + break; + + case ACTION_LEFT: + if(plevel->player_x[2] > 0) + { + plevel->player_x[2] --; moved = 1; + } + break; + + case ACTION_RIGHT: + if(plevel->player_x[2] < plevel->size_x - 1) + { + plevel->player_x[2] ++; moved = 1; + } + break; + + case ACTION_UP: + if(plevel->player_y[2] > 0) + { + plevel->player_y[2] --; moved = 1; + } + break; + + case ACTION_DOWN: + if(plevel->player_y[2] < plevel->size_y -1) + { + plevel->player_y[2] ++; moved = 1; + } + break; + + case ACTION_PIECE_LEFT: + effect = ACTION_PIECE_LEFT; + break; + + case ACTION_PIECE_RIGHT: + effect = ACTION_PIECE_RIGHT; + break; + + case ACTION_SWAP: + effect = ACTION_SWAP; + moved = 1; + break; + + default: + break; + } + break; + + + case SDL_MOUSEBUTTONDOWN: + mouse_x = event.button.x; + mouse_y = event.button.y; + mouse_button = event.button.button; + mouse_time = SDL_GetTicks(); + screen_cursor(1); + + if(mouse_button > 0 && mouse_button < MOUSE_BUTTONS_MAX) + action = actions_mouse[ACTIONS_EDIT][mouse_button]; + + switch(action) + { + case ACTION_HIDE: + SDL_WM_IconifyWindow(); + action = ACTION_NONE; + break; + + case ACTION_QUIT: + quit = 1; + break; + + case ACTION_PIECE_LEFT: + effect = ACTION_PIECE_LEFT; + break; + + case ACTION_PIECE_RIGHT: + effect = ACTION_PIECE_RIGHT; + break; + + default: + break; + } + break; + + case SDL_MOUSEBUTTONUP: + if(action == ACTION_MOUSE_CLICK || + (action == ACTION_MOUSE_DRAG_OR_CLICK && ((SDL_GetTicks() < mouse_time + MOUSE_TIMEOUT_CLICK) || (mouse_y > (screen_height - display_bar_pixels))))) + { + /* Have they clicked within the piece bar? */ + if(mouse_y > (screen_height - display_bar_pixels)) + { + editor_piece = piece_start + ((mouse_x) / pdisplaygraphics->size_x); + pmoved = 1; + } + else + { + plevel->player_x[2] = (mouse_x - display_offset_pixels_x) / pdisplaygraphics->size_x; + plevel->player_y[2] = (mouse_y - display_offset_pixels_y) / pdisplaygraphics->size_y; + moved = 2; + effect = ACTION_SWAP; + } + } + + /* Buttons 4 and 5 can't be held down */ + if(mouse_button != 4 && mouse_button != 5) + { + mouse_button = 0; + action = ACTION_NONE; + } + break; + + case SDL_MOUSEMOTION: + mouse_time = SDL_GetTicks(); + screen_cursor(1); + + if(action == ACTION_MOUSE_DRAG || action == ACTION_MOUSE_DRAG_OR_CLICK) + { + dx = mouse_x - event.motion.x; + dy = mouse_y - event.motion.y; + + mouse_x = event.motion.x; + mouse_y = event.motion.y; + + display_offset_pixels_y -= dy; + display_offset_pixels_x -= dx; + + redraw |= 1; + } + else if(action == ACTION_MOUSE_CLICK) + { + + mouse_x = event.motion.x; + mouse_y = event.motion.y; + /* Have they clicked within the piece bar? */ + if(mouse_y > (screen_height - display_bar_pixels)) + { + editor_piece = piece_start + ((mouse_x) / pdisplaygraphics->size_x); + pmoved = 1; + } + else + { + plevel->player_x[2] = (mouse_x - display_offset_pixels_x) / pdisplaygraphics->size_x; + plevel->player_y[2] = (mouse_y - display_offset_pixels_y) / pdisplaygraphics->size_y; + moved = 2; + effect = ACTION_SWAP; + } + } + break; + + case SDL_QUIT: + exit(0); + + case SDL_VIDEORESIZE: + screen_resizeevent(&event); + redraw = 2; + break; + + case SDL_ACTIVEEVENT: + if((event.active.state & SDL_APPACTIVE) && event.active.gain == 1) + redraw = 2; + break; + } + + switch(effect) + { + case ACTION_PIECE_LEFT: + editor_piece --; + if(editor_piece < 0) + editor_piece = piece_count - 1; + pmoved = 1; + break; + + case ACTION_PIECE_RIGHT: + editor_piece ++; + if(editor_piece >= piece_count) + editor_piece = 0; + pmoved = 1; + break; + + case ACTION_SWAP: + bevel = 0; + if(editor_piece_maps[plevel->mode][editor_piece] == PIECE_WALL || level_piece(plevel, plevel->player_x[2], plevel->player_y[2]) == PIECE_WALL) + bevel = 1; + /* Don't allow the edges to be changed */ + if(!(plevel->player_x[2] < 1 || plevel->player_x[2] > plevel->size_x - 2 || plevel->player_y[2] < 1 || plevel->player_y[2] > plevel->size_y - 2)) + level_setpiece(plevel, plevel->player_x[2], plevel->player_y[2], editor_piece_maps[plevel->mode][editor_piece]); + + /* Rebevel if necessary */ + if(bevel == 1) + { + x = plevel->player_x[2]; y = plevel->player_y[2]; + for(i = -1; i < 2; i ++) + { + for(j = - 1; j < 2; j ++) + { + bevel = display_bevelsquare(plevel, x + i, y + j); + if(bevel != (level_data(plevel, x + i, y + j) & BEVEL_ALL)) + { + level_setdata(plevel, x + i, y + j, bevel | (level_data(plevel, x + i, y + j) & ~BEVEL_ALL)); + /* Redraw changed piece */ + /* The mover will get deleted when next redrawn */ + if(pdisplaygraphics->shadows != NULL) + mover_newundo(plevel, x + i, y + j, MOVE_NONE, PIECE_SPACE, PIECE_SPACE, MOVER_UNDO); + else + mover_newundo(plevel, x + i, y + j, MOVE_NONE, level_piece(plevel, x + i, y + j), PIECE_SPACE, MOVER_UNDO); + } + } + } + } + break; + + default: + break; + } + effect = ACTION_NONE; + } + + /* Restore real player value */ + plevel->player = player; + screen_cursor(1); +} + +int display_type() +{ + return DISPLAY_SDL; +} + +int scale_delay(int delay, int change) +{ + int tmp; + int magnitude; + + if(delay < 1) + delay = 1; + + if(change == 1) + { + tmp = delay; + + while(tmp >= 100) + tmp = tmp / 10; + + magnitude = delay / tmp; + + if(tmp < 20) + tmp = tmp + 1; + else if(tmp < 50) + tmp = tmp + 2; + else + tmp = tmp + 5; + + delay = tmp * magnitude; + + if(delay > 1000) + delay = 1; + } + + if(change == -1) + { + tmp = delay; + + while(tmp > 100) + tmp = tmp / 10; + + magnitude = delay / tmp; + + if(tmp > 50) + tmp = tmp - 5; + else if(tmp > 20) + tmp = tmp - 2; + else + tmp = tmp - 1; + + delay = tmp * magnitude; + + if(delay < 1) + delay = 1000; + } + + return delay; +} + +void display_options() +{ + struct menu* pmenu; + struct menu* pgraphicsmenu; + struct menu* pcoloursmenu; + struct menuentry* pentryscreensize; + struct menuentry* pentryfullscreen; + struct menuentry* pentrygraphics; + struct menuentry* pentrysize; + struct menuentry* pentrylevel; + struct menuentry* pentrycolours; + struct menuentry* pentryspeed; + struct menuentry* pentryfirstspeed; + struct menuentry* pentryreplayspeed; + struct menuentry* pentryundospeed; + int result; + int ok; + + char buffer[4096]; + + pmenu = menu_new(gettext("Display Options")); + + menuentry_new(pmenu, gettext("Return to previous menu"), 'Q', 0); + menuentry_new(pmenu, gettext("Save Options"), 'S', 0); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentrygraphics = menuentry_new(pmenu, gettext("Graphics Scheme"), 'G', 0); + pentrysize = menuentry_new(pmenu, gettext("Graphics Size"), 'I', 0); + pentrylevel = menuentry_new(pmenu, gettext("Graphics Level"), 'L', 0); + pentrycolours = menuentry_new(pmenu, gettext("Colour Scheme"), 'C', 0); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentryscreensize = menuentry_new(pmenu, gettext("Screen size"), 'Z', 0); + pentryfullscreen = menuentry_new(pmenu, gettext("Fullscreen"), 'F', 0); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentryfirstspeed = menuentry_new(pmenu, gettext("Player Speed"), 'P', MENU_SCROLLABLE); + pentryspeed = menuentry_new(pmenu, gettext("Move Speed"), 'M', MENU_SCROLLABLE); + pentryreplayspeed = menuentry_new(pmenu, gettext("Replay Speed"), 'R', MENU_SCROLLABLE); + pentryundospeed = menuentry_new(pmenu, gettext("Undo Speed"), 'U', MENU_SCROLLABLE); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + menuentry_new(pmenu, gettext("Change Keys"), 'K', 0); + menuentry_new(pmenu, gettext("Change Mouse"), 'O', 0); + + /* XOR and Enigma options are only visible once an appropriate level has + * been seen so as not to confuse those simply playing Chroma levels */ + if(0 +#ifdef XOR_COMPATIBILITY + || options_xor_options +#endif +#ifdef ENIGMA_COMPATIBILITY + || options_enigma_options +#endif + ) + { + menuentry_new(pmenu, "", 0, MENU_SPACE); + menuentry_new(pmenu, gettext("Other Games Options"), 'X', 0); + } + + if(options_debug & DEBUG_MENU) + { + menuentry_new(pmenu, "", 0, MENU_SPACE); + menuentry_new(pmenu, gettext("Debug Options"), 'D', 0); + } + + ok = 0; + while(!ok) + { + if(options_sdl_width == 0 && options_sdl_height == 0) + sprintf(buffer, gettext("Auto (%d x %d)"), screen_width, screen_height); + else + sprintf(buffer, "%d x %d", screen_width, screen_height); + menuentry_extratext(pentryscreensize, buffer, NULL, NULL); + + menuentry_extratext(pentryfullscreen, screen_fullscreen ? gettext("Yes") : gettext("No"), NULL, NULL); + + sprintf(buffer, gettext("%d milliseconds"), options_sdl_delay); + menuentry_extratext(pentryspeed, buffer, NULL, NULL); + + sprintf(buffer, gettext("%d milliseconds"), options_sdl_player_delay); + menuentry_extratext(pentryfirstspeed, buffer, NULL, NULL); + + sprintf(buffer, gettext("%d milliseconds"), options_sdl_replay_delay); + menuentry_extratext(pentryreplayspeed, buffer, NULL, NULL); + + sprintf(buffer, gettext("%d milliseconds"), options_sdl_undo_delay); + menuentry_extratext(pentryundospeed, buffer, NULL, NULL); + + if(pdisplaygraphics != NULL) + { + if(options_sdl_size_x != pdisplaygraphics->size_x || options_sdl_size_y != pdisplaygraphics->size_y) + sprintf(buffer, gettext("Auto (%d x %d)"), pdisplaygraphics->size_x, pdisplaygraphics->size_y); + + else + sprintf(buffer, "%d x %d", pdisplaygraphics->size_x, pdisplaygraphics->size_y); + + menuentry_extratext(pentrysize, buffer, NULL, NULL); + + menuentry_extratext(pentrygraphics, pdisplaygraphics->title != NULL ? pdisplaygraphics->title : gettext("[untitled graphics]"), NULL, NULL); + + if(pdisplaygraphics->title == NULL) + menuentry_extratext(pentrygraphics, gettext("[untitled graphics]"), NULL, NULL); + else if(pdisplaygraphics->flags & GRAPHICS_TRANSLATE) + menuentry_extratext(pentrygraphics, gettext(pdisplaygraphics->title), NULL, NULL); + else + menuentry_extratext(pentrygraphics, pdisplaygraphics->title, NULL, NULL); + + if(options_graphic_level != 0) + sprintf(buffer, "%d / %d", options_graphic_level, pdisplaygraphics->levels); + else + sprintf(buffer, gettext("Auto (%d)"), pdisplaygraphics->levels); + + menuentry_extratext(pentrylevel, buffer, NULL, NULL); + } + else + menuentry_extratext(pentrygraphics, gettext("** NONE **"), NULL, NULL); + + if(pdisplaygraphics != NULL && (pdisplaygraphics->flags & GRAPHICS_CURSES)) + pentrycolours->flags = 0; + else + pentrycolours->flags = MENU_INVISIBLE | MENU_GREY; + + if(pdisplaygraphics != NULL && pdisplaygraphics->sizes != NULL) + pentrysize->flags = 0; + else + pentrysize->flags = MENU_INVISIBLE | MENU_GREY; + + if(pdisplaygraphics != NULL && pdisplaygraphics->levels > 0) + pentrylevel->flags = MENU_SCROLLABLE; + else + pentrylevel->flags = MENU_INVISIBLE | MENU_GREY; + + if(pdisplaycolours == NULL) + menuentry_extratext(pentrycolours, gettext("** NONE **"), NULL, NULL); + else if(pdisplaycolours->title == NULL) + menuentry_extratext(pentrycolours, gettext("[untitled colours]"), NULL, NULL); + else if(pdisplaycolours->flags & COLOURS_TRANSLATE) + menuentry_extratext(pentrycolours, gettext(pdisplaycolours->title), NULL, NULL); + else + menuentry_extratext(pentrycolours, pdisplaycolours->title, NULL, NULL); + + result = menu_process(pmenu); + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'Q': + ok = 1; + break; + + case 'Z': + display_screensizemenu(); + break; + + case 'F': + screen_fullscreen = 1 - screen_fullscreen; + screen_resize(screen_width, screen_height, screen_fullscreen); + options_sdl_fullscreen = screen_fullscreen; + break; + + case 'G': + pgraphicsmenu = graphics_menu(); + if(menu_process(pgraphicsmenu) == MENU_SELECT) + { + if(pgraphicsmenu->entry_selected != NULL && pgraphicsmenu->entry_selected->value != NULL) + { + strcpy(options_graphics, pgraphicsmenu->entry_selected->value); + graphics_init(); + } + } + menu_delete(pgraphicsmenu); + break; + + case 'C': + pcoloursmenu = colours_menu(); + if(menu_process(pcoloursmenu) == MENU_SELECT) + { + if(pcoloursmenu->entry_selected != NULL && pcoloursmenu->entry_selected->value != NULL) + { + strcpy(options_colours, pcoloursmenu->entry_selected->value); + colours_init(); + graphics_init(); + } + } + menu_delete(pcoloursmenu); + break; + + case 'I': + display_options_size(); + break; + + case 'S': + display_options_save(); + ok = 1; + break; + + case 'K': + display_options_keys(); + break; + + case 'O': + display_options_mouse(); + break; + + case 'X': + display_options_othergames(); + break; + + case 'D': + display_options_debug(); + break; + } + } + + if(result == MENU_SCROLLLEFT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'M': + options_sdl_delay = scale_delay(options_sdl_delay, -1); + break; + case 'P': + options_sdl_player_delay = scale_delay(options_sdl_player_delay, -1); + break; + case 'R': + options_sdl_replay_delay = scale_delay(options_sdl_replay_delay, -1); + break; + case 'U': + options_sdl_undo_delay = scale_delay(options_sdl_undo_delay, -1); + break; + case 'L': + options_graphic_level --; + if(options_graphic_level < 0) + options_graphic_level = pdisplaygraphics->levels; + graphics_reload(); + break; + } + } + + if(result == MENU_SCROLLRIGHT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'M': + options_sdl_delay = scale_delay(options_sdl_delay, 1); + break; + case 'P': + options_sdl_player_delay = scale_delay(options_sdl_player_delay, 1); + break; + case 'R': + options_sdl_replay_delay = scale_delay(options_sdl_replay_delay, 1); + break; + case 'U': + options_sdl_undo_delay = scale_delay(options_sdl_undo_delay, 1); + break; + case 'L': + options_graphic_level ++; + if(options_graphic_level > pdisplaygraphics->levels) + options_graphic_level = 0; + graphics_reload(); + break; + } + } + + + } + + menu_delete(pmenu); +} + +void display_clip(struct level* plevel, int clip) +{ + SDL_Rect crect; + + if(clip) + { + crect.x = 0; + crect.y = 0; + crect.w = screen_width; + crect.h = screen_height - display_bar_pixels; + +#ifdef XOR_COMPATIBILITY + if(plevel->mode == MODE_XOR && options_xor_display) + { + crect.w = pdisplaygraphics->size_x * 8; + crect.h = pdisplaygraphics->size_y * 8; + crect.x = (screen_width - crect.w) / 2; + crect.y = (screen_height - display_bar_pixels - crect.h) / 2; + + /* Ensure bar is always visible */ + if(crect.y + crect.h > screen_height - display_bar_pixels) + crect.h = screen_height - display_bar_pixels - crect.y; + } +#endif + + SDL_SetClipRect(screen_surface, &crect); + } + else + { + SDL_SetClipRect(screen_surface, NULL); + } +} + + +void display_screensizemenu() +{ + struct menu* pmenu; + struct menuentry *pentry; + + int sizes[6][2] = { {640, 480}, {800, 600}, {1024, 768}, {1280, 1024}, {1600, 1200}, {0, 0} }; + int i; + char buffer[256], tmp[256]; + int custom; + SDL_Rect **modes; + int w, h; + int ok; + + custom = 1; + + pmenu = menu_new(gettext("Screen Size")); + + menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentry = menuentry_new(pmenu, gettext("Automatic sizing"), 0, 0); + menuentry_extratext(pentry, NULL, "0", "0"); + if(options_sdl_width == 0 && options_sdl_height == 0) + { + pmenu->entry_selected = pentry; + custom = 0; + } + + /* First, add modes that we know the screen can do */ + modes = SDL_ListModes(NULL, SDL_FULLSCREEN); + if(modes != (SDL_Rect **)0 && modes != (SDL_Rect **)-1) + { + for(i = 0; modes[i]; i ++) + { + w = modes[i]->w; h = modes[i]->h; + sprintf(buffer, "%d x %d", w, h); + + pentry = pmenu->entry_first; ok = 1; + while(pentry != NULL) + { + if(pentry->text != NULL && strcmp(pentry->text, buffer) == 0) + { + ok = 0; + } + pentry = pentry->next; + } + + if(ok) + { + sprintf(tmp, "%04dx%04d", w, h); + pentry = menuentry_newwithvalue(pmenu, buffer, 0, MENU_SORT, tmp); + sprintf(buffer, "%d", w); + sprintf(tmp, "%d", h); + menuentry_extratext(pentry, NULL, buffer, tmp); + if(options_sdl_width == w && options_sdl_height == h) + pmenu->entry_selected = pentry; + if(screen_width == w && screen_height == h) + custom = 0; + } + } + } + + /* Then add any of the default modes that haven't been already added */ + i = 0; + while(sizes[i][0] != 0) + { + sprintf(buffer, "%d x %d", sizes[i][0], sizes[i][1]); + pentry = pmenu->entry_first; ok = 1; + while(pentry != NULL) + { + if(pentry->text != NULL && strcmp(pentry->text, buffer) == 0) + { + ok = 0; + } + pentry = pentry->next; + } + + if(ok) + { + sprintf(tmp, "%04dx%04d", sizes[i][0], sizes[i][1]); + pentry = menuentry_newwithvalue(pmenu, buffer, 0, MENU_SORT, tmp); + sprintf(buffer, "%d", sizes[i][0]); + sprintf(tmp, "%d", sizes[i][1]); + menuentry_extratext(pentry, NULL, buffer, tmp); + if(options_sdl_width == sizes[i][0] && options_sdl_height == sizes[i][1]) + pmenu->entry_selected = pentry; + if(screen_width == sizes[i][0] && screen_height == sizes[i][1]) + custom = 0; + } + + i ++; + } + if(custom) + { + sprintf(buffer, gettext("Custom (%d x %d)"), screen_width, screen_height); + pentry = menuentry_new(pmenu, buffer, 0, 0); + sprintf(buffer, "%d", screen_width); + sprintf(buffer + 16, "%d", screen_height); + menuentry_extratext(pentry, NULL, buffer, buffer + 16); + pmenu->entry_selected = pentry; + } + + pentry = menuentry_new(pmenu, gettext("Current screen size:"), 0, MENU_NOTE); + sprintf(buffer, gettext("%d x %d (%d bits per pixel)"), screen_width, screen_height, screen_surface->format->BitsPerPixel); + pentry = menuentry_new(pmenu, buffer, 0, MENU_NOTE | MENU_RIGHT); + + menu_assignletters(pmenu); + + if(menu_process(pmenu) == MENU_SELECT) + { + if(pmenu->entry_selected->text3 != NULL) + { + options_sdl_width = atoi(pmenu->entry_selected->text3); + options_sdl_height = atoi(pmenu->entry_selected->text4); + screen_resize(options_sdl_width, options_sdl_height, screen_fullscreen); + } + } + + menu_delete(pmenu); +} + +int display_keyfixed(SDLKey key) +{ + if(key == SDLK_ESCAPE || key == SDLK_q || key == SDLK_RETURN || key == SDLK_UP || key == SDLK_DOWN || key == SDLK_LEFT || key == SDLK_RIGHT) + return 1; + + return 0; +} + +char *display_keyname(SDLKey key) +{ + return SDL_GetKeyName(key); +} + +void display_addkeytomenu(struct menu* pmenu, int action, char *text) +{ + struct menuentry *pentry; + char buffer[256]; + SDLKey key; + + sprintf(buffer, "%d", action); + pentry = menuentry_newwithvalue(pmenu, text, 0, MENU_DOUBLE, buffer); + + strcpy(buffer, ""); + for(key = SDLK_FIRST; key < SDLK_LAST; key ++) + { + if(actions[key] == action) + { + if(strlen(buffer) != 0) + strcat(buffer,", "); + strcat(buffer, "["); + strcat(buffer, display_keyname(key)); + strcat(buffer, "]"); + } + } + + if(strcmp(buffer, "") == 0) + strcpy(buffer, gettext("(none)")); + + menuentry_extratext(pentry, NULL, NULL, buffer); +} + +void display_options_keys() +{ + struct menu *pmenu; + struct menu *psubmenu; + struct menuentry *pentry; + int redraw; + int action; + int result; + int ok; + int subok; + char buffer[256]; + SDLKey key; + SDL_Event event; + + ok = 0; + while(!ok) + { + pmenu = menu_new(gettext("Keys")); + + menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + display_addkeytomenu(pmenu, ACTION_LEFT, gettext(action_name[ACTION_LEFT])); + display_addkeytomenu(pmenu, ACTION_RIGHT, gettext(action_name[ACTION_RIGHT])); + display_addkeytomenu(pmenu, ACTION_UP, gettext(action_name[ACTION_UP])); + display_addkeytomenu(pmenu, ACTION_DOWN, gettext(action_name[ACTION_DOWN])); + display_addkeytomenu(pmenu, ACTION_SWAP, gettext(action_name[ACTION_SWAP])); + display_addkeytomenu(pmenu, ACTION_UNDO, gettext(action_name[ACTION_UNDO])); + display_addkeytomenu(pmenu, ACTION_REDO, gettext(action_name[ACTION_REDO])); + display_addkeytomenu(pmenu, ACTION_FAST, gettext(action_name[ACTION_FAST])); + display_addkeytomenu(pmenu, ACTION_FASTER, gettext(action_name[ACTION_FASTER])); + display_addkeytomenu(pmenu, ACTION_SLOWER, gettext(action_name[ACTION_SLOWER])); + display_addkeytomenu(pmenu, ACTION_PAUSE, gettext(action_name[ACTION_PAUSE])); + display_addkeytomenu(pmenu, ACTION_QUIT, gettext(action_name[ACTION_QUIT])); + display_addkeytomenu(pmenu, ACTION_REDRAW, gettext(action_name[ACTION_REDRAW])); + display_addkeytomenu(pmenu, ACTION_HIDE, gettext(action_name[ACTION_HIDE])); + display_addkeytomenu(pmenu, ACTION_PIECE_LEFT, gettext(action_name[ACTION_PIECE_LEFT])); + display_addkeytomenu(pmenu, ACTION_PIECE_RIGHT, gettext(action_name[ACTION_PIECE_RIGHT])); + + menu_assignletters(pmenu); + + result = menu_process(pmenu); + + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT) + { + if(pmenu->entry_selected->key == 'Q') + ok = 1; + else if(pmenu->entry_selected->value != NULL) + { + subok = 0; + redraw = MENUREDRAW_ALL; + while(!subok) + { + action = atoi(pmenu->entry_selected->value); + + sprintf(buffer, gettext("Set keys for '%s'"), gettext(action_name[action])); + psubmenu = menu_new(buffer); + + menuentry_new(psubmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(psubmenu, "", 0, MENU_SPACE); + + for(key = SDLK_FIRST; key < SDLK_LAST; key ++) + { + if(actions[key] == action) + { + sprintf(buffer, "[%s]", display_keyname(key)); + pentry = menuentry_new(psubmenu, buffer, 0, MENU_GREY); + if(display_keyfixed(key)) + menuentry_extratext(pentry, gettext("(fixed)"), NULL, NULL); + } + } + + menuentry_new(psubmenu, gettext("Press a key to add or remove it from this list."), 0, MENU_NOTE | MENU_CENTRE); + + menu_display(psubmenu, redraw); + redraw = MENUREDRAW_ENTRIES; + + menu_delete(psubmenu); + + subok = 0; + while(!subok) + { + SDL_WaitEvent(&event); + + switch(event.type) + { + case SDL_KEYDOWN: + key = event.key.keysym.sym; + if(key == SDLK_q || key == SDLK_ESCAPE) + subok = 1; + else if(!display_keyfixed(key)) + { + if(actions[key] == action) + actions[key] = ACTION_NONE; + else + actions[key] = action; + + subok = 2; + } + break; + + case SDL_QUIT: + exit(0); + + case SDL_VIDEORESIZE: + screen_resizeevent(&event); + subok = 2; + redraw = MENUREDRAW_ALL; + break; + + case SDL_ACTIVEEVENT: + if((event.active.state & SDL_APPACTIVE) && event.active.gain == 1) + redraw = MENUREDRAW_ALL; + break; + } + } + if(subok == 2) + subok = 0; + } + } + } + + menu_delete(pmenu); + } +} + +void display_options_mouse() +{ + struct menu *pmenu; + struct menu *psubmenu; + struct menuentry *pentry; + int result; + int ok; + int subok; + int i, j, k; + int button, where; + char buffer[256]; + + char *locations[] = {"Game", "Editor", "Menu"}; + + int actions_game[] = { + ACTION_NONE, + ACTION_MOUSE_CLICK, + ACTION_MOUSE_DRAG, + ACTION_MOUSE_DRAG_OR_CLICK, + ACTION_SWAP, + ACTION_UNDO, + ACTION_REDO, + ACTION_HIDE, + ACTION_QUIT, + ACTION_MAX + }; + + int actions_edit[] = { + ACTION_NONE, + ACTION_MOUSE_CLICK, + ACTION_MOUSE_DRAG, + ACTION_MOUSE_DRAG_OR_CLICK, + ACTION_PIECE_LEFT, + ACTION_PIECE_RIGHT, + ACTION_HIDE, + ACTION_QUIT, + ACTION_MAX + }; + + int actions_menu[] = { + ACTION_NONE, + ACTION_UP, + ACTION_DOWN, + ACTION_PAGE_UP, + ACTION_PAGE_DOWN, + ACTION_HIDE, + ACTION_MOUSE_CLICK, + ACTION_QUIT, + ACTION_MAX + }; + + int *actions_available[] = { + actions_game, + actions_edit, + actions_menu, + }; + + char *actions_names_game[] = { + "Do nothing", + "Click to move player", + "Drag to scroll screen", + "Click to move player, drag to scroll screen", + "Click to swap player", + "Undo move", + "Redo move", + "Hide screen", + "Return to previous menu", + "" + }; + + char *actions_names_edit[] = { + "Do nothing", + "Click to set piece", + "Drag to scroll screen", + "Click to set piece, drag to scroll screen", + "Piece left", + "Piece right", + "Hide screen", + "Return to previous menu", + "" + }; + + char *actions_names_menu[] = { + "Do nothing", + "Move up", + "Move down", + "Page up", + "Page down", + "Hide screen", + "Select entry", + "Return to previous menu", + "" + }; + + char **actions_names[] = { + actions_names_game, + actions_names_edit, + actions_names_menu, + }; + + ok = 0; + pmenu = menu_new(gettext("Mouse")); + + menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); + + for(i = 0; i < 3; i ++) + { + menuentry_new(pmenu, "", 0, MENU_SPACE); + menuentry_new(pmenu, locations[i], 0, MENU_GREY); + for(j = 1; j < MOUSE_BUTTONS_MAX; j ++) + { + sprintf(buffer, gettext("Button %d"), j); + pentry = menuentry_new(pmenu, buffer, 0, 0); + + sprintf(buffer, "%d%d", i, j); + menuentry_value(pentry, buffer); + + /* Should be overwritten shortly - this is a fallback if not */ + sprintf(buffer, "? %s", gettext(action_name[actions_mouse[i][j]])); + menuentry_extratext(pentry, buffer, NULL, NULL); + + /* Perhaps not the neatest way of doing this here, but saves + having to have redundant actions merely to give them different + names. */ + k = 0; + while(actions_available[i][k] != ACTION_MAX) + { + if(actions_available[i][k] == actions_mouse[i][j]) + menuentry_extratext(pentry, gettext(actions_names[i][k]), NULL, NULL); + k ++; + } + } + } + + menu_assignletters(pmenu); + + ok = 0; + while(!ok) + { + result = menu_process(pmenu); + + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT) + { + if(pmenu->entry_selected->key == 'Q') + ok = 1; + else if(pmenu->entry_selected->value != NULL) + { + where = pmenu->entry_selected->value[0] - '0'; + button = pmenu->entry_selected->value[1] - '0'; + sprintf(buffer, gettext("Set action for button %d in %s"), button, locations[where]); + psubmenu = menu_new(buffer); + + menuentry_new(psubmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(psubmenu, "", 0, MENU_SPACE); + + i = 0; + while(actions_available[where][i] != ACTION_MAX) + { + pentry = menuentry_new(psubmenu, gettext(actions_names[where][i]), 0, 0); + sprintf(buffer, "%d", i); + menuentry_value(pentry, buffer); + if(actions_mouse[where][button] == actions_available[where][i]) + { + psubmenu->entry_selected = pentry; + + menuentry_new(psubmenu, gettext("Current action is:"), 0, MENU_NOTE); + menuentry_new(psubmenu, gettext(actions_names[where][i]), 0, MENU_NOTE | MENU_RIGHT); + } + + i ++; + } + + menu_assignletters(psubmenu); + + subok = 0; + while(!subok) + { + result = menu_process(psubmenu); + + if(result == MENU_QUIT) + subok = 1; + + if(result == MENU_SELECT) + { + if(psubmenu->entry_selected->key == 'Q') + subok = 1; + else if(psubmenu->entry_selected->value != NULL) + { + actions_mouse[where][button] = actions_available[where][atoi(psubmenu->entry_selected->value)]; + menuentry_extratext(pmenu->entry_selected, gettext(actions_names[where][atoi(psubmenu->entry_selected->value)]), NULL, NULL); + subok = 1; + } + } + + } + menu_delete(psubmenu); + } + } + + } + + menu_delete(pmenu); +} + +void display_options_size() +{ + struct menu* pmenu; + struct menuentry* pentry; + struct graphicssize* psize; + char buffer[4096]; + + pmenu = menu_new(gettext("Graphics Size")); + + menuentry_new(pmenu, gettext("Quit and return to previous menu"), 'Q', 0); + menuentry_new(pmenu, "", 0, MENU_SPACE); + + menuentry_new(pmenu, gettext("Current graphics size:"), 0, MENU_NOTE); + if(pdisplaygraphics != NULL) + { + if(options_sdl_size_x != pdisplaygraphics->size_x || options_sdl_size_y != pdisplaygraphics->size_y) + sprintf(buffer, gettext("Automatic (%d x %d)"), pdisplaygraphics->size_x, pdisplaygraphics->size_y); + else + sprintf(buffer, "%d x %d", pdisplaygraphics->size_x, pdisplaygraphics->size_y); + menuentry_new(pmenu, buffer, 0, MENU_NOTE | MENU_RIGHT); + } + else + menuentry_new(pmenu, gettext("** NONE **"), 0, MENU_NOTE | MENU_RIGHT); + + pentry = menuentry_new(pmenu, gettext("Automatic sizing"), 0, 0); + menuentry_extratext(pentry, NULL, "0", "0"); + if(options_sdl_size_x != pdisplaygraphics->size_x || options_sdl_size_y != pdisplaygraphics->size_y) + pmenu->entry_selected = pentry; + + psize = pdisplaygraphics->sizes; + while(psize != NULL) + { + if(psize->flags & SIZE_PIECES) + { + sprintf(buffer, "%d x %d", psize->x, psize->y); + pentry = menuentry_new(pmenu, buffer, 0, 0); + if(psize->x == options_sdl_size_x && psize->y == options_sdl_size_y) + pmenu->entry_selected = pentry; + sprintf(buffer, "%d", psize->x); + sprintf(buffer + 16, "%d", psize->y); + menuentry_extratext(pentry, NULL, buffer, buffer + 16); + } + psize = psize->next; + } + menu_assignletters(pmenu); + + if(menu_process(pmenu) == MENU_SELECT) + { + if(pmenu->entry_selected->text3 != NULL) + { + options_sdl_size_x = atoi(pmenu->entry_selected->text3); + options_sdl_size_y = atoi(pmenu->entry_selected->text4); + + graphics_init(); + } + } + + menu_delete(pmenu); +} + +void display_options_debug() +{ + struct menu* pmenu; + struct menuentry* pentryorder; + struct menuentry* pentrymovers; + struct menuentry* pentryspeed; + struct menuentry* pentryhidden; + + int ok; + int result; + + pmenu = menu_new(gettext("Debug Options")); + + menuentry_new(pmenu, gettext("Return to previous menu"), 'Q', 0); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + + pentryorder = menuentry_new(pmenu, gettext("Display order of movers"), 'O', 0); + pentrymovers = menuentry_new(pmenu, gettext("List movers on stderr"), 'M', 0); + pentryspeed = menuentry_new(pmenu, gettext("Show frames per second"), 'F', 0); + pentryhidden = menuentry_new(pmenu, gettext("Show hidden items"), 'H', 0); + + ok = 0; + while(!ok) + { + menuentry_extratext(pentryorder, options_debug & DEBUG_ORDER ? gettext("yes") : gettext("no"), NULL, NULL); + menuentry_extratext(pentrymovers, options_debug & DEBUG_MOVERS ? gettext("yes") : gettext("no"), NULL, NULL); + menuentry_extratext(pentryspeed, options_debug & DEBUG_SPEED ? gettext("yes") : gettext("no"), NULL, NULL); + menuentry_extratext(pentryhidden, options_debug & DEBUG_HIDDEN ? gettext("yes") : gettext("no"), NULL, NULL); + + result = menu_process(pmenu); + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'Q': + ok = 1; + break; + + case 'O': + options_debug ^= DEBUG_ORDER; + break; + + case 'M': + options_debug ^= DEBUG_MOVERS; + break; + + case 'F': + options_debug ^= DEBUG_SPEED; + break; + + case 'H': + options_debug ^= DEBUG_HIDDEN; + break; + } + + pmenu->redraw = MENUREDRAW_CHANGED; + pmenu->entry_selected->redraw = 1; + } + + } + + menu_delete(pmenu); +} + +void display_options_othergames() +{ + struct menu* pmenu; +#ifdef XOR_COMPATIBILITY + struct menuentry* pentryxormode; + struct menuentry* pentryxordisplay; +#endif +#ifdef ENIGMA_COMPATIBILITY + struct menuentry* pentryenigmamode; +#endif + + int ok; + int result; + + pmenu = menu_new(gettext("Other Games Options")); + + menuentry_new(pmenu, gettext("Return to previous menu"), 'Q', 0); + + menuentry_new(pmenu, "", 0, MENU_SPACE); + +#ifdef XOR_COMPATIBILITY + pentryxormode = menuentry_new(pmenu, gettext("XOR Engine"), 'X', options_xor_options ? 0 : MENU_INVISIBLE | MENU_GREY); + pentryxordisplay = menuentry_new(pmenu, gettext("XOR Display"), 'D', options_xor_options ? 0 : MENU_INVISIBLE | MENU_GREY); + if(options_xor_options) + menuentry_new(pmenu, "", 0, MENU_SPACE); +#endif + +#ifdef ENIGMA_COMPATIBILITY + pentryenigmamode = menuentry_new(pmenu, gettext("Enigma Engine"), 'E', options_enigma_options ? 0 : MENU_INVISIBLE | MENU_GREY); +#endif + + ok = 0; + while(!ok) + { +#ifdef XOR_COMPATIBILITY + menuentry_extratext(pentryxormode, options_xor_mode ? gettext("exact") : gettext("approximate"), NULL, NULL); + menuentry_extratext(pentryxordisplay, options_xor_display ? gettext("partial") : gettext("full"), NULL, NULL); +#endif +#ifdef ENIGMA_COMPATIBILITY + menuentry_extratext(pentryenigmamode, options_enigma_mode ? gettext("exact") : gettext("approximate"), NULL, NULL); +#endif + + result = menu_process(pmenu); + if(result == MENU_QUIT) + ok = 1; + + if(result == MENU_SELECT && pmenu->entry_selected != NULL) + { + switch(pmenu->entry_selected->key) + { + case 'Q': + ok = 1; + break; + +#ifdef XOR_COMPATIBILITY + case 'X': + options_xor_mode = 1 - options_xor_mode; + break; + + case 'D': + options_xor_display = 1 - options_xor_display; + break; +#endif + +#ifdef ENIGMA_COMPATIBILITY + case 'E': + options_enigma_mode = 1 - options_enigma_mode; + break; +#endif + } + + pmenu->redraw = MENUREDRAW_CHANGED; + pmenu->entry_selected->redraw = 1; + } + + } + + menu_delete(pmenu); +} + +void display_options_save() +{ + FILE *file; + char filename[FILENAME_MAX]; + SDLKey key; + int i, j; + char *locations[] = {"game", "editor", "menu"}; + + getfilename("sdl.chroma", filename, 1, LOCATION_LOCAL); + + file = fopen(filename, "w"); + if(file == NULL) + { + warning("Unable to save options"); + return; + } + + fprintf(file, "\n" + "\n" + "\n"); + + fprintf(file, " \n", options_sdl_fullscreen == 1 ? "yes" : "no"); + + fprintf(file, " \n"); + else + fprintf(file, "width=\"%d\" height=\"%d\" />\n", options_sdl_size_x, options_sdl_size_y); + + fprintf(file, " \n", options_colours); + + fprintf(file, " \n", options_sdl_delay); + fprintf(file, " \n", options_sdl_player_delay); + fprintf(file, " \n", options_sdl_replay_delay); + fprintf(file, " \n", options_sdl_undo_delay); + +#ifdef XOR_COMPATIBILITY + if(options_xor_options) + fprintf(file, " \n", options_xor_mode ? "exact" : "approximate", options_xor_display ? "partial" : "full"); +#endif +#ifdef ENIGMA_COMPATIBILITY + if(options_enigma_options) + fprintf(file, " \n", options_enigma_mode ? "exact" : "approximate"); +#endif + + fprintf(file, " \n"); + fprintf(file, " \n"); + + fprintf(file, " \n"); + + for(key = SDLK_FIRST; key < SDLK_LAST; key ++) + { + if(actions[key] != ACTION_NONE) + fprintf(file, " \n", display_keyname(key), action_shortname[actions[key]]); + } + + fprintf(file, " \n"); + + for(i = 0; i < 3; i ++) + { + fprintf(file, " \n", locations[i]); + for(j = 1; j < MOUSE_BUTTONS_MAX; j ++) + { + fprintf(file, "