--- /dev/null
+
+Prerelease Version 0.9 [23 OCT 95]
+----------------------------------
+ - first (pre)release version
--- /dev/null
+This program is copyrighted (c) 1995 by Holger Schemel.
+
+It is freely distributable as long as no profit is made with it
+and as long as the package is left complete and unmodified.
+
+The fact that this program comes with full source does not mean
+that you can do what you want with it - it is only intended to
+give you the chance to build it on your own machine.
+
+If you want to distribute this program on CDROM, you have to ask for
+permission first -- just send me E-Mail and tell me what kind of
+CDROM it is. Normally I will give my permission if
+ - the CDROM itself contains only freely distributable software
+ - the author of this program (me!) gets a free copy of the CDROM
+ - the program is distributed in its original, unmodified package
+
+If the three conditions above are fulfilled, this permission will
+automatically given to the following CDROM distributions:
+ - InfoMagic "LINUX Developer's Resource"
+ - The Debian Linux Distribution CDROM
+ - any CDROM with a mirror of sunsite.unc.edu or a mirror of another
+ FTP server that contains this program
+
+If you are in doubt (e.g., want to distribute a pre-installed version),
+feel free to mail me about it (see the file 'README' in this archive).
--- /dev/null
+
+THIS GAME IS PROVIDED "AS IS" -- USE IT AT YOUR OWN RISK!
+IF THIS GAME BLOWS UP YOUR COMPUTER OR OPERATING SYSTEM
+OR ANYTHING ELSE, IT'S NOT MY FAULT! I'M NOT RESPONSIBLE
+FOR ANY DAMAGE THAT MIGHT BE CAUSED BY MY PROGRAM!
--- /dev/null
+
+WHAT TO DO TO INSTALL "ROCKS_N_DIAMONDS-0.9" ON YOUR SYSTEM
+===========================================================
+
+If you have a Linux system (Intel based, a.out, kernel 1.2.x), you
+can use the precompiled binary.
+
+If you have another Unix system, or an ELF system or just want to
+compile the program by yourself, do the following:
+
+Edit the file "Makefile" and set the following options:
+
+XPM_INCLUDE_FILE - change this to the location where you
+ have your XPM-Library include file.
+
+ You must have the XPM-Library "libXpm"
+ installed on your system to run this game.
+ If you don't have it, look at your local
+ FTP site with X11 archive to get it! :)
+
+GAME_DIR - You can leave these values untouched
+ if you use the default location for
+ the game directory.
+ If you want to move it to other places in
+ your directory tree, just change them
+ accordingly. (You can use symlinks instead,
+ of course.)
+ You might want to set GAME_DIR to the full
+ path of the game in your file system, so
+ you don't have to go to the game directory
+ when you want to play it.
+
+SOUNDS - If you never want to hear any sounds,
+ set this to "-DNO_SOUNDS", but be warned:
+ It's much less fun playing without sound! :)
+ (The program detects by itself if it can
+ play sounds or not, anyway.)
+
+SCORE_ENTRIES - Set this to "-DONE_PER_NAME" if you want
+ to allow only one entry per player in the
+ score file for each level. This is useful
+ if there are many players to prevent one
+ single player to "flood" the Hall Of Fame
+ of every level completely with his name...
+ On single user systems, "-DMANY_PER_NAME"
+ might be useful to have your name more
+ than once in the list.
+
+SYSTEM - If you have problems with the default
+ settings, it might be useful to uncomment
+ one of the defines for "SYSTEM" in the
+ Makefile, which defines values like
+ "-DSYSV" and something like that.
+
+CC, INCL, LIBS - Set these ones to the appropriate values
+ you usually use on your system to compile.
+
+
+Now you can 'make clean' and 'make' and the game binary should be
+compiled right out of the box. I have tested it with "-Wall" on my
+system, so I hope that it compiles fine on other systems, too.
+
+The program should compile and run on Linux (of course),
+HP-UX, AIX, Net-BSD, SUN and IRIX.
+
+Have fun!
+
+Holger Schemel, 22. Oktober 1995
--- /dev/null
+Welcome to
+
+ R O C K S ' N ' D I A M O N D S
+ -----------------------------------
+
+A game for Unix/X11 by Holger Schemel, (c) 1995 by Holger Schemel.
+
+Introduction
+============
+This is a nice little game with color graphics and sound for your
+Unix system with color X11. You need an 8-Bit color display or better.
+It is not recommended on black&white systems, and maybe not on gray
+scale systems.
+
+If you know the game "Boulderdash" (Commodore C64) or "Emerald Mine"
+(Amiga), you know what "ROCKS'N'DIAMONDS" is about.
+
+
+Getting started
+===============
+Just 'cd' to the 'rocks_n_diamonds' directory and type 'rocksndiamonds'!
+This works only on Linux boxes, because the included binary was
+compiled for Linux systems. If you have another Unix system like
+HPUX, NetBSD or SUN, you first have to type 'make' to compile it.
+This may be needed on Linux systems, too, if you have an older
+system (kernel, libraries, ...) or if you have only ELF libraries.
+
+(The included binary was compiled on the following system:
+Kernel 1.2.13, libc 4.5.26, GCC 2.5.8, 'a.out' format)
+
+The Menues
+==========
+You can see eight blue circles on the left side of the eight green menu
+texts; these are buttons to activate the menu commands by simply clicking
+on them with the left mouse button. The button will then change to red.
+(You can control the menues over the keyboard or joystick, too. Just use
+the arrow keys and the 'Return' or 'Enter' key or, if you use a joystick,
+the appropriate direction and the fire button.)
+
+The menu 'name'
+---------------
+When you start the game the first time, your login name will appear in
+the 'NAME:' field. If you want to use a different name for playing, for
+example a funny player name or a name for cheating, you can click on the
+button and enter a new name.
+
+If you choose a certain special name, you will be in a cheat mode where
+you can choose all levels without playing the lower levels before... :)
+
+The menue 'level'
+-----------------
+If you have played some levels of this game, you can choose the already
+played levels at any time, but you cannot choose the higher levels. This
+means, you can choose levels from level 0 to the highest level that you
+have ever won. This is known as your 'handicap'.
+
+If the level number is red, you have choosen a 'ready' level, if it is
+yellow, you have choosen a 'user' level, which is blank and can be
+edited by yourself with the built-in level editor (see below).
+
+To choose new level series, click on the button on the left and choose
+the new level serie.
+
+Hall of fame
+------------
+Click on this button to see a list of the best players of this level.
+Click again to go back to the main menu.
+
+Level creator
+-------------
+This brings you to the level editor, if you have switched to a 'yellow'
+level, which are empty and can be filled by yourself. See below.
+
+Info screen
+-----------
+This screen shows you all elements which appear in the game and presents
+you the background music loops which you can listen to while playing the
+levels (only available on Linux systems).
+
+Start game
+----------
+This will start the game.
+
+Setup
+-----
+To change some things in the game, use the setup menu.
+You can enable/disable "Sound" (enables/disables _all_ sounds in
+the game), "Sound loops" (only allowed on Linux systems with
+VoxWare[tm] sound driver; don't worry if you never heard of it --
+it's the name of the standard Linux sound driver), "Game music"
+(can always be enabled on very fast systems [exception: you don't
+like it], on slower systems it will take some percent of CPU time
+which will slow things down a bit) and "Toons", which will forbid/
+permit the little animated toons.
+
+"Buffered Gfx" can be set to "off" on slower systems, "Fading" gives
+a nice fading effect when displaying new screens, but unfortunately
+I haven't found a system which is fast enough to display it so far.
+(Maybe this works better on highly accelerated X servers.) Better set
+this to "off" if you have a normal system...
+
+Set "auto-record" to "on" if you want to automatically record each game
+to tape.
+
+If you have a Linux system with a joystick, you can choose the "1st" or
+the "2nd" joystick port and use "Cal. Joystick" to calibrate it. Use
+"Save and exit" after calibration to save it for later playing sessions.
+
+"Exit" quits the setup menu without saving the changes, "Save and exit"
+will save and then return to the main menu.
+
+Quit
+----
+Exit the game.
+
+
+How To Play The Game
+====================
+When the game has started, you can see the playfield on the left side
+and a control field on the right side. The control field contains the
+following elements:
+
+Level indicator Tells you which level you are playing.
+
+Emeralds Shows you how many emeralds you still need
+ to win the current level.
+
+Dynamite Shows you how many dynamite bombs you have.
+
+Keys Shows you which keys you have in your inventory.
+
+Score Shows the current score. In some levels there
+ are some extra items giving extra score points.
+
+Time The seconds you have still left to play the level.
+
+Stop/Pause/Play Game controls to stop the game, pause it and go on
+ playing. If the tape recorder is recording your
+ game, it is stopping/pausing/playing as well.
+
+Music buttons The three music buttons can be used to control the
+ background music loop, the 'looping' sounds and
+ all other sounds. The little red light shows you
+ if it is enabled or disabled. On slower systems
+ (and a 486DX33 with Soundblaster _is_ a slower
+ system) it increases the game speed to turn off
+ background music. You can completely turn off all
+ sound effects in the setup menu, although it is
+ much more fun to have them enabled when it
+ doesn't eats up to much speed.
+
+ (A little note: The sound server currently needs
+ about 10% CPU time on my 486DX/33/SBPro system
+ when playing background music. I wonder if this
+ would get better with a better soundcard, like
+ Gravis Ultrasound, or if only pure CPU power
+ helps in this case...)
+
+About the game itself: Of course you know Boulderdash, so you will know
+how to play the game. :)
+If not: You can move your playing figure (the smiley) with the arrow
+keys or with the joystick (if you have no joystick and even no arrow
+keys on your keyboard, you can use the keys 'i', 'j', 'k' and 'm' for
+the directions. To 'snap' a field near you without moving to it, you
+can use the left fire button on your joystick (hold it down, move the
+stick to 'snap' the field, release the button) or the keys 'e', 's',
+'d' and 'x'. To place a piece of dynamite, use the right fire button
+on your joystick or use the 'b' key (and, after placing the dynamite,
+better see to move away from this field...).
+
+Just try the levels from the 'tutorial' level serie to see what most
+of the elements do or have a look at the info screen!
+
+Note: It is *highly recommended* to use a joystick for playing this
+game! It is possible to play it with the keyboard, but it is *much
+more fun* to play with a joystick, and some levels are very difficult
+to solve with the keyboard. So, the best platform for this game is a
+Linux system (which gives you background music, too).
+
+The Level Editor
+================
+To build your own levels, just choose a 'yellow', empty level. If you
+cannot find any 'yellow' levels, choose a different level serie or
+choose the higher level numbers (if you have a small 'handicap' number,
+the higher levels will be skipped to reach the 'empty' levels.
+
+Another way is to create your own level series. Just add a line to the
+file 'levels/ROCKS.levelinfo' with the following entries:
+- the name of the level directory (create this directory under 'levels')
+- the name of the level serie (don't use any whitespaces within the name)
+- the 'ready' (red) levels (start with zero)
+- the 'empty' (yellow) levels (set this to some number of blank levels)
+
+To edit a level, you can use all three mouse buttons to draw in the
+level window. Click into the elements field with one of the three buttons
+to remap it to the new element. Use the arrow widgets to scroll around in
+the level. Use the 'flood fill' field to init exactly ony flood fill
+operation in the level field (you will be prompted). Click on 'control
+window' to switch to the control window.
+
+In the control window you can modify different parameters like the size
+of the level playfield, the name of the level, the scores for different
+elements and something like that. The four 3x3 field on the upper left
+can be edited like the level field and indicate the 'contents' of smashed
+crunchers (just try it out with some crunchers in one of your own levels).
+
+'Undo & Exit' leaves the level editor, throwing away all the changes you
+have done to the level.
+'Save & Exit' leveas the level editor and saves the new level (the old one
+will be deleted).
+
+
+The Tape Recorder
+=================
+You can use the tape recorder to record games and play tapes of previously
+played games. Just use them like a normal video recorder.
+
+Recording a game on tape:
+-------------------------
+Just press the 'record' button (the one with the red point on it) and
+either press 'Start Game' or press on 'record' or 'pause' to end the
+pause mode and start playing and recording.
+
+If you have set "auto record" in the setup menu to "on", you just have
+to press 'Start Game' as usual.
+
+Saving a game tape:
+-------------------
+To save a tape to the tape file corresponding to the level (that means
+that you can only save one tape file for each level), just press the
+'eject' button (the very left button). Then you will be prompted if
+you really want to replace the old tape (if an old tape exists).
+
+Playing a tape:
+---------------
+Just press 'play' and then either 'play' or 'pause'.
+
+While recording or playing, you can press 'pause' to stop the recording
+or the playing of the tape and continue by pressing 'pause' again.
+You can use either the tape recorder buttons or the game control buttons
+for this purpose.
+
+
+And Now Have Fun!
+=================
+Have fun playing the game, building new levels and breaking all high
+scores! ;)
+
+If you have any comments, problems, suggestions, donations, flames,
+send them to
+
+ aeglos@valinor.owl.de
+or aeglos@uni-paderborn.de
+
+or Snail Mail
+
+ Holger Schemel
+ Sennehof 28
+ 33659 Bielefeld
+ GERMANY
+
+Have fun,
+ Holger
--- /dev/null
+
+Some recommendations for more fun playing Rocks'n'Diamonds:
+===========================================================
+
+About sound
+-----------
+It is highly recommended to have a decent sound interface for playing
+this game (although it only comes with bad-quality 8000-Hz-samples to
+save memory and to be compatible with /dev/audio).
+
+The best sound platform is an actual Linux system with (at least) kernel
+1.2.x, because it offers some nice real-time sound features which are
+needed to have background music loops in the game.
+
+On all other systems you don't have music loops, but you still have all
+the other sounds.
+
+
+About game speed
+----------------
+You should have a relatively fast hardware.
+
+The game was developed on a i486/33 (which is three years old now),
+and you should probably better not try to run it on a slower system.
+
+You should have an accelerated graphic card; I have found out that it
+starts being playable on my 486/33 with an old ISA cirrus logic 5426
+graphic card, which has a blitter that is supported by XFree86[tm],
+but that it was nearly unplayable on a 486/66 with old, unaccelerated
+ET4000.
+
+If all works fine, you should have something around 30 frames per second.
+
+If you think that the game is to slow to play, you should try out the
+following things:
+
+- Set "Buffered Gfx" to "off" in the setup menu. Normally (on a fast
+ enough system) you should use buffered graphics, which means that
+ all graphics is drawn into an invisible Pixmap and is then copied
+ to the X11 window to avoid flickering. If you disable this double
+ buffering, the graphic is directly drawn into the window. This can
+ cause some slight flickering, but makes graphic operations roughly
+ twice as fast compared to double buffering.
+
+- Set "Game Music" to "off" in the setup menu (and maybe "sound loops"
+ too). Where disabling buffered graphics may be required with slow
+ graphics hardware, disabling sound is especially recommended on slow
+ CPU systems (486/33 and slower), because the sound server eats up a
+ significant amount of CPU time when playing long sounds.
+
+You might also notice that bigger levels tend to be slower on slow
+systems.
+
+About the option "Fading" in the setup menu: It gives a nice looking
+fading when switching to a new screen, but you should really only try
+this out if you think that you have a very fast graphics hardware.
+
+
+About music
+-----------
+The background music loops are ripped out from several nice music albums.
+Just have a look at the info screen to find out from which album each
+sound loop came from -- they are all very well done pieces of music, but
+unfortunately they don't sound better after converting them to 8 kHz
+samples (to conform to standard SUN /dev/audio). Maybe I change this to
+a better quality in the future, but at the moment, where the sounds
+directory has a size of nearly a megabyte, I'll stay with 8 kHz samples.
+
+So, if you have a non-Linux system (which cannot play sound loops) or
+don't like the "telephone quality" of the music loops, just get some of
+these CDs and play them while your playing the game! ;-)
+
+
+About game-play
+---------------
+It is *strongly recommended* to play this game with a high-quality joystick.
+That means, throw your $10 joystick out of the window and buy a decent
+Competition-Pro Digital PC joystick or a high-quality CH Products Analog
+joystick. Believe me, it doubles the fun of playing the game.
+
+If you only have a normal Unix system (and no fine Linux system), you
+are forced to play with the keyboard. It works, but is not only less fun,
+but also more difficult with some levels, because you cannot move in
+diagonal directions with keyboard control at the moment. Another bad thing
+is that you will have some problems when pressing many keys at the same
+time. This might change in the future, when I implement a better keyboard
+handling which not only solves these problems but allows diagonal directions,
+too.
+
--- /dev/null
+
+How to (and why) become a registered user of Rocks'n'Diamonds
+=============================================================
+
+It was much fun writing this game, and I hope that it is much fun playing
+it, too.
+
+Writing it was much work, too, and if you like this game, please think about
+becoming a registered user. Registered users will get a keyfile which allows
+them to use registered-users-only level series, starting with 50 new levels
+when version 1.0 come out (around December '95 or January '96). If you own
+the Amiga game "Emerald Mine", you can use its levels with the registered
+version of Rocks'n'Diamonds, too.
+
+There are some other plans for future versions of Rocks'n'Diamonds which
+will be only available for registered users, like support for more than
+one player on one machine, multi-player support for games over a network
+or Dyna-Blaster like levels (especially for multi player modes).
+
+If you want to become a registered user, send $20 or DM 20 to the
+following Snail-Mail address:
+
+ Holger Schemel
+ Sennehof 28
+ 33659 Bielefeld
+ GERMANY
+
+... and send the filled-out registration form (at the end of this file)
+to the following E-Mail address:
+
+ aeglos@valinor.owl.de
+
+If you live outside Europe, you can use an international money order
+or just send a banknote, if you live in Europe, you can send an Euro-
+Cheque or remit the registration fee directly to my bank account in
+Germany (please write a short e-mail note and I'll send you the bank
+account information).
+
+You will then get a patch to change the program to a registered version
+(together with each main release version, if needed), a keyfile to use
+the registered-users-only level series and a little program to convert
+old "Emerald Mine" levels to Rocks'n'Diamonds levels.
+
+---------- 8< ---------- cut here ---------- 8< ----------
+
+Name:
+----------------------------------------------------------
+Street:
+----------------------------------------------------------
+City:
+----------------------------------------------------------
+Country:
+----------------------------------------------------------
+E-Mail:
+----------------------------------------------------------
+Username:
+----------------------------------------------------------
+
+(All informations will only be used to create a personalized
+keyfile. The game will work for the user in "Username", the
+fields "Name" to "Country" will appear in the info screen
+and your e-mail address will be used to inform you of new
+main release versions of Rocks'n'Diamonds.)
+
+---------- 8< ---------- cut here ---------- 8< ----------
--- /dev/null
+#
+# Makefile fuer "Rocks'n'Diamonds -- McDuffin Strikes Back"
+#
+
+PROGNAME = rocksndiamonds
+
+RM = rm -f
+CC = gcc
+# CC = cc # for HP-UX and others
+
+GAME_DIR = -DGAME_DIR=\".\" # path of the game and its data
+# JOYSTICK = -DNO_JOYSTICK # no joystick
+# SOUNDS = -DNO_SOUNDS # no sounds
+# SCORE_ENTRIES = -DONE_PER_NAME # only one score entry per name
+SCORE_ENTRIES = -DMANY_PER_NAME # many score entries per name
+
+# the XPM-Library is needed to build this program:
+XPM_INCLUDE_FILE = -DXPM_INCLUDE_FILE="<X11/xpm.h>"
+
+CONFIG = $(GAME_DIR) $(SOUNDS) $(JOYSTICK) \
+ $(SCORE_ENTRIES) $(XPM_INCLUDE_FILE)
+
+# DEBUG = -DDEBUG -g -ansi -pedantic -Wall
+# DEBUG = -DDEBUG -g -Wall
+DEBUG = -O6
+
+# SYSTEM = -Aa -D_HPUX_SOURCE -Dhpux # for HP-UX (obsolete)
+# SYSTEM = -DSYSV -Ae # for HP-UX
+# SYSTEM = -DSYSV # for systems without 'usleep()'
+# INCL = -I/usr/include/X11R5 # for HP-UX and others
+# LIBS = -lXpm -lX11 -lm
+# LIBS = -L/usr/lib/X11R5 -lXpm -lX11 -lm # for HP-UX and others
+LIBS = -lXpm -lXpm -lXpm -lX11 -lm # triple -lXpm; else I got an error...
+
+# CFLAGS = -O2 $(CONFIG) $(SYSTEM)
+CFLAGS = $(DEBUG) $(CONFIG) $(SYSTEM) $(INCL)
+
+OBJS = main.o \
+ init.o \
+ images.o \
+ events.o \
+ tools.o \
+ screens.o \
+ misc.o \
+ game.o \
+ editor.o \
+ sound.o
+
+all: $(OBJS)
+ $(CC) $(CFLAGS) $(OBJS) $(LIBS) -o $(PROGNAME)
+
+.c.o:
+ $(CC) $(CFLAGS) -c $*.c
+
+clean:
+ $(RM) $(OBJS)
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* editor.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#include "editor.h"
+#include "screens.h"
+#include "game.h"
+#include "tools.h"
+#include "misc.h"
+
+static int level_xpos,level_ypos;
+static BOOL edit_mode;
+static BOOL name_typing;
+static int element_shift;
+static int new_element1 = EL_MAUERWERK;
+static int new_element2 = EL_LEERRAUM;
+static int new_element3 = EL_ERDREICH;
+static int editor_element[] =
+{
+ EL_SPIELFIGUR,
+ EL_LEERRAUM,
+ EL_ERDREICH,
+ EL_FELSBROCKEN,
+
+ EL_BETON,
+ EL_MAUERWERK,
+ EL_FELSBODEN,
+ EL_SIEB_LEER,
+
+ EL_EDELSTEIN,
+ EL_DIAMANT,
+ EL_KOKOSNUSS,
+ EL_BOMBE,
+
+ EL_MORAST_LEER,
+ EL_MORAST_VOLL,
+ EL_AUSGANG_ZU,
+ EL_AUSGANG_AUF,
+
+ EL_KAEFER,
+ EL_FLIEGER,
+ EL_MAMPFER,
+ EL_ZOMBIE,
+
+ EL_PACMAN,
+ EL_DYNAMIT_AUS,
+ EL_DYNAMIT,
+ EL_ABLENK_AUS,
+
+ EL_BADEWANNE1,
+ EL_SALZSAEURE,
+ EL_BADEWANNE2,
+ EL_BADEWANNE,
+
+ EL_BADEWANNE3,
+ EL_BADEWANNE4,
+ EL_BADEWANNE5,
+ EL_UNSICHTBAR,
+
+ EL_TROPFEN,
+ EL_AMOEBE1,
+ EL_AMOEBE2,
+ EL_AMOEBE3,
+
+ EL_LIFE,
+ EL_LIFE_ASYNC,
+
+ EL_ERZ_1,
+ EL_ERZ_2,
+
+/*
+ EL_BIRNE_AUS,
+ EL_BIRNE_EIN,
+*/
+
+ EL_SCHLUESSEL1,
+ EL_SCHLUESSEL2,
+ EL_SCHLUESSEL3,
+ EL_SCHLUESSEL4,
+
+ EL_PFORTE1,
+ EL_PFORTE2,
+ EL_PFORTE3,
+ EL_PFORTE4,
+
+ EL_PFORTE1X,
+ EL_PFORTE2X,
+ EL_PFORTE3X,
+ EL_PFORTE4X,
+
+ EL_KAEFER_R,
+ EL_KAEFER_O,
+ EL_KAEFER_L,
+ EL_KAEFER_U,
+
+ EL_FLIEGER_R,
+ EL_FLIEGER_O,
+ EL_FLIEGER_L,
+ EL_FLIEGER_U,
+
+ EL_PACMAN_R,
+ EL_PACMAN_O,
+ EL_PACMAN_L,
+ EL_PACMAN_U,
+
+ EL_CHAR_AUSRUF,
+ EL_CHAR_ZOLL,
+ EL_CHAR_DOLLAR,
+ EL_CHAR_PROZ,
+
+ EL_CHAR_APOSTR,
+ EL_CHAR_KLAMM1,
+ EL_CHAR_KLAMM2,
+ EL_CHAR_PLUS,
+
+ EL_CHAR_KOMMA,
+ EL_CHAR_MINUS,
+ EL_CHAR_PUNKT,
+ EL_CHAR_SLASH,
+
+ EL_CHAR_0 + 0,
+ EL_CHAR_0 + 1,
+ EL_CHAR_0 + 2,
+ EL_CHAR_0 + 3,
+
+ EL_CHAR_0 + 4,
+ EL_CHAR_0 + 5,
+ EL_CHAR_0 + 6,
+ EL_CHAR_0 + 7,
+
+ EL_CHAR_0 + 8,
+ EL_CHAR_0 + 9,
+ EL_CHAR_DOPPEL,
+ EL_CHAR_SEMIKL,
+
+ EL_CHAR_LT,
+ EL_CHAR_GLEICH,
+ EL_CHAR_GT,
+ EL_CHAR_FRAGE,
+
+ EL_CHAR_AT,
+ EL_CHAR_A + 0,
+ EL_CHAR_A + 1,
+ EL_CHAR_A + 2,
+
+ EL_CHAR_A + 3,
+ EL_CHAR_A + 4,
+ EL_CHAR_A + 5,
+ EL_CHAR_A + 6,
+
+ EL_CHAR_A + 7,
+ EL_CHAR_A + 8,
+ EL_CHAR_A + 9,
+ EL_CHAR_A + 10,
+
+ EL_CHAR_A + 11,
+ EL_CHAR_A + 12,
+ EL_CHAR_A + 13,
+ EL_CHAR_A + 14,
+
+ EL_CHAR_A + 15,
+ EL_CHAR_A + 16,
+ EL_CHAR_A + 17,
+ EL_CHAR_A + 18,
+
+ EL_CHAR_A + 19,
+ EL_CHAR_A + 20,
+ EL_CHAR_A + 21,
+ EL_CHAR_A + 22,
+
+ EL_CHAR_A + 23,
+ EL_CHAR_A + 24,
+ EL_CHAR_A + 25,
+ EL_CHAR_AE,
+
+ EL_CHAR_OE,
+ EL_CHAR_UE,
+ EL_CHAR_COPY
+};
+static int elements_in_list = sizeof(editor_element)/sizeof(int);
+
+void DrawLevelEd()
+{
+ int i, graphic;
+
+ level_xpos=-1;
+ level_ypos=-1;
+ edit_mode = TRUE;
+ name_typing = FALSE;
+ element_shift = 0;
+
+ CloseDoor(DOOR_CLOSE_2);
+
+ DrawMiniLevel(level_xpos,level_ypos);
+ FadeToFront();
+
+ XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY1,
+ DXSIZE,DYSIZE,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
+ XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX6+ED_BUTTON_ELEM_XPOS,
+ DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS,
+ 4*ED_BUTTON_ELEM_XSIZE,5*ED_BUTTON_ELEM_YSIZE,
+ DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS,
+ DOOR_GFX_PAGEY1+ED_BUTTON_EUP_Y2POS);
+
+ for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
+ {
+ if (i < elements_in_list)
+ graphic = el2gfx(editor_element[i]);
+ else
+ graphic = GFX_LEERRAUM;
+
+ DrawMiniGraphicExtHiRes(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1+ED_BUTTON_ELEM_XPOS+3 +
+ (i%MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
+ DOOR_GFX_PAGEY1+ED_BUTTON_ELEM_YPOS+3 +
+ (i/MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
+ graphic);
+ }
+
+ DrawMiniGraphicExtHiRes(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1+ED_WIN_MB_LEFT_XPOS,
+ DOOR_GFX_PAGEY1+ED_WIN_MB_LEFT_YPOS,
+ el2gfx(new_element1));
+ DrawMiniGraphicExtHiRes(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1+ED_WIN_MB_MIDDLE_XPOS,
+ DOOR_GFX_PAGEY1+ED_WIN_MB_MIDDLE_YPOS,
+ el2gfx(new_element2));
+ DrawMiniGraphicExtHiRes(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1+ED_WIN_MB_RIGHT_XPOS,
+ DOOR_GFX_PAGEY1+ED_WIN_MB_RIGHT_YPOS,
+ el2gfx(new_element3));
+ DrawTextExt(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS,
+ DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
+ int2str(level_nr,2),FS_SMALL,FC_SPECIAL1);
+ XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+3,
+ DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
+ 7,FONT3_YSIZE,
+ DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS,
+ DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
+ XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX2+ED_WIN_LEVELNR_XPOS+14,
+ DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS,
+ 7,FONT3_YSIZE,
+ DOOR_GFX_PAGEX1+ED_WIN_LEVELNR_XPOS+9,
+ DOOR_GFX_PAGEY1+ED_WIN_LEVELNR_YPOS);
+
+ XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
+ VXSIZE,VYSIZE,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
+
+ OpenDoor(DOOR_OPEN_1 | DOOR_OPEN_2);
+}
+
+void DrawControlWindow()
+{
+ int i,x,y;
+
+ ClearWindow();
+
+ DrawText(ED_COUNT_GADGET_XPOS+1,SY+6,
+ "Contents of a smashed cruncher:",FS_SMALL,FC_YELLOW);
+ for(i=0;i<4;i++) for(y=0;y<4;y++) for(x=0;x<4;x++)
+ {
+ DrawMiniElement(1+5*i+x,2+y,EL_ERDREICH);
+ XFillRectangle(display,drawto,gc,
+ SX+(2+5*i)*MINI_TILEX-MINI_TILEX/2-1,
+ SY+(3)*MINI_TILEY-MINI_TILEY/2-1,
+ 3*MINI_TILEX+2,3*MINI_TILEY+2);
+ }
+ XCopyArea(display,drawto,drawto,gc,
+ SX+MINI_TILEX,SY+2*MINI_TILEY,
+ 4*5*MINI_TILEX,5*MINI_TILEY,
+ SX+MINI_TILEX-MINI_TILEX/2,SY+2*MINI_TILEY-MINI_TILEY/2);
+ for(i=0;i<4;i++)
+ {
+ for(y=0;y<3;y++) for(x=0;x<3;x++)
+ DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
+
+ DrawText(SX+MINI_TILEX+(5*i+1)*MINI_TILEX+1,
+ SY+2*MINI_TILEY+(4)*MINI_TILEY-4,
+ int2str(i+1,1),FS_SMALL,FC_YELLOW);
+ }
+
+ for(i=0;i<11+3+2;i++)
+ {
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
+ DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
+ DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
+ ED_COUNT_GADGET_XPOS,
+ ED_COUNT_GADGET_YPOS+i*ED_COUNT_GADGET_YSIZE);
+
+ if (i<11)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+i*ED_COUNT_GADGET_YSIZE,
+ int2str(level.score[i],3),FS_SMALL,FC_YELLOW);
+ else if (i==11)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
+ int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
+ else if (i==12)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
+ int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
+ else if (i==13)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
+ int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
+ else if (i==14)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
+ int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
+ else if (i==15)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
+ int2str(level.time,3),FS_SMALL,FC_YELLOW);
+ }
+
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+0*ED_COUNT_TEXT_YSIZE,
+ "Score for Emerald",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+1*ED_COUNT_TEXT_YSIZE,
+ "Score for Diamond",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+2*ED_COUNT_TEXT_YSIZE,
+ "Score for smashing a Bug",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+3*ED_COUNT_TEXT_YSIZE,
+ "Score for smashing a Spaceship",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+4*ED_COUNT_TEXT_YSIZE,
+ "Score for smashing a Cruncher",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+5*ED_COUNT_TEXT_YSIZE,
+ "Score for smashing an Alien",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+6*ED_COUNT_TEXT_YSIZE,
+ "Score for smashing a Pacman",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+7*ED_COUNT_TEXT_YSIZE,
+ "Score for cracking a nut",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+8*ED_COUNT_TEXT_YSIZE,
+ "Score for dynamite",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+9*ED_COUNT_TEXT_YSIZE,
+ "Score for key",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+10*ED_COUNT_TEXT_YSIZE,
+ "Score for each 10 seconds left",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+11*ED_COUNT_TEXT_YSIZE,
+ "Speed of the amoeba",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+12*ED_COUNT_TEXT_YSIZE,
+ "Time for magic wall",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+13*ED_COUNT_TEXT_YSIZE,
+ "Time for wheel",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+14*ED_COUNT_TEXT_YSIZE,
+ "Emeralds needed in this level",FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_TEXT_XPOS,ED_COUNT_TEXT_YPOS+15*ED_COUNT_TEXT_YSIZE,
+ "Time available for this level",FS_SMALL,FC_YELLOW);
+
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS,
+ DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
+ ED_WIN_COUNT_XSIZE,ED_WIN_COUNT_YSIZE,
+ ED_COUNT_GADGET_XPOS,
+ ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
+ for(i=1;i<31;i++)
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ DOOR_GFX_PAGEX4+ED_WIN_COUNT_XPOS+3+2*FONT2_XSIZE,
+ DOOR_GFX_PAGEY1+ED_WIN_COUNT_YPOS,
+ ED_WIN_COUNT_XSIZE-3-2*FONT2_XSIZE,ED_WIN_COUNT_YSIZE,
+ ED_COUNT_GADGET_XPOS+3+i*FONT2_XSIZE,
+ ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE);
+ DrawText(ED_COUNT_GADGET_XPOS+5,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ level.name,FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_GADGET_XPOS+(30+3)*FONT2_XSIZE-5,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ "Title",FS_SMALL,FC_YELLOW);
+
+ DrawText(ED_SIZE_GADGET_XPOS,ED_SIZE_GADGET_YPOS-18,
+ "Playfield size:",FS_SMALL,FC_YELLOW);
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
+ DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
+ DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
+ ED_SIZE_GADGET_XPOS,
+ ED_SIZE_GADGET_YPOS+0*ED_COUNT_GADGET_YSIZE);
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ DOOR_GFX_PAGEX4+ED_BUTTON_MINUS_XPOS,
+ DOOR_GFX_PAGEY1+ED_BUTTON_MINUS_YPOS,
+ DXSIZE-4,ED_BUTTON_MINUS_YSIZE,
+ ED_SIZE_GADGET_XPOS,
+ ED_SIZE_GADGET_YPOS+1*ED_COUNT_GADGET_YSIZE);
+ DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+0*ED_SIZE_TEXT_YSIZE,
+ "Width",FS_SMALL,FC_YELLOW);
+ DrawText(ED_SIZE_TEXT_XPOS,ED_SIZE_TEXT_YPOS+1*ED_SIZE_TEXT_YSIZE,
+ "Height",FS_SMALL,FC_YELLOW);
+ DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
+ int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
+ DrawText(ED_SIZE_VALUE_XPOS,ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
+ int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
+}
+
+void ScrollMiniLevel(int from_x, int from_y, int scroll)
+{
+ int x,y;
+ int dx = (scroll==ED_SCROLL_LEFT ? -1 : scroll==ED_SCROLL_RIGHT ? 1 : 0);
+ int dy = (scroll==ED_SCROLL_UP ? -1 : scroll==ED_SCROLL_DOWN ? 1 : 0);
+
+ XCopyArea(display,drawto,drawto,gc,
+ SX+MINI_TILEX*(dx==-1),SY+MINI_TILEY*(dy==-1),
+ SXSIZE-MINI_TILEX*ABS(dx),SYSIZE-MINI_TILEY*ABS(dy),
+ SX+MINI_TILEX*(dx==+1),SY+MINI_TILEY*(dy==+1));
+ if (dx)
+ {
+ x = (dx==1 ? 0 : 2*SCR_FIELDX-1);
+ for(y=0;y<2*SCR_FIELDY;y++)
+ DrawMiniElementOrWall(x,y,from_x,from_y);
+ }
+ else if (dy)
+ {
+ y = (dy==1 ? 0 : 2*SCR_FIELDY-1);
+ for(x=0;x<2*SCR_FIELDX;x++)
+ DrawMiniElementOrWall(x,y,from_x,from_y);
+ }
+
+ redraw_mask |= REDRAW_FIELD;
+ BackToFront();
+}
+
+void AdjustLevelScrollPosition()
+{
+ if (level_xpos<-1)
+ level_xpos = -1;
+ if (level_xpos>lev_fieldx-2*SCR_FIELDX+1)
+ level_xpos = lev_fieldx-2*SCR_FIELDX+1;
+ if (lev_fieldx<2*SCR_FIELDX-2)
+ level_xpos = -1;
+
+ if (level_ypos<-1)
+ level_ypos = -1;
+ if (level_ypos>lev_fieldy-2*SCR_FIELDY+1)
+ level_ypos = lev_fieldy-2*SCR_FIELDY+1;
+ if (lev_fieldy<2*SCR_FIELDY-2)
+ level_ypos = -1;
+}
+
+void FloodFill(int from_x, int from_y, int fill_element)
+{
+ int i,x,y;
+ int old_element;
+ static int check[4][2] = { -1,0, 0,-1, 1,0, 0,1 };
+ static int safety = 0;
+
+ safety++;
+
+ if (safety>lev_fieldx*lev_fieldy)
+ {
+ fprintf(stderr,"Something went wrong in 'FloodFill()'. Please debug.\n");
+ exit(-1);
+ }
+
+ old_element = Feld[from_x][from_y];
+ Feld[from_x][from_y] = fill_element;
+
+ for(i=0;i<4;i++)
+ {
+ x = from_x+check[i][0];
+ y = from_y+check[i][1];
+
+ if (IN_LEV_FIELD(x,y) && Feld[x][y]==old_element)
+ FloodFill(x,y,fill_element);
+ }
+
+ safety--;
+}
+
+void LevelEd(int mx, int my, int button)
+{
+ static int last_button = 0;
+ static int in_field_pressed = FALSE;
+ static BOOL use_floodfill = FALSE;
+ int x = (mx-SX)/MINI_TILEX;
+ int y = (my-SY)/MINI_TILEY;
+
+ if (use_floodfill) /********** FLOOD FILL **********/
+ {
+ if (button)
+ {
+ if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
+ {
+ int from_x, from_y;
+ int fill_element;
+
+ if (x>lev_fieldx || y>lev_fieldy ||
+ (x==0 && level_xpos<0) ||
+ (x==2*SCR_FIELDX-1 && level_xpos>lev_fieldx-2*SCR_FIELDX) ||
+ (y==0 && level_ypos<0) ||
+ (y==2*SCR_FIELDY-1 && level_ypos>lev_fieldy-2*SCR_FIELDY))
+ return;
+
+ from_x = x+level_xpos;
+ from_y = y+level_ypos;
+ fill_element = (button==1 ? new_element1 :
+ button==2 ? new_element2 :
+ button==3 ? new_element3 : 0);
+
+ FloodFill(from_x,from_y,fill_element);
+ DrawMiniLevel(level_xpos,level_ypos);
+ }
+
+ use_floodfill = FALSE;
+ CloseDoor(DOOR_CLOSE_1);
+ OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+ }
+ return;
+ }
+ else /********** EDIT/CTRL-FENSTER **********/
+ {
+ int choice = CheckElemButtons(mx,my,button);
+ int elem_pos = choice-ED_BUTTON_ELEM;
+
+ switch(choice)
+ {
+ case ED_BUTTON_EUP:
+ case ED_BUTTON_EDOWN:
+ if ((choice==ED_BUTTON_EUP && element_shift>0) ||
+ (choice==ED_BUTTON_EDOWN &&
+ element_shift<elements_in_list-MAX_ELEM_X*MAX_ELEM_Y))
+ {
+ int i, step;
+
+ step = (button==1 ? MAX_ELEM_X : button==2 ? 5*MAX_ELEM_X :
+ elements_in_list);
+ element_shift += (choice==ED_BUTTON_EUP ? -step : step);
+ if (element_shift<0)
+ element_shift = 0;
+ if (element_shift>elements_in_list-MAX_ELEM_X*MAX_ELEM_Y)
+ element_shift = elements_in_list-MAX_ELEM_X*MAX_ELEM_Y;
+ if (element_shift % MAX_ELEM_X)
+ element_shift += MAX_ELEM_X-(element_shift % MAX_ELEM_X);
+
+ for(i=0;i<MAX_ELEM_X*MAX_ELEM_Y;i++)
+ DrawElemButton(i+2,ED_BUTTON_RELEASED);
+ BackToFront();
+ Delay(100000);
+ }
+ break;
+ default:
+ if (elem_pos>=0 && elem_pos<MAX_ELEM_X*MAX_ELEM_Y)
+ {
+ int new_element;
+
+ if (elem_pos+element_shift < elements_in_list)
+ new_element = editor_element[elem_pos+element_shift];
+ else
+ new_element = EL_LEERRAUM;
+
+ if (last_button==1)
+ new_element1 = new_element;
+ else if (last_button==2)
+ new_element2 = new_element;
+ else if (last_button==3)
+ new_element3 = new_element;
+
+ DrawMiniGraphicExtHiRes(drawto,gc,
+ DX+ED_WIN_MB_LEFT_XPOS,
+ DY+ED_WIN_MB_LEFT_YPOS,
+ el2gfx(new_element1));
+ DrawMiniGraphicExtHiRes(drawto,gc,
+ DX+ED_WIN_MB_MIDDLE_XPOS,
+ DY+ED_WIN_MB_MIDDLE_YPOS,
+ el2gfx(new_element2));
+ DrawMiniGraphicExtHiRes(drawto,gc,
+ DX+ED_WIN_MB_RIGHT_XPOS,
+ DY+ED_WIN_MB_RIGHT_YPOS,
+ el2gfx(new_element3));
+ redraw_mask |= REDRAW_DOOR_1;
+ }
+ break;
+ }
+
+ if (edit_mode) /********** EDIT-FENSTER **********/
+ {
+ switch(CheckEditButtons(mx,my,button))
+ {
+ case ED_BUTTON_CTRL:
+ CloseDoor(DOOR_CLOSE_2);
+ DrawControlWindow();
+ XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX4,DOOR_GFX_PAGEY1+80,
+ VXSIZE,VYSIZE,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
+ OpenDoor(DOOR_OPEN_2);
+ edit_mode = FALSE;
+ break;
+ case ED_BUTTON_FILL:
+ AreYouSure("Caution ! Flood fill mode ! Choose area !",AYS_OPEN);
+ use_floodfill = TRUE;
+ return;
+ break;
+ case ED_BUTTON_LEFT:
+ if (level_xpos>=0)
+ {
+ if (lev_fieldx<2*SCR_FIELDX-2)
+ break;
+
+ level_xpos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
+ if (level_xpos<-1)
+ level_xpos = -1;
+ if (button==1)
+ ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_RIGHT);
+ else
+ DrawMiniLevel(level_xpos,level_ypos);
+ BackToFront();
+ Delay(100000);
+ }
+ break;
+ case ED_BUTTON_RIGHT:
+ if (level_xpos<=lev_fieldx-2*SCR_FIELDX)
+ {
+ if (lev_fieldx<2*SCR_FIELDX-2)
+ break;
+
+ level_xpos += (button==1 ? 1 : button==2 ? 5 : lev_fieldx);
+ if (level_xpos>lev_fieldx-2*SCR_FIELDX+1)
+ level_xpos = lev_fieldx-2*SCR_FIELDX+1;
+ if (button==1)
+ ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_LEFT);
+ else
+ DrawMiniLevel(level_xpos,level_ypos);
+ BackToFront();
+ Delay(100000);
+ }
+ break;
+ case ED_BUTTON_UP:
+ if (level_ypos>=0)
+ {
+ if (lev_fieldy<2*SCR_FIELDY-2)
+ break;
+
+ level_ypos -= (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
+ if (level_ypos<-1)
+ level_ypos = -1;
+ if (button==1)
+ ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_DOWN);
+ else
+ DrawMiniLevel(level_xpos,level_ypos);
+ BackToFront();
+ Delay(100000);
+ }
+ break;
+ case ED_BUTTON_DOWN:
+ if (level_ypos<=lev_fieldy-2*SCR_FIELDY)
+ {
+ if (lev_fieldy<2*SCR_FIELDY-2)
+ break;
+
+ level_ypos += (button==1 ? 1 : button==2 ? 5 : lev_fieldy);
+ if (level_ypos>lev_fieldy-2*SCR_FIELDY+1)
+ level_ypos = lev_fieldy-2*SCR_FIELDY+1;
+ if (button==1)
+ ScrollMiniLevel(level_xpos,level_ypos,ED_SCROLL_UP);
+ else
+ DrawMiniLevel(level_xpos,level_ypos);
+ BackToFront();
+ Delay(100000);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (mx>=SX && mx<SX+SXSIZE && my>=SY && my<SY+SYSIZE)
+ {
+ int new_element;
+
+ if (button && !motion_status)
+ in_field_pressed = TRUE;
+
+ if (!button || !in_field_pressed || button<1 || button>3 ||
+ (y==0 && level_ypos<0) ||
+ (y==2*SCR_FIELDY-1 && level_ypos>lev_fieldy-2*SCR_FIELDY) ||
+ (x==0 && level_xpos<0) ||
+ (x==2*SCR_FIELDX-1 && level_xpos>lev_fieldx-2*SCR_FIELDX) ||
+ x>lev_fieldx || y>lev_fieldy)
+ return;
+
+ new_element = (button==1 ? new_element1 :
+ button==2 ? new_element2 :
+ button==3 ? new_element3 : 0);
+
+ if (new_element != Feld[x+level_xpos][y+level_ypos])
+ {
+ if (new_element==EL_SPIELFIGUR) /* Jeder nur EINE Figur bitte... */
+ {
+ int x,y;
+
+ for(x=0;x<lev_fieldx;x++) for(y=0;y<lev_fieldy;y++)
+ {
+ if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
+ {
+ Feld[x][y] = EL_LEERRAUM;
+ if (x-level_xpos>=0 && x-level_xpos<2*SCR_FIELDX &&
+ y-level_ypos>=0 && y-level_ypos<2*SCR_FIELDY)
+ DrawMiniElement(x-level_xpos,y-level_ypos,EL_LEERRAUM);
+ }
+ }
+ }
+
+ Feld[x+level_xpos][y+level_ypos] = new_element;
+ DrawMiniElement(x,y,new_element);
+ }
+ }
+ else if (!motion_status) /* Mauszeiger nicht im Level-Feld */
+ in_field_pressed = FALSE;
+ }
+ else /********** KONTROLL-FENSTER **********/
+ {
+ static long choice_delay = 0;
+ int choice = CheckCountButtons(mx,my,button);
+ int step = (button==1 ? 1 : button==2 ? 5 : button==3 ? 10 : 0);
+
+ if (choice>=0 && choice<36 && DelayReached(&choice_delay,10))
+ {
+ if (!(choice % 2))
+ step = -step;
+
+ choice /= 2;
+
+ if (choice<11)
+ {
+ level.score[choice] += step;
+ if (level.score[choice]<0)
+ level.score[choice] = 0;
+ else if (level.score[choice]>255)
+ level.score[choice] = 255;
+ }
+ else if (choice==11)
+ {
+ level.tempo_amoebe += step;
+ if (level.tempo_amoebe<0)
+ level.tempo_amoebe = 0;
+ else if (level.tempo_amoebe>255)
+ level.tempo_amoebe = 255;
+ }
+ else if (choice==12)
+ {
+ level.dauer_sieb += step;
+ if (level.dauer_sieb<0)
+ level.dauer_sieb = 0;
+ else if (level.dauer_sieb>255)
+ level.dauer_sieb = 255;
+ }
+ else if (choice==13)
+ {
+ level.dauer_ablenk += step;
+ if (level.dauer_ablenk<0)
+ level.dauer_ablenk = 0;
+ else if (level.dauer_ablenk>255)
+ level.dauer_ablenk = 255;
+ }
+ else if (choice==14)
+ {
+ level.edelsteine += step;
+ if (level.edelsteine<0)
+ level.edelsteine = 0;
+ else if (level.edelsteine>999)
+ level.edelsteine = 999;
+ }
+ else if (choice==15)
+ {
+ level.time += step;
+ if (level.time<0)
+ level.time = 0;
+ else if (level.time>999)
+ level.time = 999;
+ }
+ else if (choice==16)
+ {
+ lev_fieldx += step;
+ if (lev_fieldx<MIN_LEV_FIELDX)
+ lev_fieldx = MIN_LEV_FIELDX;
+ else if (lev_fieldx>MAX_LEV_FIELDX)
+ lev_fieldx = MAX_LEV_FIELDX;
+ level.fieldx = lev_fieldx;
+ }
+ else if (choice==17)
+ {
+ lev_fieldy += step;
+ if (lev_fieldy<MIN_LEV_FIELDY)
+ lev_fieldy = MIN_LEV_FIELDY;
+ else if (lev_fieldy>MAX_LEV_FIELDY)
+ lev_fieldy = MAX_LEV_FIELDY;
+ level.fieldy = lev_fieldy;
+ }
+
+ if (choice<11)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
+ int2str(level.score[choice],3),FS_SMALL,FC_YELLOW);
+ else if (choice==11)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+11*ED_COUNT_GADGET_YSIZE,
+ int2str(level.tempo_amoebe,3),FS_SMALL,FC_YELLOW);
+ else if (choice==12)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+12*ED_COUNT_GADGET_YSIZE,
+ int2str(level.dauer_sieb,3),FS_SMALL,FC_YELLOW);
+ else if (choice==13)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+13*ED_COUNT_GADGET_YSIZE,
+ int2str(level.dauer_ablenk,3),FS_SMALL,FC_YELLOW);
+ else if (choice==14)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+14*ED_COUNT_GADGET_YSIZE,
+ int2str(level.edelsteine,3),FS_SMALL,FC_YELLOW);
+ else if (choice==15)
+ DrawText(ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+15*ED_COUNT_GADGET_YSIZE,
+ int2str(level.time,3),FS_SMALL,FC_YELLOW);
+ else if (choice==16)
+ DrawText(ED_SIZE_VALUE_XPOS,
+ ED_SIZE_VALUE_YPOS+0*ED_SIZE_GADGET_YSIZE,
+ int2str(level.fieldx,3),FS_SMALL,FC_YELLOW);
+ else if (choice==17)
+ DrawText(ED_SIZE_VALUE_XPOS,
+ ED_SIZE_VALUE_YPOS+1*ED_SIZE_GADGET_YSIZE,
+ int2str(level.fieldy,3),FS_SMALL,FC_YELLOW);
+
+ redraw_mask &= ~REDRAW_FIELD;
+ if (choice<16)
+ XCopyArea(display,drawto,window,gc,
+ ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE,
+ 3*FONT2_XSIZE,FONT2_YSIZE,
+ ED_COUNT_VALUE_XPOS,
+ ED_COUNT_VALUE_YPOS+choice*ED_COUNT_GADGET_YSIZE);
+ else
+ XCopyArea(display,drawto,window,gc,
+ ED_SIZE_VALUE_XPOS,
+ ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE,
+ 3*FONT2_XSIZE,FONT2_YSIZE,
+ ED_SIZE_VALUE_XPOS,
+ ED_SIZE_VALUE_YPOS+(choice-16)*ED_SIZE_GADGET_YSIZE);
+ XFlush(display);
+ }
+
+ switch(CheckCtrlButtons(mx,my,button))
+ {
+ case ED_BUTTON_EDIT:
+ CloseDoor(DOOR_CLOSE_2);
+ AdjustLevelScrollPosition();
+ DrawMiniLevel(level_xpos,level_ypos);
+ XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX6,DOOR_GFX_PAGEY2,
+ VXSIZE,VYSIZE,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
+ OpenDoor(DOOR_OPEN_2);
+ edit_mode = TRUE;
+ break;
+ case ED_BUTTON_CLEAR:
+ if (AreYouSure("Are you sure to clear this level ?",AYS_ASK))
+ {
+ for(x=0;x<MAX_LEV_FIELDX;x++)
+ for(y=0;y<MAX_LEV_FIELDY;y++)
+ Feld[x][y] = EL_ERDREICH;
+ DrawMiniLevel(level_xpos,level_ypos);
+ }
+ break;
+ case ED_BUTTON_UNDO:
+ if (AreYouSure("Exit without saving ?",AYS_ASK | AYS_STAY_OPEN))
+ {
+ CloseDoor(DOOR_CLOSE_BOTH);
+ game_status=MAINMENU;
+ DrawMainMenu();
+ }
+ else
+ {
+ CloseDoor(DOOR_CLOSE_1);
+ OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+ }
+ break;
+ case ED_BUTTON_EXIT:
+ {
+ int figur_vorhanden = FALSE;
+ for(y=0;y<lev_fieldy;y++)
+ for(x=0;x<lev_fieldx;x++)
+ if (Feld[x][y]==EL_SPIELFIGUR || Feld[x][y]==EL_SPIELER1)
+ figur_vorhanden = TRUE;
+
+ if (!figur_vorhanden)
+ AreYouSure("No Level without Gregor Mc Duffin please !",
+ AYS_CONFIRM);
+ else
+ {
+ if (AreYouSure("Save this level and kill the old ?",
+ AYS_ASK | AYS_STAY_OPEN))
+ {
+ for(x=0;x<lev_fieldx;x++)
+ for(y=0;y<lev_fieldy;y++)
+ Ur[x][y]=Feld[x][y];
+ SaveLevel(level_nr);
+ }
+ CloseDoor(DOOR_CLOSE_BOTH);
+ game_status=MAINMENU;
+ DrawMainMenu();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (mx>=ED_COUNT_GADGET_XPOS &&
+ mx<ED_COUNT_GADGET_XPOS+31*FONT2_XSIZE+10 &&
+ my>=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE &&
+ my<ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE+ED_WIN_COUNT_YSIZE)
+ {
+ if (!name_typing)
+ {
+ name_typing = TRUE;
+ DrawText(ED_COUNT_GADGET_XPOS+5,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ level.name,FS_SMALL,FC_GREEN);
+ DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ "<",FS_SMALL,FC_RED);
+ }
+ }
+ else
+ {
+ if (name_typing)
+ {
+ name_typing = FALSE;
+ DrawText(ED_COUNT_GADGET_XPOS+5,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ level.name,FS_SMALL,FC_YELLOW);
+ DrawText(ED_COUNT_GADGET_XPOS+5+strlen(level.name)*FONT2_XSIZE,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ " ",FS_SMALL,FC_RED);
+ }
+ }
+
+ if (mx>=SX+1*MINI_TILEX && mx<SX+(1+4*5)*MINI_TILEX &&
+ my>=SY+2*MINI_TILEY && my<SY+(2+3)*MINI_TILEY)
+ {
+ int x = (mx-SX-1*MINI_TILEX)/MINI_TILEX;
+ int y = (my-SY-2*MINI_TILEY)/MINI_TILEY;
+ int i = x/5;
+ int new_element;
+
+ x = x-i*5;
+ if (i>=0 && i<43 && x>=0 && x<3 && y>=0 && y<3)
+ {
+ if (button && !motion_status)
+ in_field_pressed = TRUE;
+
+ if (!button || !in_field_pressed || button<1 || button>3)
+ return;
+
+ new_element = (button==1 ? new_element1 :
+ button==2 ? new_element2 :
+ button==3 ? new_element3 : 0);
+
+ if (new_element != level.mampfer_inhalt[i][x][y])
+ {
+ level.mampfer_inhalt[i][x][y] = new_element;
+ DrawMiniElement(1+5*i+x,2+y,level.mampfer_inhalt[i][x][y]);
+ }
+ }
+ else if (!motion_status)/* Mauszeiger nicht im Cruncher-Feld */
+ in_field_pressed = FALSE;
+ }
+ else if (!motion_status) /* Mauszeiger nicht im Cruncher-Feld */
+ in_field_pressed = FALSE;
+ }
+ }
+
+ last_button = button;
+
+ BackToFront();
+}
+
+void LevelNameTyping(KeySym key)
+{
+ unsigned char ascii = 0;
+ int len = strlen(level.name);
+
+ if (!name_typing)
+ return;
+
+ if (key>=XK_A && key<=XK_Z)
+ ascii = 'A'+(char)(key-XK_A);
+ else if (key>=XK_a && key<=XK_z)
+ ascii = 'a'+(char)(key-XK_a);
+ else if (key>=XK_0 && key<=XK_9)
+ ascii = '0'+(char)(key-XK_0);
+#ifdef XK_LATIN1
+ else if (key>=XK_space && key<=XK_at)
+ ascii = ' '+(char)(key-XK_space);
+ else if (key==XK_Adiaeresis)
+ ascii = 'Ä';
+ else if (key==XK_Odiaeresis)
+ ascii = 'Ö';
+ else if (key==XK_Udiaeresis)
+ ascii = 'Ü';
+ else if (key==XK_adiaeresis)
+ ascii = 'ä';
+ else if (key==XK_odiaeresis)
+ ascii = 'ö';
+ else if (key==XK_udiaeresis)
+ ascii = 'ü';
+ else if (key==XK_underscore)
+ ascii = '_';
+#endif
+
+ if (ascii && len<MAX_LEVNAMLEN-2)
+ {
+ level.name[len] = ascii;
+ level.name[len+1] = 0;
+ len++;
+
+ DrawTextExt(drawto,gc,
+ ED_COUNT_GADGET_XPOS+5,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ level.name,FS_SMALL,FC_GREEN);
+ DrawTextExt(window,gc,
+ ED_COUNT_GADGET_XPOS+5,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ level.name,FS_SMALL,FC_GREEN);
+ DrawTextExt(drawto,gc,
+ ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ "<",FS_SMALL,FC_RED);
+ DrawTextExt(window,gc,
+ ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ "<",FS_SMALL,FC_RED);
+ }
+ else if (key==XK_Delete && len>0)
+ {
+ level.name[len-1] = 0;
+ len--;
+
+ DrawTextExt(drawto,gc,
+ ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ "< ",FS_SMALL,FC_GREEN);
+ DrawTextExt(window,gc,
+ ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ "< ",FS_SMALL,FC_GREEN);
+ }
+ else if (key==XK_Return)
+ {
+ DrawTextExt(drawto,gc,
+ ED_COUNT_GADGET_XPOS+5,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ level.name,FS_SMALL,FC_YELLOW);
+ DrawTextExt(window,gc,
+ ED_COUNT_GADGET_XPOS+5,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ level.name,FS_SMALL,FC_YELLOW);
+ DrawTextExt(drawto,gc,
+ ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ " ",FS_SMALL,FC_YELLOW);
+ DrawTextExt(window,gc,
+ ED_COUNT_GADGET_XPOS+5+len*FONT2_XSIZE,
+ ED_COUNT_TEXT_YPOS+16*ED_COUNT_TEXT_YSIZE,
+ " ",FS_SMALL,FC_YELLOW);
+
+ name_typing = FALSE;
+ }
+}
+
+void DrawEditButton(unsigned long state)
+{
+ int i;
+ int xpos = 0, ypos = 1, xsize = 2, ysize = 3;
+ int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY2;
+ static int edit_pos[6][4] =
+ {
+ ED_BUTTON_CTRL_XPOS,ED_BUTTON_CTRL_YPOS,
+ ED_BUTTON_CTRL_XSIZE,ED_BUTTON_CTRL_YSIZE,
+
+ ED_BUTTON_FILL_XPOS,ED_BUTTON_FILL_YPOS,
+ ED_BUTTON_FILL_XSIZE,ED_BUTTON_FILL_YSIZE,
+
+ ED_BUTTON_LEFT_XPOS,ED_BUTTON_LEFT_YPOS,
+ ED_BUTTON_LEFT_XSIZE,ED_BUTTON_LEFT_YSIZE,
+
+ ED_BUTTON_UP_XPOS,ED_BUTTON_UP_YPOS,
+ ED_BUTTON_UP_XSIZE,ED_BUTTON_UP_YSIZE,
+
+ ED_BUTTON_DOWN_XPOS,ED_BUTTON_DOWN_YPOS,
+ ED_BUTTON_DOWN_XSIZE,ED_BUTTON_DOWN_YSIZE,
+
+ ED_BUTTON_RIGHT_XPOS,ED_BUTTON_RIGHT_YPOS,
+ ED_BUTTON_RIGHT_XSIZE,ED_BUTTON_RIGHT_YSIZE
+ };
+
+ if (state & ED_BUTTON_PRESSED)
+ cx = DOOR_GFX_PAGEX5;
+
+ for(i=0;i<6;i++)
+ {
+ if (state & (1<<i))
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ cx + edit_pos[i][xpos],
+ cy + edit_pos[i][ypos],
+ edit_pos[i][xsize],
+ edit_pos[i][ysize],
+ VX + edit_pos[i][xpos],
+ VY + edit_pos[i][ypos]);
+ }
+
+ redraw_mask |= REDRAW_DOOR_2;
+}
+
+void DrawCtrlButton(unsigned long state)
+{
+ int i;
+ int xpos = 0, ypos = 1, xsize = 2, ysize = 3;
+ int cx = DOOR_GFX_PAGEX4, cy = DOOR_GFX_PAGEY1+80;
+ static int edit_pos[4][4] =
+ {
+ ED_BUTTON_EDIT_XPOS,ED_BUTTON_EDIT_YPOS,
+ ED_BUTTON_EDIT_XSIZE,ED_BUTTON_EDIT_YSIZE,
+
+ ED_BUTTON_CLEAR_XPOS,ED_BUTTON_CLEAR_YPOS,
+ ED_BUTTON_CLEAR_XSIZE,ED_BUTTON_CLEAR_YSIZE,
+
+ ED_BUTTON_UNDO_XPOS,ED_BUTTON_UNDO_YPOS,
+ ED_BUTTON_UNDO_XSIZE,ED_BUTTON_UNDO_YSIZE,
+
+ ED_BUTTON_EXIT_XPOS,ED_BUTTON_EXIT_YPOS,
+ ED_BUTTON_EXIT_XSIZE,ED_BUTTON_EXIT_YSIZE
+ };
+
+ if (state & ED_BUTTON_PRESSED)
+ cx = DOOR_GFX_PAGEX3;
+
+ for(i=0;i<4;i++)
+ {
+ if (state & (1<<(i+6)))
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ cx + edit_pos[i][xpos],
+ cy + edit_pos[i][ypos],
+ edit_pos[i][xsize],
+ edit_pos[i][ysize],
+ VX + edit_pos[i][xpos],
+ VY + edit_pos[i][ypos]);
+ }
+
+ redraw_mask |= REDRAW_DOOR_2;
+}
+
+void DrawElemButton(int button_nr, int button_state)
+{
+ int xpos = 0, ypos = 1, xsize = 2, ysize = 3;
+ int cx = DOOR_GFX_PAGEX6, cy = DOOR_GFX_PAGEY1;
+ int from_x, from_y, to_x,to_y, size_x, size_y;
+ static int edit_pos[3][4] =
+ {
+ ED_BUTTON_EUP_XPOS,ED_BUTTON_EUP_YPOS,
+ ED_BUTTON_EUP_XSIZE,ED_BUTTON_EUP_YSIZE,
+
+ ED_BUTTON_EDOWN_XPOS,ED_BUTTON_EDOWN_YPOS,
+ ED_BUTTON_EDOWN_XSIZE,ED_BUTTON_EDOWN_YSIZE,
+
+ ED_BUTTON_ELEM_XPOS,ED_BUTTON_ELEM_YPOS,
+ ED_BUTTON_ELEM_XSIZE,ED_BUTTON_ELEM_YSIZE
+ };
+
+ if (button_nr<ED_BUTTON_ELEM)
+ {
+ int pos = button_nr;
+
+ from_x = cx + edit_pos[pos][xpos];
+ from_y = cy + edit_pos[pos][ypos];
+ size_x = edit_pos[pos][xsize];
+ size_y = edit_pos[pos][ysize];
+ to_x = DX + edit_pos[pos][xpos];
+ to_y = DY + edit_pos[pos][ypos];
+
+ if (button_state & ED_BUTTON_PRESSED)
+ {
+ if (button_nr==ED_BUTTON_EUP)
+ from_y = cy + ED_BUTTON_EUP_Y2POS;
+ else
+ from_y = cy + ED_BUTTON_EDOWN_Y2POS;
+ }
+
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ from_x,from_y, size_x,size_y, to_x,to_y);
+ }
+ else
+ {
+ int pos = ED_BUTTON_ELEM;
+ int elem_pos = button_nr-ED_BUTTON_ELEM;
+ int x = elem_pos % MAX_ELEM_X;
+ int y = elem_pos / MAX_ELEM_X;
+ int graphic;
+ int shift = 0;
+
+ if (elem_pos+element_shift < elements_in_list)
+ graphic = el2gfx(editor_element[elem_pos+element_shift]);
+ else
+ graphic = GFX_LEERRAUM;
+
+ from_x = cx + edit_pos[pos][xpos];
+ from_y = cy + edit_pos[pos][ypos];
+ size_x = edit_pos[pos][xsize];
+ size_y = edit_pos[pos][ysize];
+ to_x = DX + edit_pos[pos][xpos] + x * ED_BUTTON_ELEM_XSIZE;
+ to_y = DY + edit_pos[pos][ypos] + y * ED_BUTTON_ELEM_YSIZE;
+
+ if (button_state & ED_BUTTON_PRESSED)
+ {
+ from_y = ED_BUTTON_ELEM_Y2POS;
+ shift = 1;
+ }
+
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ from_x,from_y, size_x,size_y, to_x,to_y);
+
+ DrawMiniGraphicExtHiRes(drawto,gc,
+ DX+ED_BUTTON_ELEM_XPOS+3+shift +
+ (elem_pos % MAX_ELEM_X)*ED_BUTTON_ELEM_XSIZE,
+ DY+ED_BUTTON_ELEM_YPOS+3-shift +
+ (elem_pos / MAX_ELEM_X)*ED_BUTTON_ELEM_YSIZE,
+ graphic);
+ }
+
+ redraw_mask |= REDRAW_DOOR_1;
+}
+
+void DrawCountButton(int button_nr, int button_state)
+{
+ int from_x, from_y, to_x,to_y, size_x, size_y;
+
+ from_x =
+ DOOR_GFX_PAGEX4+(button_nr%2 ? ED_BUTTON_PLUS_XPOS : ED_BUTTON_MINUS_XPOS);
+ from_y = DOOR_GFX_PAGEY1 + ED_BUTTON_MINUS_YPOS;
+ size_x = ED_BUTTON_MINUS_XSIZE;
+ size_y = ED_BUTTON_MINUS_YSIZE;
+ to_x = (button_nr<32 ? ED_COUNT_GADGET_XPOS : ED_SIZE_GADGET_XPOS);
+ if (button_nr % 2)
+ to_x += (ED_BUTTON_PLUS_XPOS - ED_BUTTON_MINUS_XPOS);
+ to_y = (button_nr<32 ? ED_COUNT_GADGET_YPOS : ED_SIZE_GADGET_YPOS) +
+ ((button_nr<32 ? button_nr : button_nr-32)/2)*ED_COUNT_GADGET_YSIZE;
+
+ if (button_state & ED_BUTTON_PRESSED)
+ from_x -= DXSIZE;
+
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ from_x,from_y, size_x,size_y, to_x,to_y);
+ XCopyArea(display,pix[PIX_DOOR],window,gc,
+ from_x,from_y, size_x,size_y, to_x,to_y);
+}
+
+int CheckEditButtons(int mx, int my, int button)
+{
+ int return_code = 0;
+ static int choice = -1;
+ static BOOL pressed = FALSE;
+ static int edit_button[6] =
+ {
+ ED_BUTTON_CTRL,
+ ED_BUTTON_FILL,
+ ED_BUTTON_LEFT,
+ ED_BUTTON_UP,
+ ED_BUTTON_DOWN,
+ ED_BUTTON_RIGHT
+ };
+
+ if (button)
+ {
+ if (!motion_status) /* Maustaste neu gedrückt */
+ {
+ if (ON_EDIT_BUTTON(mx,my))
+ {
+ choice = EDIT_BUTTON(mx,my);
+ pressed = TRUE;
+ DrawEditButton(edit_button[choice] | ED_BUTTON_PRESSED);
+ if (edit_button[choice]!=ED_BUTTON_CTRL &&
+ edit_button[choice]!=ED_BUTTON_FILL)
+ return_code = 1<<choice;
+ }
+ }
+ else /* Mausbewegung bei gedrückter Maustaste */
+ {
+ if ((!ON_EDIT_BUTTON(mx,my) || EDIT_BUTTON(mx,my)!=choice) &&
+ choice>=0 && pressed)
+ {
+ pressed = FALSE;
+ DrawEditButton(edit_button[choice] | ED_BUTTON_RELEASED);
+ }
+ else if (ON_EDIT_BUTTON(mx,my) && EDIT_BUTTON(mx,my)==choice)
+ {
+ if (!pressed)
+ DrawEditButton(edit_button[choice] | ED_BUTTON_PRESSED);
+ pressed = TRUE;
+ if (edit_button[choice]!=ED_BUTTON_CTRL &&
+ edit_button[choice]!=ED_BUTTON_FILL)
+ return_code = 1<<choice;
+ }
+ }
+ }
+ else /* Maustaste wieder losgelassen */
+ {
+ if (ON_EDIT_BUTTON(mx,my) && EDIT_BUTTON(mx,my)==choice && pressed)
+ {
+ DrawEditButton(edit_button[choice] | ED_BUTTON_RELEASED);
+ if (edit_button[choice]==ED_BUTTON_CTRL ||
+ edit_button[choice]==ED_BUTTON_FILL)
+ return_code = 1<<choice;
+ choice = -1;
+ pressed = FALSE;
+ }
+ else
+ {
+ choice = -1;
+ pressed = FALSE;
+ }
+ }
+
+ BackToFront();
+ return(return_code);
+}
+
+int CheckCtrlButtons(int mx, int my, int button)
+{
+ int return_code = 0;
+ static int choice = -1;
+ static BOOL pressed = FALSE;
+ static int ctrl_button[4] =
+ {
+ ED_BUTTON_EDIT,
+ ED_BUTTON_CLEAR,
+ ED_BUTTON_UNDO,
+ ED_BUTTON_EXIT
+ };
+
+ if (button)
+ {
+ if (!motion_status) /* Maustaste neu gedrückt */
+ {
+ if (ON_CTRL_BUTTON(mx,my))
+ {
+ choice = CTRL_BUTTON(mx,my);
+ pressed = TRUE;
+ DrawCtrlButton(ctrl_button[choice] | ED_BUTTON_PRESSED);
+ }
+ }
+ else /* Mausbewegung bei gedrückter Maustaste */
+ {
+ if ((!ON_CTRL_BUTTON(mx,my) || CTRL_BUTTON(mx,my)!=choice) &&
+ choice>=0 && pressed)
+ {
+ pressed = FALSE;
+ DrawCtrlButton(ctrl_button[choice] | ED_BUTTON_RELEASED);
+ }
+ else if (ON_CTRL_BUTTON(mx,my) && CTRL_BUTTON(mx,my)==choice && !pressed)
+ {
+ pressed = TRUE;
+ DrawCtrlButton(ctrl_button[choice] | ED_BUTTON_PRESSED);
+ }
+ }
+ }
+ else /* Maustaste wieder losgelassen */
+ {
+ if (ON_CTRL_BUTTON(mx,my) && CTRL_BUTTON(mx,my)==choice && pressed)
+ {
+ DrawCtrlButton(ctrl_button[choice] | ED_BUTTON_RELEASED);
+ return_code = 1<<(choice+6);
+ choice = -1;
+ pressed = FALSE;
+ }
+ else
+ {
+ choice = -1;
+ pressed = FALSE;
+ }
+ }
+
+ BackToFront();
+ return(return_code);
+}
+
+int CheckElemButtons(int mx, int my, int button)
+{
+ int return_code = -1;
+ static int choice = -1;
+ static BOOL pressed = FALSE;
+
+ if (button)
+ {
+ if (!motion_status) /* Maustaste neu gedrückt */
+ {
+ if (ON_ELEM_BUTTON(mx,my))
+ {
+ choice = ELEM_BUTTON(mx,my);
+ pressed = TRUE;
+ DrawElemButton(choice,ED_BUTTON_PRESSED);
+ if (choice==ED_BUTTON_EUP ||
+ choice==ED_BUTTON_EDOWN)
+ return_code = choice;
+ }
+ }
+ else /* Mausbewegung bei gedrückter Maustaste */
+ {
+ if ((!ON_ELEM_BUTTON(mx,my) || ELEM_BUTTON(mx,my)!=choice) &&
+ choice>=0 && pressed)
+ {
+ pressed = FALSE;
+ DrawElemButton(choice,ED_BUTTON_RELEASED);
+ }
+ else if (ON_ELEM_BUTTON(mx,my) && ELEM_BUTTON(mx,my)==choice)
+ {
+ if (!pressed)
+ DrawElemButton(choice,ED_BUTTON_PRESSED);
+ pressed = TRUE;
+ if (choice==ED_BUTTON_EUP ||
+ choice==ED_BUTTON_EDOWN)
+ return_code = choice;
+ }
+ }
+ }
+ else /* Maustaste wieder losgelassen */
+ {
+ if (ON_ELEM_BUTTON(mx,my) && ELEM_BUTTON(mx,my)==choice && pressed)
+ {
+ DrawElemButton(choice,ED_BUTTON_RELEASED);
+ if (choice!=ED_BUTTON_EUP &&
+ choice!=ED_BUTTON_EDOWN)
+ return_code = choice;
+ choice = -1;
+ pressed = FALSE;
+ }
+ else
+ {
+ choice = -1;
+ pressed = FALSE;
+ }
+ }
+
+ BackToFront();
+ return(return_code);
+}
+
+int CheckCountButtons(int mx, int my, int button)
+{
+ int return_code = -1;
+ static int choice = -1;
+ static BOOL pressed = FALSE;
+
+ if (button)
+ {
+ if (!motion_status) /* Maustaste neu gedrückt */
+ {
+ if (ON_COUNT_BUTTON(mx,my))
+ {
+ choice = COUNT_BUTTON(mx,my);
+ pressed = TRUE;
+ DrawCountButton(choice,ED_BUTTON_PRESSED);
+ return_code = choice;
+ }
+ }
+ else /* Mausbewegung bei gedrückter Maustaste */
+ {
+ if ((!ON_COUNT_BUTTON(mx,my) || COUNT_BUTTON(mx,my)!=choice) &&
+ choice>=0 && pressed)
+ {
+ pressed = FALSE;
+ DrawCountButton(choice,ED_BUTTON_RELEASED);
+ }
+ else if (ON_COUNT_BUTTON(mx,my) && COUNT_BUTTON(mx,my)==choice)
+ {
+ if (!pressed)
+ DrawCountButton(choice,ED_BUTTON_PRESSED);
+ pressed = TRUE;
+ return_code = choice;
+ }
+ }
+ }
+ else /* Maustaste wieder losgelassen */
+ {
+ if (ON_COUNT_BUTTON(mx,my) && COUNT_BUTTON(mx,my)==choice && pressed)
+ {
+ DrawCountButton(choice,ED_BUTTON_RELEASED);
+ choice = -1;
+ pressed = FALSE;
+ }
+ else
+ {
+ choice = -1;
+ pressed = FALSE;
+ }
+ }
+
+ BackToFront();
+ return(return_code);
+}
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* editor.h *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#ifndef EDITOR_H
+#define EDITOR_H
+
+#include "main.h"
+
+/* sizes in the level editor */
+/* edit window */
+#define ED_WIN_MB_LEFT_XPOS 7
+#define ED_WIN_MB_LEFT_YPOS 6
+#define ED_WIN_LEVELNR_XPOS 77
+#define ED_WIN_LEVELNR_YPOS 7
+#define ED_WIN_MB_MIDDLE_XPOS 7
+#define ED_WIN_MB_MIDDLE_YPOS 258
+#define ED_WIN_MB_RIGHT_XPOS 77
+#define ED_WIN_MB_RIGHT_YPOS 258
+
+#define ED_BUTTON_EUP_XPOS 35
+#define ED_BUTTON_EUP_YPOS 5
+#define ED_BUTTON_EUP_XSIZE 30
+#define ED_BUTTON_EUP_YSIZE 25
+#define ED_BUTTON_EDOWN_XPOS 35
+#define ED_BUTTON_EDOWN_YPOS 250
+#define ED_BUTTON_EDOWN_XSIZE 30
+#define ED_BUTTON_EDOWN_YSIZE 25
+#define ED_BUTTON_ELEM_XPOS 6
+#define ED_BUTTON_ELEM_YPOS 30
+#define ED_BUTTON_ELEM_XSIZE 22
+#define ED_BUTTON_ELEM_YSIZE 22
+
+#define MAX_ELEM_X 4
+#define MAX_ELEM_Y 10
+
+#define ED_BUTTON_EUP_Y2POS 140
+#define ED_BUTTON_EDOWN_Y2POS 165
+#define ED_BUTTON_ELEM_Y2POS 190
+
+#define ED_BUTTON_CTRL_XPOS 5
+#define ED_BUTTON_CTRL_YPOS 5
+#define ED_BUTTON_CTRL_XSIZE 90
+#define ED_BUTTON_CTRL_YSIZE 30
+#define ED_BUTTON_FILL_XPOS 5
+#define ED_BUTTON_FILL_YPOS 35
+#define ED_BUTTON_FILL_XSIZE 90
+#define ED_BUTTON_FILL_YSIZE 20
+#define ED_BUTTON_LEFT_XPOS 5
+#define ED_BUTTON_LEFT_YPOS 65
+#define ED_BUTTON_LEFT_XSIZE 30
+#define ED_BUTTON_LEFT_YSIZE 20
+#define ED_BUTTON_UP_XPOS 35
+#define ED_BUTTON_UP_YPOS 55
+#define ED_BUTTON_UP_XSIZE 30
+#define ED_BUTTON_UP_YSIZE 20
+#define ED_BUTTON_DOWN_XPOS 35
+#define ED_BUTTON_DOWN_YPOS 75
+#define ED_BUTTON_DOWN_XSIZE 30
+#define ED_BUTTON_DOWN_YSIZE 20
+#define ED_BUTTON_RIGHT_XPOS 65
+#define ED_BUTTON_RIGHT_YPOS 65
+#define ED_BUTTON_RIGHT_XSIZE 30
+#define ED_BUTTON_RIGHT_YSIZE 20
+
+#define ED_BUTTON_EDIT_XPOS 5
+#define ED_BUTTON_EDIT_YPOS 5
+#define ED_BUTTON_EDIT_XSIZE 90
+#define ED_BUTTON_EDIT_YSIZE 30
+#define ED_BUTTON_CLEAR_XPOS 5
+#define ED_BUTTON_CLEAR_YPOS 35
+#define ED_BUTTON_CLEAR_XSIZE 90
+#define ED_BUTTON_CLEAR_YSIZE 20
+#define ED_BUTTON_UNDO_XPOS 5
+#define ED_BUTTON_UNDO_YPOS 55
+#define ED_BUTTON_UNDO_XSIZE 90
+#define ED_BUTTON_UNDO_YSIZE 20
+#define ED_BUTTON_EXIT_XPOS 5
+#define ED_BUTTON_EXIT_YPOS 75
+#define ED_BUTTON_EXIT_XSIZE 90
+#define ED_BUTTON_EXIT_YSIZE 20
+
+#define ED_BUTTON_MINUS_XPOS 2
+#define ED_BUTTON_MINUS_YPOS 60
+#define ED_BUTTON_MINUS_XSIZE 20
+#define ED_BUTTON_MINUS_YSIZE 20
+#define ED_WIN_COUNT_XPOS (ED_BUTTON_MINUS_XPOS+ED_BUTTON_MINUS_XSIZE+2)
+#define ED_WIN_COUNT_YPOS ED_BUTTON_MINUS_YPOS
+#define ED_WIN_COUNT_XSIZE 52
+#define ED_WIN_COUNT_YSIZE ED_BUTTON_MINUS_YSIZE
+#define ED_BUTTON_PLUS_XPOS (ED_WIN_COUNT_XPOS+ED_WIN_COUNT_XSIZE+2)
+#define ED_BUTTON_PLUS_YPOS ED_BUTTON_MINUS_YPOS
+#define ED_BUTTON_PLUS_XSIZE ED_BUTTON_MINUS_XSIZE
+#define ED_BUTTON_PLUS_YSIZE ED_BUTTON_MINUS_YSIZE
+
+#define ED_COUNT_GADGET_XPOS 16
+#define ED_COUNT_GADGET_YPOS (16+3*MINI_TILEY+64)
+#define ED_COUNT_GADGET_YSIZE (ED_BUTTON_MINUS_YSIZE+4)
+#define ED_COUNT_TEXT_XPOS (ED_COUNT_GADGET_XPOS+DXSIZE+10)
+#define ED_COUNT_TEXT_YPOS (ED_COUNT_GADGET_YPOS+3)
+#define ED_COUNT_TEXT_YSIZE ED_COUNT_GADGET_YSIZE
+#define ED_COUNT_VALUE_XPOS (ED_COUNT_GADGET_XPOS+ED_BUTTON_MINUS_XSIZE+7)
+#define ED_COUNT_VALUE_YPOS ED_COUNT_TEXT_YPOS
+#define ED_SIZE_GADGET_XPOS (SX+21*MINI_TILEX)
+#define ED_SIZE_GADGET_YPOS (SY+4*MINI_TILEY)
+#define ED_SIZE_GADGET_YSIZE (ED_BUTTON_MINUS_YSIZE+4)
+#define ED_SIZE_TEXT_XPOS (ED_SIZE_GADGET_XPOS+DXSIZE+10)
+#define ED_SIZE_TEXT_YPOS (ED_SIZE_GADGET_YPOS+3)
+#define ED_SIZE_TEXT_YSIZE ED_COUNT_GADGET_YSIZE
+#define ED_SIZE_VALUE_XPOS (ED_SIZE_GADGET_XPOS+ED_BUTTON_MINUS_XSIZE+7)
+#define ED_SIZE_VALUE_YPOS ED_SIZE_TEXT_YPOS
+
+#define ON_EDIT_BUTTON(x,y) (((x)>=(VX+ED_BUTTON_CTRL_XPOS) && \
+ (x)< (VX+ED_BUTTON_CTRL_XPOS + \
+ ED_BUTTON_CTRL_XSIZE) && \
+ (y)>=(VY+ED_BUTTON_CTRL_YPOS) && \
+ (y)< (VY+ED_BUTTON_CTRL_YPOS + \
+ ED_BUTTON_CTRL_YSIZE + \
+ ED_BUTTON_FILL_YSIZE)) || \
+ ((x)>=(VX+ED_BUTTON_LEFT_XPOS) && \
+ (x)< (VX+ED_BUTTON_LEFT_XPOS + \
+ ED_BUTTON_LEFT_XSIZE + \
+ ED_BUTTON_UP_XSIZE + \
+ ED_BUTTON_RIGHT_XSIZE) && \
+ (y)>=(VY+ED_BUTTON_LEFT_YPOS) && \
+ (y)< (VY+ED_BUTTON_LEFT_YPOS + \
+ ED_BUTTON_LEFT_YSIZE)) || \
+ ((x)>=(VX+ED_BUTTON_UP_XPOS) && \
+ (x)< (VX+ED_BUTTON_UP_XPOS + \
+ ED_BUTTON_UP_XSIZE) && \
+ (y)>=(VY+ED_BUTTON_UP_YPOS) && \
+ (y)< (VY+ED_BUTTON_UP_YPOS + \
+ ED_BUTTON_UP_YSIZE + \
+ ED_BUTTON_DOWN_YSIZE)))
+
+#define ON_CTRL_BUTTON(x,y) ((x)>=(VX+ED_BUTTON_EDIT_XPOS) && \
+ (x)< (VX+ED_BUTTON_EDIT_XPOS + \
+ ED_BUTTON_EDIT_XSIZE) && \
+ (y)>=(VY+ED_BUTTON_EDIT_YPOS) && \
+ (y)< (VY+ED_BUTTON_EDIT_YPOS + \
+ ED_BUTTON_EDIT_YSIZE + \
+ ED_BUTTON_CLEAR_YSIZE + \
+ ED_BUTTON_UNDO_YSIZE + \
+ ED_BUTTON_EXIT_YSIZE))
+
+#define ON_ELEM_BUTTON(x,y) (((x)>=(DX+ED_BUTTON_EUP_XPOS) && \
+ (x)< (DX+ED_BUTTON_EUP_XPOS + \
+ ED_BUTTON_EUP_XSIZE) && \
+ (y)>=(DY+ED_BUTTON_EUP_YPOS) && \
+ (y)< (DY+ED_BUTTON_EUP_YPOS + \
+ ED_BUTTON_EUP_YSIZE)) || \
+ ((x)>=(DX+ED_BUTTON_EDOWN_XPOS) && \
+ (x)< (DX+ED_BUTTON_EDOWN_XPOS + \
+ ED_BUTTON_EDOWN_XSIZE) && \
+ (y)>=(DY+ED_BUTTON_EDOWN_YPOS) && \
+ (y)< (DY+ED_BUTTON_EDOWN_YPOS + \
+ ED_BUTTON_EDOWN_YSIZE)) || \
+ ((x)>=(DX+ED_BUTTON_ELEM_XPOS) && \
+ (x)< (DX+ED_BUTTON_ELEM_XPOS + \
+ MAX_ELEM_X*ED_BUTTON_ELEM_XSIZE) && \
+ (y)>=(DY+ED_BUTTON_ELEM_YPOS) && \
+ (y)< (DY+ED_BUTTON_ELEM_YPOS + \
+ MAX_ELEM_Y*ED_BUTTON_ELEM_YSIZE)))
+
+#define ON_COUNT_BUTTON(x,y) (((((x)>=ED_COUNT_GADGET_XPOS && \
+ (x)<(ED_COUNT_GADGET_XPOS + \
+ ED_BUTTON_MINUS_XSIZE)) || \
+ ((x)>=(ED_COUNT_GADGET_XPOS + \
+ (ED_BUTTON_PLUS_XPOS - \
+ ED_BUTTON_MINUS_XPOS)) && \
+ (x)<(ED_COUNT_GADGET_XPOS + \
+ (ED_BUTTON_PLUS_XPOS - \
+ ED_BUTTON_MINUS_XPOS) + \
+ ED_BUTTON_PLUS_XSIZE))) && \
+ ((y)>=ED_COUNT_GADGET_YPOS && \
+ (y)<(ED_COUNT_GADGET_YPOS + \
+ 16*ED_COUNT_GADGET_YSIZE)) && \
+ (((y)-ED_COUNT_GADGET_YPOS) % \
+ ED_COUNT_GADGET_YSIZE) < \
+ ED_BUTTON_MINUS_YSIZE) || \
+ ((((x)>=ED_SIZE_GADGET_XPOS && \
+ (x)<(ED_SIZE_GADGET_XPOS + \
+ ED_BUTTON_MINUS_XSIZE)) || \
+ ((x)>=(ED_SIZE_GADGET_XPOS + \
+ (ED_BUTTON_PLUS_XPOS - \
+ ED_BUTTON_MINUS_XPOS)) && \
+ (x)<(ED_SIZE_GADGET_XPOS + \
+ (ED_BUTTON_PLUS_XPOS - \
+ ED_BUTTON_MINUS_XPOS) + \
+ ED_BUTTON_PLUS_XSIZE))) && \
+ ((y)>=ED_SIZE_GADGET_YPOS && \
+ (y)<(ED_SIZE_GADGET_YPOS + \
+ 2*ED_SIZE_GADGET_YSIZE)) && \
+ (((y)-ED_SIZE_GADGET_YPOS) % \
+ ED_SIZE_GADGET_YSIZE) < \
+ ED_BUTTON_MINUS_YSIZE))
+
+#define EDIT_BUTTON(x,y) (((y) < (VY + ED_BUTTON_CTRL_YPOS + \
+ ED_BUTTON_CTRL_YSIZE)) ? 0 : \
+ ((y) < (VY + ED_BUTTON_CTRL_YPOS + \
+ ED_BUTTON_CTRL_YSIZE + \
+ ED_BUTTON_FILL_YSIZE)) ? 1 : \
+ ((x) < (VX + ED_BUTTON_LEFT_XPOS + \
+ ED_BUTTON_LEFT_XSIZE) ? 2 : \
+ (x) > (VX + ED_BUTTON_LEFT_XPOS + \
+ ED_BUTTON_LEFT_XSIZE + \
+ ED_BUTTON_UP_XSIZE) ? 5 : \
+ 3+(((y)-(VY + ED_BUTTON_CTRL_YPOS + \
+ ED_BUTTON_CTRL_YSIZE + \
+ ED_BUTTON_FILL_YSIZE)) / \
+ ED_BUTTON_UP_YSIZE)))
+
+#define CTRL_BUTTON(x,y) (((y) < (VY + ED_BUTTON_EDIT_YPOS + \
+ ED_BUTTON_EDIT_YSIZE)) ? 0 : \
+ 1+(((y)-(VY + ED_BUTTON_EDIT_YPOS + \
+ ED_BUTTON_EDIT_YSIZE)) / \
+ ED_BUTTON_CLEAR_YSIZE))
+
+#define ELEM_BUTTON(x,y) (((y) < (DY + ED_BUTTON_EUP_YPOS + \
+ ED_BUTTON_EUP_YSIZE)) ? 0 : \
+ ((y) > (DY + ED_BUTTON_EDOWN_YPOS)) ? 1 : \
+ 2+(((y) - (DY + ED_BUTTON_ELEM_YPOS)) / \
+ ED_BUTTON_ELEM_YSIZE)*MAX_ELEM_X + \
+ ((x) - (DX + ED_BUTTON_ELEM_XPOS)) / \
+ ED_BUTTON_ELEM_XSIZE)
+
+#define COUNT_BUTTON(x,y) ((x) < ED_SIZE_GADGET_XPOS ? \
+ ((((y) - ED_COUNT_GADGET_YPOS) / \
+ ED_COUNT_GADGET_YSIZE)*2 + \
+ ((x) < (ED_COUNT_GADGET_XPOS + \
+ ED_BUTTON_MINUS_XSIZE) ? 0 : 1)) : \
+ 32+((((y) - ED_SIZE_GADGET_YPOS) / \
+ ED_SIZE_GADGET_YSIZE)*2 + \
+ ((x) < (ED_SIZE_GADGET_XPOS + \
+ ED_BUTTON_MINUS_XSIZE) ? 0 : 1)))
+
+/* values for asking control */
+#define ED_BUTTON_CTRL (1L<<0)
+#define ED_BUTTON_FILL (1L<<1)
+#define ED_BUTTON_LEFT (1L<<2)
+#define ED_BUTTON_UP (1L<<3)
+#define ED_BUTTON_DOWN (1L<<4)
+#define ED_BUTTON_RIGHT (1L<<5)
+#define ED_BUTTON_EDIT (1L<<6)
+#define ED_BUTTON_CLEAR (1L<<7)
+#define ED_BUTTON_UNDO (1L<<8)
+#define ED_BUTTON_EXIT (1L<<9)
+
+#define ED_BUTTON_PRESSED (1L<<10)
+#define ED_BUTTON_RELEASED (1L<<11)
+
+#define ED_BUTTON_EUP 0
+#define ED_BUTTON_EDOWN 1
+#define ED_BUTTON_ELEM 2
+
+#if 0
+
+/* OBSOLETE *********************** */
+
+/* sizes in the level editor */
+#define ED_PFEIL_XSIZE 46
+#define ED_PFEIL_YSIZE 19
+#define ED_ZEIT_XSIZE 20
+#define ED_ZEIT_YSIZE 20
+#define ED_CLEX_XSIZE 46
+#define ED_CLEX_YSIZE 18
+#define ED_BUT_CLEX_Y (DYSIZE-2-ED_CLEX_YSIZE)
+#define ED_BUT_ZEIT_Y (ED_BUT_CLEX_Y-2-ED_ZEIT_YSIZE)
+#define ED_BUT_PFEIL_Y (ED_BUT_ZEIT_Y-2-ED_PFEIL_YSIZE)
+#define ED_BUT_ZEIT2_X (ED_ZEIT_XSIZE+10)
+#define ED_BUT_ZEIT2_Y (ED_BUT_ZEIT_Y+4)
+#define ED_BUT_X 2
+#define ED_BUT_Y ED_BUT_PFEIL_Y
+
+/* OBSOLETE *********************** */
+
+#endif
+
+
+/* other constants for the editor */
+#define ED_SCROLL_NO 0
+#define ED_SCROLL_LEFT 1
+#define ED_SCROLL_RIGHT 2
+#define ED_SCROLL_UP 4
+#define ED_SCROLL_DOWN 8
+
+void DrawLevelEd(void);
+void ScrollMiniLevel(int, int, int);
+void LevelEd(int, int, int);
+void LevelNameTyping(KeySym);
+void DrawEditButton(unsigned long state);
+void DrawCtrlButton(unsigned long state);
+void DrawElemButton(int, int);
+void DrawCountButton(int, int);
+int CheckEditButtons(int, int, int);
+int CheckCtrlButtons(int, int, int);
+int CheckElemButtons(int, int, int);
+int CheckCountButtons(int, int, int);
+
+#endif
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* events.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#include "events.h"
+#include "screens.h"
+#include "tools.h"
+#include "game.h"
+#include "editor.h"
+
+void EventLoop(void)
+{
+ while(1)
+ {
+ if (XPending(display)) /* got an event */
+ {
+ XEvent event;
+
+ XNextEvent(display, &event);
+
+ switch(event.type)
+ {
+ case Expose:
+ HandleExposeEvent((XExposeEvent *) &event);
+ break;
+ case UnmapNotify:
+ SleepWhileUnmapped();
+ break;
+ case ButtonPress:
+ HandleButtonEvent((XButtonEvent *) &event);
+ break;
+ case ButtonRelease:
+ HandleButtonEvent((XButtonEvent *) &event);
+ break;
+ case MotionNotify:
+ HandleMotionEvent((XMotionEvent *) &event);
+ break;
+ case KeyPress:
+ HandleKeyEvent((XKeyEvent *) &event);
+ break;
+ case KeyRelease:
+ HandleKeyEvent((XKeyEvent *) &event);
+ break;
+ case FocusIn:
+ HandleFocusEvent(FOCUS_IN);
+ break;
+ case FocusOut:
+ HandleFocusEvent(FOCUS_OUT);
+ break;
+ default:
+ break;
+ }
+ }
+ else /* got no event, but don't be lazy... */
+ {
+ HandleNoXEvent();
+
+ if (game_status!=PLAYING)
+ Delay(10000); /* don't use all CPU time when idle */
+ }
+
+ if (game_status==EXITGAME)
+ return;
+ }
+}
+
+void ClearEventQueue()
+{
+ while(XPending(display))
+ {
+ XEvent event;
+
+ XNextEvent(display, &event);
+
+ switch(event.type)
+ {
+ case Expose:
+ HandleExposeEvent((XExposeEvent *) &event);
+ break;
+ case UnmapNotify:
+ SleepWhileUnmapped();
+ break;
+ case ButtonRelease:
+ button_status = MB_RELEASED;
+ break;
+ case KeyRelease:
+ key_status = KEY_RELEASED;
+ break;
+ case FocusIn:
+ HandleFocusEvent(FOCUS_IN);
+ break;
+ case FocusOut:
+ HandleFocusEvent(FOCUS_OUT);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void SleepWhileUnmapped()
+{
+ BOOL window_unmapped = TRUE;
+
+ XAutoRepeatOn(display);
+
+ while(window_unmapped)
+ {
+ XEvent event;
+
+ XNextEvent(display, &event);
+
+ switch(event.type)
+ {
+ case Expose:
+ HandleExposeEvent((XExposeEvent *) &event);
+ break;
+ case ButtonRelease:
+ button_status = MB_RELEASED;
+ break;
+ case KeyRelease:
+ key_status = KEY_RELEASED;
+ break;
+ case MapNotify:
+ window_unmapped = FALSE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (game_status==PLAYING)
+ XAutoRepeatOff(display);
+}
+
+void HandleExposeEvent(XExposeEvent *event)
+{
+ int x = event->x, y = event->y;
+ int width = event->width, height = event->height;
+
+ XCopyArea(display,drawto,window,gc, x,y, width,height, x,y);
+
+ if (direct_draw_on && game_status==PLAYING)
+ {
+ int xx,yy;
+ int x1 = (x-SX)/TILEX, y1 = (y-SY)/TILEY;
+ int x2 = (x-SX+width)/TILEX, y2 = (y-SY+height)/TILEY;
+
+ for(xx=0;xx<SCR_FIELDX;xx++)
+ for(yy=0;yy<SCR_FIELDY;yy++)
+ if (xx>=x1 && xx<=x2 && yy>=y1 && yy<=y2)
+ DrawScreenField(xx,yy);
+ DrawLevelElement(JX,JY,EL_SPIELFIGUR);
+ }
+
+ XFlush(display);
+}
+
+void HandleButtonEvent(XButtonEvent *event)
+{
+ motion_status = FALSE;
+
+ if (event->type==ButtonPress)
+ button_status = event->button;
+ else
+ button_status = MB_RELEASED;
+
+ HandleButton(event->x, event->y, button_status);
+}
+
+void HandleMotionEvent(XMotionEvent *event)
+{
+ motion_status = TRUE;
+
+ HandleButton(event->x, event->y, button_status);
+}
+
+void HandleKeyEvent(XKeyEvent *event)
+{
+ static KeySym old_keycode = 0;
+ int new_keycode = event->keycode;
+ KeySym new_key = XLookupKeysym(event,event->state);
+ int new_key_status = (event->type==KeyPress ? KEY_PRESSED : KEY_RELEASED);
+
+ if (game_status==PLAYING &&
+ (old_keycode!=new_keycode || key_status!=new_key_status))
+ {
+ DigField(0,0,DF_NO_PUSH);
+ SnapField(0,0);
+ }
+
+ if (event->type==KeyPress)
+ {
+ key_status = KEY_PRESSED;
+ HandleKey(new_key);
+ old_keycode = new_keycode;
+ }
+ else if (key_status==KEY_PRESSED && old_keycode==new_keycode)
+ key_status = KEY_RELEASED;
+}
+
+void HandleFocusEvent(int focus_status)
+{
+ if (focus_status==FOCUS_OUT)
+ XAutoRepeatOn(display);
+ else if (game_status==PLAYING)
+ XAutoRepeatOff(display);
+}
+
+void HandleButton(int mx, int my, int button)
+{
+ static int old_mx = 0, old_my = 0;
+
+ if (mx<0 || my<0)
+ {
+ mx = old_mx;
+ my = old_my;
+ }
+ else
+ {
+ old_mx = mx;
+ old_my = my;
+
+ HandleVideoButtons(mx,my,button);
+ HandleSoundButtons(mx,my,button);
+ HandleGameButtons(mx,my,button);
+ }
+
+ switch(game_status)
+ {
+ case MAINMENU:
+ HandleMainMenu(mx,my,0,0,button);
+ break;
+ case TYPENAME:
+ HandleTypeName(0,XK_Return);
+ break;
+ case CHOOSELEVEL:
+ HandleChooseLevel(mx,my,0,0,button);
+ break;
+ case HALLOFFAME:
+ HandleHallOfFame(button);
+ break;
+ case LEVELED:
+ LevelEd(mx,my,button);
+ break;
+ case HELPSCREEN:
+ HandleHelpScreen(button);
+ break;
+ case SETUP:
+ HandleSetupScreen(mx,my,0,0,button);
+ break;
+ case PLAYING:
+ if (!LevelSolved)
+ {
+ switch(GameActions(mx,my,button))
+ {
+ case ACT_GAME_OVER:
+ game_status = MAINMENU;
+ DrawMainMenu();
+ BackToFront();
+ break;
+ case ACT_NEW_GAME:
+ game_status = PLAYING;
+ InitGame();
+ break;
+ case ACT_GO_ON:
+ break;
+ default:
+ break;
+ }
+ }
+ BackToFront();
+ Delay(10000);
+ break;
+ default:
+ break;
+ }
+}
+
+void HandleKey(KeySym key)
+{
+ static KeySym old_key = 0;
+
+ if (!key)
+ key = old_key;
+ else
+ old_key = key;
+
+ if (key==XK_Escape && game_status!=MAINMENU) /* quick quit to MAINMENU */
+ {
+ CloseDoor(DOOR_CLOSE_1 | DOOR_NO_DELAY);
+ game_status = MAINMENU;
+ DrawMainMenu();
+ return;
+ }
+
+ if (game_status==PLAYING && (tape.playing || tape.pausing))
+ return;
+
+ switch(game_status)
+ {
+ case TYPENAME:
+ HandleTypeName(0,key);
+ break;
+ case MAINMENU:
+ case CHOOSELEVEL:
+ case SETUP:
+ {
+ int dx = 0, dy = 0;
+
+ switch(key)
+ {
+ case XK_Return:
+ if (game_status==MAINMENU)
+ HandleMainMenu(0,0,0,0,MB_MENU_CHOICE);
+ else if (game_status==CHOOSELEVEL)
+ HandleChooseLevel(0,0,0,0,MB_MENU_CHOICE);
+ else if (game_status==SETUP)
+ HandleSetupScreen(0,0,0,0,MB_MENU_CHOICE);
+ break;
+ case XK_Left:
+#ifdef XK_KP_Left
+ case XK_KP_Left:
+#endif
+ case XK_KP_4:
+ case XK_J:
+ case XK_j:
+ dx = -1;
+ break;
+ case XK_Right:
+#ifdef XK_KP_Right
+ case XK_KP_Right:
+#endif
+ case XK_KP_6:
+ case XK_K:
+ case XK_k:
+ dx = 1;
+ break;
+ case XK_Up:
+#ifdef XK_KP_Up
+ case XK_KP_Up:
+#endif
+ case XK_KP_8:
+ case XK_I:
+ case XK_i:
+ dy = -1;
+ break;
+ case XK_Down:
+#ifdef XK_KP_Down
+ case XK_KP_Down:
+#endif
+ case XK_KP_2:
+ case XK_M:
+ case XK_m:
+ dy = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (dx || dy)
+ {
+ if (game_status==MAINMENU)
+ HandleMainMenu(0,0,dx,dy,MB_MENU_MARK);
+ else if (game_status==CHOOSELEVEL)
+ HandleChooseLevel(0,0,dx,dy,MB_MENU_MARK);
+ else if (game_status==SETUP)
+ HandleSetupScreen(0,0,dx,dy,MB_MENU_MARK);
+ }
+ break;
+ }
+ case HELPSCREEN:
+ HandleHelpScreen(MB_RELEASED);
+ break;
+ case HALLOFFAME:
+ switch(key)
+ {
+ case XK_Return:
+ game_status = MAINMENU;
+ DrawMainMenu();
+ BackToFront();
+ break;
+ default:
+ break;
+ }
+ break;
+ case LEVELED:
+ LevelNameTyping(key);
+ break;
+ case PLAYING:
+ {
+ int mvx = 0, mvy = 0;
+ int sbx = 0, sby = 0;
+ int joy = 0;
+ BOOL bomb = FALSE;
+ BOOL moved = FALSE, snapped = FALSE, bombed = FALSE;
+
+ switch(key)
+ {
+ case XK_Left: /* normale Richtungen */
+#ifdef XK_KP_Left
+ case XK_KP_Left:
+#endif
+ case XK_KP_4:
+ case XK_J:
+ case XK_j:
+ mvx = -1;
+ joy = JOY_LEFT;
+ break;
+ case XK_Right:
+#ifdef XK_KP_Right
+ case XK_KP_Right:
+#endif
+ case XK_KP_6:
+ case XK_K:
+ case XK_k:
+ mvx = 1;
+ joy = JOY_RIGHT;
+ break;
+ case XK_Up:
+#ifdef XK_KP_Up
+ case XK_KP_Up:
+#endif
+ case XK_KP_8:
+ case XK_I:
+ case XK_i:
+ mvy = -1;
+ joy = JOY_UP;
+ break;
+ case XK_Down:
+#ifdef XK_KP_Down
+ case XK_KP_Down:
+#endif
+ case XK_KP_2:
+ case XK_M:
+ case XK_m:
+ mvy = 1;
+ joy = JOY_DOWN;
+ break;
+#ifdef XK_KP_Home
+ case XK_KP_Home: /* Diagonalrichtungen */
+#endif
+ case XK_KP_7:
+ mvx = -1;
+ mvy = -1;
+ joy = JOY_UP | JOY_LEFT;
+ break;
+#ifdef XK_KP_Page_Up
+ case XK_KP_Page_Up:
+#endif
+ case XK_KP_9:
+ mvx = 1;
+ mvy = -1;
+ joy = JOY_UP | JOY_RIGHT;
+ break;
+#ifdef XK_KP_End
+ case XK_KP_End:
+#endif
+ case XK_KP_1:
+ mvx = -1;
+ mvy = 1;
+ joy = JOY_DOWN | JOY_LEFT;
+ break;
+#ifdef XK_KP_Page_Down
+ case XK_KP_Page_Down:
+#endif
+ case XK_KP_3:
+ mvx = 1;
+ mvy = 1;
+ joy = JOY_DOWN | JOY_RIGHT;
+ break;
+ case XK_S: /* Feld entfernen */
+ case XK_s:
+ sbx = -1;
+ joy = JOY_BUTTON_1 | JOY_LEFT;
+ break;
+ case XK_D:
+ case XK_d:
+ sbx = 1;
+ joy = JOY_BUTTON_1 | JOY_RIGHT;
+ break;
+ case XK_E:
+ case XK_e:
+ sby = -1;
+ joy = JOY_BUTTON_1 | JOY_UP;
+ break;
+ case XK_X:
+ case XK_x:
+ sby = 1;
+ joy = JOY_BUTTON_1 | JOY_DOWN;
+ break;
+ case XK_B: /* Bombe legen */
+ case XK_b:
+ bomb = TRUE;
+ joy = JOY_BUTTON_2;
+ break;
+ case XK_Q:
+ Dynamite = 1000;
+ break;
+ default:
+ break;
+ }
+
+ if (mvx || mvy)
+ moved = MoveFigure(mvx,mvy);
+ else if (sbx || sby)
+ snapped = SnapField(sbx,sby);
+ else if (bomb)
+ bombed = PlaceBomb();
+
+ if (tape.recording && (moved || snapped || bombed))
+ TapeRecordAction(joy);
+
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void HandleNoXEvent()
+{
+ if (button_status)
+ {
+ HandleButton(-1,-1,button_status);
+ return;
+ }
+
+ switch(game_status)
+ {
+ case MAINMENU:
+ case CHOOSELEVEL:
+ case HALLOFFAME:
+ case HELPSCREEN:
+ case SETUP:
+ HandleJoystick();
+ break;
+ case PLAYING:
+ HandleJoystick();
+ if (key_status)
+ HandleKey(0);
+ if (game_status!=PLAYING)
+ break;
+
+ if (!LevelSolved)
+ {
+ switch(GameActions(0,0,MB_NOT_PRESSED))
+ {
+ case ACT_GAME_OVER:
+ game_status = MAINMENU;
+ DrawMainMenu();
+ BackToFront();
+ break;
+ case ACT_NEW_GAME:
+ game_status = PLAYING;
+ InitGame();
+ break;
+ case ACT_GO_ON:
+ break;
+ default:
+ break;
+ }
+ }
+
+ Delay(10000);
+
+ break;
+ default:
+ break;
+ }
+}
+
+void HandleJoystick()
+{
+ int joy = Joystick();
+ int left = joy & JOY_LEFT;
+ int right = joy & JOY_RIGHT;
+ int up = joy & JOY_UP;
+ int down = joy & JOY_DOWN;
+ int button = joy & JOY_BUTTON;
+ int button1 = joy & JOY_BUTTON_1;
+ int button2 = joy & JOY_BUTTON_2;
+ int newbutton = (JoystickButton()==JOY_BUTTON_NEW_PRESSED);
+
+ if (button_status || key_status)
+ return;
+
+ switch(game_status)
+ {
+ case MAINMENU:
+ case CHOOSELEVEL:
+ case SETUP:
+ {
+ int dx = 0, dy = 0;
+ static long joystickmove_delay = 0;
+
+ if (DelayReached(&joystickmove_delay,15) || button)
+ {
+ if (left)
+ dx = -1;
+ else if (right)
+ dx = 1;
+ if (up)
+ dy = -1;
+ else if (down)
+ dy = 1;
+ }
+
+ if (game_status==MAINMENU)
+ HandleMainMenu(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
+ else if (game_status==CHOOSELEVEL)
+ HandleChooseLevel(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
+ else if (game_status==SETUP)
+ HandleSetupScreen(0,0,dx,dy,newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
+ break;
+ }
+ case HALLOFFAME:
+ HandleHallOfFame(!newbutton);
+ break;
+ case HELPSCREEN:
+ HandleHelpScreen(!newbutton);
+ break;
+ case PLAYING:
+ {
+ int mvx = 0, mvy = 0;
+ BOOL moved = FALSE, snapped = FALSE, bombed = FALSE;
+
+ if (tape.playing)
+ {
+ joy = TapePlayAction();
+
+ left = joy & JOY_LEFT;
+ right = joy & JOY_RIGHT;
+ up = joy & JOY_UP;
+ down = joy & JOY_DOWN;
+ button = joy & JOY_BUTTON;
+ button1 = joy & JOY_BUTTON_1;
+ button2 = joy & JOY_BUTTON_2;
+ }
+ else if (tape.pausing)
+ joy = 0;
+
+ if (!joy)
+ {
+ DigField(0,0,DF_NO_PUSH);
+ break;
+ }
+
+ if ((GameOver || LevelSolved) && newbutton)
+ {
+ CloseDoor(DOOR_CLOSE_1);
+ game_status = MAINMENU;
+ DrawMainMenu();
+ return;
+ }
+
+ if (left)
+ mvx = -1;
+ else if (right)
+ mvx = 1;
+ if (up)
+ mvy = -1;
+ else if (down)
+ mvy = 1;
+
+ if (button1)
+ snapped = SnapField(mvx,mvy);
+ else
+ {
+ if (button2)
+ bombed = PlaceBomb();
+ moved = MoveFigure(mvx,mvy);
+ }
+
+ if (tape.recording && (moved || snapped || bombed))
+ {
+ if (bombed && !moved)
+ joy &= JOY_BUTTON;
+ TapeRecordAction(joy);
+ }
+ else if (tape.playing && snapped)
+ SnapField(0,0);
+
+ break;
+ }
+ default:
+ break;
+ }
+}
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* events.h *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#ifndef EVENTS_H
+#define EVENTS_H
+
+#include "main.h"
+
+void EventLoop(void);
+void ClearEventQueue(void);
+void SleepWhileUnmapped(void);
+
+void HandleExposeEvent(XExposeEvent *);
+void HandleButtonEvent(XButtonEvent *);
+void HandleMotionEvent(XMotionEvent *);
+void HandleKeyEvent(XKeyEvent *);
+void HandleFocusEvent(int);
+void HandleNoXEvent(void);
+
+void HandleButton(int, int, int);
+void HandleKey(KeySym);
+void HandleJoystick();
+
+#endif
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* game.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#include "game.h"
+#include "misc.h"
+#include "tools.h"
+#include "screens.h"
+#include "sound.h"
+#include "init.h"
+
+BOOL CreateNewScoreFile()
+{
+ int i,j,k;
+ char filename[MAX_FILENAME];
+ char empty_alias[MAX_NAMELEN];
+ FILE *file;
+
+ sprintf(filename,"%s/%s/%s",
+ SCORE_PATH,leveldir[leveldir_nr].filename,SCORE_FILENAME);
+
+ if (!(file=fopen(filename,"w")))
+ return(FALSE);
+
+ for(i=0;i<MAX_NAMELEN;i++)
+ empty_alias[i] = 0;
+ strncpy(empty_alias,EMPTY_ALIAS,MAX_NAMELEN-1);
+
+ fputs(SCORE_COOKIE,file); /* Formatkennung */
+ for(i=0;i<LEVELDIR_SIZE(leveldir[leveldir_nr]);i++)
+ {
+ for(j=0;j<MAX_SCORE_ENTRIES;j++)
+ {
+ for(k=0;k<MAX_NAMELEN;k++)
+ fputc(empty_alias[k],file);
+ fputc(0,file);
+ fputc(0,file);
+ }
+ }
+ fclose(file);
+
+ chmod(filename, SCORE_PERMS);
+ return(TRUE);
+}
+
+BOOL CreateNewNamesFile(int mode)
+{
+ char filename[MAX_FILENAME];
+ FILE *file;
+
+ if (mode==PLAYER_LEVEL)
+ sprintf(filename,"%s/%s/%s",
+ NAMES_PATH,leveldir[leveldir_nr].filename,NAMES_FILENAME);
+ else
+ sprintf(filename,"%s/%s",CONFIG_PATH,NAMES_FILENAME);
+
+ if (!(file=fopen(filename,"w")))
+ return(FALSE);
+
+ fputs(NAMES_COOKIE,file); /* Formatkennung */
+ fclose(file);
+
+ chmod(filename, NAMES_PERMS);
+ return(TRUE);
+}
+
+void LoadLevelInfo()
+{
+ int i;
+ char filename[MAX_FILENAME];
+ char cookie[MAX_FILENAME];
+ FILE *file;
+
+ sprintf(filename,"%s/%s",LEVEL_PATH,LEVDIR_FILENAME);
+
+ if (!(file=fopen(filename,"r")))
+ {
+ fprintf(stderr,"%s: cannot load level info '%s'!\n",progname,filename);
+ CloseAll();
+ }
+
+ fscanf(file,"%s\n",cookie);
+ if (strcmp(cookie,LEVELDIR_COOKIE)) /* ungültiges Format? */
+ {
+ fprintf(stderr,"%s: wrong format of level info file!\n",progname);
+ fclose(file);
+ CloseAll();
+ }
+
+ num_leveldirs = 0;
+ leveldir_nr = 0;
+ for(i=0;i<MAX_LEVDIR_ENTRIES;i++)
+ {
+ fscanf(file,"%s",leveldir[i].filename);
+ fscanf(file,"%s",leveldir[i].name);
+ fscanf(file,"%d",&leveldir[i].num_ready);
+ fscanf(file,"%d",&leveldir[i].num_free);
+ if (feof(file))
+ break;
+
+ num_leveldirs++;
+ }
+
+ if (!num_leveldirs)
+ {
+ fprintf(stderr,"%s: empty level info '%s'!\n",progname,filename);
+ CloseAll();
+ }
+}
+
+void LoadLevel(int level_nr)
+{
+ int i,x,y;
+ char filename[MAX_FILENAME];
+ char cookie[MAX_FILENAME];
+ FILE *file;
+
+ sprintf(filename,"%s/%s/%d",
+ LEVEL_PATH,leveldir[leveldir_nr].filename,level_nr);
+
+ if (!(file=fopen(filename,"r")))
+ {
+/*
+ fprintf(stderr,"%s: cannot load level '%s'!\n",progname,filename);
+*/
+ }
+ else
+ {
+ fgets(cookie,LEVEL_COOKIE_LEN,file);
+ fgetc(file);
+ if (strcmp(cookie,LEVEL_COOKIE)) /* ungültiges Format? */
+ {
+ fprintf(stderr,"%s: wrong format of level file '%s'!\n",
+ progname,filename);
+ fclose(file);
+ file = NULL;
+ }
+ }
+
+ if (file)
+ {
+ lev_fieldx = level.fieldx = fgetc(file);
+ lev_fieldy = level.fieldy = fgetc(file);
+
+ level.time = (fgetc(file)<<8) | fgetc(file);
+ level.edelsteine = (fgetc(file)<<8) | fgetc(file);
+ for(i=0;i<MAX_LEVNAMLEN;i++)
+ level.name[i] = fgetc(file);
+ for(i=0;i<MAX_SC_ENTRIES;i++)
+ level.score[i] = fgetc(file);
+ for(i=0;i<4;i++)
+ for(y=0;y<3;y++)
+ for(x=0;x<3;x++)
+ level.mampfer_inhalt[i][x][y] = fgetc(file);
+ level.tempo_amoebe = fgetc(file);
+ level.dauer_sieb = fgetc(file);
+ level.dauer_ablenk = fgetc(file);
+
+ for(i=0;i<19;i++) /* Rest reserviert / Headergröße 80 Bytes */
+ fgetc(file);
+
+ for(y=0;y<lev_fieldy;y++)
+ for(x=0;x<lev_fieldx;x++)
+ Feld[x][y] = Ur[x][y] = fgetc(file);
+
+ fclose(file);
+
+ if (level.time<=10) /* Mindestspieldauer */
+ level.time = 10;
+ }
+ else
+ {
+ lev_fieldx = level.fieldx = STD_LEV_FIELDX;
+ lev_fieldy = level.fieldy = STD_LEV_FIELDY;
+
+ level.time = 100;
+ level.edelsteine = 0;
+ strncpy(level.name,"Nameless Level",MAX_LEVNAMLEN-1);
+ for(i=0;i<MAX_SC_ENTRIES;i++)
+ level.score[i] = 10;
+ for(i=0;i<4;i++)
+ for(y=0;y<3;y++)
+ for(x=0;x<3;x++)
+ level.mampfer_inhalt[i][x][y] = EL_FELSBROCKEN;
+ level.tempo_amoebe = 10;
+ level.dauer_sieb = 10;
+ level.dauer_ablenk = 10;
+
+ for(y=0;y<STD_LEV_FIELDY;y++)
+ for(x=0;x<STD_LEV_FIELDX;x++)
+ Feld[x][y] = Ur[x][y] = EL_ERDREICH;
+ Feld[0][0] = Ur[0][0] = EL_SPIELFIGUR;
+ Feld[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] =
+ Ur[STD_LEV_FIELDX-1][STD_LEV_FIELDY-1] = EL_AUSGANG_ZU;
+ }
+}
+
+void LoadLevelTape(int level_nr)
+{
+ int i;
+ char filename[MAX_FILENAME];
+ char cookie[MAX_FILENAME];
+ FILE *file;
+
+ sprintf(filename,"%s/%s/%d.tape",
+ LEVEL_PATH,leveldir[leveldir_nr].filename,level_nr);
+
+ if ((file=fopen(filename,"r")))
+ {
+ fgets(cookie,LEVELREC_COOKIE_LEN,file);
+ fgetc(file);
+ if (strcmp(cookie,LEVELREC_COOKIE)) /* ungültiges Format? */
+ {
+ fprintf(stderr,"%s: wrong format of level recording file '%s'!\n",
+ progname,filename);
+ fclose(file);
+ file = NULL;
+ }
+ }
+
+ if (!file)
+ return;
+
+ tape.random_seed =
+ (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
+ tape.date =
+ (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
+ tape.length =
+ (fgetc(file)<<24) | (fgetc(file)<<16) | (fgetc(file)<<8) | fgetc(file);
+
+ tape.level_nr = level_nr;
+ tape.counter = 0;
+ tape.recording = FALSE;
+ tape.playing = FALSE;
+ tape.pausing = FALSE;
+
+ for(i=0;i<tape.length;i++)
+ {
+ if (i>=MAX_TAPELEN)
+ break;
+ tape.pos[i].joystickdata = fgetc(file);
+ tape.pos[i].delay = fgetc(file);
+ if (feof(file))
+ break;
+ }
+
+ if (i != tape.length)
+ fprintf(stderr,"%s: level recording file '%s' corrupted!\n",
+ progname,filename);
+
+ fclose(file);
+
+ master_tape = tape;
+}
+
+void LoadScore(int level_nr)
+{
+ int i,j;
+ char filename[MAX_FILENAME];
+ char cookie[MAX_FILENAME];
+ FILE *file;
+
+ sprintf(filename,"%s/%s/%s",
+ SCORE_PATH,leveldir[leveldir_nr].filename,SCORE_FILENAME);
+
+ if (!(file=fopen(filename,"r")))
+ {
+ if (!CreateNewScoreFile())
+ {
+ fprintf(stderr,"%s: cannot create score file '%s'!\n",
+ progname,filename);
+ }
+ else if (!(file=fopen(filename,"r")))
+ {
+ fprintf(stderr,"%s: cannot load score for level %d!\n",
+ progname,level_nr);
+ }
+ }
+
+ if (file)
+ {
+ fgets(cookie,SCORE_COOKIE_LEN,file);
+ if (strcmp(cookie,SCORE_COOKIE)) /* ungültiges Format? */
+ {
+ fprintf(stderr,"%s: wrong format of score file!\n",progname);
+ fclose(file);
+ file = NULL;
+ }
+ }
+
+ if (file)
+ {
+ fseek(file,
+ SCORE_COOKIE_LEN-1+level_nr*(MAX_SCORE_ENTRIES*(MAX_NAMELEN+2)),
+ SEEK_SET);
+ for(i=0;i<MAX_SCORE_ENTRIES;i++)
+ {
+ for(j=0;j<MAX_NAMELEN;j++)
+ highscore[i].Name[j] = fgetc(file);
+ highscore[i].Score = (fgetc(file)<<8) | fgetc(file);
+ }
+ fclose(file);
+ }
+ else
+ {
+ for(i=0;i<MAX_SCORE_ENTRIES;i++)
+ {
+ strcpy(highscore[i].Name,EMPTY_ALIAS);
+ highscore[i].Score = 0;
+ }
+ }
+}
+
+void LoadPlayerInfo(int mode)
+{
+ int i;
+ char filename[MAX_FILENAME];
+ char cookie[MAX_FILENAME];
+ FILE *file;
+ char *login_name = GetLoginName();
+ struct PlayerInfo default_player, new_player;
+
+ if (mode==PLAYER_LEVEL)
+ sprintf(filename,"%s/%s/%s",
+ NAMES_PATH,leveldir[leveldir_nr].filename,NAMES_FILENAME);
+ else
+ sprintf(filename,"%s/%s",CONFIG_PATH,NAMES_FILENAME);
+
+ for(i=0;i<MAX_NAMELEN;i++)
+ default_player.login_name[i] = default_player.alias_name[i] = 0;
+ strncpy(default_player.login_name,login_name,MAX_NAMELEN-1);
+ strncpy(default_player.alias_name,login_name,MAX_NAMELEN-1);
+ default_player.handicap = 0;
+ default_player.setup = DEFAULT_SETUP;
+ default_player.leveldir_nr = 0;
+
+ new_player = default_player;
+
+ if (!(file=fopen(filename,"r")))
+ {
+ if (!CreateNewNamesFile(mode))
+ {
+ fprintf(stderr,"%s: cannot create names file '%s'!\n",
+ progname,filename);
+ }
+ else if (!(file=fopen(filename,"r")))
+ {
+ fprintf(stderr,"%s: cannot load player information '%s'!\n",
+ progname,filename);
+ }
+ }
+
+ if (file)
+ {
+ fgets(cookie,NAMES_COOKIE_LEN,file);
+ if (strcmp(cookie,NAMES_COOKIE)) /* ungültiges Format? */
+ {
+ fprintf(stderr,"%s: wrong format of names file '%s'!\n",
+ progname,filename);
+ fclose(file);
+ file = NULL;
+ }
+ }
+
+ if (!file)
+ {
+ player = default_player;
+ level_nr = default_player.handicap;
+ return;
+ }
+
+ while(1)
+ {
+ for(i=0;i<MAX_NAMELEN;i++)
+ new_player.login_name[i] = fgetc(file);
+ for(i=0;i<MAX_NAMELEN;i++)
+ new_player.alias_name[i] = fgetc(file);
+ new_player.handicap = fgetc(file);
+ new_player.setup = (fgetc(file)<<8) | fgetc(file);
+ new_player.leveldir_nr = fgetc(file);
+
+ if (feof(file)) /* Spieler noch nicht in Liste enthalten */
+ {
+ new_player = default_player;
+
+ fclose(file);
+ if (!(file=fopen(filename,"a")))
+ {
+ fprintf(stderr,"%s: cannot append new player to names file '%s'!\n",
+ progname,filename);
+ }
+ else
+ {
+ for(i=0;i<MAX_NAMELEN;i++)
+ fputc(new_player.login_name[i],file);
+ for(i=0;i<MAX_NAMELEN;i++)
+ fputc(new_player.alias_name[i],file);
+ fputc(new_player.handicap,file);
+ fputc(new_player.setup / 256,file);
+ fputc(new_player.setup % 256,file);
+ fputc(new_player.leveldir_nr,file);
+ }
+ break;
+ }
+ else /* prüfen, ob Spieler in Liste enthalten */
+ if (!strncmp(new_player.login_name,login_name,MAX_NAMELEN-1))
+ break;
+ }
+
+ if (mode==PLAYER_SETUP)
+ {
+ player = new_player;
+ if (player.leveldir_nr < num_leveldirs)
+ leveldir_nr = player.leveldir_nr;
+ else
+ leveldir_nr = 0;
+ }
+ else
+ player.handicap = new_player.handicap;
+
+ level_nr = player.handicap;
+ fclose(file);
+}
+
+void SaveLevel(int level_nr)
+{
+ int i,x,y;
+ char filename[MAX_FILENAME];
+ FILE *file;
+
+ sprintf(filename,"%s/%s/%d",
+ LEVEL_PATH,leveldir[leveldir_nr].filename,level_nr);
+
+ if (!(file=fopen(filename,"w")))
+ {
+ fprintf(stderr,"%s: cannot save level file '%s'!\n",progname,filename);
+ return;
+ }
+
+ fputs(LEVEL_COOKIE,file); /* Formatkennung */
+ fputc(0x0a,file);
+
+ fputc(level.fieldx,file);
+ fputc(level.fieldy,file);
+ fputc(level.time / 256,file);
+ fputc(level.time % 256,file);
+ fputc(level.edelsteine / 256,file);
+ fputc(level.edelsteine % 256,file);
+
+ for(i=0;i<MAX_LEVNAMLEN;i++)
+ fputc(level.name[i],file);
+ for(i=0;i<MAX_SC_ENTRIES;i++)
+ fputc(level.score[i],file);
+ for(i=0;i<4;i++)
+ for(y=0;y<3;y++)
+ for(x=0;x<3;x++)
+ fputc(level.mampfer_inhalt[i][x][y],file);
+ fputc(level.tempo_amoebe,file);
+ fputc(level.dauer_sieb,file);
+ fputc(level.dauer_ablenk,file);
+
+ for(i=0;i<19;i++) /* Rest reserviert / Headergröße 80 Bytes */
+ fputc(0,file);
+
+ for(y=0;y<lev_fieldy;y++)
+ for(x=0;x<lev_fieldx;x++)
+ fputc(Ur[x][y],file);
+
+ fclose(file);
+
+ chmod(filename, LEVEL_PERMS);
+}
+
+void SaveLevelTape(int level_nr)
+{
+ int i;
+ char filename[MAX_FILENAME];
+ FILE *file;
+ BOOL new_tape = TRUE;
+
+ sprintf(filename,"%s/%s/%d.tape",
+ LEVEL_PATH,leveldir[leveldir_nr].filename,level_nr);
+
+ /* Testen, ob bereits eine Aufnahme existiert */
+ if ((file=fopen(filename,"r")))
+ {
+ new_tape = FALSE;
+ fclose(file);
+
+ if (!AreYouSure("Replace old tape ?",AYS_ASK))
+ return;
+ }
+
+ if (!(file=fopen(filename,"w")))
+ {
+ fprintf(stderr,"%s: cannot save level recording file '%s'!\n",
+ progname,filename);
+ return;
+ }
+
+ fputs(LEVELREC_COOKIE,file); /* Formatkennung */
+ fputc(0x0a,file);
+
+ tape = master_tape;
+
+ fputc((tape.random_seed >> 24) & 0xff,file);
+ fputc((tape.random_seed >> 16) & 0xff,file);
+ fputc((tape.random_seed >> 8) & 0xff,file);
+ fputc((tape.random_seed >> 0) & 0xff,file);
+
+ fputc((tape.date >> 24) & 0xff,file);
+ fputc((tape.date >> 16) & 0xff,file);
+ fputc((tape.date >> 8) & 0xff,file);
+ fputc((tape.date >> 0) & 0xff,file);
+
+ fputc((tape.length >> 24) & 0xff,file);
+ fputc((tape.length >> 16) & 0xff,file);
+ fputc((tape.length >> 8) & 0xff,file);
+ fputc((tape.length >> 0) & 0xff,file);
+
+ for(i=0;i<tape.length;i++)
+ {
+ fputc(tape.pos[i].joystickdata,file);
+ fputc(tape.pos[i].delay,file);
+ }
+
+ fclose(file);
+
+ chmod(filename, LEVREC_PERMS);
+
+ if (new_tape)
+ AreYouSure("tape saved !",AYS_CONFIRM);
+}
+
+void SaveScore(int level_nr)
+{
+ int i,j;
+ char filename[MAX_FILENAME];
+ FILE *file;
+
+ sprintf(filename,"%s/%s/%s",
+ SCORE_PATH,leveldir[leveldir_nr].filename,SCORE_FILENAME);
+
+ if (!(file=fopen(filename,"r+")))
+ {
+ fprintf(stderr,"%s: cannot save score for level %d!\n",
+ progname,level_nr);
+ return;
+ }
+
+ fseek(file,
+ SCORE_COOKIE_LEN-1+level_nr*(MAX_SCORE_ENTRIES*(MAX_NAMELEN+2)),
+ SEEK_SET);
+ for(i=0;i<MAX_SCORE_ENTRIES;i++)
+ {
+ for(j=0;j<MAX_NAMELEN;j++)
+ fputc(highscore[i].Name[j],file);
+ fputc(highscore[i].Score / 256,file);
+ fputc(highscore[i].Score % 256,file);
+ }
+ fclose(file);
+}
+
+void SavePlayerInfo(int mode)
+{
+ int i;
+ char filename[MAX_FILENAME];
+ char cookie[MAX_FILENAME];
+ FILE *file;
+ struct PlayerInfo default_player;
+
+ if (mode==PLAYER_LEVEL)
+ sprintf(filename,"%s/%s/%s",
+ NAMES_PATH,leveldir[leveldir_nr].filename,NAMES_FILENAME);
+ else
+ sprintf(filename,"%s/%s",CONFIG_PATH,NAMES_FILENAME);
+
+ if (!(file=fopen(filename,"r+")))
+ {
+ fprintf(stderr,"%s: cannot save player information '%s'!\n",
+ progname,filename);
+ return;
+ }
+
+ fgets(cookie,NAMES_COOKIE_LEN,file);
+ if (strcmp(cookie,NAMES_COOKIE)) /* ungültiges Format? */
+ {
+ fprintf(stderr,"%s: wrong format of names file '%s'!\n",
+ progname,filename);
+ fclose(file);
+ return;
+ }
+
+ while(1)
+ {
+ for(i=0;i<MAX_NAMELEN;i++)
+ default_player.login_name[i] = fgetc(file);
+ for(i=0;i<MAX_NAMELEN;i++)
+ default_player.alias_name[i] = fgetc(file);
+ default_player.handicap = fgetc(file);
+ default_player.setup = (fgetc(file)<<8) | fgetc(file);
+ default_player.leveldir_nr = fgetc(file);
+
+ if (feof(file)) /* Spieler noch nicht in Liste enthalten */
+ break;
+ else /* prüfen, ob Spieler in Liste enthalten */
+ if (!strncmp(default_player.login_name,player.login_name,MAX_NAMELEN-1))
+ {
+ fseek(file,-(2*MAX_NAMELEN+1+2+1),SEEK_CUR);
+ break;
+ }
+ }
+
+ for(i=0;i<MAX_NAMELEN;i++)
+ fputc(player.login_name[i],file);
+ for(i=0;i<MAX_NAMELEN;i++)
+ fputc(player.alias_name[i],file);
+ fputc(player.handicap,file);
+ fputc(player.setup / 256,file);
+ fputc(player.setup % 256,file);
+ fputc(player.leveldir_nr,file);
+
+ fclose(file);
+}
+
+void GetPlayerConfig()
+{
+ int old_joystick_nr = joystick_nr;
+
+ if (sound_status==SOUND_OFF)
+ player.setup &= ~SETUP_SOUND;
+ if (!sound_loops_allowed)
+ {
+ player.setup &= ~SETUP_SOUND_LOOPS;
+ player.setup &= ~SETUP_SOUND_MUSIC;
+ }
+
+ sound_on = SETUP_SOUND_ON(player.setup);
+ sound_loops_on = SETUP_SOUND_LOOPS_ON(player.setup);
+ sound_music_on = SETUP_SOUND_MUSIC_ON(player.setup);
+ toons_on = SETUP_TOONS_ON(player.setup);
+ direct_draw_on = SETUP_DIRECT_DRAW_ON(player.setup);
+ fading_on = SETUP_FADING_ON(player.setup);
+ autorecord_on = SETUP_RECORD_EACH_GAME_ON(player.setup);
+ joystick_nr = SETUP_2ND_JOYSTICK_ON(player.setup);
+
+ if (joystick_nr != old_joystick_nr)
+ {
+ if (joystick_device)
+ close(joystick_device);
+ InitJoystick();
+ }
+}
+
+void InitGame()
+{
+ int x,y;
+
+ Dynamite = Score = 0;
+ Gems = level.edelsteine;
+ Key[0] = Key[1] = Key[2] = Key[3] = FALSE;
+ MampferNr = 0;
+ TimeLeft = level.time;
+ CheckMoving = TRUE;
+ CheckExploding = FALSE;
+ LevelSolved = GameOver = SiebAktiv = FALSE;
+ JX = JY = 0;
+ ZX = ZY = -1;
+
+ if (tape.recording)
+ TapeStartRecording();
+ else if (tape.playing)
+ TapeStartPlaying();
+
+ DigField(0,0,DF_NO_PUSH);
+ SnapField(0,0);
+
+ for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
+ {
+ Feld[x][y]=Ur[x][y];
+ MovPos[x][y]=MovDir[x][y]=MovDelay[x][y]=0;
+ Store[x][y]=Store2[x][y]=Frame[x][y]=0;
+
+ switch(Feld[x][y])
+ {
+ case EL_SPIELFIGUR:
+ case EL_SPIELER1:
+ Feld[x][y] = EL_LEERRAUM;
+ JX = x;
+ JY = y;
+ break;
+ case EL_SPIELER2:
+ Feld[x][y] = EL_LEERRAUM;
+ break;
+ case EL_BADEWANNE:
+ if (x<lev_fieldx-1 && Feld[x+1][y]==EL_SALZSAEURE)
+ Feld[x][y] = EL_BADEWANNE1;
+ else if (x>0 && Feld[x-1][y]==EL_SALZSAEURE)
+ Feld[x][y] = EL_BADEWANNE2;
+ else if (y>0 && Feld[x][y-1]==EL_BADEWANNE1)
+ Feld[x][y] = EL_BADEWANNE3;
+ else if (y>0 && Feld[x][y-1]==EL_SALZSAEURE)
+ Feld[x][y] = EL_BADEWANNE4;
+ else if (y>0 && Feld[x][y-1]==EL_BADEWANNE2)
+ Feld[x][y] = EL_BADEWANNE5;
+ break;
+ case EL_KAEFER_R:
+ case EL_KAEFER_O:
+ case EL_KAEFER_L:
+ case EL_KAEFER_U:
+ case EL_KAEFER:
+ case EL_FLIEGER_R:
+ case EL_FLIEGER_O:
+ case EL_FLIEGER_L:
+ case EL_FLIEGER_U:
+ case EL_FLIEGER:
+ case EL_PACMAN_R:
+ case EL_PACMAN_O:
+ case EL_PACMAN_L:
+ case EL_PACMAN_U:
+ case EL_MAMPFER:
+ case EL_ZOMBIE:
+ case EL_PACMAN:
+ InitMovDir(x,y);
+ break;
+ default:
+ break;
+ }
+ }
+
+ scroll_x = scroll_y = -1;
+ if (JX>=MIDPOSX-1)
+ scroll_x =
+ (JX<=lev_fieldx-MIDPOSX ? JX-MIDPOSX : lev_fieldx-SCR_FIELDX+1);
+ if (JY>=MIDPOSY-1)
+ scroll_y =
+ (JY<=lev_fieldy-MIDPOSY ? JY-MIDPOSY : lev_fieldy-SCR_FIELDY+1);
+
+ DrawLevel();
+ DrawLevelElement(JX,JY,EL_SPIELFIGUR);
+ FadeToFront();
+
+ XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX5,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
+ DrawTextExt(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1+XX_LEVEL,DOOR_GFX_PAGEY1+YY_LEVEL,
+ int2str(level_nr,2),FS_SMALL,FC_YELLOW);
+ DrawTextExt(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1+XX_EMERALDS,DOOR_GFX_PAGEY1+YY_EMERALDS,
+ int2str(Gems,3),FS_SMALL,FC_YELLOW);
+ DrawTextExt(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1+XX_DYNAMITE,DOOR_GFX_PAGEY1+YY_DYNAMITE,
+ int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
+ DrawTextExt(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1+XX_SCORE,DOOR_GFX_PAGEY1+YY_SCORE,
+ int2str(Score,5),FS_SMALL,FC_YELLOW);
+ DrawTextExt(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1+XX_TIME,DOOR_GFX_PAGEY1+YY_TIME,
+ int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
+
+ DrawGameButton(BUTTON_GAME_STOP);
+ DrawGameButton(BUTTON_GAME_PAUSE);
+ DrawGameButton(BUTTON_GAME_PLAY);
+ DrawSoundDisplay(BUTTON_SOUND_MUSIC | (BUTTON_ON * sound_music_on));
+ DrawSoundDisplay(BUTTON_SOUND_LOOPS | (BUTTON_ON * sound_loops_on));
+ DrawSoundDisplay(BUTTON_SOUND_SOUND | (BUTTON_ON * sound_on));
+ XCopyArea(display,drawto,pix[PIX_DB_DOOR],gc,
+ DX+GAME_CONTROL_XPOS,DY+GAME_CONTROL_YPOS,
+ GAME_CONTROL_XSIZE,2*GAME_CONTROL_YSIZE,
+ DOOR_GFX_PAGEX1+GAME_CONTROL_XPOS,
+ DOOR_GFX_PAGEY1+GAME_CONTROL_YPOS);
+
+ OpenDoor(DOOR_OPEN_1);
+
+ if (sound_music_on)
+ PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
+
+ XAutoRepeatOff(display);
+}
+
+void InitMovDir(int x, int y)
+{
+ int i, element = Feld[x][y];
+ static int xy[4][2] =
+ {
+ 0,+1,
+ +1,0,
+ 0,-1,
+ -1,0
+ };
+ static int direction[2][4] =
+ {
+ MV_RIGHT, MV_UP, MV_LEFT, MV_DOWN,
+ MV_LEFT, MV_DOWN, MV_RIGHT, MV_UP
+ };
+
+ switch(element)
+ {
+ case EL_KAEFER_R:
+ case EL_KAEFER_O:
+ case EL_KAEFER_L:
+ case EL_KAEFER_U:
+ Feld[x][y] = EL_KAEFER;
+ MovDir[x][y] = direction[0][element-EL_KAEFER_R];
+ break;
+ case EL_FLIEGER_R:
+ case EL_FLIEGER_O:
+ case EL_FLIEGER_L:
+ case EL_FLIEGER_U:
+ Feld[x][y] = EL_FLIEGER;
+ MovDir[x][y] = direction[0][element-EL_FLIEGER_R];
+ break;
+ case EL_PACMAN_R:
+ case EL_PACMAN_O:
+ case EL_PACMAN_L:
+ case EL_PACMAN_U:
+ Feld[x][y] = EL_PACMAN;
+ MovDir[x][y] = direction[0][element-EL_PACMAN_R];
+ break;
+ default:
+ MovDir[x][y] = 1<<RND(4);
+ if (element!=EL_KAEFER && element!=EL_FLIEGER)
+ break;
+
+ for(i=0;i<4;i++)
+ {
+ int x1,y1;
+
+ x1 = x+xy[i][0];
+ y1 = y+xy[i][1];
+
+ if (!IN_LEV_FIELD(x1,y1) || !IS_FREE(x1,y1))
+ {
+ if (element==EL_KAEFER)
+ {
+ MovDir[x][y] = direction[0][i];
+ break;
+ }
+ else if (element==EL_FLIEGER)
+ {
+ MovDir[x][y] = direction[1][i];
+ break;
+ }
+ }
+ }
+ break;
+ }
+}
+
+void GameWon()
+{
+ int hi_pos;
+ int bumplevel = FALSE;
+
+ if (sound_loops_on)
+ PlaySoundExt(SND_SIRR,PSND_MAX_VOLUME,PSND_MAX_RIGHT,PSND_LOOP);
+
+ if (TimeLeft>0)
+ {
+ for(;TimeLeft>=0;TimeLeft--)
+ {
+ if (!sound_loops_on)
+ PlaySoundStereo(SND_SIRR,PSND_MAX_RIGHT);
+ if (TimeLeft && !(TimeLeft % 10))
+ RaiseScore(level.score[SC_ZEITBONUS]);
+ DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
+ BackToFront();
+ Delay(10000);
+ }
+ }
+
+ if (sound_loops_on)
+ StopSound(SND_SIRR);
+ FadeSounds();
+
+ if (tape.playing)
+ return;
+
+ CloseDoor(DOOR_CLOSE_1);
+
+ if (level_nr==player.handicap &&
+ level_nr<leveldir[leveldir_nr].num_ready)
+ {
+ player.handicap++;
+ bumplevel = TRUE;
+ SavePlayerInfo(PLAYER_LEVEL);
+ }
+
+ if ((hi_pos=NewHiScore())>=0)
+ {
+ game_status = HALLOFFAME;
+ DrawHallOfFame(hi_pos);
+ if (bumplevel && TAPE_IS_EMPTY(tape))
+ level_nr++;
+ }
+ else
+ {
+ game_status = MAINMENU;
+ if (bumplevel && TAPE_IS_EMPTY(tape))
+ level_nr++;
+ DrawMainMenu();
+ }
+ BackToFront();
+}
+
+BOOL NewHiScore()
+{
+ int k,l;
+ int position = -1;
+
+ LoadScore(level_nr);
+
+ if (!strcmp(player.alias_name,EMPTY_ALIAS) ||
+ Score<highscore[MAX_SCORE_ENTRIES-1].Score)
+ return(-1);
+
+ for(k=0;k<MAX_SCORE_ENTRIES;k++)
+ {
+ if (Score>highscore[k].Score) /* Spieler kommt in Highscore-Liste */
+ {
+ if (k<MAX_SCORE_ENTRIES-1)
+ {
+ int m = MAX_SCORE_ENTRIES-1;
+
+#ifdef ONE_PER_NAME
+ for(l=k;l<MAX_SCORE_ENTRIES;l++)
+ if (!strcmp(player.alias_name,highscore[l].Name))
+ m = l;
+ if (m==k) /* Spieler überschreibt seine alte Position */
+ goto put_into_list;
+#endif
+
+ for(l=m;l>k;l--)
+ {
+ strcpy(highscore[l].Name,highscore[l-1].Name);
+ highscore[l].Score = highscore[l-1].Score;
+ }
+ }
+
+#ifdef ONE_PER_NAME
+ put_into_list:
+#endif
+ sprintf(highscore[k].Name,player.alias_name);
+ highscore[k].Score = Score;
+ position = k;
+ break;
+ }
+ }
+
+#ifdef ONE_PER_NAME
+ else if (!strcmp(player.alias_name,highscore[k].Name))
+ break; /* Spieler schon mit besserer Punktzahl in der Liste */
+#endif
+
+ if (position>=0)
+ SaveScore(level_nr);
+
+ return(position);
+}
+
+void InitMovingField(int x, int y, int direction)
+{
+ int newx = x + (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
+ int newy = y + (direction==MV_UP ? -1 : direction==MV_DOWN ? +1 : 0);
+
+ CheckMoving = TRUE;
+ MovDir[x][y] = direction;
+ MovDir[newx][newy] = direction;
+ if (Feld[newx][newy]==EL_LEERRAUM)
+ Feld[newx][newy] = EL_BLOCKED;
+}
+
+void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
+{
+ int direction = MovDir[x][y];
+ int newx = x + (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
+ int newy = y + (direction==MV_UP ? -1 : direction==MV_DOWN ? +1 : 0);
+
+ *goes_to_x = newx;
+ *goes_to_y = newy;
+}
+
+void Blocked2Moving(int x, int y, int *comes_from_x, int *comes_from_y)
+{
+ int oldx = x, oldy = y;
+ int direction = MovDir[x][y];
+
+ if (direction==MV_LEFT)
+ oldx++;
+ else if (direction==MV_RIGHT)
+ oldx--;
+ else if (direction==MV_UP)
+ oldy++;
+ else if (direction==MV_DOWN)
+ oldy--;
+
+ *comes_from_x = oldx;
+ *comes_from_y = oldy;
+}
+
+int MovingOrBlocked2Element(int x, int y)
+{
+ int element = Feld[x][y];
+
+ if (element==EL_BLOCKED)
+ {
+ int oldx,oldy;
+
+ Blocked2Moving(x,y,&oldx,&oldy);
+ return(Feld[oldx][oldy]);
+ }
+ else
+ return(element);
+}
+
+void RemoveMovingField(int x, int y)
+{
+ int oldx=x,oldy=y, newx=x,newy=y;
+
+ if (Feld[x][y]!=EL_BLOCKED && !IS_MOVING(x,y))
+ return;
+
+ if (IS_MOVING(x,y))
+ {
+ Moving2Blocked(x,y,&newx,&newy);
+ if (Feld[newx][newy]!=EL_BLOCKED)
+ return;
+ }
+ else if (Feld[x][y]==EL_BLOCKED)
+ {
+ Blocked2Moving(x,y,&oldx,&oldy);
+ if (!IS_MOVING(oldx,oldy))
+ return;
+ }
+
+ Feld[oldx][oldy] = EL_LEERRAUM;
+ Feld[newx][newy] = EL_LEERRAUM;
+ MovPos[oldx][oldy] = MovDir[oldx][oldy] = MovDelay[oldx][oldy] = 0;
+ MovPos[newx][newy] = MovDir[newx][newy] = MovDelay[newx][newy] = 0;
+ DrawLevelField(oldx,oldy);
+ DrawLevelField(newx,newy);
+}
+
+void DrawDynamite(int x, int y)
+{
+ int phase = (48-MovDelay[x][y])/6;
+
+ if (!IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ return;
+
+ if (phase>6)
+ phase = 6;
+
+ if (Store[x][y])
+ {
+ DrawGraphic(SCROLLX(x),SCROLLY(y),el2gfx(Store[x][y]));
+ if (PLAYER(x,y))
+ DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
+ }
+ else if (PLAYER(x,y))
+ DrawGraphic(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
+
+ if (Store[x][y] || PLAYER(x,y))
+ DrawGraphicThruMask(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
+ else
+ DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_DYNAMIT+phase);
+}
+
+void CheckDynamite(int x, int y)
+{
+ CheckExploding=TRUE;
+
+ if (MovDelay[x][y]) /* neues Dynamit / in Wartezustand */
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y])
+ {
+ if (!(MovDelay[x][y] % 6))
+ {
+ DrawDynamite(x,y);
+ PlaySoundLevel(x,y,SND_ZISCH);
+ }
+
+ return;
+ }
+ }
+
+ StopSound(SND_ZISCH);
+ Bang(x,y);
+}
+
+void Explode(int ex, int ey, int phase)
+{
+ int x,y;
+ int num_phase = 9, delay = 1;
+ int last_phase = num_phase*delay;
+ int half_phase = (num_phase/2)*delay;
+
+ if (phase==0) /* Feld 'Store' initialisieren */
+ {
+ int center_element = Feld[ex][ey];
+
+ if (center_element==EL_BLOCKED)
+ center_element = MovingOrBlocked2Element(ex,ey);
+
+ for(y=ey-1;y<ey+2;y++) for(x=ex-1;x<ex+2;x++)
+ {
+ int element = Feld[x][y];
+
+ if (!IN_LEV_FIELD(x,y) || IS_MASSIV(element))
+ continue;
+
+ if (element==EL_EXPLODING)
+ element = Store2[x][y];
+
+ if (PLAYER(ex,ey) || center_element==EL_KAEFER)
+ Store[x][y] = ((x==ex && y==ey) ? EL_DIAMANT : EL_EDELSTEIN);
+ else if (center_element==EL_MAMPFER)
+ Store[x][y] = level.mampfer_inhalt[MampferNr][x-ex+1][y-ey+1];
+ else if (Feld[x][y]==EL_ERZ_1)
+ Store[x][y] = EL_EDELSTEIN;
+ else if (Feld[x][y]==EL_ERZ_2)
+ Store[x][y] = EL_DIAMANT;
+ else if (!IS_PFORTE(Store[x][y]))
+ Store[x][y] = EL_LEERRAUM;
+
+ if (x!=ex || y!=ey)
+ Store2[x][y] = element;
+
+ RemoveMovingField(x,y);
+ Feld[x][y] = EL_EXPLODING;
+ MovDir[x][y] = MovPos[x][y] = 0;
+ Frame[x][y] = 1;
+ Stop[x][y] = TRUE;
+ }
+
+ if (center_element==EL_MAMPFER)
+ MampferNr = (MampferNr+1) % 4;
+
+ return;
+ }
+
+ if (Stop[ex][ey])
+ return;
+
+ x = ex;
+ y = ey;
+
+ Frame[x][y] = (phase<last_phase ? phase+1 : 0);
+
+ if (phase==half_phase)
+ {
+ int element = Store2[x][y];
+
+ if (PLAYER(x,y))
+ KillHero();
+ else if (element==EL_BOMBE ||
+ element==EL_DYNAMIT ||
+ element==EL_DYNAMIT_AUS ||
+ element==EL_KAEFER)
+ {
+ Feld[x][y] = Store2[x][y];
+ Store2[x][y] = 0;
+ Bang(x,y);
+ }
+ }
+
+ if (phase==last_phase)
+ {
+ int element;
+
+ element = Feld[x][y] = Store[x][y];
+ Store[x][y] = Store2[x][y] = 0;
+ MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
+ if (CAN_MOVE(element) || COULD_MOVE(element))
+ InitMovDir(x,y);
+ DrawLevelField(x,y);
+ }
+ else if (!(phase%delay) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ {
+ if (phase==delay)
+ ErdreichAnbroeckeln(SCROLLX(x),SCROLLY(y));
+
+ DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_EXPLOSION+(phase/delay-1));
+ }
+
+ CheckExploding=TRUE;
+}
+
+void Bang(int x, int y)
+{
+ int element = Feld[x][y];
+
+ CheckExploding=TRUE;
+ PlaySoundLevel(x,y,SND_ROAAAR);
+
+ switch(element)
+ {
+ case EL_KAEFER:
+ RaiseScore(level.score[SC_KAEFER]);
+ break;
+ case EL_FLIEGER:
+ RaiseScore(level.score[SC_FLIEGER]);
+ break;
+ case EL_MAMPFER:
+ RaiseScore(level.score[SC_MAMPFER]);
+ break;
+ case EL_ZOMBIE:
+ RaiseScore(level.score[SC_ZOMBIE]);
+ break;
+ case EL_PACMAN:
+ RaiseScore(level.score[SC_PACMAN]);
+ break;
+ default:
+ break;
+ }
+
+ Explode(x,y,0);
+}
+
+void Blurb(int x, int y)
+{
+ int element = Feld[x][y];
+
+ if (element!=EL_BLURB_LEFT && element!=EL_BLURB_RIGHT) /* Anfang */
+ {
+ PlaySoundLevel(x,y,SND_BLURB);
+ if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y) &&
+ (!IN_LEV_FIELD(x-1,y-1) ||
+ !CAN_FALL(MovingOrBlocked2Element(x-1,y-1))))
+ {
+ Feld[x-1][y] = EL_BLURB_LEFT;
+ }
+ if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y) &&
+ (!IN_LEV_FIELD(x+1,y-1) ||
+ !CAN_FALL(MovingOrBlocked2Element(x+1,y-1))))
+ {
+ Feld[x+1][y] = EL_BLURB_RIGHT;
+ }
+ }
+ else /* Blubbern */
+ {
+ int graphic = (element==EL_BLURB_LEFT ? GFX_BLURB_LEFT : GFX_BLURB_RIGHT);
+
+ CheckExploding=TRUE;
+
+ if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
+ MovDelay[x][y] = 5;
+
+ if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ DrawGraphic(SCROLLX(x),SCROLLY(y),graphic+4-MovDelay[x][y]);
+
+ if (!MovDelay[x][y])
+ {
+ Feld[x][y] = EL_LEERRAUM;
+ DrawLevelField(x,y);
+ }
+ }
+ }
+}
+
+void Impact(int x, int y)
+{
+ BOOL lastline = (y==lev_fieldy-1);
+ BOOL object_hit = FALSE;
+ int element = Feld[x][y];
+
+ /* Element darunter berührt? */
+ if (!lastline)
+ object_hit = (!IS_FREE(x,y+1) && (!IS_MOVING(x,y+1) ||
+ MovDir[x][y+1]!=MV_DOWN ||
+ MovPos[x][y+1]<=TILEY/2));
+
+ /* Auftreffendes Element fällt in Salzsäure */
+ if (!lastline && Feld[x][y+1]==EL_SALZSAEURE)
+ {
+ Blurb(x,y);
+ return;
+ }
+
+ /* Auftreffendes Element ist Bombe */
+ if (element==EL_BOMBE && (lastline || object_hit))
+ {
+ Bang(x,y);
+ return;
+ }
+
+ /* Auftreffendes Element ist Säuretropfen */
+ if (element==EL_TROPFEN && (lastline || object_hit))
+ {
+ if (object_hit && PLAYER(x,y+1))
+ KillHero();
+ else
+ Feld[x][y] = EL_AMOEBING2;
+ return;
+ }
+
+ /* Welches Element kriegt was auf die Rübe? */
+ if (!lastline && object_hit)
+ {
+ int smashed = Feld[x][y+1];
+
+ if (PLAYER(x,y+1))
+ {
+ KillHero();
+ return;
+ }
+ else if (element==EL_FELSBROCKEN)
+ {
+ if (IS_ENEMY(MovingOrBlocked2Element(x,y+1)))
+ {
+ Bang(x,y+1);
+ return;
+ }
+ else if (!IS_MOVING(x,y+1))
+ {
+ if (smashed==EL_BOMBE)
+ {
+ Bang(x,y+1);
+ return;
+ }
+ else if (smashed==EL_KOKOSNUSS)
+ {
+ Feld[x][y+1] = EL_CRACKINGNUT;
+ PlaySoundLevel(x,y,SND_KNACK);
+ RaiseScore(level.score[SC_KOKOSNUSS]);
+ return;
+ }
+ else if (smashed==EL_DIAMANT)
+ {
+ Feld[x][y+1] = EL_LEERRAUM;
+ PlaySoundLevel(x,y,SND_QUIRK);
+ return;
+ }
+ }
+ }
+ }
+
+ /* Kein Geräusch beim Durchqueren des Siebes */
+ if (!lastline && Feld[x][y+1]==EL_SIEB_LEER)
+ return;
+
+ /* Geräusch beim Auftreffen */
+ if (lastline || object_hit)
+ {
+ int sound;
+
+ switch(element)
+ {
+ case EL_EDELSTEIN:
+ case EL_DIAMANT:
+ sound = SND_PLING;
+ break;
+ case EL_KOKOSNUSS:
+ sound = SND_KLUMPF;
+ break;
+ case EL_FELSBROCKEN:
+ sound = SND_KLOPF;
+ break;
+ case EL_SCHLUESSEL:
+ case EL_SCHLUESSEL1:
+ case EL_SCHLUESSEL2:
+ case EL_SCHLUESSEL3:
+ case EL_SCHLUESSEL4:
+ sound = SND_KINK;
+ break;
+ default:
+ sound = -1;
+ break;
+ }
+
+ if (sound>=0)
+ PlaySoundLevel(x,y,sound);
+ }
+}
+
+void TurnRound(int x, int y)
+{
+ int element = Feld[x][y];
+ int direction = MovDir[x][y];
+
+ if (element==EL_KAEFER)
+ {
+ TestIfBadThingHitsOtherBadThing(x,y);
+
+ if (MovDir[x][y]==MV_LEFT)
+ {
+ if (IN_LEV_FIELD(x,y-1) && IS_FREE(x,y-1))
+ MovDir[x][y]=MV_UP;
+ else if (!IN_LEV_FIELD(x-1,y) || !IS_FREE(x-1,y))
+ MovDir[x][y]=MV_DOWN;
+ }
+ else if (MovDir[x][y]==MV_RIGHT)
+ {
+ if (IN_LEV_FIELD(x,y+1) && IS_FREE(x,y+1))
+ MovDir[x][y]=MV_DOWN;
+ else if (!IN_LEV_FIELD(x+1,y) || !IS_FREE(x+1,y))
+ MovDir[x][y]=MV_UP;
+ }
+ else if (MovDir[x][y]==MV_UP)
+ {
+ if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y))
+ MovDir[x][y]=MV_RIGHT;
+ else if (!IN_LEV_FIELD(x,y-1) || !IS_FREE(x,y-1))
+ MovDir[x][y]=MV_LEFT;
+ }
+ else if (MovDir[x][y]==MV_DOWN)
+ {
+ if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y))
+ MovDir[x][y]=MV_LEFT;
+ else if (!IN_LEV_FIELD(x,y+1) || !IS_FREE(x,y+1))
+ MovDir[x][y]=MV_RIGHT;
+ }
+
+ if (direction!=MovDir[x][y])
+ MovDelay[x][y]=5;
+ }
+ else if (element==EL_FLIEGER)
+ {
+ TestIfBadThingHitsOtherBadThing(x,y);
+
+ if (MovDir[x][y]==MV_LEFT)
+ {
+ if (IN_LEV_FIELD(x,y+1) && IS_FREE(x,y+1))
+ MovDir[x][y]=MV_DOWN;
+ else if (!IN_LEV_FIELD(x-1,y) || !IS_FREE(x-1,y))
+ MovDir[x][y]=MV_UP;
+ }
+ else if (MovDir[x][y]==MV_RIGHT)
+ {
+ if (IN_LEV_FIELD(x,y-1) && IS_FREE(x,y-1))
+ MovDir[x][y]=MV_UP;
+ else if (!IN_LEV_FIELD(x+1,y) || !IS_FREE(x+1,y))
+ MovDir[x][y]=MV_DOWN;
+ }
+ else if (MovDir[x][y]==MV_UP)
+ {
+ if (IN_LEV_FIELD(x-1,y) && IS_FREE(x-1,y))
+ MovDir[x][y]=MV_LEFT;
+ else if (!IN_LEV_FIELD(x,y-1) || !IS_FREE(x,y-1))
+ MovDir[x][y]=MV_RIGHT;
+ }
+ else if (MovDir[x][y]==MV_DOWN)
+ {
+ if (IN_LEV_FIELD(x+1,y) && IS_FREE(x+1,y))
+ MovDir[x][y]=MV_RIGHT;
+ else if (!IN_LEV_FIELD(x,y+1) || !IS_FREE(x,y+1))
+ MovDir[x][y]=MV_LEFT;
+ }
+
+ if (direction!=MovDir[x][y])
+ MovDelay[x][y]=5;
+ }
+ else if (element==EL_MAMPFER)
+ {
+ if (MovDir[x][y]==MV_LEFT || MovDir[x][y]==MV_RIGHT)
+ {
+ MovDir[x][y]=(MovDir[x][y]==MV_LEFT ? MV_RIGHT : MV_LEFT);
+ if (IN_LEV_FIELD(x,y-1) &&
+ (IS_FREE(x,y-1) || Feld[x][y-1]==EL_DIAMANT) &&
+ RND(2))
+ MovDir[x][y]=MV_UP;
+ if (IN_LEV_FIELD(x,y+1) &&
+ (IS_FREE(x,y+1) || Feld[x][y+1]==EL_DIAMANT) &&
+ RND(2))
+ MovDir[x][y]=MV_DOWN;
+ }
+ else if (MovDir[x][y]==MV_UP || MovDir[x][y]==MV_DOWN)
+ {
+ MovDir[x][y]=(MovDir[x][y]==MV_UP ? MV_DOWN : MV_UP);
+ if (IN_LEV_FIELD(x-1,y) &&
+ (IS_FREE(x-1,y) || Feld[x-1][y]==EL_DIAMANT) &&
+ RND(2))
+ MovDir[x][y]=MV_LEFT;
+ if (IN_LEV_FIELD(x+1,y) &&
+ (IS_FREE(x+1,y) || Feld[x+1][y]==EL_DIAMANT) &&
+ RND(2))
+ MovDir[x][y]=MV_RIGHT;
+ }
+
+ MovDelay[x][y]=8+8*RND(3);
+ }
+ else if (element==EL_PACMAN)
+ {
+ if (MovDir[x][y]==MV_LEFT || MovDir[x][y]==MV_RIGHT)
+ {
+ MovDir[x][y]=(MovDir[x][y]==MV_LEFT ? MV_RIGHT : MV_LEFT);
+ if (IN_LEV_FIELD(x,y-1) &&
+ (IS_FREE(x,y-1) || IS_AMOEBOID(Feld[x][y-1])) &&
+ RND(2))
+ MovDir[x][y]=MV_UP;
+ if (IN_LEV_FIELD(x,y+1) &&
+ (IS_FREE(x,y+1) || IS_AMOEBOID(Feld[x][y+1])) &&
+ RND(2))
+ MovDir[x][y]=MV_DOWN;
+ }
+ else if (MovDir[x][y]==MV_UP || MovDir[x][y]==MV_DOWN)
+ {
+ MovDir[x][y]=(MovDir[x][y]==MV_UP ? MV_DOWN : MV_UP);
+ if (IN_LEV_FIELD(x-1,y) &&
+ (IS_FREE(x-1,y) || IS_AMOEBOID(Feld[x-1][y])) &&
+ RND(2))
+ MovDir[x][y]=MV_LEFT;
+ if (IN_LEV_FIELD(x+1,y) &&
+ (IS_FREE(x+1,y) || IS_AMOEBOID(Feld[x+1][y])) &&
+ RND(2))
+ MovDir[x][y]=MV_RIGHT;
+ }
+
+ MovDelay[x][y]=3+RND(20);
+ }
+ else if (element==EL_ZOMBIE)
+ {
+ int attr_x = JX, attr_y = JY;
+
+ if (ZX>=0 && ZY>=0)
+ {
+ attr_x = ZX;
+ attr_y = ZY;
+ }
+
+ MovDir[x][y]=MV_NO_MOVING;
+ if (attr_x<x)
+ MovDir[x][y]|=MV_LEFT;
+ else if (attr_x>x)
+ MovDir[x][y]|=MV_RIGHT;
+ if (attr_y<y)
+ MovDir[x][y]|=MV_UP;
+ else if (attr_y>y)
+ MovDir[x][y]|=MV_DOWN;
+ if ((MovDir[x][y]&(MV_LEFT|MV_RIGHT)) && (MovDir[x][y]&(MV_UP|MV_DOWN)))
+ MovDir[x][y] &= (RND(2) ? (MV_LEFT|MV_RIGHT) : (MV_UP|MV_DOWN));
+
+ MovDelay[x][y] = 8+8*RND(2);
+ }
+}
+
+void StartMoving(int x, int y)
+{
+ int element = Feld[x][y];
+
+ if (Stop[x][y])
+ return;
+
+ if (CAN_FALL(element) && y<lev_fieldy-1)
+ {
+ if (element==EL_MORAST_VOLL)
+ {
+ if (IS_FREE(x,y+1))
+ {
+ InitMovingField(x,y,MV_DOWN);
+ Feld[x][y] = EL_FELSBROCKEN;
+ Store[x][y] = EL_MORAST_LEER;
+ }
+ else if (Feld[x][y+1]==EL_MORAST_LEER)
+ {
+ CheckMoving=TRUE;
+
+ if (!MovDelay[x][y])
+ MovDelay[x][y] = 16;
+
+ if (MovDelay[x][y])
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y])
+ return;
+ }
+
+ Feld[x][y] = EL_MORAST_LEER;
+ Feld[x][y+1] = EL_MORAST_VOLL;
+ }
+ }
+ else if (element==EL_FELSBROCKEN && Feld[x][y+1]==EL_MORAST_LEER)
+ {
+ InitMovingField(x,y,MV_DOWN);
+ Store[x][y] = EL_MORAST_VOLL;
+ }
+ else if (element==EL_SIEB_VOLL)
+ {
+ if (IS_FREE(x,y+1))
+ {
+ InitMovingField(x,y,MV_DOWN);
+ Feld[x][y] = EL_CHANGED(Store2[x][y]);
+ Store[x][y] = EL_SIEB_LEER;
+ }
+ }
+ else if (CAN_CHANGE(element) && Feld[x][y+1]==EL_SIEB_LEER)
+ {
+ InitMovingField(x,y,MV_DOWN);
+ Store[x][y] = EL_SIEB_VOLL;
+ Store2[x][y+1] = element;
+ SiebAktiv = 330;
+ }
+ else if (CAN_SMASH(element) && Feld[x][y+1]==EL_SALZSAEURE)
+ {
+ Blurb(x,y);
+ InitMovingField(x,y,MV_DOWN);
+ Store[x][y] = EL_SALZSAEURE;
+ }
+ else if (CAN_SMASH(element) && Feld[x][y+1]==EL_BLOCKED)
+ {
+ Impact(x,y);
+ }
+ else if (IS_FREE(x,y+1))
+ {
+ InitMovingField(x,y,MV_DOWN);
+ }
+ else if (element==EL_TROPFEN)
+ {
+ Feld[x][y] = EL_AMOEBING2;
+ }
+ else if (SLIPPERY(Feld[x][y+1]) && !Store[x][y+1])
+ {
+ int left = (x>0 && IS_FREE(x-1,y) &&
+ (IS_FREE(x-1,y+1) || Feld[x-1][y+1]==EL_SALZSAEURE));
+ int right = (x<lev_fieldx-1 && IS_FREE(x+1,y) &&
+ (IS_FREE(x+1,y+1) || Feld[x+1][y+1]==EL_SALZSAEURE));
+
+ if (left || right)
+ {
+ if (left && right)
+ left = !(right=RND(2));
+ InitMovingField(x,y,left ? MV_LEFT : MV_RIGHT);
+ }
+ }
+ }
+ else if (CAN_MOVE(element))
+ {
+ int newx,newy;
+
+ CheckMoving = TRUE;
+
+ if (!MovDelay[x][y]) /* neuer Schritt / noch nicht gewartet */
+ {
+ if (element==EL_ZOMBIE || element==EL_KAEFER || element==EL_FLIEGER)
+ {
+ TurnRound(x,y);
+ if (MovDelay[x][y] && (element==EL_KAEFER || element==EL_FLIEGER))
+ DrawLevelField(x,y);
+ }
+ }
+
+ if (MovDelay[x][y]) /* neuer Schritt / in Wartezustand */
+ {
+ MovDelay[x][y]--;
+
+ if (element==EL_ZOMBIE || element==EL_MAMPFER)
+ {
+ int phase = MovDelay[x][y] % 8;
+
+ if (phase>3)
+ phase = 7-phase;
+
+ if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ DrawGraphic(SCROLLX(x),SCROLLY(y),
+ el2gfx(element)+phase);
+
+ if (element==EL_MAMPFER && MovDelay[x][y]%4==3)
+ PlaySoundLevel(x,y,SND_NJAM);
+ }
+
+ if (MovDelay[x][y])
+ return;
+ }
+
+ if (element==EL_KAEFER)
+ {
+ PlaySoundLevel(x,y,SND_KLAPPER);
+ }
+ else if (element==EL_FLIEGER)
+ {
+ PlaySoundLevel(x,y,SND_ROEHR);
+ }
+
+ /* neuer Schritt / Wartezustand beendet */
+
+ Moving2Blocked(x,y,&newx,&newy); /* wohin soll's gehen? */
+
+ if (PLAYER(newx,newy)) /* Spieler erwischt */
+ {
+ MovDir[x][y] = 0;
+ KillHero();
+ return;
+ }
+ else if (element==EL_MAMPFER && IN_LEV_FIELD(newx,newy) &&
+ Feld[newx][newy]==EL_DIAMANT)
+ {
+ Feld[newx][newy] = EL_LEERRAUM;
+ DrawLevelField(newx,newy);
+ }
+ else if (element==EL_PACMAN && IN_LEV_FIELD(newx,newy) &&
+ IS_AMOEBOID(Feld[newx][newy]))
+ {
+ Feld[newx][newy] = EL_LEERRAUM;
+ DrawLevelField(newx,newy);
+ }
+ else if (element==EL_ZOMBIE && IN_LEV_FIELD(newx,newy) &&
+ MovDir[x][y]==MV_DOWN && Feld[newx][newy]==EL_SALZSAEURE)
+ {
+ Blurb(x,y);
+ Store[x][y] = EL_SALZSAEURE;
+ }
+ else if (!IN_LEV_FIELD(newx,newy) || !IS_FREE(newx,newy))
+ { /* gegen Wand gelaufen */
+ TurnRound(x,y);
+ DrawLevelField(x,y);
+ return;
+ }
+
+ InitMovingField(x,y,MovDir[x][y]);
+ }
+
+ if (MovDir[x][y])
+ ContinueMoving(x,y);
+}
+
+void ContinueMoving(int x, int y)
+{
+ int element = Feld[x][y];
+ int direction = MovDir[x][y];
+ int dx = (direction==MV_LEFT ? -1 : direction==MV_RIGHT ? +1 : 0);
+ int dy = (direction==MV_UP ? -1 : direction==MV_DOWN ? +1 : 0);
+ int horiz_move = (dx!=0);
+ int newx = x + dx, newy = y + dy;
+ int step = (horiz_move ? dx : dy)*TILEX/4;
+
+ if (CAN_FALL(element) && horiz_move)
+ step*=2;
+ else if (element==EL_TROPFEN)
+ step/=2;
+ else if (Store[x][y]==EL_MORAST_VOLL || Store[x][y]==EL_MORAST_LEER)
+ step/=4;
+
+ MovPos[x][y] += step;
+
+ if (ABS(MovPos[x][y])>=TILEX) /* Zielfeld erreicht */
+ {
+ Feld[x][y]=EL_LEERRAUM;
+ Feld[newx][newy]=element;
+
+ if (Store[x][y]==EL_MORAST_VOLL)
+ {
+ Store[x][y] = 0;
+ Feld[newx][newy] = EL_MORAST_VOLL;
+ element = EL_MORAST_VOLL;
+ }
+ else if (Store[x][y]==EL_MORAST_LEER)
+ {
+ Store[x][y] = 0;
+ Feld[x][y] = EL_MORAST_LEER;
+ }
+ else if (Store[x][y]==EL_SIEB_VOLL)
+ {
+ Store[x][y] = 0;
+ Feld[newx][newy] = EL_SIEB_VOLL;
+ element = EL_SIEB_VOLL;
+ }
+ else if (Store[x][y]==EL_SIEB_LEER)
+ {
+ Store[x][y] = Store2[x][y] = 0;
+ Feld[x][y] = EL_SIEB_LEER;
+ }
+ else if (Store[x][y]==EL_SALZSAEURE)
+ {
+ Store[x][y] = 0;
+ Feld[newx][newy] = EL_SALZSAEURE;
+ element = EL_SALZSAEURE;
+ }
+ else if (Store[x][y]==EL_AMOEBE2)
+ {
+ Store[x][y] = 0;
+ Feld[x][y] = EL_AMOEBE2;
+ }
+
+ MovPos[x][y] = MovDir[x][y] = 0;
+
+ if (!CAN_MOVE(element))
+ MovDir[newx][newy] = 0;
+
+ DrawLevelField(x,y);
+ DrawLevelField(newx,newy);
+
+ Stop[newx][newy]=TRUE;
+ CheckMoving=TRUE;
+
+ if (DONT_TOUCH(element)) /* Käfer oder Flieger */
+ {
+ TestIfBadThingHitsHero();
+ TestIfBadThingHitsOtherBadThing(newx,newy);
+ }
+
+ if (CAN_SMASH(element) && direction==MV_DOWN &&
+ (newy==lev_fieldy-1 || !IS_FREE(x,newy+1)))
+ Impact(x,newy);
+ }
+ else /* noch in Bewegung */
+ {
+ DrawLevelField(x,y);
+ CheckMoving=TRUE;
+ }
+}
+
+void AmoebeWaechst(int x, int y)
+{
+ static long sound_delay = 0;
+ static int sound_delay_value = 0;
+
+ CheckExploding=TRUE;
+
+ if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
+ {
+ MovDelay[x][y] = 4;
+
+ if (DelayReached(&sound_delay,sound_delay_value))
+ {
+ PlaySoundLevel(x,y,SND_AMOEBE);
+ sound_delay_value = 30;
+ }
+ }
+
+ if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AMOEBING+3-MovDelay[x][y]);
+
+ if (!MovDelay[x][y])
+ {
+ Feld[x][y] = (Feld[x][y]==EL_AMOEBING2 ? EL_AMOEBE2 : EL_AMOEBE3);
+ DrawLevelField(x,y);
+ }
+ }
+}
+
+void AmoebeAbleger(int ax, int ay)
+{
+ int i,j,start;
+ int newax = ax, neway = ay;
+ BOOL waiting_for_player = FALSE;
+ static int xy[4][2] =
+ {
+ 0,-1,
+ -1,0,
+ +1,0,
+ 0,+1
+ };
+
+ CheckExploding=TRUE;
+
+ if (!level.tempo_amoebe)
+ {
+ Feld[ax][ay] = EL_AMOEBE1;
+ DrawLevelField(ax,ay);
+ return;
+ }
+
+ if (!MovDelay[ax][ay]) /* neue Amoebe / noch nicht gewartet */
+ MovDelay[ax][ay] = RND(33*20/(1+level.tempo_amoebe));
+
+ if (MovDelay[ax][ay]) /* neue Amoebe / in Wartezustand */
+ {
+ MovDelay[ax][ay]--;
+ if (MovDelay[ax][ay])
+ return;
+ }
+
+ if (Feld[ax][ay]==EL_AMOEBE3)
+ {
+ start = RND(4);
+ for(i=0;i<4;i++)
+ {
+ int x,y;
+
+ j = (start+i)%4;
+ x = ax+xy[j][0];
+ y = ay+xy[j][1];
+ if (!IN_LEV_FIELD(x,y))
+ continue;
+
+ if (IS_FREE(x,y) ||
+ Feld[x][y]==EL_ERDREICH || Feld[x][y]==EL_MORAST_LEER)
+ {
+ newax=x;
+ neway=y;
+ break;
+ }
+ else if (PLAYER(x,y))
+ waiting_for_player = TRUE;
+ }
+
+ if (newax==ax && neway==ay)
+ {
+ if (Feld[ax][ay]==EL_AMOEBE3 && i==4 && !waiting_for_player)
+ {
+ Feld[ax][ay] = EL_AMOEBE1;
+ DrawLevelField(ax,ay);
+ }
+ return;
+ }
+ }
+ else
+ {
+ int x,y;
+
+ start = RND(4);
+ x = ax+xy[start][0];
+ y = ay+xy[start][1];
+ if (!IN_LEV_FIELD(x,y))
+ return;
+
+ if (IS_FREE(x,y) ||
+ Feld[x][y]==EL_ERDREICH || Feld[x][y]==EL_MORAST_LEER)
+ {
+ newax=x;
+ neway=y;
+ }
+
+ if (newax==ax && neway==ay)
+ return;
+ }
+
+ if (Feld[ax][ay]==EL_AMOEBE3)
+ Feld[newax][neway] = EL_AMOEBING3;
+ else if (neway==lev_fieldy-1)
+ Feld[newax][neway] = EL_AMOEBING2;
+ else if (neway<=ay || !IS_FREE(newax,neway))
+ Feld[newax][neway] = EL_TROPFEN;
+ else
+ {
+ InitMovingField(ax,ay,MV_DOWN);
+ Feld[ax][ay]=EL_TROPFEN;
+ Store[ax][ay]=EL_AMOEBE2;
+ ContinueMoving(ax,ay);
+ return;
+ }
+
+ DrawLevelField(newax,neway);
+}
+
+void Life(int ax, int ay)
+{
+ int x1,y1,x2,y2;
+ static int life[4] = { 2,3,3,3 }; /* "Life"-Parameter */
+ int life_time = 20;
+ int element = Feld[ax][ay];
+
+ CheckExploding=TRUE;
+
+ if (Stop[ax][ay])
+ return;
+
+ if (!MovDelay[ax][ay]) /* neue Phase / noch nicht gewartet */
+ MovDelay[ax][ay] = life_time;
+
+ if (MovDelay[ax][ay]) /* neue Phase / in Wartezustand */
+ {
+ MovDelay[ax][ay]--;
+ if (MovDelay[ax][ay])
+ return;
+ }
+
+ for(y1=-1;y1<2;y1++) for(x1=-1;x1<2;x1++)
+ {
+ int xx = ax+x1, yy = ay+y1;
+ int nachbarn = 0;
+
+ if (!IN_LEV_FIELD(xx,yy))
+ continue;
+
+ for(y2=-1;y2<2;y2++) for(x2=-1;x2<2;x2++)
+ {
+ int x = xx+x2, y = yy+y2;
+
+ if (!IN_LEV_FIELD(x,y) || (x==xx && y==yy))
+ continue;
+
+ if ((Feld[x][y]==element && !Stop[x][y]) ||
+ (IS_FREE(x,y) && Stop[x][y]))
+ nachbarn++;
+ }
+
+ if (xx==ax && yy==ay) /* mittleres Feld mit Amoebe */
+ {
+ if (nachbarn<life[0] || nachbarn>life[1])
+ {
+ Feld[xx][yy] = EL_LEERRAUM;
+ if (!Stop[xx][yy])
+ DrawLevelField(xx,yy);
+ Stop[xx][yy] = TRUE;
+ }
+ }
+ else if (IS_FREE(xx,yy) || Feld[xx][yy]==EL_ERDREICH)
+ { /* Randfeld ohne Amoebe */
+ if (nachbarn>=life[2] && nachbarn<=life[3])
+ {
+ Feld[xx][yy] = element;
+ MovDelay[xx][yy] = (element==EL_LIFE ? 0 : life_time-1);
+ if (!Stop[xx][yy])
+ DrawLevelField(xx,yy);
+ Stop[xx][yy] = TRUE;
+ }
+ }
+ }
+}
+
+void Ablenk(int x, int y)
+{
+ CheckExploding=TRUE;
+
+ if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
+ MovDelay[x][y] = 33*(level.dauer_ablenk/10);
+ if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y])
+ {
+ if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_ABLENK+MovDelay[x][y]%4);
+ if (!(MovDelay[x][y]%4))
+ PlaySoundLevel(x,y,SND_MIEP);
+ return;
+ }
+ }
+
+ Feld[x][y]=EL_ABLENK_AUS;
+ DrawLevelField(x,y);
+ if (ZX==x && ZY==y)
+ ZX=ZY=-1;
+}
+
+void Birne(int x, int y)
+{
+ CheckExploding=TRUE;
+
+ if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
+ MovDelay[x][y] = 400;
+
+ if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y])
+ {
+ if (!(MovDelay[x][y]%5))
+ {
+ if (!(MovDelay[x][y]%10))
+ Feld[x][y]=EL_ABLENK_EIN;
+ else
+ Feld[x][y]=EL_ABLENK_AUS;
+ DrawLevelField(x,y);
+ Feld[x][y]=EL_ABLENK_EIN;
+ }
+ return;
+ }
+ }
+
+ Feld[x][y]=EL_ABLENK_AUS;
+ DrawLevelField(x,y);
+ if (ZX==x && ZY==y)
+ ZX=ZY=-1;
+}
+
+void Blubber(int x, int y)
+{
+ CheckExploding=TRUE;
+
+ if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
+ MovDelay[x][y] = 20;
+
+ if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
+ {
+ int blubber;
+
+ MovDelay[x][y]--;
+ blubber = MovDelay[x][y]/5;
+ if (!(MovDelay[x][y]%5) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_GEBLUBBER+3-blubber);
+ }
+}
+
+void NussKnacken(int x, int y)
+{
+ CheckExploding=TRUE;
+
+ if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
+ MovDelay[x][y] = 4;
+
+ if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
+ {
+ MovDelay[x][y]--;
+ if (MovDelay[x][y] && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_CRACKINGNUT+3-MovDelay[x][y]);
+
+ if (!MovDelay[x][y])
+ {
+ Feld[x][y] = EL_EDELSTEIN;
+ DrawLevelField(x,y);
+ }
+ }
+}
+
+void SiebAktivieren(int x, int y)
+{
+ CheckExploding=TRUE;
+
+ if (SiebAktiv>1)
+ {
+ if (SiebAktiv%2 && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_SIEB_VOLL+3-(SiebAktiv%8)/2);
+
+/*
+ if (!(SiebAktiv%4))
+ PlaySoundLevel(x,y,SND_MIEP);
+*/
+
+ }
+ else
+ {
+ Feld[x][y] = EL_SIEB_TOT;
+ DrawLevelField(x,y);
+ }
+}
+
+void AusgangstuerPruefen(int x, int y)
+{
+ CheckExploding=TRUE;
+
+ if (!Gems)
+ Feld[x][y] = EL_AUSGANG_ACT;
+}
+
+void AusgangstuerOeffnen(int x, int y)
+{
+ CheckExploding=TRUE;
+
+ if (!MovDelay[x][y]) /* neue Phase / noch nicht gewartet */
+ MovDelay[x][y] = 20;
+
+ if (MovDelay[x][y]) /* neue Phase / in Wartezustand */
+ {
+ int tuer;
+
+ MovDelay[x][y]--;
+ tuer = MovDelay[x][y]/5;
+ if (!(MovDelay[x][y]%5) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ DrawGraphic(SCROLLX(x),SCROLLY(y),GFX_AUSGANG_ZU+3-tuer);
+
+ if (!MovDelay[x][y])
+ {
+ Feld[x][y] = EL_AUSGANG_AUF;
+ DrawLevelField(x,y);
+ }
+ }
+}
+
+int GameActions(int mx, int my, int button)
+{
+ static long time_delay=0, action_delay=0;
+ int Action;
+
+ if (TimeLeft>0 && DelayReached(&time_delay,100) && !tape.pausing)
+ {
+ TimeLeft--;
+
+ if (tape.recording || tape.playing)
+ DrawVideoDisplay(VIDEO_STATE_TIME_ON,level.time-TimeLeft);
+
+ if (TimeLeft<=10)
+ PlaySoundStereo(SND_GONG,PSND_MAX_RIGHT);
+
+ DrawText(DX_TIME,DY_TIME,int2str(TimeLeft,3),FS_SMALL,FC_YELLOW);
+ BackToFront();
+ }
+
+ if (!TimeLeft)
+ KillHero();
+
+ Action = (CheckMoving || CheckExploding || SiebAktiv);
+
+/*
+ if (Action && DelayReached(&action_delay,3))
+*/
+
+ if (DelayReached(&action_delay,3))
+ {
+ int x,y,element;
+
+ if (tape.pausing || (tape.playing && !TapePlayDelay()))
+ return(ACT_GO_ON);
+ else if (tape.recording)
+ TapeRecordDelay();
+
+ CheckMoving = CheckExploding = FALSE;
+ for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
+ Stop[x][y] = FALSE;
+
+ for(y=0;y<lev_fieldy;y++) for(x=0;x<lev_fieldx;x++)
+ {
+ element = Feld[x][y];
+
+ if (element==EL_LEERRAUM || element==EL_ERDREICH)
+ continue;
+
+ if (!IS_MOVING(x,y) && (CAN_FALL(element) || CAN_MOVE(element)))
+ StartMoving(x,y);
+ else if (IS_MOVING(x,y))
+ ContinueMoving(x,y);
+ else if (element==EL_DYNAMIT)
+ CheckDynamite(x,y);
+ else if (element==EL_EXPLODING)
+ Explode(x,y,Frame[x][y]);
+ else if (element==EL_AMOEBING2 || element==EL_AMOEBING3)
+ AmoebeWaechst(x,y);
+ else if (element==EL_AMOEBE2 || element==EL_AMOEBE3)
+ AmoebeAbleger(x,y);
+ else if (element==EL_LIFE || element==EL_LIFE_ASYNC)
+ Life(x,y);
+ else if (element==EL_ABLENK_EIN)
+ Ablenk(x,y);
+ else if (element==EL_SALZSAEURE)
+ Blubber(x,y);
+ else if (element==EL_BLURB_LEFT || element==EL_BLURB_RIGHT)
+ Blurb(x,y);
+ else if (element==EL_CRACKINGNUT)
+ NussKnacken(x,y);
+ else if (element==EL_AUSGANG_ZU)
+ AusgangstuerPruefen(x,y);
+ else if (element==EL_AUSGANG_ACT)
+ AusgangstuerOeffnen(x,y);
+
+ if (SiebAktiv && (element==EL_SIEB_LEER ||
+ element==EL_SIEB_VOLL ||
+ Store[x][y]==EL_SIEB_LEER))
+ SiebAktivieren(x,y);
+ }
+
+ if (SiebAktiv)
+ SiebAktiv--;
+
+ if (CheckMoving || CheckExploding)
+ BackToFront();
+ }
+
+ return(ACT_GO_ON);
+}
+
+void ScrollLevel(int dx, int dy)
+{
+ int x,y;
+
+ XCopyArea(display,drawto_field,drawto_field,gc,
+ SX+TILEX*(dx==-1),SY+TILEY*(dy==-1),
+ SXSIZE-TILEX*(dx!=0),SYSIZE-TILEY*(dy!=0),
+ SX+TILEX*(dx==1),SY+TILEY*(dy==1));
+
+ if (dx)
+ {
+ x = dx==1 ? 0 : SCR_FIELDX-1;
+ for(y=0;y<SCR_FIELDY;y++)
+ DrawScreenField(x,y);
+ }
+ if (dy)
+ {
+ y = dy==1 ? 0 : SCR_FIELDY-1;
+ for(x=0;x<SCR_FIELDY;x++)
+ DrawScreenField(x,y);
+ }
+
+ redraw_mask|=REDRAW_FIELD;
+}
+
+BOOL MoveFigureOneStep(int dx, int dy)
+{
+ int oldJX,oldJY, newJX=JX+dx,newJY=JY+dy;
+ int element;
+ int can_move;
+
+ if (!dx && !dy)
+ return(MF_NO_ACTION);
+ if (!IN_LEV_FIELD(newJX,newJY))
+ return(MF_NO_ACTION);
+
+ element = MovingOrBlocked2Element(newJX,newJY);
+
+ if (DONT_GO_TO(element))
+ {
+ if (element==EL_SALZSAEURE && dx==0 && dy==1)
+ {
+ Blurb(JX,JY);
+ Feld[JX][JY] = EL_SPIELFIGUR;
+ InitMovingField(JX,JY,MV_DOWN);
+ Store[JX][JY] = EL_SALZSAEURE;
+ ContinueMoving(JX,JY);
+
+ PlaySoundLevel(JX,JY,SND_AUTSCH);
+ PlaySoundLevel(JX,JY,SND_LACHEN);
+ GameOver=TRUE;
+ JX=JY=-1;
+ }
+ else
+ KillHero();
+
+ return(MF_MOVING);
+ }
+
+ can_move = DigField(newJX,newJY,DF_DIG);
+ if (can_move != MF_MOVING)
+ return(can_move);
+
+ oldJX = JX;
+ oldJY = JY;
+ JX = newJX;
+ JY = newJY;
+
+ if (Store[oldJX][oldJY])
+ {
+ DrawGraphic(SCROLLX(oldJX),SCROLLY(oldJY),el2gfx(Store[oldJX][oldJY]));
+ DrawGraphicThruMask(SCROLLX(oldJX),SCROLLY(oldJY),
+ el2gfx(Feld[oldJX][oldJY]));
+ }
+ else if (Feld[oldJX][oldJY]==EL_DYNAMIT)
+ DrawDynamite(oldJX,oldJY);
+ else
+ DrawLevelField(oldJX,oldJY);
+
+ return(MF_MOVING);
+}
+
+BOOL MoveFigure(int dx, int dy)
+{
+ static long move_delay = 0;
+ int moved = MF_NO_ACTION;
+
+ if (GameOver || (!dx && !dy))
+ return(FALSE);
+
+ if (!DelayReached(&move_delay,10) && !tape.playing)
+ return(FALSE);
+
+ if (moved |= MoveFigureOneStep(dx,0))
+ moved |= MoveFigureOneStep(0,dy);
+ else
+ {
+ moved |= MoveFigureOneStep(0,dy);
+ moved |= MoveFigureOneStep(dx,0);
+ }
+
+ if (moved & MF_MOVING)
+ {
+ int old_scroll_x=scroll_x, old_scroll_y=scroll_y;
+
+ if (scroll_x!=JX-MIDPOSX && JX>=MIDPOSX-1 && JX<=lev_fieldx-MIDPOSX)
+ scroll_x = JX-MIDPOSX;
+ if (scroll_y!=JY-MIDPOSY && JY>=MIDPOSY-1 && JY<=lev_fieldy-MIDPOSY)
+ scroll_y = JY-MIDPOSY;
+
+ if (scroll_x!=old_scroll_x || scroll_y!=old_scroll_y)
+ ScrollLevel(old_scroll_x-scroll_x,old_scroll_y-scroll_y);
+
+ if (Feld[JX][JY]==EL_LEERRAUM)
+ DrawLevelElement(JX,JY,EL_SPIELFIGUR);
+ else
+ DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_SPIELFIGUR);
+ }
+
+ TestIfHeroHitsBadThing();
+
+ BackToFront();
+
+ if (LevelSolved)
+ GameWon();
+
+ return(moved);
+}
+
+void TestIfHeroHitsBadThing()
+{
+ int i, killx = JX,killy = JY;
+ static int xy[4][2] =
+ {
+ 0,-1,
+ -1,0,
+ +1,0,
+ 0,+1
+ };
+ static int harmless[4] =
+ {
+ MV_UP,
+ MV_LEFT,
+ MV_RIGHT,
+ MV_DOWN
+ };
+
+ for(i=0;i<4;i++)
+ {
+ int x,y,element;
+
+ x = JX+xy[i][0];
+ y = JY+xy[i][1];
+ if (!IN_LEV_FIELD(x,y))
+ continue;
+
+ element = Feld[x][y];
+
+ if (DONT_TOUCH(element))
+ {
+ if (MovDir[x][y]==harmless[i])
+ continue;
+
+ killx = x;
+ killy = y;
+ break;
+ }
+ }
+
+ if (killx!=JX || killy!=JY)
+ KillHero();
+}
+
+void TestIfBadThingHitsHero()
+{
+ TestIfHeroHitsBadThing();
+}
+
+void TestIfBadThingHitsOtherBadThing(int badx, int bady)
+{
+ int i, killx=badx, killy=bady;
+ static int xy[4][2] =
+ {
+ 0,-1,
+ -1,0,
+ +1,0,
+ 0,+1
+ };
+
+ for(i=0;i<4;i++)
+ {
+ int x,y,element;
+
+ x=badx+xy[i][0];
+ y=bady+xy[i][1];
+ if (!IN_LEV_FIELD(x,y))
+ continue;
+
+ element=Feld[x][y];
+ if (IS_AMOEBOID(element) || element==EL_LIFE ||
+ element==EL_AMOEBING2 || element==EL_AMOEBING3 || element==EL_TROPFEN)
+ {
+ killx=x;
+ killy=y;
+ break;
+ }
+ }
+
+ if (killx!=badx || killy!=bady)
+ Bang(badx,bady);
+}
+
+void KillHero()
+{
+ if (PLAYER(-1,-1))
+ return;
+
+ if (IS_PFORTE(Feld[JX][JY]))
+ Feld[JX][JY] = EL_LEERRAUM;
+
+ PlaySoundLevel(JX,JY,SND_AUTSCH);
+ PlaySoundLevel(JX,JY,SND_LACHEN);
+ Bang(JX,JY);
+ GameOver = TRUE;
+ JX = JY = -1;
+}
+
+int DigField(int x, int y, int mode)
+{
+ int dx=x-JX, dy=y-JY;
+ int element;
+ static long push_delay = 0;
+ static int push_delay_value = 20;
+
+ if (mode==DF_NO_PUSH)
+ {
+ push_delay = 0;
+ return(MF_NO_ACTION);
+ }
+
+ if (IS_MOVING(x,y))
+ return(MF_NO_ACTION);
+
+ element = Feld[x][y];
+
+ switch(element)
+ {
+ case EL_LEERRAUM:
+ CheckMoving=TRUE;
+ break;
+ case EL_ERDREICH:
+ Feld[x][y]=EL_LEERRAUM;
+ CheckMoving=TRUE;
+ break;
+ case EL_EDELSTEIN:
+ Feld[x][y]=EL_LEERRAUM;
+ CheckMoving=TRUE;
+ if (Gems>0)
+ Gems--;
+ RaiseScore(level.score[SC_EDELSTEIN]);
+ DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW);
+ PlaySoundLevel(x,y,SND_PONG);
+ break;
+ case EL_DIAMANT:
+ Feld[x][y]=EL_LEERRAUM;
+ CheckMoving=TRUE;
+ Gems -= 3;
+ if (Gems<0)
+ Gems=0;
+ RaiseScore(level.score[SC_DIAMANT]);
+ DrawText(DX_EMERALDS,DY_EMERALDS,int2str(Gems,3),FS_SMALL,FC_YELLOW);
+ PlaySoundLevel(x,y,SND_PONG);
+ break;
+ case EL_DYNAMIT_AUS:
+ Feld[x][y]=EL_LEERRAUM;
+ CheckMoving=TRUE;
+ Dynamite++;
+ RaiseScore(level.score[SC_DYNAMIT]);
+ DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
+ PlaySoundLevel(x,y,SND_PONG);
+ break;
+ case EL_SCHLUESSEL1:
+ case EL_SCHLUESSEL2:
+ case EL_SCHLUESSEL3:
+ case EL_SCHLUESSEL4:
+ {
+ int key_nr = element-EL_SCHLUESSEL1;
+
+ Feld[x][y] = EL_LEERRAUM;
+ CheckMoving = TRUE;
+ Key[key_nr] = TRUE;
+ RaiseScore(level.score[SC_SCHLUESSEL]);
+ DrawMiniGraphicExtHiRes(drawto,gc,
+ DX_KEYS+key_nr*MINI_TILEX,DY_KEYS,
+ GFX_SCHLUESSEL1+key_nr);
+ DrawMiniGraphicExtHiRes(window,gc,
+ DX_KEYS+key_nr*MINI_TILEX,DY_KEYS,
+ GFX_SCHLUESSEL1+key_nr);
+ PlaySoundLevel(x,y,SND_PONG);
+ break;
+ }
+ case EL_ABLENK_AUS:
+ Feld[x][y]=EL_ABLENK_EIN;
+ CheckExploding=TRUE;
+ ZX=x;
+ ZY=y;
+ DrawLevelField(x,y);
+/*
+ PlaySoundLevel(x,y,SND_DENG);
+*/
+ return(MF_ACTION);
+ break;
+ case EL_FELSBROCKEN:
+ case EL_BOMBE:
+ case EL_KOKOSNUSS:
+ if (mode==DF_SNAP)
+ return(MF_NO_ACTION);
+ if (dy || !IN_LEV_FIELD(x+dx,y+dy) || Feld[x+dx][y+dy]!=EL_LEERRAUM)
+ return(MF_NO_ACTION);
+
+ if (Counter() > push_delay+4*push_delay_value)
+ push_delay = Counter();
+ if (!DelayReached(&push_delay,push_delay_value) && !tape.playing)
+ return(MF_NO_ACTION);
+
+ Feld[x][y] = EL_LEERRAUM;
+ Feld[x+dx][y+dy] = element;
+ push_delay_value = 10+RND(30);
+ CheckMoving = TRUE;
+ DrawLevelField(x+dx,y+dy);
+ if (element==EL_FELSBROCKEN)
+ PlaySoundLevel(x+dx,y+dy,SND_PUSCH);
+ else if (element==EL_KOKOSNUSS)
+ PlaySoundLevel(x+dx,y+dy,SND_KNURK);
+ else
+ PlaySoundLevel(x+dx,y+dy,SND_KLOPF);
+ break;
+ case EL_PFORTE1:
+ case EL_PFORTE2:
+ case EL_PFORTE3:
+ case EL_PFORTE4:
+ if (!Key[element-EL_PFORTE1])
+ return(MF_NO_ACTION);
+ break;
+ case EL_PFORTE1X:
+ case EL_PFORTE2X:
+ case EL_PFORTE3X:
+ case EL_PFORTE4X:
+ if (!Key[element-EL_PFORTE1X])
+ return(MF_NO_ACTION);
+ break;
+ case EL_AUSGANG_ZU:
+ case EL_AUSGANG_ACT:
+ /* Tür ist (noch) nicht offen! */
+ return(MF_NO_ACTION);
+ break;
+ case EL_AUSGANG_AUF:
+ if (mode==DF_SNAP || Gems>0)
+ return(MF_NO_ACTION);
+ LevelSolved = TRUE;
+ PlaySoundLevel(x,y,SND_BUING);
+ break;
+ default:
+ return(MF_NO_ACTION);
+ break;
+ }
+ push_delay=0;
+ return(MF_MOVING);
+}
+
+BOOL SnapField(int dx, int dy)
+{
+ int x = JX+dx, y = JY+dy;
+ static int snapped = FALSE;
+
+ if (GameOver || !IN_LEV_FIELD(x,y))
+ return(FALSE);
+ if (dx && dy)
+ return(FALSE);
+ if (!dx && !dy)
+ {
+ snapped = FALSE;
+ return(FALSE);
+ }
+ if (snapped)
+ return(FALSE);
+
+ if (!DigField(x,y,DF_SNAP))
+ return(FALSE);
+
+ snapped = TRUE;
+ DrawLevelField(x,y);
+ BackToFront();
+
+ return(TRUE);
+}
+
+BOOL PlaceBomb(void)
+{
+ if (Dynamite==0 || Feld[JX][JY]==EL_DYNAMIT)
+ return(FALSE);
+
+ if (Feld[JX][JY]!=EL_LEERRAUM)
+ Store[JX][JY] = Feld[JX][JY];
+ Feld[JX][JY] = EL_DYNAMIT;
+ MovDelay[JX][JY] = 48;
+ Dynamite--;
+ DrawText(DX_DYNAMITE,DY_DYNAMITE,int2str(Dynamite,3),FS_SMALL,FC_YELLOW);
+ DrawGraphicThruMask(SCROLLX(JX),SCROLLY(JY),GFX_DYNAMIT);
+ CheckExploding = TRUE;
+ return(TRUE);
+}
+
+void PlaySoundLevel(int x, int y, int sound_nr)
+{
+ int sx = SCROLLX(x), sy = SCROLLY(y);
+ int volume, stereo;
+
+ if (!sound_loops_on && IS_LOOP_SOUND(sound_nr))
+ return;
+
+ if (!IN_LEV_FIELD(x,y))
+ return;
+
+ volume = PSND_MAX_VOLUME;
+ stereo = (sx-SCR_FIELDX/2)*12;
+
+ if (!IN_SCR_FIELD(sx,sy))
+ {
+ if (sx<0 || sx>=SCR_FIELDX)
+ volume = PSND_MAX_VOLUME - 2*ABS(sx-SCR_FIELDX/2);
+ else
+ volume = PSND_MAX_VOLUME - 2*ABS(sy-SCR_FIELDY/2);
+ }
+
+ PlaySoundExt(sound_nr, volume, stereo, PSND_NO_LOOP);
+}
+
+void RaiseScore(int value)
+{
+ Score += value;
+ DrawText(DX_SCORE,DY_SCORE,int2str(Score,5),FS_SMALL,FC_YELLOW);
+ BackToFront();
+}
+
+void TapeInitRecording()
+{
+ time_t zeit1 = time(NULL);
+ struct tm *zeit2 = localtime(&zeit1);
+
+ if (tape.recording || tape.playing)
+ return;
+
+ tape.level_nr = level_nr;
+ tape.recording = TRUE;
+ tape.pausing = TRUE;
+ tape.date =
+ 10000*(zeit2->tm_year%100) + 100*zeit2->tm_mon + zeit2->tm_mday;
+
+ DrawVideoDisplay(VIDEO_STATE_REC_ON | VIDEO_STATE_PAUSE_ON,0);
+ DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
+ DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
+}
+
+void TapeStartRecording()
+{
+ tape.length = 0;
+ tape.counter = 0;
+ tape.pos[tape.counter].delay = 0;
+ tape.recording = TRUE;
+ tape.playing = FALSE;
+ tape.pausing = FALSE;
+ tape.random_seed = InitRND(NEW_RANDOMIZE);
+ DrawVideoDisplay(VIDEO_STATE_REC_ON | VIDEO_STATE_PAUSE_OFF,0);
+}
+
+void TapeStopRecording()
+{
+ if (!tape.recording)
+ return;
+
+ tape.length = tape.counter;
+ tape.recording = FALSE;
+ tape.pausing = FALSE;
+ DrawVideoDisplay(VIDEO_STATE_REC_OFF,0);
+
+ master_tape = tape;
+}
+
+void TapeRecordAction(int joy)
+{
+ if (!tape.recording || tape.pausing)
+ return;
+
+ if (tape.counter>=MAX_TAPELEN-1)
+ {
+ TapeStopRecording();
+ return;
+ }
+
+ if (joy)
+ {
+ tape.pos[tape.counter].joystickdata = joy;
+ tape.counter++;
+ tape.pos[tape.counter].delay = 0;
+ }
+}
+
+void TapeRecordDelay()
+{
+ if (!tape.recording || tape.pausing)
+ return;
+
+ if (tape.counter>=MAX_TAPELEN)
+ {
+ TapeStopRecording();
+ return;
+ }
+
+ tape.pos[tape.counter].delay++;
+
+ if (tape.pos[tape.counter].delay>=255)
+ {
+ tape.pos[tape.counter].joystickdata = 0;
+ tape.counter++;
+ tape.pos[tape.counter].delay = 0;
+ }
+}
+
+void TapeTogglePause()
+{
+ if (!tape.recording && !tape.playing)
+ return;
+
+ if (tape.pausing)
+ {
+ tape.pausing = FALSE;
+ DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
+ if (game_status==MAINMENU)
+ HandleMainMenu(SX+16,SY+7*32+16,0,0,MB_MENU_CHOICE);
+ }
+ else
+ {
+ tape.pausing = TRUE;
+ DrawVideoDisplay(VIDEO_STATE_PAUSE_ON,0);
+ }
+}
+
+void TapeInitPlaying()
+{
+ if (tape.recording || tape.playing || TAPE_IS_EMPTY(tape))
+ return;
+
+ tape.playing = TRUE;
+ tape.pausing = TRUE;
+ DrawVideoDisplay(VIDEO_STATE_PLAY_ON | VIDEO_STATE_PAUSE_ON,0);
+ DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
+ DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
+}
+
+void TapeStartPlaying()
+{
+ tape = master_tape;
+
+ tape.counter = 0;
+ tape.recording = FALSE;
+ tape.playing = TRUE;
+ tape.pausing = FALSE;
+ InitRND(tape.random_seed);
+ DrawVideoDisplay(VIDEO_STATE_PLAY_ON | VIDEO_STATE_PAUSE_OFF,0);
+}
+
+void TapeStopPlaying()
+{
+ if (!tape.playing)
+ return;
+
+ tape.playing = FALSE;
+ tape.pausing = FALSE;
+ DrawVideoDisplay(VIDEO_STATE_PLAY_OFF,0);
+}
+
+int TapePlayAction()
+{
+ if (!tape.playing || tape.pausing)
+ return(0);
+
+ if (tape.counter>=tape.length)
+ {
+ TapeStopPlaying();
+ return(0);
+ }
+
+ if (!tape.pos[tape.counter].delay)
+ {
+ tape.counter++;
+ return(tape.pos[tape.counter-1].joystickdata);
+ }
+ else
+ return(0);
+}
+
+BOOL TapePlayDelay()
+{
+ if (!tape.playing || tape.pausing)
+ return(0);
+
+ if (tape.counter>=tape.length)
+ {
+ TapeStopPlaying();
+ return(TRUE);
+ }
+
+ if (tape.pos[tape.counter].delay)
+ {
+ tape.pos[tape.counter].delay--;
+ return(TRUE);
+ }
+ else
+ return(FALSE);
+}
+
+void TapeStop()
+{
+ TapeStopRecording();
+ TapeStopPlaying();
+ DrawVideoDisplay(VIDEO_ALL_OFF,0);
+ if (tape.date && tape.length)
+ {
+ DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
+ DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
+ }
+}
+
+void TapeErase()
+{
+ tape.length = 0;
+}
+
+void DrawVideoDisplay(unsigned long state, unsigned long value)
+{
+ int i;
+ int part1 = 0, part2 = 1;
+ int xpos = 0, ypos = 1, xsize = 2, ysize = 3;
+ static char *monatsname[12] =
+ {
+ "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
+ "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
+ };
+ static int video_pos[10][2][4] =
+ {
+ VIDEO_PLAY_LABEL_XPOS, VIDEO_PLAY_LABEL_YPOS,
+ VIDEO_PLAY_LABEL_XSIZE,VIDEO_PLAY_LABEL_YSIZE,
+ VIDEO_PLAY_SYMBOL_XPOS, VIDEO_PLAY_SYMBOL_YPOS,
+ VIDEO_PLAY_SYMBOL_XSIZE,VIDEO_PLAY_SYMBOL_YSIZE,
+
+ VIDEO_REC_LABEL_XPOS, VIDEO_REC_LABEL_YPOS,
+ VIDEO_REC_LABEL_XSIZE,VIDEO_REC_LABEL_YSIZE,
+ VIDEO_REC_SYMBOL_XPOS, VIDEO_REC_SYMBOL_YPOS,
+ VIDEO_REC_SYMBOL_XSIZE,VIDEO_REC_SYMBOL_YSIZE,
+
+ VIDEO_PAUSE_LABEL_XPOS, VIDEO_PAUSE_LABEL_YPOS,
+ VIDEO_PAUSE_LABEL_XSIZE,VIDEO_PAUSE_LABEL_YSIZE,
+ VIDEO_PAUSE_SYMBOL_XPOS, VIDEO_PAUSE_SYMBOL_YPOS,
+ VIDEO_PAUSE_SYMBOL_XSIZE,VIDEO_PAUSE_SYMBOL_YSIZE,
+
+ VIDEO_DATE_LABEL_XPOS, VIDEO_DATE_LABEL_YPOS,
+ VIDEO_DATE_LABEL_XSIZE,VIDEO_DATE_LABEL_YSIZE,
+ VIDEO_DATE_XPOS, VIDEO_DATE_YPOS,
+ VIDEO_DATE_XSIZE,VIDEO_DATE_YSIZE,
+
+ 0,0,
+ 0,0,
+ VIDEO_TIME_XPOS, VIDEO_TIME_YPOS,
+ VIDEO_TIME_XSIZE,VIDEO_TIME_YSIZE,
+
+ VIDEO_BUTTON_PLAY_XPOS, VIDEO_BUTTON_ANY_YPOS,
+ VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE,
+ 0,0,
+ 0,0,
+
+ VIDEO_BUTTON_REC_XPOS, VIDEO_BUTTON_ANY_YPOS,
+ VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE,
+ 0,0,
+ 0,0,
+
+ VIDEO_BUTTON_PAUSE_XPOS, VIDEO_BUTTON_ANY_YPOS,
+ VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE,
+ 0,0,
+ 0,0,
+
+ VIDEO_BUTTON_STOP_XPOS, VIDEO_BUTTON_ANY_YPOS,
+ VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE,
+ 0,0,
+ 0,0,
+
+ VIDEO_BUTTON_EJECT_XPOS, VIDEO_BUTTON_ANY_YPOS,
+ VIDEO_BUTTON_XSIZE,VIDEO_BUTTON_YSIZE,
+ 0,0,
+ 0,0
+ };
+
+ for(i=0;i<20;i++)
+ {
+ if (state & (1<<i))
+ {
+ int pos = i/2, cx, cy = DOOR_GFX_PAGEY2;
+
+ if (i%2) /* i ungerade => STATE_ON / PRESS_OFF */
+ cx = DOOR_GFX_PAGEX4;
+ else
+ cx = DOOR_GFX_PAGEX3; /* i gerade => STATE_OFF / PRESS_ON */
+
+ if (video_pos[pos][part1][0])
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ cx + video_pos[pos][part1][xpos],
+ cy + video_pos[pos][part1][ypos],
+ video_pos[pos][part1][xsize],
+ video_pos[pos][part1][ysize],
+ VX + video_pos[pos][part1][xpos],
+ VY + video_pos[pos][part1][ypos]);
+ if (video_pos[pos][part2][0])
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ cx + video_pos[pos][part2][xpos],
+ cy + video_pos[pos][part2][ypos],
+ video_pos[pos][part2][xsize],
+ video_pos[pos][part2][ysize],
+ VX + video_pos[pos][part2][xpos],
+ VY + video_pos[pos][part2][ypos]);
+ }
+ }
+
+ if (state & VIDEO_STATE_DATE_ON)
+ {
+ int tag = value % 100;
+ int monat = (value/100) % 100;
+ int jahr = (value/10000);
+
+ DrawText(VX+VIDEO_DATE_XPOS,VY+VIDEO_DATE_YPOS,
+ int2str(tag,2),FS_SMALL,FC_SPECIAL1);
+ DrawText(VX+VIDEO_DATE_XPOS+27,VY+VIDEO_DATE_YPOS,
+ monatsname[monat],FS_SMALL,FC_SPECIAL1);
+ DrawText(VX+VIDEO_DATE_XPOS+64,VY+VIDEO_DATE_YPOS,
+ int2str(jahr,2),FS_SMALL,FC_SPECIAL1);
+ }
+
+ if (state & VIDEO_STATE_TIME_ON)
+ {
+ int min = value / 60;
+ int sec = value % 60;
+
+ DrawText(VX+VIDEO_TIME_XPOS,VY+VIDEO_TIME_YPOS,
+ int2str(min,2),FS_SMALL,FC_SPECIAL1);
+ DrawText(VX+VIDEO_TIME_XPOS+27,VY+VIDEO_TIME_YPOS,
+ int2str(sec,2),FS_SMALL,FC_SPECIAL1);
+ }
+
+ if (state & VIDEO_STATE_DATE)
+ redraw_mask |= REDRAW_VIDEO_1;
+ if ((state & ~VIDEO_STATE_DATE) & VIDEO_STATE)
+ redraw_mask |= REDRAW_VIDEO_2;
+ if (state & VIDEO_PRESS)
+ redraw_mask |= REDRAW_VIDEO_3;
+}
+
+void DrawSoundDisplay(unsigned long state)
+{
+ int pos, cx = DOOR_GFX_PAGEX4, cy = 0;
+
+ pos = (state & BUTTON_SOUND_MUSIC ? SOUND_BUTTON_MUSIC_XPOS :
+ state & BUTTON_SOUND_LOOPS ? SOUND_BUTTON_LOOPS_XPOS :
+ SOUND_BUTTON_SOUND_XPOS);
+
+ if (state & BUTTON_ON)
+ cy -= SOUND_BUTTON_YSIZE;
+
+ if (state & BUTTON_PRESSED)
+ cx = DOOR_GFX_PAGEX3;
+
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ cx + pos,cy + SOUND_BUTTON_ANY_YPOS,
+ SOUND_BUTTON_XSIZE,SOUND_BUTTON_YSIZE,
+ DX + pos,DY + SOUND_BUTTON_ANY_YPOS);
+
+ redraw_mask |= REDRAW_DOOR_1;
+}
+
+void DrawGameButton(unsigned long state)
+{
+ int pos, cx = DOOR_GFX_PAGEX4, cy = -GAME_BUTTON_YSIZE;
+
+ pos = (state & BUTTON_GAME_STOP ? GAME_BUTTON_STOP_XPOS :
+ state & BUTTON_GAME_PAUSE ? GAME_BUTTON_PAUSE_XPOS :
+ GAME_BUTTON_PLAY_XPOS);
+
+ if (state & BUTTON_PRESSED)
+ cx = DOOR_GFX_PAGEX3;
+
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ cx + pos,cy + GAME_BUTTON_ANY_YPOS,
+ GAME_BUTTON_XSIZE,GAME_BUTTON_YSIZE,
+ DX + pos,DY + GAME_BUTTON_ANY_YPOS);
+
+ redraw_mask |= REDRAW_DOOR_1;
+}
+
+void DrawChooseButton(unsigned long state)
+{
+ int pos, cx = DOOR_GFX_PAGEX4, cy = 0;
+
+ pos = (state & BUTTON_OK ? OK_BUTTON_XPOS : NO_BUTTON_XPOS);
+
+ if (state & BUTTON_PRESSED)
+ cx = DOOR_GFX_PAGEX3;
+
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ cx + pos,cy + OK_BUTTON_GFX_YPOS,
+ OK_BUTTON_XSIZE,OK_BUTTON_YSIZE,
+ DX + pos,DY + OK_BUTTON_YPOS);
+
+ redraw_mask |= REDRAW_DOOR_1;
+}
+
+void DrawConfirmButton(unsigned long state)
+{
+ int cx = DOOR_GFX_PAGEX4, cy = 0;
+
+ if (state & BUTTON_PRESSED)
+ cx = DOOR_GFX_PAGEX3;
+
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ cx + CONFIRM_BUTTON_XPOS,cy + CONFIRM_BUTTON_GFX_YPOS,
+ CONFIRM_BUTTON_XSIZE,CONFIRM_BUTTON_YSIZE,
+ DX + CONFIRM_BUTTON_XPOS,DY + CONFIRM_BUTTON_YPOS);
+
+ redraw_mask |= REDRAW_DOOR_1;
+}
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* game.h *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#ifndef GAME_H
+#define GAME_H
+
+#include "main.h"
+
+#define PLAYER_LEVEL 0
+#define PLAYER_SETUP 1
+
+#define DF_DIG 0
+#define DF_SNAP 1
+#define DF_NO_PUSH 2
+
+#define MF_NO_ACTION 0
+#define MF_MOVING 1
+#define MF_ACTION 2
+
+BOOL CreateNewScoreFile(void);
+BOOL CreateNewNamesFile(int);
+void LoadLevelInfo(void);
+void LoadLevel(int);
+void LoadLevelTape(int);
+void LoadScore(int);
+void LoadPlayerInfo(int);
+void SaveLevel(int);
+void SaveLevelTape(int);
+void SaveScore(int);
+void SavePlayerInfo(int);
+void GetPlayerConfig(void);
+void InitGame(void);
+void InitMovDir(int, int);
+void GameWon(void);
+BOOL NewHiScore(void);
+void InitMovingField(int, int, int);
+void Moving2Blocked(int, int, int *, int *);
+void Blocked2Moving(int, int, int *, int *);
+int MovingOrBlocked2Element(int, int);
+void RemoveMovingField(int, int);
+void DrawDynamite(int, int);
+void CheckDynamite(int, int);
+void Explode(int, int, int);
+void Bang(int, int);
+void Blurb(int, int);
+void Impact(int, int);
+void TurnRound(int, int);
+void StartMoving(int, int);
+void ContinueMoving(int, int);
+void AmoebeWaechst(int, int);
+void AmoebeAbleger(int, int);
+void Life(int, int);
+void Ablenk(int, int);
+void Blubber(int, int);
+void NussKnacken(int, int);
+void SiebAktivieren(int x, int y);
+void AusgangstuerPruefen(int x, int y);
+void AusgangstuerOeffnen(int x, int y);
+int GameActions(int, int, int);
+void ScrollLevel(int, int);
+BOOL MoveFigure(int, int);
+void TestIfHeroHitsBadThing(void);
+void TestIfBadThingHitsHero(void);
+void TestIfBadThingHitsOtherBadThing(int, int);
+void KillHero(void);
+int DigField(int, int, int);
+BOOL SnapField(int, int);
+BOOL PlaceBomb(void);
+void PlaySoundLevel(int, int, int);
+void RaiseScore(int);
+void TapeInitRecording(void);
+void TapeStartRecording(void);
+void TapeStopRecording(void);
+void TapeRecordAction(int);
+void TapeRecordDelay(void);
+void TapeTogglePause(void);
+void TapeInitPlaying(void);
+void TapeStartPlaying(void);
+void TapeStopPlaying(void);
+int TapePlayAction(void);
+BOOL TapePlayDelay(void);
+void TapeStop(void);
+void TapeErase(void);
+void DrawVideoDisplay(unsigned long, unsigned long);
+void DrawSoundDisplay(unsigned long);
+void DrawGameButton(unsigned long);
+void DrawChooseButton(unsigned long);
+void DrawConfirmButton(unsigned long);
+
+#endif
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* images.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#include "images.h"
+
+struct PictureFile icon_pic =
+{
+ "rocks_icon.xbm",
+ "rocks_iconmask.xbm"
+};
+
+struct PictureFile pic[NUM_PICTURES] =
+{
+ "RocksScreen.xpm",
+ "RocksScreenMaske.xbm",
+
+ "RocksDoor.xpm",
+ "RocksDoorMaske.xbm",
+
+ "RocksToons.xpm",
+ "RocksToonsMaske.xbm",
+
+ "RocksFont.xpm",
+ NULL,
+
+ "RocksFont2.xpm",
+ NULL
+};
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* images.h *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#ifndef IMAGES_H
+#define IMAGES_H
+
+#include "main.h"
+
+extern struct PictureFile icon_pic;
+extern struct PictureFile pic[];
+
+#endif
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* init.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#include "init.h"
+#include "images.h"
+#include "sound.h"
+#include "screens.h"
+#include "tools.h"
+#include "game.h"
+#include "misc.h"
+
+#include <signal.h>
+
+int sound_process_id=0;
+
+void OpenAll(int argc, char *argv[])
+{
+ LoadLevelInfo();
+ LoadPlayerInfo(PLAYER_SETUP);
+ LoadPlayerInfo(PLAYER_LEVEL);
+
+ InitCounter();
+ InitSound();
+ InitSoundProcess();
+ InitJoystick();
+ InitRND(NEW_RANDOMIZE);
+
+ signal(SIGINT, CloseAll);
+ signal(SIGTERM, CloseAll);
+
+ InitDisplay(argc, argv);
+ InitWindow(argc, argv);
+ InitGfx();
+
+ DrawMainMenu();
+
+ XMapWindow(display, window);
+ XFlush(display);
+}
+
+void InitSound()
+{
+ int i;
+
+ if (sound_status==SOUND_OFF)
+ return;
+
+ if (access(sound_device_name,W_OK)<0)
+ {
+ fprintf(stderr,"%s: cannot access sound device - no sounds\n",progname);
+ sound_status=SOUND_OFF;
+ return;
+ }
+
+ if ((sound_device=open(sound_device_name,O_WRONLY))<0)
+ {
+ fprintf(stderr,"%s: cannot open sound device - no sounds\n",progname);
+ sound_status=SOUND_OFF;
+ return;
+ }
+
+ close(sound_device);
+ sound_status=SOUND_AVAILABLE;
+
+#ifdef VOXWARE
+ sound_loops_allowed = TRUE;
+ sound_loops_on = TRUE;
+#endif
+
+ for(i=0;i<NUM_SOUNDS;i++)
+ {
+ Sound[i].name = sound_name[i];
+ if (!LoadSound(&Sound[i]))
+ {
+ sound_status=SOUND_OFF;
+ return;
+ }
+ }
+}
+
+void InitSoundProcess()
+{
+ if (sound_status==SOUND_OFF)
+ return;
+
+ if (pipe(sound_pipe)<0)
+ {
+ fprintf(stderr,"%s: cannot create pipe - no sounds\n",progname);
+ sound_status=SOUND_OFF;
+ return;
+ }
+
+ if ((sound_process_id=fork())<0)
+ {
+ fprintf(stderr,"%s: cannot create child process - no sounds\n",progname);
+ sound_status=SOUND_OFF;
+ return;
+ }
+
+ if (!sound_process_id) /* we are child */
+ SoundServer();
+ else /* we are parent */
+ close(sound_pipe[0]); /* no reading from pipe needed */
+}
+
+void InitJoystick()
+{
+ if (global_joystick_status==JOYSTICK_OFF)
+ return;
+
+ if (access(joystick_device_name[joystick_nr],R_OK)<0)
+ {
+ fprintf(stderr,"%s: cannot access joystick device '%s'\n",
+ joystick_device_name[joystick_nr],progname);
+ joystick_status = JOYSTICK_OFF;
+ return;
+ }
+
+ if ((joystick_device=open(joystick_device_name[joystick_nr],O_RDONLY))<0)
+ {
+ fprintf(stderr,"%s: cannot open joystick device '%s'\n",
+ joystick_device_name[joystick_nr],progname);
+ joystick_status = JOYSTICK_OFF;
+ return;
+ }
+
+ joystick_status = JOYSTICK_AVAILABLE;
+ LoadJoystickData();
+}
+
+void InitDisplay(int argc, char *argv[])
+{
+ char *display_name = NULL;
+ int i;
+
+ /* get X server to connect to, if given as an argument */
+ for (i=1;i<argc-1;i++)
+ {
+ char *dispstr="-display";
+ int len=MAX(strlen(dispstr),strlen(argv[i]));
+
+ if (len<4)
+ continue;
+ else if (!strncmp(argv[i],dispstr,len))
+ {
+ display_name=argv[i+1];
+ break;
+ }
+ }
+
+ /* connect to X server */
+ if (!(display=XOpenDisplay(display_name)))
+ {
+ fprintf(stderr,"%s: cannot connect to X server %s\n",
+ progname, XDisplayName(display_name));
+ exit(-1);
+ }
+
+ screen = DefaultScreen(display);
+ cmap = DefaultColormap(display, screen);
+ pen_fg = WhitePixel(display,screen);
+ pen_bg = BlackPixel(display,screen);
+}
+
+void InitWindow(int argc, char *argv[])
+{
+ unsigned int border_width = 4;
+ Pixmap icon_pixmap, iconmask_pixmap;
+ unsigned int icon_width,icon_height;
+ int icon_hot_x,icon_hot_y;
+ char icon_filename[256];
+ XSizeHints size_hints;
+ XWMHints wm_hints;
+ XClassHint class_hints;
+ XTextProperty windowName, iconName;
+ XGCValues gc_values;
+ unsigned long gc_valuemask;
+ char *window_name = "Rocks'n'Diamonds";
+ char *icon_name = "Rocks'n'Diamonds";
+ long window_event_mask;
+
+ width = WIN_XSIZE;
+ height = WIN_YSIZE;
+
+ window = XCreateSimpleWindow(display, RootWindow(display, screen),
+ WIN_XPOS, WIN_YPOS, width, height, border_width,
+ pen_fg, pen_bg);
+
+ sprintf(icon_filename,"%s/%s",GFX_PATH,icon_pic.picture_filename);
+ XReadBitmapFile(display,window,icon_filename,
+ &icon_width,&icon_height,
+ &icon_pixmap,&icon_hot_x,&icon_hot_y);
+ if (!icon_pixmap)
+ {
+ fprintf(stderr, "%s: cannot read icon bitmap file '%s'.\n",
+ progname,icon_filename);
+ exit(-1);
+ }
+
+ sprintf(icon_filename,"%s/%s",GFX_PATH,icon_pic.picturemask_filename);
+ XReadBitmapFile(display,window,icon_filename,
+ &icon_width,&icon_height,
+ &iconmask_pixmap,&icon_hot_x,&icon_hot_y);
+ if (!iconmask_pixmap)
+ {
+ fprintf(stderr, "%s: cannot read icon bitmap file '%s'.\n",
+ progname,icon_filename);
+ exit(-1);
+ }
+
+ size_hints.flags = PSize | PMinSize | PMaxSize;
+ size_hints.width = size_hints.min_width = size_hints.max_width = width;
+ size_hints.height = size_hints.min_height = size_hints.max_height = height;
+
+ if (!XStringListToTextProperty(&window_name, 1, &windowName))
+ {
+ fprintf(stderr, "%s: structure allocation for windowName failed.\n",
+ progname);
+ exit(-1);
+ }
+
+ if (!XStringListToTextProperty(&icon_name, 1, &iconName))
+ {
+ fprintf(stderr, "%s: structure allocation for iconName failed.\n",
+ progname);
+ exit(-1);
+ }
+
+ wm_hints.initial_state = NormalState;
+ wm_hints.input = True;
+ wm_hints.icon_pixmap = icon_pixmap;
+ wm_hints.icon_mask = iconmask_pixmap;
+ wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
+
+ class_hints.res_name = progname;
+ class_hints.res_class = "Rocks'n'Diamonds";
+
+ XSetWMProperties(display, window, &windowName, &iconName,
+ argv, argc, &size_hints, &wm_hints,
+ &class_hints);
+
+ XFree(windowName.value);
+ XFree(iconName.value);
+
+ /* Select event types wanted */
+ window_event_mask = ExposureMask | StructureNotifyMask | FocusChangeMask |
+ ButtonPressMask | ButtonReleaseMask | ButtonMotionMask |
+ KeyPressMask | KeyReleaseMask;
+ XSelectInput(display, window, window_event_mask);
+
+ /* create GC for drawing with window depth */
+ gc_values.graphics_exposures = False;
+ gc_values.foreground = pen_bg;
+ gc_values.background = pen_bg;
+ gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
+ gc = XCreateGC(display, window, gc_valuemask, &gc_values);
+}
+
+void InitGfx()
+{
+ int i,j,x,y;
+ int xpm_err, xbm_err;
+ unsigned int width,height;
+ int hot_x,hot_y;
+ XGCValues gc_values;
+ unsigned long gc_valuemask;
+ XGCValues clip_gc_values;
+ unsigned long clip_gc_valuemask;
+ char filename[256];
+ Pixmap shapemask;
+
+ for(i=0;i<NUM_PICTURES;i++)
+ {
+ if (pic[i].picture_filename)
+ {
+ sprintf(filename,"%s/%s",GFX_PATH,pic[i].picture_filename);
+
+ xpm_att[i].valuemask = XpmCloseness;
+ xpm_att[i].closeness = 20000;
+ xpm_err = XpmReadFileToPixmap(display,window,filename,
+ &pix[i],&shapemask,&xpm_att[i]);
+ switch(xpm_err)
+ {
+ case XpmOpenFailed:
+ fprintf(stderr,"Xpm file open failed on '%s' !\n",filename);
+ CloseAll();
+ exit(-1);
+ case XpmFileInvalid:
+ fprintf(stderr,"Invalid Xpm file '%s'!\n",filename);
+ CloseAll();
+ exit(-1);
+ case XpmNoMemory:
+ fprintf(stderr,"Not enough memory !\n");
+ CloseAll();
+ exit(1);
+ case XpmColorFailed:
+ fprintf(stderr,"Can`t get any colors...\n");
+ CloseAll();
+ exit(-1);
+ default:
+ break;
+ }
+ if (!pix[i])
+ {
+ fprintf(stderr, "%s: cannot read Xpm file '%s'.\n",
+ progname,filename);
+ CloseAll();
+ exit(-1);
+ }
+ }
+
+ if (pic[i].picturemask_filename)
+ {
+ sprintf(filename,"%s/%s",GFX_PATH,pic[i].picturemask_filename);
+
+ xbm_err = XReadBitmapFile(display,window,filename,
+ &width,&height,&clipmask[i],&hot_x,&hot_y);
+ switch(xbm_err)
+ {
+ case BitmapSuccess:
+ break;
+ case BitmapOpenFailed:
+ fprintf(stderr,"Bitmap file open failed on '%s' !\n",filename);
+ CloseAll();
+ exit(-1);
+ break;
+ case BitmapFileInvalid:
+ fprintf(stderr,"Bitmap file invalid: '%s' !\n",filename);
+ CloseAll();
+ exit(-1);
+ break;
+ case BitmapNoMemory:
+ fprintf(stderr,"No memory for file '%s' !\n",filename);
+ CloseAll();
+ exit(-1);
+ break;
+ default:
+ break;
+ }
+ if (!clipmask[i])
+ {
+ fprintf(stderr, "%s: cannot read X11 bitmap file '%s'.\n",
+ progname,filename);
+ CloseAll();
+ exit(-1);
+ }
+ }
+ }
+
+ pix[PIX_DB_BACK] = XCreatePixmap(display, window,
+ WIN_XSIZE,WIN_YSIZE,
+ XDefaultDepth(display,screen));
+ pix[PIX_DB_DOOR] = XCreatePixmap(display, window,
+ 3*DXSIZE,DYSIZE+VYSIZE,
+ XDefaultDepth(display,screen));
+
+ clipmask[PIX_FADEMASK] = XCreatePixmap(display, window,
+ SXSIZE+TILEX,SYSIZE+TILEY,1);
+
+ if (!pix[PIX_DB_BACK] || !pix[PIX_DB_DOOR] || !clipmask[PIX_FADEMASK])
+ {
+ fprintf(stderr, "%s: cannot create additional Pixmaps!\n",progname);
+ CloseAll();
+ exit(-1);
+ }
+
+ /* create GC for drawing with bitplane depth */
+ gc_values.graphics_exposures = False;
+ gc_values.foreground = pen_bg;
+ gc_values.background = pen_bg;
+ gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
+ plane_gc = XCreateGC(display, clipmask[PIX_BACK], gc_valuemask, &gc_values);
+
+ for(y=0;y<=SCR_FIELDY;y++) for(x=0;x<=SCR_FIELDX;x++)
+ XCopyArea(display,clipmask[PIX_BACK],clipmask[PIX_FADEMASK],plane_gc,
+ SX+2*TILEX,SY+10*TILEY,TILEX,TILEY,x*TILEX,y*TILEY);
+
+ for(i=0;i<NUM_PIXMAPS;i++)
+ {
+ if (clipmask[i])
+ {
+ clip_gc_values.graphics_exposures = False;
+ clip_gc_values.foreground = pen_fg;
+ clip_gc_values.background = pen_bg;
+ clip_gc_values.clip_mask = clipmask[i];
+ clip_gc_valuemask =
+ GCGraphicsExposures | GCForeground | GCBackground | GCClipMask;
+ clip_gc[i] = XCreateGC(display,window,clip_gc_valuemask,&clip_gc_values);
+ }
+ }
+
+ drawto = drawto_field = backbuffer = pix[PIX_DB_BACK];
+
+ XCopyArea(display,pix[PIX_BACK],backbuffer,gc,
+ 0,0, WIN_XSIZE,WIN_YSIZE, 0,0);
+ XFillRectangle(display,backbuffer,gc,
+ REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE);
+
+ for(i=0;i<SCR_FIELDX;i++)
+ for(j=0;j<SCR_FIELDY;j++)
+ redraw[i][j]=0;
+ redraw_tiles=0;
+ redraw_mask=REDRAW_ALL;
+}
+
+void CloseAll()
+{
+ int i;
+
+ if (sound_process_id)
+ {
+ StopSounds();
+ kill(sound_process_id, SIGTERM);
+ FreeSounds(NUM_SOUNDS);
+ }
+
+ for(i=0;i<NUM_PIXMAPS;i++)
+ {
+ if (pix[i])
+ {
+ if (i<NUM_PICTURES) /* XPM pictures */
+ {
+ XFreeColors(display,DefaultColormap(display,screen),
+ xpm_att[i].pixels,xpm_att[i].npixels,0);
+ XpmFreeAttributes(&xpm_att[i]);
+ }
+ XFreePixmap(display,pix[i]);
+ }
+ if (clipmask[i])
+ XFreePixmap(display,clipmask[i]);
+ if (clip_gc[i])
+ XFreeGC(display, clip_gc[i]);
+ }
+
+ if (gc)
+ XFreeGC(display, gc);
+ if (plane_gc)
+ XFreeGC(display, plane_gc);
+
+ XCloseDisplay(display);
+
+ exit(0);
+}
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* init.h *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#ifndef INIT_H
+#define INIT_H
+
+#include "main.h"
+
+void OpenAll(int, char **);
+void InitDisplay(int, char **);
+void InitSound(void);
+void InitSoundProcess(void);
+void InitJoystick(void);
+void InitWindow(int, char **);
+void InitGfx(void);
+void CloseAll();
+
+#endif
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* main.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#include "main.h"
+#include "init.h"
+#include "events.h"
+#include "sound.h"
+
+Display *display;
+int screen;
+Window window;
+GC gc, plane_gc;
+GC clip_gc[NUM_PIXMAPS];
+Pixmap pix[NUM_PIXMAPS];
+Pixmap clipmask[NUM_PIXMAPS];
+XpmAttributes xpm_att[NUM_PICTURES];
+Drawable drawto, drawto_field, backbuffer;
+Colormap cmap;
+
+int sound_pipe[2];
+int sound_device;
+char *sound_device_name = SOUND_DEVICE;
+int joystick_device = 0;
+char *joystick_device_name[2] = { DEV_JOYSTICK_0, DEV_JOYSTICK_1 };
+int width, height;
+unsigned long pen_fg, pen_bg;
+
+int game_status = MAINMENU;
+int button_status = MB_NOT_PRESSED, motion_status = FALSE;
+int key_status = KEY_NOT_PRESSED;
+int global_joystick_status = JOYSTICK_STATUS;
+int joystick_status = JOYSTICK_STATUS;
+int sound_status = SOUND_STATUS, sound_on=TRUE;
+int sound_loops_allowed = FALSE, sound_loops_on = FALSE;
+int sound_music_on = FALSE;
+int toons_on = TRUE;
+int direct_draw_on = FALSE;
+int fading_on = FALSE;
+int autorecord_on = FALSE;
+int joystick_nr = 0;
+
+BOOL redraw[SCR_FIELDX][SCR_FIELDY];
+int redraw_mask;
+int redraw_tiles;
+
+int Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+int Ur[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+int MovPos[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+int MovDir[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+int MovDelay[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+int Store[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+int Store2[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+int Frame[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+int Stop[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+int level_nr, leveldir_nr, num_leveldirs;
+int lev_fieldx,lev_fieldy, scroll_x,scroll_y;
+
+int LevelSolved,GameOver, JX,JY, ZX,ZY;
+int Gems,Dynamite,Key[4],TimeLeft,Score,MampferNr;
+int CheckMoving,CheckExploding, SiebAktiv;
+
+struct LevelDirInfo leveldir[MAX_LEVDIR_ENTRIES];
+struct LevelInfo level;
+struct PlayerInfo player;
+struct HiScore highscore[MAX_SCORE_ENTRIES];
+struct SoundInfo Sound[NUM_SOUNDS];
+struct RecordingInfo tape,master_tape;
+
+/* data needed for playing sounds */
+char *sound_name[NUM_SOUNDS] =
+{
+ "alchemy",
+ "amoebe",
+ "antigrav",
+ "autsch",
+ "blurb",
+ "bong",
+ "buing",
+ "chase",
+ "czardasz",
+ "deng",
+ "fuel",
+ "gong",
+ "halloffame",
+ "holz",
+ "hui",
+ "kabumm",
+ "kink",
+ "klapper",
+ "kling",
+ "klopf",
+ "klumpf",
+ "knack",
+ "knurk",
+ "krach",
+ "lachen",
+ "laser",
+ "miep",
+ "network",
+ "njam",
+ "oeffnen",
+ "pling",
+ "pong",
+ "pusch",
+ "quiek",
+ "quirk",
+ "rhythmloop",
+ "roaaar",
+ "roehr",
+ "rumms",
+ "schlopp",
+ "schlurf",
+ "schrff",
+ "schwirr",
+ "sirr",
+ "slurp",
+ "sproing",
+ "twilight",
+ "tyger",
+ "voyager",
+ "warnton",
+ "whoosh",
+ "zisch"
+};
+
+/* background music */
+int background_loop[] =
+{
+ SND_ALCHEMY,
+ SND_CHASE,
+ SND_NETWORK,
+ SND_CZARDASZ,
+ SND_TYGER,
+ SND_VOYAGER,
+ SND_TWILIGHT
+};
+int num_bg_loops = sizeof(background_loop)/sizeof(int);
+
+char *progname;
+
+int main(int argc, char *argv[])
+{
+ progname = argv[0];
+
+ OpenAll(argc,argv);
+ EventLoop();
+ CloseAll();
+
+ exit(0);
+}
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* main.h *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#ifndef MAIN_H
+#define MAIN_H
+
+#define XK_MISCELLANY
+#define XK_LATIN1
+
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xos.h>
+#include <X11/Intrinsic.h>
+#include <X11/keysymdef.h>
+
+#include XPM_INCLUDE_FILE
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+typedef int BOOL;
+
+#define TRUE 1
+#define FALSE 0
+
+#define WIN_XPOS 0
+#define WIN_YPOS 0
+#define WIN_XSIZE 672
+#define WIN_YSIZE 560
+#define SCR_FIELDX 17
+#define SCR_FIELDY 17
+
+/*
+
+#define LEV_FIELDX 64
+#define LEV_FIELDY 32
+
+*/
+
+#define MIN_LEV_FIELDX (SCR_FIELDX-2)
+#define MIN_LEV_FIELDY (SCR_FIELDY-2)
+#define STD_LEV_FIELDX 64
+#define STD_LEV_FIELDY 32
+#define MAX_LEV_FIELDX 128
+#define MAX_LEV_FIELDY 128
+
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+#define MAX(a,b) ((a)>(b) ? (a) : (b))
+#define ABS(a) ((a)<0 ? -(a) : (a))
+#define SIGN(a) ((a)<0 ? -1 : ((a)>0 ? 1 : 0))
+#define SCROLLX(a) ((a)-scroll_x)
+#define SCROLLY(a) ((a)-scroll_y)
+#define UNSCROLLX(a) ((a)+scroll_x)
+#define UNSCROLLY(a) ((a)+scroll_y)
+#define IN_SCR_FIELD(x,y) ((x)>=0 && (x)<SCR_FIELDX && (y)>=0 &&(y)<SCR_FIELDY)
+#define IN_LEV_FIELD(x,y) ((x)>=0 && (x)<lev_fieldx && (y)>=0 &&(y)<lev_fieldy)
+#define PLAYER(x,y) (JX==(x) && JY==(y))
+#define IS_FREE(x,y) (Feld[x][y]==EL_LEERRAUM && !PLAYER(x,y))
+#define IS_MOVING(x,y) (MovPos[x][y]!=0)
+#define IS_BLOCKED(x,y) (Feld[x][y]==EL_BLOCKED)
+#define IS_AMOEBOID(e) ((e)==EL_AMOEBE1 || (e)==EL_AMOEBE2 || (e)==EL_AMOEBE3)
+#define IS_BADEWANNOID(e) ((e)>=EL_BADEWANNE1 && (e)<=EL_BADEWANNE5)
+#define IS_SCHLUESSEL(e) ((e)>=EL_SCHLUESSEL1 && (e)<=EL_SCHLUESSEL4)
+#define IS_PFORTE(e) ((e)>=EL_PFORTE1 && (e)<=EL_PFORTE4X)
+#define IS_CHAR(e) ((e)>=EL_CHAR_START && (e)<=EL_CHAR_END)
+
+#define IS_SOLID(e) ((e)==EL_BETON || (e)==EL_MAUERWERK || (e)==EL_FELSBODEN || (e)==EL_AUSGANG_ZU || (e)==EL_AUSGANG_ACT || (e)==EL_AUSGANG_AUF || IS_AMOEBOID(e) || (e)==EL_MORAST_VOLL || (e)==EL_MORAST_LEER || (e)==EL_SIEB_VOLL || (e)==EL_SIEB_LEER || (e)==EL_LIFE || (e)==EL_LIFE_ASYNC || IS_BADEWANNOID(e))
+
+#define IS_MASSIV(e) ((e)==EL_BETON || (e)==EL_SALZSAEURE || IS_BADEWANNOID(e) || IS_PFORTE(e))
+
+#define CAN_FALL(e) ((e)==EL_FELSBROCKEN || (e)==EL_EDELSTEIN || (e)==EL_DIAMANT || (e)==EL_BOMBE || (e)==EL_KOKOSNUSS || (e)==EL_TROPFEN || (e)==EL_MORAST_VOLL || (e)==EL_SIEB_VOLL)
+
+#define CAN_SMASH(e) ((e)==EL_FELSBROCKEN || (e)==EL_EDELSTEIN || (e)==EL_DIAMANT || IS_SCHLUESSEL(e) || (e)==EL_BOMBE || (e)==EL_KOKOSNUSS || (e)==EL_TROPFEN)
+
+#define CAN_CHANGE(e) ((e)==EL_FELSBROCKEN || (e)==EL_EDELSTEIN || (e)==EL_DIAMANT)
+
+#define CAN_MOVE(e) ((e)==EL_KAEFER || (e)==EL_FLIEGER || (e)==EL_MAMPFER || (e)==EL_ZOMBIE || (e)==EL_PACMAN)
+
+#define COULD_MOVE(e) (((e)>=EL_KAEFER_R && (e)<=EL_KAEFER_U) || ((e)>=EL_FLIEGER_R && (e)<=EL_FLIEGER_U) || ((e)>=EL_PACMAN && (e)==EL_PACMAN_U))
+
+/*
+#define CAN_KILL(e) ((e)==EL_KAEFER || (e)==EL_FLIEGER || (e)==EL_MAMPFER || (e)==EL_ZOMBIE || (e)==EL_PACMAN || (e)==EL_TROPFEN)
+*/
+
+#define IS_ENEMY(e) ((e)==EL_KAEFER || (e)==EL_FLIEGER || (e)==EL_MAMPFER || (e)==EL_ZOMBIE || (e)==EL_PACMAN)
+#define DONT_TOUCH(e) ((e)==EL_KAEFER || (e)==EL_FLIEGER)
+#define DONT_GO_TO(e) (IS_ENEMY(e) || (e)==EL_TROPFEN || (e)==EL_SALZSAEURE)
+
+#define SLIPPERY(e) ((e)==EL_FELSBODEN || (e)==EL_FELSBROCKEN || (e)==EL_EDELSTEIN || (e)==EL_DIAMANT || (e)==EL_BOMBE || (e)==EL_KOKOSNUSS || (e)==EL_ABLENK_EIN || (e)==EL_ABLENK_AUS || (e)==EL_BADEWANNE1 || (e)==EL_BADEWANNE2)
+
+#define EL_CHANGED(e) ((e)==EL_FELSBROCKEN ? EL_EDELSTEIN : (e)==EL_EDELSTEIN ? EL_DIAMANT : EL_FELSBROCKEN)
+#define IS_DRAWABLE(e) ((e)<EL_BLOCKED)
+#define IS_NOT_DRAWABLE(e) ((e)>=EL_BLOCKED)
+#define TIMESIZE (TimeLeft*100/level.time)
+
+#define LEVELDIR_SIZE(x) ((x).num_ready + (x).num_free)
+#define TAPE_IS_EMPTY(x) ((x).length == 0)
+
+/* Pixmaps with Xpm or X11 Bitmap files */
+#define PIX_BACK 0
+#define PIX_DOOR 1
+#define PIX_TOONS 2
+#define PIX_BIGFONT 3
+#define PIX_SMALLFONT 4
+/* Pixmaps without them */
+#define PIX_DB_BACK 5
+#define PIX_DB_DOOR 6
+#define PIX_FADEMASK 7
+
+#define NUM_PICTURES 5
+#define NUM_PIXMAPS 8
+
+#define MAX_NAMELEN (10+1)
+
+#define MAX_LEVNAMLEN 32
+#define MAX_SC_ENTRIES 16
+#define MAX_TAPELEN 10000
+
+#define MAX_LEVDIR_FILENAME (64+1)
+#define MAX_LEVDIR_NAME (16+1)
+#define MAX_LEVDIR_ENTRIES 15
+#define MAX_SCORE_ENTRIES 15
+
+#define MAX_FILENAME 256
+
+struct PictureFile
+{
+ char *picture_filename;
+ char *picturemask_filename;
+};
+
+struct HiScore
+{
+ char Name[MAX_NAMELEN];
+ int Score;
+};
+
+struct PlayerInfo
+{
+ char login_name[MAX_NAMELEN];
+ char alias_name[MAX_NAMELEN];
+ int handicap;
+ unsigned int setup;
+ int leveldir_nr;
+};
+
+struct LevelInfo
+{
+ int fieldx;
+ int fieldy;
+ int time;
+ int edelsteine;
+ char name[MAX_LEVNAMLEN];
+ int score[MAX_SC_ENTRIES];
+ int mampfer_inhalt[4][3][3];
+ int tempo_amoebe;
+ int dauer_sieb;
+ int dauer_ablenk;
+};
+
+struct LevelDirInfo
+{
+ char filename[MAX_LEVDIR_FILENAME];
+ char name[MAX_LEVDIR_NAME];
+ int num_ready;
+ int num_free;
+};
+
+struct RecordingInfo
+{
+ int level_nr;
+ unsigned int random_seed;
+ unsigned long date;
+ unsigned long counter;
+ unsigned long length;
+ BOOL recording, playing, pausing;
+ struct
+ {
+ unsigned char joystickdata;
+ unsigned char delay;
+ } pos[MAX_TAPELEN];
+};
+
+struct JoystickInfo
+{
+ int xleft, xright, xmiddle;
+ int yupper, ylower, ymiddle;
+};
+
+extern Display *display;
+extern int screen;
+extern Window window;
+extern GC gc, plane_gc;
+extern GC clip_gc[];
+extern XImage *image[];
+extern Pixmap clipmask[];
+extern Pixmap pix[];
+extern XpmAttributes xpm_att[];
+extern Drawable drawto, drawto_field, backbuffer;
+extern Colormap cmap;
+
+extern int sound_pipe[2];
+extern int sound_device;
+extern char *sound_device_name;
+extern int joystick_device;
+extern char *joystick_device_name[2];
+extern int width, height;
+extern unsigned long pen_fg, pen_bg;
+
+extern int game_status;
+extern int button_status, motion_status;
+extern int key_status;
+extern int global_joystick_status, joystick_status;
+extern int sound_status, sound_on;
+extern int sound_loops_allowed, sound_loops_on;
+extern int sound_music_on;
+extern int toons_on;
+extern int direct_draw_on;
+extern int fading_on;
+extern int autorecord_on;
+extern int joystick_nr;
+
+extern BOOL redraw[SCR_FIELDX][SCR_FIELDY];
+extern int redraw_mask;
+extern int redraw_tiles;
+
+extern int Feld[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern int Ur[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern int MovPos[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern int MovDir[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern int MovDelay[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern int Store[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern int Store2[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern int Frame[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern int Stop[MAX_LEV_FIELDX][MAX_LEV_FIELDY];
+extern int level_nr, leveldir_nr, num_leveldirs;
+extern int lev_fieldx,lev_fieldy, scroll_x,scroll_y;
+
+extern int LevelSolved,GameOver, JX,JY, ZX,ZY;
+extern int Gems,Dynamite,Key[4],TimeLeft,Score,MampferNr;
+extern int CheckMoving,CheckExploding, SiebAktiv;
+
+extern struct LevelDirInfo leveldir[];
+extern struct LevelInfo level;
+extern struct PlayerInfo player;
+extern struct HiScore highscore[];
+extern struct RecordingInfo tape, master_tape;
+
+extern int background_loop[];
+extern int num_bg_loops;
+
+extern char *progname;
+
+
+/* often used screen positions */
+#define SX 8
+#define SY 8
+#define REAL_SX (SX-2)
+#define REAL_SY (SY-2)
+#define DX 566
+#define DY 60
+#define VX DX
+#define VY 400
+#define TILEX 32
+#define TILEY 32
+#define MINI_TILEX (TILEX/2)
+#define MINI_TILEY (TILEY/2)
+#define MICRO_TILEX (TILEX/8)
+#define MICRO_TILEY (TILEY/8)
+#define MIDPOSX (SCR_FIELDX/2)
+#define MIDPOSY (SCR_FIELDY/2)
+#define SXSIZE (SCR_FIELDX*TILEX)
+#define SYSIZE (SCR_FIELDY*TILEY)
+#define DXSIZE 100
+#define DYSIZE 280
+#define VXSIZE DXSIZE
+#define VYSIZE 100
+#define FULL_SXSIZE (2+SXSIZE+2)
+#define FULL_SYSIZE (2+SYSIZE+2)
+#define MICROLEV_XPOS (SX+4*32+16)
+#define MICROLEV_YPOS (SX+12*32)
+#define MICROLEV_XSIZE (STD_LEV_FIELDX*MICRO_TILEX)
+#define MICROLEV_YSIZE (STD_LEV_FIELDY*MICRO_TILEY)
+#define MICROLABEL_YPOS (MICROLEV_YPOS+MICROLEV_YSIZE+12)
+#define FONT1_XSIZE 32
+#define FONT1_YSIZE 32
+#define FONT2_XSIZE 14
+#define FONT2_YSIZE 14
+#define FONT3_XSIZE 11
+#define FONT3_YSIZE 14
+#define FONT4_XSIZE 16
+#define FONT4_YSIZE 16
+
+#define GFX_STARTX SX
+#define GFX_STARTY SY
+#define MINI_GFX_STARTX SX
+#define MINI_GFX_STARTY 432
+#define MICRO_GFX_STARTX SX
+#define MICRO_GFX_STARTY 528
+#define GFX_PER_LINE 16
+#define MINI_GFX_PER_LINE 32
+#define MICRO_GFX_PER_LINE 128
+#define FONT_CHARS_PER_LINE 16
+#define FONT_LINES_PER_FONT 4
+
+/* game elements:
+** 0 - 255: real elements, stored in level file
+** 256 - ?: flag elements, only used at runtime
+*/
+/* "real" level elements */
+#define EL_LEERRAUM 0
+#define EL_ERDREICH 1
+#define EL_MAUERWERK 2
+#define EL_FELSBODEN 3
+#define EL_FELSBROCKEN 4
+#define EL_SCHLUESSEL 5
+#define EL_EDELSTEIN 6
+#define EL_AUSGANG_ZU 7
+#define EL_SPIELFIGUR 8
+#define EL_KAEFER 9
+#define EL_FLIEGER 10
+#define EL_MAMPFER 11
+#define EL_ZOMBIE 12
+#define EL_BETON 13
+#define EL_DIAMANT 14
+#define EL_AMOEBE1 15
+#define EL_MORAST_LEER 16
+#define EL_MORAST_VOLL 17
+#define EL_TROPFEN 18
+#define EL_BOMBE 19
+#define EL_SIEB_LEER 20
+#define EL_SIEB_VOLL 21
+#define EL_SALZSAEURE 22
+#define EL_AMOEBE2 23
+#define EL_AMOEBE3 24
+#define EL_KOKOSNUSS 25
+#define EL_LIFE 26
+#define EL_LIFE_ASYNC 27
+#define EL_DYNAMIT 28
+#define EL_BADEWANNE 29
+#define EL_ABLENK_AUS 30
+#define EL_ABLENK_EIN 31
+#define EL_SCHLUESSEL1 32
+#define EL_SCHLUESSEL2 33
+#define EL_SCHLUESSEL3 34
+#define EL_SCHLUESSEL4 35
+#define EL_PFORTE1 36
+#define EL_PFORTE2 37
+#define EL_PFORTE3 38
+#define EL_PFORTE4 39
+#define EL_PFORTE1X 40
+#define EL_PFORTE2X 41
+#define EL_PFORTE3X 42
+#define EL_PFORTE4X 43
+#define EL_DYNAMIT_AUS 44
+#define EL_PACMAN 45
+#define EL_UNSICHTBAR 46
+#define EL_BIRNE_AUS 47
+#define EL_BIRNE_EIN 48
+#define EL_ERZ_1 49
+#define EL_ERZ_2 50
+
+#define EL_SPIELER1 80
+#define EL_SPIELER2 81
+#define EL_SPIELER3 82
+#define EL_SPIELER4 83
+#define EL_KAEFER_R 84
+#define EL_KAEFER_O 85
+#define EL_KAEFER_L 86
+#define EL_KAEFER_U 87
+#define EL_FLIEGER_R 88
+#define EL_FLIEGER_O 89
+#define EL_FLIEGER_L 90
+#define EL_FLIEGER_U 91
+#define EL_PACMAN_R 92
+#define EL_PACMAN_O 93
+#define EL_PACMAN_L 94
+#define EL_PACMAN_U 95
+
+#define EL_BADEWANNE1 100
+#define EL_BADEWANNE2 101
+#define EL_BADEWANNE3 102
+#define EL_BADEWANNE4 103
+#define EL_BADEWANNE5 104
+#define EL_SIEB_TOT 105
+#define EL_AUSGANG_ACT 106
+#define EL_AUSGANG_AUF 107
+
+#define EL_CHAR_START 120
+#define EL_CHAR_ASCII0 (EL_CHAR_START-32)
+#define EL_CHAR_AUSRUF (EL_CHAR_ASCII0+33)
+#define EL_CHAR_ZOLL (EL_CHAR_ASCII0+34)
+#define EL_CHAR_DOLLAR (EL_CHAR_ASCII0+36)
+#define EL_CHAR_PROZ (EL_CHAR_ASCII0+37)
+#define EL_CHAR_APOSTR (EL_CHAR_ASCII0+39)
+#define EL_CHAR_KLAMM1 (EL_CHAR_ASCII0+40)
+#define EL_CHAR_KLAMM2 (EL_CHAR_ASCII0+41)
+#define EL_CHAR_PLUS (EL_CHAR_ASCII0+43)
+#define EL_CHAR_KOMMA (EL_CHAR_ASCII0+44)
+#define EL_CHAR_MINUS (EL_CHAR_ASCII0+45)
+#define EL_CHAR_PUNKT (EL_CHAR_ASCII0+46)
+#define EL_CHAR_SLASH (EL_CHAR_ASCII0+47)
+#define EL_CHAR_0 (EL_CHAR_ASCII0+48)
+#define EL_CHAR_9 (EL_CHAR_ASCII0+57)
+#define EL_CHAR_DOPPEL (EL_CHAR_ASCII0+58)
+#define EL_CHAR_SEMIKL (EL_CHAR_ASCII0+59)
+#define EL_CHAR_LT (EL_CHAR_ASCII0+60)
+#define EL_CHAR_GLEICH (EL_CHAR_ASCII0+61)
+#define EL_CHAR_GT (EL_CHAR_ASCII0+62)
+#define EL_CHAR_FRAGE (EL_CHAR_ASCII0+63)
+#define EL_CHAR_AT (EL_CHAR_ASCII0+64)
+#define EL_CHAR_A (EL_CHAR_ASCII0+65)
+#define EL_CHAR_Z (EL_CHAR_ASCII0+90)
+#define EL_CHAR_AE (EL_CHAR_ASCII0+91)
+#define EL_CHAR_OE (EL_CHAR_ASCII0+92)
+#define EL_CHAR_UE (EL_CHAR_ASCII0+93)
+#define EL_CHAR_COPY (EL_CHAR_ASCII0+94)
+#define EL_CHAR_END (EL_CHAR_START+79)
+
+/* "unreal" runtime elements */
+#define EL_BLOCKED 300
+#define EL_EXPLODING 301
+#define EL_CRACKINGNUT 302
+#define EL_BLURB_LEFT 303
+#define EL_BLURB_RIGHT 304
+#define EL_AMOEBING2 305
+#define EL_AMOEBING3 306
+
+/* names for the graphic objects */
+/* Zeile 0 (0) */
+#define GFX_LEERRAUM (-1)
+#define GFX_ERDREICH 0
+#define GFX_ERDENRAND 1
+#define GFX_MORAST_LEER 2
+#define GFX_MORAST_VOLL 3
+#define GFX_BETON 4
+#define GFX_MAUERWERK 5
+#define GFX_FELSBODEN 6
+#define GFX_BOMBE_MM 7
+#define GFX_EDELSTEIN 8
+#define GFX_DIAMANT 10
+#define GFX_FELSBROCKEN 12
+/* Zeile 1 (16) */
+#define GFX_BADEWANNE1 16
+#define GFX_SALZSAEURE 17
+#define GFX_BADEWANNE2 18
+#define GFX_UNSICHTBAR 19
+#define GFX_SCHLUESSEL1 20
+#define GFX_SCHLUESSEL2 21
+#define GFX_SCHLUESSEL3 22
+#define GFX_SCHLUESSEL4 23
+#define GFX_LIFE 24
+#define GFX_LIFE_ASYNC 25
+#define GFX_BADEWANNE 26
+#define GFX_BOMBE 27
+#define GFX_KOKOSNUSS 28
+#define GFX_CRACKINGNUT 29
+/* Zeile 2 (32) */
+#define GFX_BADEWANNE3 32
+#define GFX_BADEWANNE4 33
+#define GFX_BADEWANNE5 34
+#define GFX_SPIELFIGUR 35
+#define GFX_PFORTE1 36
+#define GFX_PFORTE2 37
+#define GFX_PFORTE3 38
+#define GFX_PFORTE4 39
+#define GFX_PFORTE1X 40
+#define GFX_PFORTE2X 41
+#define GFX_PFORTE3X 42
+#define GFX_PFORTE4X 43
+#define GFX_AUSGANG_ZU 44
+#define GFX_AUSGANG_ACT 44
+#define GFX_AUSGANG_AUF 47
+/* Zeile 3 (48) */
+#define GFX_DYNAMIT_AUS 48
+#define GFX_DYNAMIT 49
+#define GFX_FLIEGER 56
+#define GFX_FLIEGER_R 56
+#define GFX_FLIEGER_O 57
+#define GFX_FLIEGER_L 58
+#define GFX_FLIEGER_U 59
+/* Zeile 4 (64) */
+#define GFX_EXPLOSION 64
+#define GFX_KAEFER 72
+#define GFX_KAEFER_R 72
+#define GFX_KAEFER_O 73
+#define GFX_KAEFER_L 74
+#define GFX_KAEFER_U 75
+/* Zeile 5 (80) */
+#define GFX_MAMPFER 80
+#define GFX_ZOMBIE 84
+#define GFX_PACMAN 88
+#define GFX_PACMAN_R 88
+#define GFX_PACMAN_O 89
+#define GFX_PACMAN_L 90
+#define GFX_PACMAN_U 91
+/* Zeile 6 (96) */
+#define GFX_ABLENK 96
+#define GFX_ABLENK_EIN GFX_ABLENK
+#define GFX_ABLENK_AUS GFX_ABLENK
+#define GFX_AMOEBE2 100
+#define GFX_TROPFEN 101
+#define GFX_AMOEBING GFX_TROPFEN
+#define GFX_AMOEBE_LEBT 104
+#define GFX_AMOEBE3 GFX_AMOEBE_LEBT
+#define GFX_AMOEBE_TOT 108
+#define GFX_AMOEBE1 GFX_AMOEBE_TOT
+/* Zeile 7 (112) */
+#define GFX_GEBLUBBER 124
+/* Zeile 8 (128) */
+#define GFX_SIEB_LEER 128
+#define GFX_SIEB_VOLL GFX_SIEB_LEER
+#define GFX_SIEB_TOT GFX_SIEB_LEER
+#define GFX_ERZ_1 132
+#define GFX_ERZ_2 133
+#define GFX_BIRNE_AUS 134
+#define GFX_BIRNE_EIN 135
+#define GFX_KUGEL_ROT 140
+#define GFX_KUGEL_BLAU 141
+#define GFX_KUGEL_GELB 142
+/* Zeile 9 (144) */
+#define GFX_BLURB_LEFT 144
+#define GFX_BLURB_RIGHT 148
+
+#define GFX_SCHLUESSEL GFX_SCHLUESSEL1
+
+#define GFX_SPIELER1 116
+#define GFX_SPIELER2 117
+#define GFX_SPIELER3 118
+#define GFX_SPIELER4 119
+
+/* nicht in "RocksScreen" sondern woanders :) */
+#define GFX_CHAR_START 256
+#define GFX_CHAR_ASCII0 (GFX_CHAR_START-32)
+#define GFX_CHAR_AUSRUF (GFX_CHAR_ASCII0+33)
+#define GFX_CHAR_ZOLL (GFX_CHAR_ASCII0+34)
+#define GFX_CHAR_DOLLAR (GFX_CHAR_ASCII0+36)
+#define GFX_CHAR_PROZ (GFX_CHAR_ASCII0+37)
+#define GFX_CHAR_APOSTR (GFX_CHAR_ASCII0+39)
+#define GFX_CHAR_KLAMM1 (GFX_CHAR_ASCII0+40)
+#define GFX_CHAR_KLAMM2 (GFX_CHAR_ASCII0+41)
+#define GFX_CHAR_PLUS (GFX_CHAR_ASCII0+43)
+#define GFX_CHAR_KOMMA (GFX_CHAR_ASCII0+44)
+#define GFX_CHAR_MINUS (GFX_CHAR_ASCII0+45)
+#define GFX_CHAR_PUNKT (GFX_CHAR_ASCII0+46)
+#define GFX_CHAR_SLASH (GFX_CHAR_ASCII0+47)
+#define GFX_CHAR_0 (GFX_CHAR_ASCII0+48)
+#define GFX_CHAR_9 (GFX_CHAR_ASCII0+57)
+#define GFX_CHAR_DOPPEL (GFX_CHAR_ASCII0+58)
+#define GFX_CHAR_SEMIKL (GFX_CHAR_ASCII0+59)
+#define GFX_CHAR_LT (GFX_CHAR_ASCII0+60)
+#define GFX_CHAR_GLEICH (GFX_CHAR_ASCII0+61)
+#define GFX_CHAR_GT (GFX_CHAR_ASCII0+62)
+#define GFX_CHAR_FRAGE (GFX_CHAR_ASCII0+63)
+#define GFX_CHAR_AT (GFX_CHAR_ASCII0+64)
+#define GFX_CHAR_A (GFX_CHAR_ASCII0+65)
+#define GFX_CHAR_Z (GFX_CHAR_ASCII0+90)
+#define GFX_CHAR_AE (GFX_CHAR_ASCII0+91)
+#define GFX_CHAR_OE (GFX_CHAR_ASCII0+92)
+#define GFX_CHAR_UE (GFX_CHAR_ASCII0+93)
+#define GFX_CHAR_COPY (GFX_CHAR_ASCII0+94)
+#define GFX_CHAR_END (GFX_CHAR_START+79)
+
+/* score for elements */
+#define SC_EDELSTEIN 0
+#define SC_DIAMANT 1
+#define SC_KAEFER 2
+#define SC_FLIEGER 3
+#define SC_MAMPFER 4
+#define SC_ZOMBIE 5
+#define SC_PACMAN 6
+#define SC_KOKOSNUSS 7
+#define SC_DYNAMIT 8
+#define SC_SCHLUESSEL 9
+#define SC_ZEITBONUS 10
+
+/* the names of the sounds */
+#define SND_ALCHEMY 0
+#define SND_AMOEBE 1
+#define SND_ANTIGRAV 2
+#define SND_AUTSCH 3
+#define SND_BLURB 4
+#define SND_BONG 5
+#define SND_BUING 6
+#define SND_CHASE 7
+#define SND_CZARDASZ 8
+#define SND_DENG 9
+#define SND_FUEL 10
+#define SND_GONG 11
+#define SND_HALLOFFAME 12
+#define SND_HOLZ 13
+#define SND_HUI 14
+#define SND_KABUMM 15
+#define SND_KINK 16
+#define SND_KLAPPER 17
+#define SND_KLING 18
+#define SND_KLOPF 19
+#define SND_KLUMPF 20
+#define SND_KNACK 21
+#define SND_KNURK 22
+#define SND_KRACH 23
+#define SND_LACHEN 24
+#define SND_LASER 25
+#define SND_MIEP 26
+#define SND_NETWORK 27
+#define SND_NJAM 28
+#define SND_OEFFNEN 29
+#define SND_PLING 30
+#define SND_PONG 31
+#define SND_PUSCH 32
+#define SND_QUIEK 33
+#define SND_QUIRK 34
+#define SND_RHYTHMLOOP 35
+#define SND_ROAAAR 36
+#define SND_ROEHR 37
+#define SND_RUMMS 38
+#define SND_SCHLOPP 39
+#define SND_SCHLURF 40
+#define SND_SCHRFF 41
+#define SND_SCHWIRR 42
+#define SND_SIRR 43
+#define SND_SLURP 44
+#define SND_SPROING 45
+#define SND_TWILIGHT 46
+#define SND_TYGER 47
+#define SND_VOYAGER 48
+#define SND_WARNTON 49
+#define SND_WHOOSH 50
+#define SND_ZISCH 51
+
+#define NUM_SOUNDS 52
+
+#define IS_LOOP_SOUND(s) ((s)==SND_KLAPPER || (s)==SND_ROEHR || \
+ (s)==SND_NJAM || (s)==SND_MIEP)
+#define IS_MUSIC_SOUND(s) ((s)==SND_ALCHEMY || (s)==SND_CHASE || \
+ (s)==SND_NETWORK || (s)==SND_CZARDASZ || \
+ (s)==SND_TYGER || (s)==SND_VOYAGER || \
+ (s)==SND_TWILIGHT)
+extern char *sound_name[NUM_SOUNDS];
+
+/* this structure contains the sound data for the sound server */
+extern struct SoundInfo Sound[NUM_SOUNDS];
+
+/* directions for moving */
+#define MV_NO_MOVING 0
+#define MV_LEFT 1
+#define MV_RIGHT 2
+#define MV_UP 4
+#define MV_DOWN 8
+
+/* font types */
+#define FS_SMALL 0
+#define FS_BIG 1
+/* font colors */
+#define FC_RED 0
+#define FC_BLUE 1
+#define FC_GREEN 2
+#define FC_YELLOW 3
+#define FC_SPECIAL1 4
+#define FC_SPECIAL2 5
+
+/* values for game_status */
+#define MAINMENU 0
+#define PLAYING 1
+#define LEVELED 2
+#define HELPSCREEN 3
+#define CHOOSELEVEL 4
+#define TYPENAME 5
+#define HALLOFFAME 6
+#define SETUP 7
+#define EXITGAME 8
+
+/* return values for GameActions */
+#define ACT_GO_ON 0
+#define ACT_GAME_OVER 1
+#define ACT_NEW_GAME 2
+
+/* values for the joystick */
+#define JOYSTICK_OFF 0
+#define JOYSTICK_AVAILABLE 1
+#define DEV_JOYSTICK_0 "/dev/js0"
+#define DEV_JOYSTICK_1 "/dev/js1"
+
+/* get these values from the program 'js' from the joystick package, */
+/* set JOYSTICK_PERCENT to a threshold appropriate for your joystick */
+#define JOYSTICK_XLEFT 30
+#define JOYSTICK_XRIGHT 1250
+#define JOYSTICK_XMIDDLE 530
+#define JOYSTICK_YUPPER 40
+#define JOYSTICK_YLOWER 1440
+#define JOYSTICK_YMIDDLE 680
+#define JOYSTICK_PERCENT 25
+#define JOY_LEFT MV_LEFT
+#define JOY_RIGHT MV_RIGHT
+#define JOY_UP MV_UP
+#define JOY_DOWN MV_DOWN
+#define JOY_BUTTON_1 16
+#define JOY_BUTTON_2 32
+#define JOY_BUTTON (JOY_BUTTON_1 | JOY_BUTTON_2)
+#define JOY_BUTTON_NOT_PRESSED 0
+#define JOY_BUTTON_PRESSED 1
+#define JOY_BUTTON_NEW_PRESSED 2
+#define JOY_BUTTON_NEW_RELEASED 3
+
+#ifdef NO_JOYSTICK
+#define JOYSTICK_STATUS JOYSTICK_OFF
+#else
+#define JOYSTICK_STATUS JOYSTICK_AVAILABLE
+#endif
+
+#ifndef GAME_DIR
+#define GAME_DIR "."
+#endif
+
+#ifndef GFX_PATH
+#define GFX_PATH GAME_DIR "/graphics"
+#endif
+#ifndef SND_PATH
+#define SND_PATH GAME_DIR "/sounds"
+#endif
+#ifndef LEVEL_PATH
+#define LEVEL_PATH GAME_DIR "/levels"
+#endif
+#ifndef SCORE_PATH
+#define SCORE_PATH LEVEL_PATH
+#endif
+#ifndef NAMES_PATH
+#define NAMES_PATH LEVEL_PATH
+#endif
+#ifndef CONFIG_PATH
+#define CONFIG_PATH GAME_DIR
+#endif
+#ifndef JOYDAT_PATH
+#define JOYDAT_PATH GAME_DIR
+#endif
+
+#define SCORE_FILENAME "ROCKS.score"
+#define NAMES_FILENAME "ROCKS.names"
+#define LEVDIR_FILENAME "ROCKS.levelinfo"
+#define JOYDAT_FILENAME "ROCKS.joystick"
+
+#define JOYDAT_FILE JOYDAT_PATH "/" JOYDAT_FILENAME
+
+#define LEVEL_PERMS (S_IRUSR|S_IWUSR | S_IRGRP|S_IWGRP | S_IROTH|S_IWOTH)
+#define SCORE_PERMS LEVEL_PERMS
+#define NAMES_PERMS LEVEL_PERMS
+#define LEVDIR_PERMS LEVEL_PERMS
+#define LEVREC_PERMS LEVEL_PERMS
+#define JOYDAT_PERMS LEVEL_PERMS
+
+#define LEVEL_COOKIE "ROCKSNDIAMONDS_LEVEL_FILE_VERSION_1.0"
+#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.0"
+#define NAMES_COOKIE "ROCKSNDIAMONDS_NAMES_FILE_VERSION_1.0"
+#define LEVELDIR_COOKIE "ROCKSNDIAMONDS_LEVELDIR_FILE_VERSION_1.0"
+#define LEVELREC_COOKIE "ROCKSNDIAMONDS_LEVELREC_FILE_VERSION_1.0"
+#define JOYSTICK_COOKIE "ROCKSNDIAMONDS_JOYSTICK_FILE_VERSION_1.0"
+#define LEVEL_COOKIE_LEN (strlen(LEVEL_COOKIE)+1)
+#define SCORE_COOKIE_LEN (strlen(SCORE_COOKIE)+1)
+#define NAMES_COOKIE_LEN (strlen(NAMES_COOKIE)+1)
+#define LEVELDIR_COOKIE_LEN (strlen(LEVELDIR_COOKIE)+1)
+#define LEVELREC_COOKIE_LEN (strlen(LEVELREC_COOKIE)+1)
+#define JOYSTICK_COOKIE_LEN (strlen(JOYSTICK_COOKIE)+1)
+
+/* Leerer Login- und Alias-Name */
+#define EMPTY_LOGIN "NO_LOGIN"
+#define EMPTY_ALIAS "NO_NAME"
+
+/* values for button_status */
+#define MB_NOT_PRESSED FALSE
+#define MB_RELEASED FALSE
+#define MB_PRESSED TRUE
+#define MB_MENU_CHOICE FALSE
+#define MB_MENU_MARK TRUE
+#define MB_LEFT 1
+#define MB_MIDDLE 2
+#define MB_RIGHT 3
+
+/* values for key_status */
+#define KEY_NOT_PRESSED FALSE
+#define KEY_RELEASED FALSE
+#define KEY_PRESSED TRUE
+
+/* values for focus_status */
+#define FOCUS_OUT FALSE
+#define FOCUS_IN TRUE
+
+/* values for redraw_mask */
+#define REDRAW_ALL (1L<<0)
+#define REDRAW_FIELD (1L<<1)
+#define REDRAW_TILES (1L<<2)
+#define REDRAW_DOOR_1 (1L<<3)
+#define REDRAW_VIDEO_1 (1L<<4)
+#define REDRAW_VIDEO_2 (1L<<5)
+#define REDRAW_VIDEO_3 (1L<<6)
+#define REDRAW_MICROLEV (1L<<7)
+#define REDRAW_DOOR_2 (REDRAW_VIDEO_1 | REDRAW_VIDEO_2 | REDRAW_VIDEO_3)
+#define REDRAW_DOORS (REDRAW_DOOR_1 | REDRAW_DOOR_2)
+#define REDRAW_MAIN (REDRAW_FIELD | REDRAW_TILES | REDRAW_MICROLEV)
+#define REDRAWTILES_TH SCR_FIELDX*SCR_FIELDY/2
+
+/* positions in the game control window */
+#define XX_LEVEL 37
+#define YY_LEVEL 20
+#define XX_EMERALDS 29
+#define YY_EMERALDS 54
+#define XX_DYNAMITE 29
+#define YY_DYNAMITE 89
+#define XX_KEYS 18
+#define YY_KEYS 123
+#define XX_SCORE 15
+#define YY_SCORE 159
+#define XX_TIME 29
+#define YY_TIME 194
+
+#define DX_LEVEL (DX+XX_LEVEL)
+#define DY_LEVEL (DY+YY_LEVEL)
+#define DX_EMERALDS (DX+XX_EMERALDS)
+#define DY_EMERALDS (DY+YY_EMERALDS)
+#define DX_DYNAMITE (DX+XX_DYNAMITE)
+#define DY_DYNAMITE (DY+YY_DYNAMITE)
+#define DX_KEYS (DX+XX_KEYS)
+#define DY_KEYS (DY+YY_KEYS)
+#define DX_SCORE (DX+XX_SCORE)
+#define DY_SCORE (DY+YY_SCORE)
+#define DX_TIME (DX+XX_TIME)
+#define DY_TIME (DY+YY_TIME)
+
+/* Felder in PIX_DOOR */
+/* Bedeutung in PIX_DB_DOOR: (3 PAGEs)
+ PAGEX1: 1. Zwischenspeicher für DOOR_1
+ PAGEX2: 2. Zwischenspeicher für DOOR_1
+ PAGEX3: Pufferspeicher für Animationen
+*/
+
+#define DOOR_GFX_PAGESIZE DXSIZE
+#define DOOR_GFX_PAGEX1 (0*DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX2 (1*DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX3 (2*DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX4 (3*DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX5 (4*DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEX6 (5*DOOR_GFX_PAGESIZE)
+#define DOOR_GFX_PAGEY1 0
+#define DOOR_GFX_PAGEY2 DYSIZE
+
+/* some positions in the video tape control window */
+#define VIDEO_DISPLAY1_XPOS 5
+#define VIDEO_DISPLAY1_YPOS 5
+#define VIDEO_DISPLAY2_XPOS 5
+#define VIDEO_DISPLAY2_YPOS 41
+#define VIDEO_DISPLAY_XSIZE 90
+#define VIDEO_DISPLAY_YSIZE 31
+#define VIDEO_BUTTON_XSIZE 18
+#define VIDEO_BUTTON_YSIZE 18
+#define VIDEO_CONTROL_XPOS 5
+#define VIDEO_CONTROL_YPOS 77
+#define VIDEO_CONTROL_XSIZE (VIDEO_DISPLAY_XSIZE)
+#define VIDEO_CONTROL_YSIZE (VIDEO_BUTTON_YSIZE)
+#define VIDEO_BUTTON_EJECT_XPOS (VIDEO_CONTROL_XPOS + 0 * VIDEO_BUTTON_XSIZE)
+#define VIDEO_BUTTON_STOP_XPOS (VIDEO_CONTROL_XPOS + 1 * VIDEO_BUTTON_XSIZE)
+#define VIDEO_BUTTON_PAUSE_XPOS (VIDEO_CONTROL_XPOS + 2 * VIDEO_BUTTON_XSIZE)
+#define VIDEO_BUTTON_REC_XPOS (VIDEO_CONTROL_XPOS + 3 * VIDEO_BUTTON_XSIZE)
+#define VIDEO_BUTTON_PLAY_XPOS (VIDEO_CONTROL_XPOS + 4 * VIDEO_BUTTON_XSIZE)
+#define VIDEO_BUTTON_ANY_YPOS (VIDEO_CONTROL_YPOS)
+#define VIDEO_DATE_LABEL_XPOS (VIDEO_DISPLAY1_XPOS)
+#define VIDEO_DATE_LABEL_YPOS (VIDEO_DISPLAY1_YPOS)
+#define VIDEO_DATE_LABEL_XSIZE (VIDEO_DISPLAY_XSIZE)
+#define VIDEO_DATE_LABEL_YSIZE (VIDEO_DISPLAY_YSIZE)
+#define VIDEO_DATE_XPOS (VIDEO_DISPLAY1_XPOS+1)
+#define VIDEO_DATE_YPOS (VIDEO_DISPLAY1_YPOS+14)
+#define VIDEO_DATE_XSIZE (VIDEO_DISPLAY_XSIZE)
+#define VIDEO_DATE_YSIZE 16
+#define VIDEO_REC_LABEL_XPOS (VIDEO_DISPLAY2_XPOS)
+#define VIDEO_REC_LABEL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_REC_LABEL_XSIZE 20
+#define VIDEO_REC_LABEL_YSIZE 12
+#define VIDEO_REC_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS+20)
+#define VIDEO_REC_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_REC_SYMBOL_XSIZE 16
+#define VIDEO_REC_SYMBOL_YSIZE 16
+#define VIDEO_PLAY_LABEL_XPOS (VIDEO_DISPLAY2_XPOS+65)
+#define VIDEO_PLAY_LABEL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_PLAY_LABEL_XSIZE 22
+#define VIDEO_PLAY_LABEL_YSIZE 12
+#define VIDEO_PLAY_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS+50)
+#define VIDEO_PLAY_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_PLAY_SYMBOL_XSIZE 13
+#define VIDEO_PLAY_SYMBOL_YSIZE 13
+#define VIDEO_PAUSE_LABEL_XPOS (VIDEO_DISPLAY2_XPOS)
+#define VIDEO_PAUSE_LABEL_YPOS (VIDEO_DISPLAY2_YPOS+20)
+#define VIDEO_PAUSE_LABEL_XSIZE 35
+#define VIDEO_PAUSE_LABEL_YSIZE 8
+#define VIDEO_PAUSE_SYMBOL_XPOS (VIDEO_DISPLAY2_XPOS+35)
+#define VIDEO_PAUSE_SYMBOL_YPOS (VIDEO_DISPLAY2_YPOS)
+#define VIDEO_PAUSE_SYMBOL_XSIZE 13
+#define VIDEO_PAUSE_SYMBOL_YSIZE 13
+#define VIDEO_TIME_XPOS (VIDEO_DISPLAY2_XPOS+38)
+#define VIDEO_TIME_YPOS (VIDEO_DISPLAY2_YPOS+14)
+#define VIDEO_TIME_XSIZE 50
+#define VIDEO_TIME_YSIZE 16
+
+#define ON_VIDEO_BUTTON(x,y) ((x)>=(VX+VIDEO_CONTROL_XPOS) && \
+ (x)< (VX+VIDEO_CONTROL_XPOS + \
+ VIDEO_CONTROL_XSIZE) && \
+ (y)>=(VY+VIDEO_CONTROL_YPOS) && \
+ (y)< (VY+VIDEO_CONTROL_YPOS + \
+ VIDEO_CONTROL_YSIZE))
+#define VIDEO_BUTTON(x) (((x)-(VX+VIDEO_CONTROL_XPOS))/VIDEO_BUTTON_XSIZE)
+
+/* values for video tape control */
+#define VIDEO_STATE_PLAY_OFF (1L<<0)
+#define VIDEO_STATE_PLAY_ON (1L<<1)
+#define VIDEO_STATE_PLAY (VIDEO_STATE_PLAY_OFF | VIDEO_STATE_PLAY_ON)
+#define VIDEO_STATE_REC_OFF (1L<<2)
+#define VIDEO_STATE_REC_ON (1L<<3)
+#define VIDEO_STATE_REC (VIDEO_STATE_REC_OFF | VIDEO_STATE_REC_ON)
+#define VIDEO_STATE_PAUSE_OFF (1L<<4)
+#define VIDEO_STATE_PAUSE_ON (1L<<5)
+#define VIDEO_STATE_PAUSE (VIDEO_STATE_PAUSE_OFF | VIDEO_STATE_PAUSE_ON)
+#define VIDEO_STATE_DATE_OFF (1L<<6)
+#define VIDEO_STATE_DATE_ON (1L<<7)
+#define VIDEO_STATE_DATE (VIDEO_STATE_DATE_OFF | VIDEO_STATE_DATE_ON)
+#define VIDEO_STATE_TIME_OFF (1L<<8)
+#define VIDEO_STATE_TIME_ON (1L<<9)
+#define VIDEO_STATE_TIME (VIDEO_STATE_TIME_OFF | VIDEO_STATE_TIME_ON)
+#define VIDEO_PRESS_PLAY_ON (1L<<10)
+#define VIDEO_PRESS_PLAY_OFF (1L<<11)
+#define VIDEO_PRESS_PLAY (VIDEO_PRESS_PLAY_OFF | VIDEO_PRESS_PLAY_ON)
+#define VIDEO_PRESS_REC_ON (1L<<12)
+#define VIDEO_PRESS_REC_OFF (1L<<13)
+#define VIDEO_PRESS_REC (VIDEO_PRESS_REC_OFF | VIDEO_PRESS_REC_ON)
+#define VIDEO_PRESS_PAUSE_ON (1L<<14)
+#define VIDEO_PRESS_PAUSE_OFF (1L<<15)
+#define VIDEO_PRESS_PAUSE (VIDEO_PRESS_PAUSE_OFF | VIDEO_PRESS_PAUSE_ON)
+#define VIDEO_PRESS_STOP_ON (1L<<16)
+#define VIDEO_PRESS_STOP_OFF (1L<<17)
+#define VIDEO_PRESS_STOP (VIDEO_PRESS_STOP_OFF | VIDEO_PRESS_STOP_ON)
+#define VIDEO_PRESS_EJECT_ON (1L<<18)
+#define VIDEO_PRESS_EJECT_OFF (1L<<19)
+#define VIDEO_PRESS_EJECT (VIDEO_PRESS_EJECT_OFF | VIDEO_PRESS_EJECT_ON)
+
+#define BUTTON_VIDEO_EJECT 1
+#define BUTTON_VIDEO_STOP 2
+#define BUTTON_VIDEO_PAUSE 3
+#define BUTTON_VIDEO_REC 4
+#define BUTTON_VIDEO_PLAY 5
+
+#define VIDEO_STATE_OFF (VIDEO_STATE_PLAY_OFF | \
+ VIDEO_STATE_REC_OFF | \
+ VIDEO_STATE_PAUSE_OFF | \
+ VIDEO_STATE_DATE_OFF | \
+ VIDEO_STATE_TIME_OFF)
+#define VIDEO_PRESS_OFF (VIDEO_PRESS_PLAY_OFF | \
+ VIDEO_PRESS_REC_OFF | \
+ VIDEO_PRESS_PAUSE_OFF | \
+ VIDEO_PRESS_STOP_OFF | \
+ VIDEO_PRESS_EJECT_OFF)
+#define VIDEO_ALL_OFF (VIDEO_STATE_OFF | VIDEO_PRESS_OFF)
+
+#define VIDEO_STATE_ON (VIDEO_STATE_PLAY_ON | \
+ VIDEO_STATE_REC_ON | \
+ VIDEO_STATE_PAUSE_ON | \
+ VIDEO_STATE_DATE_ON | \
+ VIDEO_STATE_TIME_ON)
+#define VIDEO_PRESS_ON (VIDEO_PRESS_PLAY_ON | \
+ VIDEO_PRESS_REC_ON | \
+ VIDEO_PRESS_PAUSE_ON | \
+ VIDEO_PRESS_STOP_ON | \
+ VIDEO_PRESS_EJECT_ON)
+#define VIDEO_ALL_ON (VIDEO_STATE_ON | VIDEO_PRESS_ON)
+
+#define VIDEO_STATE (VIDEO_STATE_ON | VIDEO_STATE_OFF)
+#define VIDEO_PRESS (VIDEO_PRESS_ON | VIDEO_PRESS_OFF)
+#define VIDEO_ALL (VIDEO_ALL_ON | VIDEO_ALL_OFF)
+
+/* some positions in the sound control window */
+#define SOUND_BUTTON_XSIZE 30
+#define SOUND_BUTTON_YSIZE 30
+#define SOUND_CONTROL_XPOS 5
+#define SOUND_CONTROL_YPOS 245
+#define SOUND_CONTROL_XSIZE 90
+#define SOUND_CONTROL_YSIZE (SOUND_BUTTON_YSIZE)
+#define SOUND_BUTTON_MUSIC_XPOS (SOUND_CONTROL_XPOS + 0 * SOUND_BUTTON_XSIZE)
+#define SOUND_BUTTON_LOOPS_XPOS (SOUND_CONTROL_XPOS + 1 * SOUND_BUTTON_XSIZE)
+#define SOUND_BUTTON_SOUND_XPOS (SOUND_CONTROL_XPOS + 2 * SOUND_BUTTON_XSIZE)
+#define SOUND_BUTTON_ANY_YPOS (SOUND_CONTROL_YPOS)
+
+#define ON_SOUND_BUTTON(x,y) ((x)>=(DX+SOUND_CONTROL_XPOS) && \
+ (x)< (DX+SOUND_CONTROL_XPOS + \
+ SOUND_CONTROL_XSIZE) && \
+ (y)>=(DY+SOUND_CONTROL_YPOS) && \
+ (y)< (DY+SOUND_CONTROL_YPOS + \
+ SOUND_CONTROL_YSIZE))
+#define SOUND_BUTTON(x) (((x)-(DX+SOUND_CONTROL_XPOS))/SOUND_BUTTON_XSIZE)
+
+/* values for sound control */
+#define BUTTON_SOUND_MUSIC (1L<<0)
+#define BUTTON_SOUND_LOOPS (1L<<1)
+#define BUTTON_SOUND_SOUND (1L<<2)
+#define BUTTON_RELEASED 0
+#define BUTTON_PRESSED (1L<<3)
+#define BUTTON_OFF 0
+#define BUTTON_ON (1L<<4)
+#define BUTTON_SOUND_MUSIC_OFF (BUTTON_SOUND_MUSIC | BUTTON_OFF)
+#define BUTTON_SOUND_LOOPS_OFF (BUTTON_SOUND_LOOPS | BUTTON_OFF)
+#define BUTTON_SOUND_SOUND_OFF (BUTTON_SOUND_SOUND | BUTTON_OFF)
+#define BUTTON_SOUND_MUSIC_ON (BUTTON_SOUND_MUSIC | BUTTON_ON)
+#define BUTTON_SOUND_LOOPS_ON (BUTTON_SOUND_LOOPS | BUTTON_ON)
+#define BUTTON_SOUND_SOUND_ON (BUTTON_SOUND_SOUND | BUTTON_ON)
+
+/* some positions in the game control window */
+#define GAME_BUTTON_XSIZE 30
+#define GAME_BUTTON_YSIZE 30
+#define GAME_CONTROL_XPOS 5
+#define GAME_CONTROL_YPOS 215
+#define GAME_CONTROL_XSIZE 90
+#define GAME_CONTROL_YSIZE (GAME_BUTTON_YSIZE)
+#define GAME_BUTTON_STOP_XPOS (GAME_CONTROL_XPOS + 0 * GAME_BUTTON_XSIZE)
+#define GAME_BUTTON_PAUSE_XPOS (GAME_CONTROL_XPOS + 1 * GAME_BUTTON_XSIZE)
+#define GAME_BUTTON_PLAY_XPOS (GAME_CONTROL_XPOS + 2 * GAME_BUTTON_XSIZE)
+#define GAME_BUTTON_ANY_YPOS (GAME_CONTROL_YPOS)
+
+#define ON_GAME_BUTTON(x,y) ((x)>=(DX+GAME_CONTROL_XPOS) && \
+ (x)< (DX+GAME_CONTROL_XPOS + \
+ GAME_CONTROL_XSIZE) && \
+ (y)>=(DY+GAME_CONTROL_YPOS) && \
+ (y)< (DY+GAME_CONTROL_YPOS + \
+ GAME_CONTROL_YSIZE))
+#define GAME_BUTTON(x) (((x)-(DX+GAME_CONTROL_XPOS))/GAME_BUTTON_XSIZE)
+
+/* values for game control */
+#define BUTTON_GAME_STOP (1L<<0)
+#define BUTTON_GAME_PAUSE (1L<<1)
+#define BUTTON_GAME_PLAY (1L<<2)
+
+/* some positions in the asking window */
+#define OK_BUTTON_XPOS 2
+#define OK_BUTTON_YPOS 250
+#define OK_BUTTON_GFX_YPOS 0
+#define OK_BUTTON_XSIZE 46
+#define OK_BUTTON_YSIZE 28
+#define NO_BUTTON_XPOS 52
+#define NO_BUTTON_YPOS OK_BUTTON_YPOS
+#define NO_BUTTON_XSIZE OK_BUTTON_XSIZE
+#define NO_BUTTON_YSIZE OK_BUTTON_YSIZE
+#define CONFIRM_BUTTON_XPOS 2
+#define CONFIRM_BUTTON_GFX_YPOS 30
+#define CONFIRM_BUTTON_YPOS OK_BUTTON_YPOS
+#define CONFIRM_BUTTON_XSIZE 96
+#define CONFIRM_BUTTON_YSIZE OK_BUTTON_YSIZE
+
+#define ON_CHOOSE_BUTTON(x,y) (((x)>=(DX+OK_BUTTON_XPOS) && \
+ (x)< (DX+OK_BUTTON_XPOS + \
+ OK_BUTTON_XSIZE) && \
+ (y)>=(DY+OK_BUTTON_YPOS) && \
+ (y)< (DY+OK_BUTTON_YPOS + \
+ OK_BUTTON_YSIZE)) || \
+ ((x)>=(DX+NO_BUTTON_XPOS) && \
+ (x)< (DX+NO_BUTTON_XPOS + \
+ NO_BUTTON_XSIZE) && \
+ (y)>=(DY+NO_BUTTON_YPOS) && \
+ (y)< (DY+NO_BUTTON_YPOS + \
+ NO_BUTTON_YSIZE)))
+#define ON_CONFIRM_BUTTON(x,y) (((x)>=(DX+CONFIRM_BUTTON_XPOS) && \
+ (x)< (DX+CONFIRM_BUTTON_XPOS + \
+ CONFIRM_BUTTON_XSIZE) && \
+ (y)>=(DY+CONFIRM_BUTTON_YPOS) && \
+ (y)< (DY+CONFIRM_BUTTON_YPOS + \
+ CONFIRM_BUTTON_YSIZE)))
+#define CHOOSE_BUTTON(x) (((x)-(DX+OK_BUTTON_XPOS))/OK_BUTTON_XSIZE)
+
+/* values for asking control */
+#define BUTTON_OK (1L<<0)
+#define BUTTON_NO (1L<<1)
+#define BUTTON_CONFIRM (1L<<2)
+
+#endif
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* misc.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#include "misc.h"
+#include "tools.h"
+#include "sound.h"
+#include <pwd.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include <sys/types.h>
+
+void microsleep(unsigned long usec)
+{
+ struct timeval delay;
+
+ delay.tv_sec = usec / 1000000;
+ delay.tv_usec = usec % 1000000;
+
+ if (select(0,NULL,NULL,NULL,&delay)!=0)
+ fprintf(stderr,"%s: in function microsleep: select failed!\n",
+ progname);
+}
+
+unsigned long be2long(unsigned long *be) /* big-endian -> longword */
+{
+ unsigned char *ptr = (unsigned char *)be;
+
+ return(ptr[0]<<24 | ptr[1]<<16 | ptr[2]<<8 | ptr[3]);
+}
+
+char *int2str(int ct, int nr)
+{
+ static char str[20];
+
+ sprintf(str,"%09d",ct);
+ return(&str[strlen(str)-nr]);
+}
+
+unsigned int RND(unsigned int max)
+{
+ return(rand() % max);
+}
+
+unsigned int InitRND(long seed)
+{
+ struct timeval current_time;
+
+ if (seed==NEW_RANDOMIZE)
+ {
+ gettimeofday(¤t_time,NULL);
+ srand((unsigned int) current_time.tv_usec);
+ return((unsigned int) current_time.tv_usec);
+ }
+ else
+ {
+ srand((unsigned int) seed);
+ return((unsigned int) seed);
+ }
+}
+
+char *GetLoginName()
+{
+ struct passwd *pwd;
+
+ if (!(pwd=getpwuid(getuid())))
+ return("ANONYMOUS");
+ else
+ return(pwd->pw_name);
+}
+
+static struct AnimInfo toon[NUM_TOONS] =
+{
+ DWARF_XSIZE, DWARF_YSIZE,
+ DWARF_X, DWARF_Y,
+ DWARF_FRAMES,
+ DWARF_FPS,
+ DWARF_STEPSIZE,
+ FALSE,
+ ANIMDIR_RIGHT,
+ ANIMPOS_DOWN,
+
+ DWARF_XSIZE, DWARF_YSIZE,
+ DWARF_X, DWARF2_Y,
+ DWARF_FRAMES,
+ DWARF_FPS,
+ DWARF_STEPSIZE,
+ FALSE,
+ ANIMDIR_LEFT,
+ ANIMPOS_DOWN,
+
+ JUMPER_XSIZE, JUMPER_YSIZE,
+ JUMPER_X, JUMPER_Y,
+ JUMPER_FRAMES,
+ JUMPER_FPS,
+ JUMPER_STEPSIZE,
+ FALSE,
+ ANIMDIR_LEFT,
+ ANIMPOS_DOWN,
+
+ CLOWN_XSIZE, CLOWN_YSIZE,
+ CLOWN_X, CLOWN_Y,
+ CLOWN_FRAMES,
+ CLOWN_FPS,
+ CLOWN_STEPSIZE,
+ FALSE,
+ ANIMDIR_UP,
+ ANIMPOS_ANY,
+
+ BIRD_XSIZE, BIRD_YSIZE,
+ BIRD1_X, BIRD1_Y,
+ BIRD_FRAMES,
+ BIRD_FPS,
+ BIRD_STEPSIZE,
+ TRUE,
+ ANIMDIR_RIGHT,
+ ANIMPOS_UPPER,
+
+ BIRD_XSIZE, BIRD_YSIZE,
+ BIRD2_X, BIRD2_Y,
+ BIRD_FRAMES,
+ BIRD_FPS,
+ BIRD_STEPSIZE,
+ TRUE,
+ ANIMDIR_LEFT,
+ ANIMPOS_UPPER
+};
+
+void InitAnimation()
+{
+ HandleAnimation(ANIM_START);
+}
+
+void StopAnimation()
+{
+ HandleAnimation(ANIM_STOP);
+}
+
+void DoAnimation()
+{
+ HandleAnimation(ANIM_CONTINUE);
+}
+
+void HandleAnimation(int mode)
+{
+ static long animstart_delay = -1;
+ static long animstart_delay_value = 0;
+ static BOOL anim_restart = TRUE;
+ static BOOL reset_delay = TRUE;
+ static int toon_nr = 0;
+
+ if (!toons_on || game_status==PLAYING)
+ return;
+
+ switch(mode)
+ {
+ case ANIM_START:
+ anim_restart = TRUE;
+ reset_delay = TRUE;
+ return;
+ break;
+ case ANIM_CONTINUE:
+ break;
+ case ANIM_STOP:
+ redraw_mask |= REDRAW_FIELD;
+ BackToFront();
+ return;
+ break;
+ default:
+ break;
+ }
+
+ if (reset_delay)
+ {
+ animstart_delay = Counter();
+ animstart_delay_value = RND(500);
+ reset_delay = FALSE;
+ }
+
+ if (anim_restart)
+ {
+ if (!DelayReached(&animstart_delay,animstart_delay_value))
+ return;
+
+ toon_nr = RND(NUM_TOONS);
+ }
+
+ anim_restart = reset_delay = AnimateToon(toon_nr,anim_restart);
+}
+
+BOOL AnimateToon(int toon_nr, BOOL restart)
+{
+ static pos_x = 0, pos_y = 0;
+ static delta_x = 0, delta_y = 0;
+ static int frame = 0, frame_step = 1;
+ static BOOL horiz_move, vert_move;
+ static long anim_delay = 0;
+ static int anim_delay_value = 0;
+ struct AnimInfo *anim = &toon[toon_nr];
+ static int width,height;
+ static int pad_x,pad_y;
+ static int cut_x,cut_y;
+ static int src_x, src_y;
+ static int dest_x, dest_y;
+
+ if (restart)
+ {
+ horiz_move = (anim->direction & (ANIMDIR_LEFT | ANIMDIR_RIGHT));
+ vert_move = (anim->direction & (ANIMDIR_UP | ANIMDIR_DOWN));
+ anim_delay_value = 100/anim->frames_per_second;
+ frame = 0;
+
+ if (horiz_move)
+ {
+ if (anim->position==ANIMPOS_UP)
+ pos_y = 0;
+ else if (anim->position==ANIMPOS_DOWN)
+ pos_y = FULL_SYSIZE-anim->height;
+ else if (anim->position==ANIMPOS_UPPER)
+ pos_y = RND((FULL_SYSIZE-anim->height)/2);
+ else
+ pos_y = RND(FULL_SYSIZE-anim->height);
+
+ if (anim->direction==ANIMDIR_RIGHT)
+ {
+ delta_x = anim->stepsize;
+ pos_x = -anim->width+delta_x;
+ }
+ else
+ {
+ delta_x = -anim->stepsize;
+ pos_x = FULL_SXSIZE+delta_x;
+ }
+ delta_y = 0;
+ }
+ else
+ {
+ if (anim->position==ANIMPOS_LEFT)
+ pos_x = 0;
+ else if (anim->position==ANIMPOS_RIGHT)
+ pos_x = FULL_SXSIZE-anim->width;
+ else
+ pos_x = RND(FULL_SXSIZE-anim->width);
+
+ if (anim->direction==ANIMDIR_DOWN)
+ {
+ delta_y = anim->stepsize;
+ pos_y = -anim->height+delta_y;
+ }
+ else
+ {
+ delta_y = -anim->stepsize;
+ pos_y = FULL_SYSIZE+delta_y;
+ }
+ delta_x = 0;
+ }
+ }
+
+ if (pos_x <= -anim->width - anim->stepsize ||
+ pos_x >= FULL_SXSIZE + anim->stepsize ||
+ pos_y <= -anim->height - anim->stepsize ||
+ pos_y >= FULL_SYSIZE + anim->stepsize)
+ return(TRUE);
+
+ if (!DelayReached(&anim_delay,anim_delay_value))
+ {
+ if (game_status==HELPSCREEN && !restart)
+ DrawAnim(src_x+cut_x,src_y+cut_y, width,height,
+ REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y);
+
+ return(FALSE);
+ }
+
+ if (pos_x<-anim->width)
+ pos_x = -anim->width;
+ else if (pos_x>FULL_SXSIZE)
+ pos_x = FULL_SXSIZE;
+ if (pos_y<-anim->height)
+ pos_y = -anim->height;
+ else if (pos_y>FULL_SYSIZE)
+ pos_y = FULL_SYSIZE;
+
+ pad_x = (horiz_move ? anim->stepsize : 0);
+ pad_y = (vert_move ? anim->stepsize : 0);
+ src_x = anim->src_x + frame * anim->width;
+ src_y = anim->src_y;
+ dest_x = pos_x;
+ dest_y = pos_y;
+ cut_x = cut_y = 0;
+ width = anim->width;
+ height = anim->height;
+
+ if (pos_x<0)
+ {
+ dest_x = 0;
+ width += pos_x;
+ cut_x = -pos_x;
+ }
+ else if (pos_x>FULL_SXSIZE-anim->width)
+ width -= (pos_x - (FULL_SXSIZE-anim->width));
+
+ if (pos_y<0)
+ {
+ dest_y = 0;
+ height += pos_y;
+ cut_y = -pos_y;
+ }
+ else if (pos_y>FULL_SYSIZE-anim->height)
+ height -= (pos_y - (FULL_SYSIZE-anim->height));
+
+ DrawAnim(src_x+cut_x,src_y+cut_y, width,height,
+ REAL_SX+dest_x,REAL_SY+dest_y, pad_x,pad_y);
+
+ pos_x += delta_x;
+ pos_y += delta_y;
+ frame += frame_step;
+
+ if (frame<0 || frame>=anim->frames)
+ {
+ if (anim->pingpong)
+ {
+ frame_step *= -1;
+ frame = (frame<0 ? 1 : anim->frames-2);
+ }
+ else
+ frame = (frame<0 ? anim->frames-1 : 0);
+ }
+
+ return(FALSE);
+}
+
+void DrawAnim(int src_x, int src_y, int width, int height,
+ int dest_x, int dest_y, int pad_x, int pad_y)
+{
+ int buf_x = DOOR_GFX_PAGEX3, buf_y = DOOR_GFX_PAGEY1;
+
+ XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y,
+ width+2*pad_x,height+2*pad_y, buf_x,buf_y);
+ XSetClipOrigin(display,clip_gc[PIX_TOONS],dest_x-src_x,dest_y-src_y);
+ XCopyArea(display,pix[PIX_TOONS],backbuffer,clip_gc[PIX_TOONS],
+ src_x,src_y, width,height, dest_x,dest_y);
+ XCopyArea(display,backbuffer,window,gc, dest_x-pad_x,dest_y-pad_y,
+ width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
+
+ BackToFront();
+
+ XCopyArea(display,pix[PIX_DB_DOOR],backbuffer,gc, buf_x,buf_y,
+ width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
+
+/*
+ XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,dest_x-pad_x,dest_y-pad_y,
+ width+2*pad_x,height+2*pad_y, buf_x,buf_y);
+ XSetClipOrigin(display,clip_gc[PIX_TOONS],
+ buf_x-src_x+pad_x,buf_y-src_y+pad_y);
+ XCopyArea(display,pix[PIX_TOONS],pix[PIX_DB_DOOR],clip_gc[PIX_TOONS],
+ src_x,src_y, width,height, buf_x+pad_x,buf_y+pad_y);
+ XCopyArea(display,pix[PIX_DB_DOOR],window,gc, buf_x,buf_y,
+ width+2*pad_x,height+2*pad_y, dest_x-pad_x,dest_y-pad_y);
+*/
+
+ XFlush(display);
+}
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* misc.h *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#ifndef MISC_H
+#define MISC_H
+
+#include "main.h"
+
+/* values for cartoon figures */
+#define NUM_TOONS 6
+
+#define DWARF_XSIZE 40
+#define DWARF_YSIZE 48
+#define DWARF_X 2
+#define DWARF_Y 72
+#define DWARF2_Y 186
+#define DWARF_FRAMES 8
+#define DWARF_FPS 10
+#define DWARF_STEPSIZE 4
+#define JUMPER_XSIZE 48
+#define JUMPER_YSIZE 56
+#define JUMPER_X 2
+#define JUMPER_Y 125
+#define JUMPER_FRAMES 8
+#define JUMPER_FPS 10
+#define JUMPER_STEPSIZE 4
+#define CLOWN_XSIZE 80
+#define CLOWN_YSIZE 110
+#define CLOWN_X 327
+#define CLOWN_Y 10
+#define CLOWN_FRAMES 1
+#define CLOWN_FPS 10
+#define CLOWN_STEPSIZE 4
+#define BIRD_XSIZE 32
+#define BIRD_YSIZE 30
+#define BIRD1_X 2
+#define BIRD1_Y 2
+#define BIRD2_X 2
+#define BIRD2_Y 37
+#define BIRD_FRAMES 8
+#define BIRD_FPS 20
+#define BIRD_STEPSIZE 4
+
+#define ANIMDIR_LEFT 1
+#define ANIMDIR_RIGHT 2
+#define ANIMDIR_UP 4
+#define ANIMDIR_DOWN 8
+
+#define ANIMPOS_ANY 0
+#define ANIMPOS_LEFT 1
+#define ANIMPOS_RIGHT 2
+#define ANIMPOS_UP 4
+#define ANIMPOS_DOWN 8
+#define ANIMPOS_UPPER 16
+
+#define ANIM_START 0
+#define ANIM_CONTINUE 1
+#define ANIM_STOP 2
+
+struct AnimInfo
+{
+ int width, height;
+ int src_x, src_y;
+ int frames;
+ int frames_per_second;
+ int stepsize;
+ BOOL pingpong;
+ int direction;
+ int position;
+};
+
+#define NEW_RANDOMIZE -1
+
+void microsleep(unsigned long);
+unsigned long be2long(unsigned long *);
+char *int2str(int, int);
+unsigned int RND(unsigned int);
+unsigned int InitRND(long);
+char *GetLoginName(void);
+
+void InitAnimation(void);
+void StopAnimation(void);
+void DoAnimation(void);
+void HandleAnimation(int);
+BOOL AnimateToon(int, BOOL);
+void DrawAnim(int, int, int, int, int, int, int, int);
+
+#endif
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* screens.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#include "screens.h"
+#include "events.h"
+#include "sound.h"
+#include "game.h"
+#include "tools.h"
+#include "editor.h"
+#include "misc.h"
+
+void DrawMainMenu()
+{
+ int i;
+
+ FadeSounds();
+ GetPlayerConfig();
+ LoadLevel(level_nr);
+
+ ClearWindow();
+ DrawText(SX+16, SY+8, "ROCKS'N'DIAMONDS",FS_BIG,FC_YELLOW);
+ DrawText(SX+25+16, SY+46, "Copyright ^1995 by Holger Schemel",
+ FS_SMALL,FC_RED);
+ DrawText(SX+32, SY+64, "Name:",FS_BIG,FC_GREEN);
+ DrawText(SX+192,SY+64, player.alias_name,FS_BIG,FC_RED);
+ DrawText(SX+32, SY+96, "Level:",FS_BIG,FC_GREEN);
+ DrawText(SX+352,SY+96, int2str(level_nr,3),FS_BIG,
+ (level_nr<leveldir[leveldir_nr].num_ready ? FC_RED : FC_YELLOW));
+ DrawText(SX+32, SY+128,"Hall Of Fame",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+160,"Level Creator",FS_BIG,FC_GREEN);
+ DrawText(SY+32, SY+192,"Info Screen",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+224,"Start Game",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+256,"Setup",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+288,"Quit",FS_BIG,FC_GREEN);
+
+ DrawMicroLevel(MICROLEV_XPOS,MICROLEV_YPOS);
+
+ for(i=2;i<10;i++)
+ DrawGraphic(0,i,GFX_KUGEL_BLAU);
+ DrawGraphic(10,3,GFX_KUGEL_BLAU);
+ DrawGraphic(14,3,GFX_KUGEL_BLAU);
+
+ DrawText(SX+54+16,SY+326,"A Game by Artsoft Development",FS_SMALL,FC_BLUE);
+ DrawText(SX+40+16,SY+344,"Graphics: Deluxe Paint IV Amiga",
+ FS_SMALL,FC_BLUE);
+ DrawText(SX+60+16,SY+362,"Sounds: AudioMaster IV Amiga",
+ FS_SMALL,FC_BLUE);
+
+ FadeToFront();
+ InitAnimation();
+ HandleMainMenu(0,0,0,0,MB_MENU_MARK);
+
+ TapeStop();
+ if (TAPE_IS_EMPTY(tape))
+ LoadLevelTape(level_nr);
+ DrawCompleteVideoDisplay();
+
+ OpenDoor(DOOR_CLOSE_1 | DOOR_OPEN_2);
+
+ XAutoRepeatOn(display);
+}
+
+void HandleMainMenu(int mx, int my, int dx, int dy, int button)
+{
+ static int choice = 3;
+ static int redraw = TRUE;
+ int x = (mx+32-SX)/32, y = (my+32-SY)/32;
+
+ if (redraw)
+ {
+ DrawGraphic(0,choice-1,GFX_KUGEL_ROT);
+ redraw = FALSE;
+ }
+
+ if (dx || dy)
+ {
+ if (dx && choice==4)
+ {
+ x = (dx<0 ? 11 : 15);
+ y = 4;
+ }
+ else if (dy)
+ {
+ x = 1;
+ y = choice+dy;
+ }
+ else
+ x = y = 0;
+
+ if (y<3)
+ y = 3;
+ else if (y>10)
+ y = 10;
+ }
+
+ if (!mx && !my && !dx && !dy)
+ {
+ x = 1;
+ y = choice;
+ }
+
+ if (y==4 && ((x==11 && level_nr>0) ||
+ (x==15 && level_nr<LEVELDIR_SIZE(leveldir[leveldir_nr]))) &&
+ button)
+ {
+ static long level_delay = 0;
+ int step = (button==1 ? 1 : button==2 ? 5 : 10);
+
+ if (!DelayReached(&level_delay,20))
+ goto out;
+
+ level_nr += (x==11 ? -step : +step);
+ if (level_nr<0)
+ level_nr = 0;
+ if (level_nr>LEVELDIR_SIZE(leveldir[leveldir_nr])-1)
+ level_nr = LEVELDIR_SIZE(leveldir[leveldir_nr])-1;
+
+ if (level_nr>player.handicap && level_nr<leveldir[leveldir_nr].num_ready)
+ {
+ if (x==11 || leveldir[leveldir_nr].num_free==0)
+ level_nr = player.handicap;
+ else
+ level_nr = leveldir[leveldir_nr].num_ready;
+ }
+
+ DrawTextExt(drawto,gc,SX+352,SY+96, int2str(level_nr,3),FS_BIG,
+ (level_nr<leveldir[leveldir_nr].num_ready ?FC_RED :FC_YELLOW));
+ DrawTextExt(window,gc,SX+352,SY+96, int2str(level_nr,3),FS_BIG,
+ (level_nr<leveldir[leveldir_nr].num_ready ?FC_RED :FC_YELLOW));
+
+ LoadLevel(level_nr);
+ DrawMicroLevel(MICROLEV_XPOS,MICROLEV_YPOS);
+
+ TapeErase();
+ LoadLevelTape(level_nr);
+ DrawCompleteVideoDisplay();
+ }
+ else if (x==1 && y>=3 && y<=10)
+ {
+ if (button)
+ {
+ if (y!=choice)
+ {
+ DrawGraphic(0,y-1,GFX_KUGEL_ROT);
+ DrawGraphic(0,choice-1,GFX_KUGEL_BLAU);
+ }
+ choice = y;
+ }
+ else
+ {
+ if (y==3)
+ {
+ game_status = TYPENAME;
+ HandleTypeName(strlen(player.alias_name),0);
+ }
+ else if (y==4)
+ {
+ if (num_leveldirs)
+ {
+ game_status = CHOOSELEVEL;
+ DrawChooseLevel();
+ redraw = TRUE;
+ }
+ }
+ else if (y==5)
+ {
+ game_status = HALLOFFAME;
+ DrawHallOfFame(-1);
+ redraw = TRUE;
+ }
+ else if (y==6)
+ {
+ game_status = LEVELED;
+ DrawLevelEd();
+ redraw = TRUE;
+ }
+ else if (y==7)
+ {
+ game_status = HELPSCREEN;
+ DrawHelpScreen();
+ redraw = TRUE;
+ }
+ else if (y==8)
+ {
+ if (autorecord_on && !tape.playing)
+ TapeInitRecording();
+
+ game_status = PLAYING;
+ InitGame();
+ redraw = TRUE;
+ }
+ else if (y==9)
+ {
+ game_status = SETUP;
+ DrawSetupScreen();
+ redraw = TRUE;
+ }
+ else if (y==10)
+ {
+ if (AreYouSure("Do you really want to quit ?",AYS_ASK|AYS_STAY_CLOSED))
+ game_status = EXITGAME;
+ }
+ }
+ }
+ BackToFront();
+
+ out:
+
+ if (game_status==MAINMENU)
+ DoAnimation();
+}
+
+#define MAX_HELPSCREEN_ELS 10
+#define HA_NEXT -999
+#define HA_END -1000
+
+static long helpscreen_state;
+static int helpscreen_step[MAX_HELPSCREEN_ELS];
+static int helpscreen_frame[MAX_HELPSCREEN_ELS];
+static int helpscreen_delay[MAX_HELPSCREEN_ELS];
+static int helpscreen_action[] =
+{
+ GFX_ERDREICH,1,100, HA_NEXT,
+ GFX_LEERRAUM,1,100, HA_NEXT,
+ GFX_MORAST_LEER,1,100, HA_NEXT,
+ GFX_BETON,1,100, HA_NEXT,
+ GFX_MAUERWERK,1,100, HA_NEXT,
+ GFX_FELSBODEN,1,100, HA_NEXT,
+ GFX_EDELSTEIN,2,5, HA_NEXT,
+ GFX_DIAMANT,2,5, HA_NEXT,
+ GFX_FELSBROCKEN,4,5, HA_NEXT,
+ GFX_BOMBE,1,50, GFX_EXPLOSION,8,1, GFX_LEERRAUM,1,10, HA_NEXT,
+ GFX_KOKOSNUSS,1,50, GFX_CRACKINGNUT,3,1, GFX_EDELSTEIN,1,10, HA_NEXT,
+ GFX_ERZ_1,1,50, GFX_EXPLOSION,8,1, GFX_EDELSTEIN,1,10, HA_NEXT,
+ GFX_ERZ_2,1,50, GFX_EXPLOSION,8,1, GFX_DIAMANT,1,10, HA_NEXT,
+ GFX_GEBLUBBER,4,4, HA_NEXT,
+ GFX_SCHLUESSEL1,4,33, HA_NEXT,
+ GFX_PFORTE1,4,33, HA_NEXT,
+ GFX_PFORTE1X,4,33, HA_NEXT,
+ GFX_DYNAMIT_AUS,1,100, HA_NEXT,
+ GFX_DYNAMIT,7,6, GFX_EXPLOSION,8,1, GFX_LEERRAUM,1,10, HA_NEXT,
+ GFX_FLIEGER+4,1,3, GFX_FLIEGER+0,1,3, GFX_FLIEGER+4,1,3,
+ GFX_FLIEGER+5,1,3, GFX_FLIEGER+1,1,3, GFX_FLIEGER+5,1,3,
+ GFX_FLIEGER+6,1,3, GFX_FLIEGER+2,1,3, GFX_FLIEGER+6,1,3,
+ GFX_FLIEGER+7,1,3, GFX_FLIEGER+3,1,3, GFX_FLIEGER+7,1,3, HA_NEXT,
+ GFX_KAEFER+4,1,1, GFX_KAEFER+0,1,1, GFX_KAEFER+4,1,1,
+ GFX_KAEFER+5,1,1, GFX_KAEFER+1,1,1, GFX_KAEFER+5,1,1,
+ GFX_KAEFER+6,1,1, GFX_KAEFER+2,1,1, GFX_KAEFER+6,1,1,
+ GFX_KAEFER+7,1,1, GFX_KAEFER+3,1,1, GFX_KAEFER+7,1,1, HA_NEXT,
+ GFX_PACMAN+0,1,3, GFX_PACMAN+4,1,2, GFX_PACMAN+0,1,3,
+ GFX_PACMAN+1,1,3, GFX_PACMAN+5,1,2, GFX_PACMAN+1,1,3,
+ GFX_PACMAN+2,1,3, GFX_PACMAN+6,1,2, GFX_PACMAN+2,1,3,
+ GFX_PACMAN+3,1,3, GFX_PACMAN+7,1,2, GFX_PACMAN+3,1,3, HA_NEXT,
+ GFX_MAMPFER+0,4,0, GFX_MAMPFER+3,1,0, GFX_MAMPFER+2,1,0,
+ GFX_MAMPFER+1,1,0, HA_NEXT,
+ GFX_ZOMBIE+0,4,0, GFX_ZOMBIE+3,1,0, GFX_ZOMBIE+2,1,0,
+ GFX_ZOMBIE+1,1,0, HA_NEXT,
+ GFX_ABLENK,4,1, HA_NEXT,
+ GFX_AMOEBE_LEBT,4,40, HA_NEXT,
+ GFX_AMOEBE_TOT+2,2,50, GFX_AMOEBE_TOT,2,50, HA_NEXT,
+ GFX_SIEB_LEER,4,2, HA_NEXT,
+ HA_END
+};
+static char *helpscreen_eltext[][2] =
+{
+ "Normal sand:", "You can dig through it",
+ "Empty field:", "You can walk through it",
+ "Quicksand: You cannot pass it,", "but rocks can fall though it",
+ "Massive Wall:", "Nothing can go through it",
+ "Normal Wall: You can't go through", "it, but you can bomb it away",
+ "Old Wall: Like normal wall, but", "some things can fall down from it",
+ "Emerald: You must collect enough of", "them to finish a level",
+ "Diamond: Counts as 3 emeralds;", "Can be destroyed by rocks",
+ "Rock: Smashes several things;", "Can be moved by the player",
+ "Bomb: You can move it, but be", "careful when dropping it",
+ "Nut: Throw a rock on it to open it;", "Each nut contains an emerald",
+ "Wall with an Emerald inside:", "Bomb the wall away to get it",
+ "Wall with a Diamond inside:", "Bomb the wall away to get it",
+ "Acid: Destroys everything that", "falls or walks into it",
+ "Key: Opens the door that has the", "same color (red/yellow/green/blue)",
+ "Door: Can be opened by the key", "with the same color",
+ "Door: You have to find out the", "right color of the key for it",
+ "Dynamite: Collect it and use it to", "destroy walls or kill enemies",
+ "Dynamite: This one explodes after", "a few seconds",
+ "Spaceship: Moves at the left side", "of walls; don't touch it!",
+ "Bug: Moves at the right side of", "walls; don't touch it!",
+ "Pacman: Eats the amoeba and you,", "if you're not careful",
+ "Cruncher: Eats diamonds and you,", "if you're not careful",
+ "Robot: Tries to kill the player", "",
+ "Magic Wheel: Touch it to get rid of", "the robots for some seconds",
+ "Living Amoeba: Grows through empty", "fields, sand and quicksand",
+ "Dead Amoeba: Does not grow, but", "can still kill bugs and spaceships",
+ "Magic Wall: Changes rocks, emeralds", "and diamonds when they pass it",
+};
+static int num_helpscreen_els = sizeof(helpscreen_eltext)/(2*sizeof(char *));
+
+static char *helpscreen_music[][3] =
+{
+ "Alchemy", "Ian Boddy", "Drive",
+ "The Chase", "Propaganda", "A Secret Wish",
+ "Network 23", "Tangerine Dream", "Exit",
+ "Czardasz", "Robert Pieculewicz", "Czardasz",
+ "21st Century Common Man", "Tangerine Dream", "Tyger",
+ "Voyager", "The Alan Parsons Project","Pyramid",
+ "Twilight Painter", "Tangerine Dream", "Heartbreakers"
+};
+static int helpscreen_musicpos;
+
+void DrawHelpScreenElAction(int start)
+{
+ int i = 0, j = 0;
+ int frame, delay, graphic;
+ int xstart = SX+16, ystart = SY+64+2*32, ystep = TILEY+4;
+
+ while(helpscreen_action[j] != HA_END)
+ {
+ if (i>=start+MAX_HELPSCREEN_ELS || i>=num_helpscreen_els)
+ break;
+ else if (i<start || helpscreen_delay[i-start])
+ {
+ if (i>=start && helpscreen_delay[i-start])
+ helpscreen_delay[i-start]--;
+
+ while(helpscreen_action[j] != HA_NEXT)
+ j++;
+ j++;
+ i++;
+ continue;
+ }
+
+ j += 3*helpscreen_step[i-start];
+ graphic = helpscreen_action[j++];
+
+ if (helpscreen_frame[i-start])
+ {
+ frame = helpscreen_action[j++] - helpscreen_frame[i-start];
+ helpscreen_frame[i-start]--;
+ }
+ else
+ {
+ frame = 0;
+ helpscreen_frame[i-start] = helpscreen_action[j++]-1;
+ }
+
+ delay = helpscreen_action[j++];
+ helpscreen_delay[i-start] = delay;
+
+ if (helpscreen_action[j] == HA_NEXT)
+ {
+ if (!helpscreen_frame[i-start])
+ helpscreen_step[i-start] = 0;
+ }
+ else
+ {
+ if (!helpscreen_frame[i-start])
+ helpscreen_step[i-start]++;
+ while(helpscreen_action[j] != HA_NEXT)
+ j++;
+ }
+ j++;
+
+ DrawGraphicExtHiRes(drawto,gc,xstart,ystart+(i-start)*ystep,
+ graphic+frame);
+ i++;
+ }
+
+ redraw_tiles += 28;
+ for(i=2;i<16;i++)
+ redraw[0][i] = redraw[1][i] = TRUE;
+ redraw_mask |= REDRAW_TILES;
+}
+
+void DrawHelpScreenElText(int start)
+{
+ int i;
+ int xstart = SX+56, ystart = SY+65+2*32, ystep = TILEY+4;
+ char text[FULL_SXSIZE/FONT2_XSIZE+10];
+
+ ClearWindow();
+ DrawText(SX+16, SY+8, "ROCKS'N'DIAMONDS",FS_BIG,FC_YELLOW);
+ DrawText(SX+25+16, SY+46, "Copyright ^1995 by Holger Schemel",
+ FS_SMALL,FC_RED);
+
+ sprintf(text,"The game elements:");
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+100,
+ text,FS_SMALL,FC_GREEN);
+
+ for(i=start;i<start+MAX_HELPSCREEN_ELS && i<num_helpscreen_els;i++)
+ {
+ DrawText(xstart,ystart+(i-start)*ystep+(*helpscreen_eltext[i][1] ? 0 : 8),
+ helpscreen_eltext[i][0],FS_SMALL,FC_YELLOW);
+ DrawText(xstart,ystart+(i-start)*ystep+16,
+ helpscreen_eltext[i][1],FS_SMALL,FC_YELLOW);
+ }
+
+ sprintf(text,"Press any key or button for next page");
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+SYSIZE-20,
+ text,FS_SMALL,FC_BLUE);
+}
+
+void DrawHelpScreenMusicText(int num)
+{
+ int ystart = 150, ystep = 30;
+ char text[FULL_SXSIZE/FONT2_XSIZE+10];
+
+ FadeSounds();
+ ClearWindow();
+ DrawText(SX+16, SY+8, "ROCKS'N'DIAMONDS",FS_BIG,FC_YELLOW);
+ DrawText(SX+25+16, SY+46, "Copyright ^1995 by Holger Schemel",
+ FS_SMALL,FC_RED);
+
+ sprintf(text,"The game background music loops:");
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+100,
+ text,FS_SMALL,FC_GREEN);
+
+ sprintf(text,"Excerpt from");
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+0*ystep,
+ text,FS_SMALL,FC_YELLOW);
+ sprintf(text,"%c%s%c",'\"',helpscreen_music[num][0],'\"');
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+1*ystep,
+ text,FS_SMALL,FC_RED);
+ sprintf(text,"by");
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+2*ystep,
+ text,FS_SMALL,FC_YELLOW);
+ sprintf(text,"%s",helpscreen_music[num][1]);
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+3*ystep,
+ text,FS_SMALL,FC_RED);
+ sprintf(text,"from the album");
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+4*ystep,
+ text,FS_SMALL,FC_YELLOW);
+ sprintf(text,"%c%s%c",'\"',helpscreen_music[num][2],'\"');
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+5*ystep,
+ text,FS_SMALL,FC_RED);
+
+ sprintf(text,"Press any key or button for next page");
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+SYSIZE-20,
+ text,FS_SMALL,FC_BLUE);
+
+ PlaySoundLoop(background_loop[num]);
+}
+
+void DrawHelpScreenRegistrationText()
+{
+ int ystart = 150, ystep = 30;
+ char text[FULL_SXSIZE/FONT2_XSIZE+10];
+
+ FadeSounds();
+ ClearWindow();
+ DrawText(SX+16, SY+8, "ROCKS'N'DIAMONDS",FS_BIG,FC_YELLOW);
+ DrawText(SX+25+16, SY+46, "Copyright ^1995 by Holger Schemel",
+ FS_SMALL,FC_RED);
+
+ sprintf(text,"Registration information:");
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+100,
+ text,FS_SMALL,FC_GREEN);
+
+ sprintf(text,"Unregistered version");
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+ystart+4*ystep,
+ text,FS_SMALL,FC_YELLOW);
+
+ sprintf(text,"Press any key or button for main menu");
+ DrawText(SX+(SXSIZE-strlen(text)*FONT2_XSIZE)/2,SY+SYSIZE-20,
+ text,FS_SMALL,FC_BLUE);
+}
+
+void DrawHelpScreen()
+{
+ int i;
+
+ CloseDoor(DOOR_CLOSE_2);
+
+ for(i=0;i<MAX_HELPSCREEN_ELS;i++)
+ helpscreen_step[i] = helpscreen_frame[i] = helpscreen_delay[i] = 0;
+ helpscreen_musicpos = 0;
+ helpscreen_state = 0;
+ DrawHelpScreenElText(0);
+ DrawHelpScreenElAction(0);
+
+ FadeToFront();
+ InitAnimation();
+ PlaySoundLoop(SND_RHYTHMLOOP);
+}
+
+void HandleHelpScreen(int button)
+{
+ static long hs_delay = 0;
+ int num_helpscreen_els_pages =
+ (num_helpscreen_els + MAX_HELPSCREEN_ELS-1) / MAX_HELPSCREEN_ELS;
+ int button_released = !button;
+ int i;
+
+ if (button_released)
+ {
+ if (helpscreen_state<num_helpscreen_els_pages-1)
+ {
+ for(i=0;i<MAX_HELPSCREEN_ELS;i++)
+ helpscreen_step[i] = helpscreen_frame[i] = helpscreen_delay[i] = 0;
+ helpscreen_state++;
+ DrawHelpScreenElText(helpscreen_state*MAX_HELPSCREEN_ELS);
+ DrawHelpScreenElAction(helpscreen_state*MAX_HELPSCREEN_ELS);
+ }
+ else if (helpscreen_state<num_helpscreen_els_pages+num_bg_loops-1)
+ {
+ helpscreen_state++;
+ DrawHelpScreenMusicText(helpscreen_state-num_helpscreen_els_pages);
+ }
+ else if (helpscreen_state==num_helpscreen_els_pages+num_bg_loops-1)
+ {
+ helpscreen_state++;
+ DrawHelpScreenRegistrationText();
+ }
+ else
+ {
+ FadeSounds();
+ DrawMainMenu();
+ game_status = MAINMENU;
+ }
+ }
+ else
+ {
+ if (DelayReached(&hs_delay,3))
+ {
+ if (helpscreen_state<num_helpscreen_els_pages)
+ DrawHelpScreenElAction(helpscreen_state*MAX_HELPSCREEN_ELS);
+ }
+ DoAnimation();
+ }
+
+ BackToFront();
+}
+
+void CheckCheat()
+{
+ int old_handicap = player.handicap;
+
+ if (!strcmp(player.alias_name,"Artsoft"))
+ player.handicap = MAX(0,leveldir[leveldir_nr].num_ready-1);
+
+ if (player.handicap != old_handicap)
+ {
+ SavePlayerInfo(PLAYER_LEVEL);
+ level_nr = player.handicap;
+ }
+}
+
+void HandleTypeName(int newxpos, KeySym key)
+{
+ static int xpos = 0, ypos = 2;
+ unsigned char ascii;
+
+ if (newxpos)
+ {
+ xpos = newxpos;
+ DrawText(SX+6*32,SY+ypos*32,player.alias_name,FS_BIG,FC_YELLOW);
+ DrawGraphic(xpos+6,ypos,GFX_KUGEL_ROT);
+ return;
+ }
+
+ if ((key>=XK_A && key<=XK_Z) || (key>=XK_a && key<=XK_z &&
+ xpos<MAX_NAMELEN-1))
+ {
+ if (key>=XK_A && key<=XK_Z)
+ ascii = 'A'+(char)(key-XK_A);
+ if (key>=XK_a && key<=XK_z)
+ ascii = 'a'+(char)(key-XK_a);
+ player.alias_name[xpos] = ascii;
+ player.alias_name[xpos+1] = 0;
+ xpos++;
+ DrawTextExt(drawto,gc,SX+6*32,SY+ypos*32,
+ player.alias_name,FS_BIG,FC_YELLOW);
+ DrawTextExt(window,gc,SX+6*32,SY+ypos*32,
+ player.alias_name,FS_BIG,FC_YELLOW);
+ DrawGraphic(xpos+6,ypos,GFX_KUGEL_ROT);
+ }
+ else if (key==XK_Delete && xpos>0)
+ {
+ player.alias_name[xpos] = 0;
+ xpos--;
+ DrawGraphic(xpos+6,ypos,GFX_KUGEL_ROT);
+ DrawGraphic(xpos+7,ypos,GFX_LEERRAUM);
+ }
+ else if (key==XK_Return && xpos>0)
+ {
+ DrawText(SX+6*32,SY+ypos*32,player.alias_name,FS_BIG,FC_RED);
+ DrawGraphic(xpos+6,ypos,GFX_LEERRAUM);
+ SavePlayerInfo(PLAYER_SETUP);
+ CheckCheat();
+
+ game_status = MAINMENU;
+ DrawMainMenu();
+ }
+ BackToFront();
+}
+
+void DrawChooseLevel()
+{
+ int i;
+
+ ClearWindow();
+ DrawText(SX,SY,"Level Directories",FS_BIG,FC_GREEN);
+ for(i=0;i<num_leveldirs;i++)
+ {
+ DrawText(SX+32,SY+(i+2)*32,leveldir[i].name,FS_BIG,FC_YELLOW);
+ DrawGraphic(0,i+2,GFX_KUGEL_BLAU);
+ }
+
+ FadeToFront();
+ InitAnimation();
+ HandleChooseLevel(0,0,0,0,MB_MENU_MARK);
+}
+
+void HandleChooseLevel(int mx, int my, int dx, int dy, int button)
+{
+ static int choice = 3;
+ static int redraw = TRUE;
+ int x = (mx+32-SX)/32, y = (my+32-SY)/32;
+
+ if (redraw)
+ {
+ DrawGraphic(0,choice-1,GFX_KUGEL_ROT);
+ redraw = FALSE;
+ }
+
+ if (dx || dy)
+ {
+ if (dy)
+ {
+ x = 1;
+ y = choice+dy;
+ }
+ else
+ x = y = 0;
+
+ if (y<3)
+ y = 3;
+ else if (y>num_leveldirs+2)
+ y = num_leveldirs+2;
+ }
+
+ if (!mx && !my && !dx && !dy)
+ {
+ x = 1;
+ y = choice;
+ }
+
+ if (x==1 && y>=3 && y<=num_leveldirs+2)
+ {
+ if (button)
+ {
+ if (y!=choice)
+ {
+ DrawGraphic(0,y-1,GFX_KUGEL_ROT);
+ DrawGraphic(0,choice-1,GFX_KUGEL_BLAU);
+ }
+ choice = y;
+ }
+ else
+ {
+ player.leveldir_nr = leveldir_nr = y-3;
+ LoadPlayerInfo(PLAYER_LEVEL);
+ SavePlayerInfo(PLAYER_SETUP);
+ CheckCheat();
+
+ game_status = MAINMENU;
+ DrawMainMenu();
+ redraw = TRUE;
+ }
+ }
+ BackToFront();
+
+ if (game_status==CHOOSELEVEL)
+ DoAnimation();
+}
+
+void DrawHallOfFame(int pos)
+{
+ int y;
+ char txt[40];
+
+ CloseDoor(DOOR_CLOSE_2);
+
+ if (pos<0)
+ LoadScore(level_nr);
+ ClearWindow();
+ DrawText(SX+64,SY+10,"Hall Of Fame",FS_BIG,FC_YELLOW);
+ sprintf(txt,"HighScores of Level %d",level_nr);
+ DrawText(SX+256-strlen(txt)*7,SY+48,txt,FS_SMALL,FC_RED);
+ for(y=0;y<MAX_SCORE_ENTRIES;y++)
+ {
+ DrawText(SX,SY+64+y*32,".................",FS_BIG,
+ (y==pos ? FC_RED : FC_GREEN));
+ DrawText(SX,SY+64+y*32,highscore[y].Name,FS_BIG,
+ (y==pos ? FC_RED : FC_GREEN));
+ DrawText(SX+12*32,SY+64+y*32,
+ int2str(highscore[y].Score,5),FS_BIG,
+ (y==pos ? FC_RED : FC_GREEN));
+ }
+
+ FadeToFront();
+ InitAnimation();
+ PlaySound(SND_HALLOFFAME);
+}
+
+void HandleHallOfFame(int button)
+{
+ int button_released = !button;
+
+ if (button_released)
+ {
+ FadeSound(SND_HALLOFFAME);
+ game_status = MAINMENU;
+ DrawMainMenu();
+ BackToFront();
+ }
+ else
+ DoAnimation();
+}
+
+void DrawSetupScreen()
+{
+ int i;
+
+ CloseDoor(DOOR_CLOSE_2);
+
+ ClearWindow();
+ DrawText(SX+16, SY+16, "SETUP",FS_BIG,FC_YELLOW);
+ DrawText(SX+32, SY+2*32,"Sound:",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+3*32,"Sound loops:",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+4*32,"Game music:",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+5*32,"Toons:",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+6*32,"Buffered gfx:",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+7*32,"Fading:",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+8*32,"Auto-Record:",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+9*32,"Joystick:",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+10*32,"Cal. Joystick",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+12*32,"Exit",FS_BIG,FC_GREEN);
+ DrawText(SX+32, SY+13*32,"Save and exit",FS_BIG,FC_GREEN);
+
+ if (SETUP_SOUND_ON(player.setup))
+ DrawText(SX+14*32, SY+2*32,"on",FS_BIG,FC_YELLOW);
+ else
+ DrawText(SX+14*32, SY+2*32,"off",FS_BIG,FC_BLUE);
+
+ if (SETUP_SOUND_LOOPS_ON(player.setup))
+ DrawText(SX+14*32, SY+3*32,"on",FS_BIG,FC_YELLOW);
+ else
+ DrawText(SX+14*32, SY+3*32,"off",FS_BIG,FC_BLUE);
+
+ if (SETUP_SOUND_MUSIC_ON(player.setup))
+ DrawText(SX+14*32, SY+4*32,"on",FS_BIG,FC_YELLOW);
+ else
+ DrawText(SX+14*32, SY+4*32,"off",FS_BIG,FC_BLUE);
+
+ if (SETUP_TOONS_ON(player.setup))
+ DrawText(SX+14*32, SY+5*32,"on",FS_BIG,FC_YELLOW);
+ else
+ DrawText(SX+14*32, SY+5*32,"off",FS_BIG,FC_BLUE);
+
+ if (!SETUP_DIRECT_DRAW_ON(player.setup))
+ DrawText(SX+14*32, SY+6*32,"on",FS_BIG,FC_YELLOW);
+ else
+ DrawText(SX+14*32, SY+6*32,"off",FS_BIG,FC_BLUE);
+
+ if (SETUP_FADING_ON(player.setup))
+ DrawText(SX+14*32, SY+7*32,"on",FS_BIG,FC_YELLOW);
+ else
+ DrawText(SX+14*32, SY+7*32,"off",FS_BIG,FC_BLUE);
+
+ if (SETUP_RECORD_EACH_GAME_ON(player.setup))
+ DrawText(SX+14*32, SY+8*32,"on",FS_BIG,FC_YELLOW);
+ else
+ DrawText(SX+14*32, SY+8*32,"off",FS_BIG,FC_BLUE);
+
+ if (SETUP_2ND_JOYSTICK_ON(player.setup))
+ DrawText(SX+14*32, SY+9*32,"2nd",FS_BIG,FC_YELLOW);
+ else
+ DrawText(SX+14*32, SY+9*32,"1st",FS_BIG,FC_YELLOW);
+
+ for(i=2;i<14;i++)
+ if (i!=11)
+ DrawGraphic(0,i,GFX_KUGEL_BLAU);
+
+ FadeToFront();
+ InitAnimation();
+ HandleSetupScreen(0,0,0,0,MB_MENU_MARK);
+}
+
+void HandleSetupScreen(int mx, int my, int dx, int dy, int button)
+{
+ static int choice = 3;
+ static int redraw = TRUE;
+ int x = (mx+32-SX)/32, y = (my+32-SY)/32;
+
+ if (redraw)
+ {
+ DrawGraphic(0,choice-1,GFX_KUGEL_ROT);
+ redraw = FALSE;
+ }
+
+ if (dx || dy)
+ {
+ if (dy)
+ {
+ x = 1;
+ y = choice+dy;
+ }
+ else
+ x = y = 0;
+
+ if (y==12)
+ y = (dy>0 ? 13 : 11);
+
+ if (y<3)
+ y = 3;
+ else if (y>14)
+ y = 14;
+ }
+
+ if (!mx && !my && !dx && !dy)
+ {
+ x = 1;
+ y = choice;
+ }
+
+ if (x==1 && y>=3 && y<=14 && y!=12)
+ {
+ if (button)
+ {
+ if (y!=choice)
+ {
+ DrawGraphic(0,y-1,GFX_KUGEL_ROT);
+ DrawGraphic(0,choice-1,GFX_KUGEL_BLAU);
+ }
+ choice = y;
+ }
+ else
+ {
+ int yy = y-1;
+
+ if (y==3 && sound_status==SOUND_AVAILABLE)
+ {
+ if (SETUP_SOUND_ON(player.setup))
+ DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+ else
+ DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+ player.setup ^= SETUP_SOUND;
+ }
+ else if (y==4 && sound_loops_allowed)
+ {
+ if (SETUP_SOUND_LOOPS_ON(player.setup))
+ DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+ else
+ DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+ player.setup ^= SETUP_SOUND_LOOPS;
+ }
+ else if (y==5 && sound_loops_allowed)
+ {
+ if (SETUP_SOUND_MUSIC_ON(player.setup))
+ DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+ else
+ DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+ player.setup ^= SETUP_SOUND_MUSIC;
+ }
+ else if (y==6)
+ {
+ if (SETUP_TOONS_ON(player.setup))
+ DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+ else
+ DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+ player.setup ^= SETUP_TOONS;
+ }
+ else if (y==7)
+ {
+ if (!SETUP_DIRECT_DRAW_ON(player.setup))
+ DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+ else
+ DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+ player.setup ^= SETUP_DIRECT_DRAW;
+ }
+ else if (y==8)
+ {
+ if (SETUP_FADING_ON(player.setup))
+ DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+ else
+ DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+ player.setup ^= SETUP_FADING;
+ }
+ else if (y==9)
+ {
+ if (SETUP_RECORD_EACH_GAME_ON(player.setup))
+ DrawText(SX+14*32, SY+yy*32,"off",FS_BIG,FC_BLUE);
+ else
+ DrawText(SX+14*32, SY+yy*32,"on ",FS_BIG,FC_YELLOW);
+ player.setup ^= SETUP_RECORD_EACH_GAME;
+ }
+ else if (y==10)
+ {
+ if (SETUP_2ND_JOYSTICK_ON(player.setup))
+ DrawText(SX+14*32, SY+yy*32,"1st",FS_BIG,FC_YELLOW);
+ else
+ DrawText(SX+14*32, SY+yy*32,"2nd",FS_BIG,FC_YELLOW);
+ player.setup ^= SETUP_2ND_JOYSTICK;
+ }
+ else if (y==11)
+ {
+ CalibrateJoystick();
+ redraw = TRUE;
+ }
+ else if (y==13 || y==14)
+ {
+ if (y==14)
+ {
+ SavePlayerInfo(PLAYER_SETUP);
+ SaveJoystickData();
+ }
+
+ game_status = MAINMENU;
+ DrawMainMenu();
+ redraw = TRUE;
+ }
+ }
+ }
+ BackToFront();
+
+ if (game_status==SETUP)
+ DoAnimation();
+}
+
+void HandleVideoButtons(int mx, int my, int button)
+{
+ if (game_status!=MAINMENU && game_status!=PLAYING)
+ return;
+
+ switch(CheckVideoButtons(mx,my,button))
+ {
+ case BUTTON_VIDEO_EJECT:
+ TapeStop();
+ if (!TAPE_IS_EMPTY(tape))
+ SaveLevelTape(tape.level_nr);
+ else
+ AreYouSure("Tape is empty !",AYS_CONFIRM);
+ DrawCompleteVideoDisplay();
+ break;
+ case BUTTON_VIDEO_STOP:
+ TapeStop();
+ break;
+ case BUTTON_VIDEO_PAUSE:
+ TapeTogglePause();
+ break;
+ case BUTTON_VIDEO_REC:
+ if (tape.pausing)
+ TapeTogglePause();
+ else if (game_status==MAINMENU)
+ TapeInitRecording();
+ break;
+ case BUTTON_VIDEO_PLAY:
+ if (tape.pausing)
+ TapeTogglePause();
+ else if (game_status==MAINMENU)
+ TapeInitPlaying();
+ break;
+ default:
+ break;
+ }
+}
+
+void HandleSoundButtons(int mx, int my, int button)
+{
+ if (game_status!=PLAYING)
+ return;
+
+ switch(CheckSoundButtons(mx,my,button))
+ {
+ case BUTTON_SOUND_MUSIC:
+ if (sound_music_on)
+ {
+ sound_music_on = FALSE;
+ player.setup &= ~SETUP_SOUND_MUSIC;
+ FadeSound(background_loop[level_nr % num_bg_loops]);
+ DrawSoundDisplay(BUTTON_SOUND_MUSIC_OFF);
+ }
+ else if (sound_loops_allowed)
+ {
+ sound_music_on = TRUE;
+ player.setup |= SETUP_SOUND_MUSIC;
+ PlaySoundLoop(background_loop[level_nr % num_bg_loops]);
+ DrawSoundDisplay(BUTTON_SOUND_MUSIC_ON);
+ }
+ else
+ DrawSoundDisplay(BUTTON_SOUND_MUSIC_OFF);
+ break;
+ case BUTTON_SOUND_LOOPS:
+ if (sound_loops_on)
+ {
+ sound_loops_on = FALSE;
+ player.setup &= ~SETUP_SOUND_LOOPS;
+ DrawSoundDisplay(BUTTON_SOUND_LOOPS_OFF);
+ }
+ else if (sound_loops_allowed)
+ {
+ sound_loops_on = TRUE;
+ player.setup |= SETUP_SOUND_LOOPS;
+ DrawSoundDisplay(BUTTON_SOUND_LOOPS_ON);
+ }
+ else
+ DrawSoundDisplay(BUTTON_SOUND_LOOPS_OFF);
+ break;
+ case BUTTON_SOUND_SOUND:
+ if (sound_on)
+ {
+ sound_on = FALSE;
+ player.setup &= ~SETUP_SOUND;
+ DrawSoundDisplay(BUTTON_SOUND_SOUND_OFF);
+ }
+ else if (sound_status==SOUND_AVAILABLE)
+ {
+ sound_on = TRUE;
+ player.setup |= SETUP_SOUND;
+ DrawSoundDisplay(BUTTON_SOUND_SOUND_ON);
+ }
+ else
+ DrawSoundDisplay(BUTTON_SOUND_SOUND_OFF);
+ break;
+ default:
+ break;
+ }
+}
+
+void HandleGameButtons(int mx, int my, int button)
+{
+ if (game_status!=PLAYING)
+ return;
+
+ switch(CheckGameButtons(mx,my,button))
+ {
+ case BUTTON_GAME_STOP:
+ if (AreYouSure("Do you really want to quit the game ?",
+ AYS_ASK | AYS_STAY_CLOSED))
+ {
+ game_status = MAINMENU;
+ DrawMainMenu();
+ }
+ else
+ OpenDoor(DOOR_OPEN_1 | DOOR_COPY_BACK);
+ break;
+ case BUTTON_GAME_PAUSE:
+ if (tape.pausing)
+ {
+ tape.pausing = FALSE;
+ DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
+ }
+ else
+ {
+ tape.pausing = TRUE;
+ DrawVideoDisplay(VIDEO_STATE_PAUSE_ON,0);
+ }
+ break;
+ case BUTTON_GAME_PLAY:
+ if (tape.pausing)
+ {
+ tape.pausing = FALSE;
+ DrawVideoDisplay(VIDEO_STATE_PAUSE_OFF,0);
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+int CheckVideoButtons(int mx, int my, int button)
+{
+ int return_code = 0;
+ static int choice = -1;
+ static BOOL pressed = FALSE;
+ static int video_button[5] =
+ {
+ VIDEO_PRESS_EJECT_ON,
+ VIDEO_PRESS_STOP_ON,
+ VIDEO_PRESS_PAUSE_ON,
+ VIDEO_PRESS_REC_ON,
+ VIDEO_PRESS_PLAY_ON
+ };
+
+ if (button)
+ {
+ if (!motion_status) /* Maustaste neu gedrückt */
+ {
+ if (ON_VIDEO_BUTTON(mx,my))
+ {
+ choice = VIDEO_BUTTON(mx);
+ pressed = TRUE;
+ DrawVideoDisplay(video_button[choice],0);
+ }
+ }
+ else /* Mausbewegung bei gedrückter Maustaste */
+ {
+ if ((!ON_VIDEO_BUTTON(mx,my) || VIDEO_BUTTON(mx)!=choice) &&
+ choice>=0 && pressed)
+ {
+ pressed = FALSE;
+ DrawVideoDisplay(video_button[choice]<<1,0);
+ }
+ else if (ON_VIDEO_BUTTON(mx,my) && VIDEO_BUTTON(mx)==choice && !pressed)
+ {
+ pressed = TRUE;
+ DrawVideoDisplay(video_button[choice],0);
+ }
+ }
+ }
+ else /* Maustaste wieder losgelassen */
+ {
+ if (ON_VIDEO_BUTTON(mx,my) && VIDEO_BUTTON(mx)==choice && pressed)
+ {
+ DrawVideoDisplay(video_button[choice]<<1,0);
+ return_code = choice+1;
+ choice = -1;
+ pressed = FALSE;
+ }
+ else
+ {
+ choice = -1;
+ pressed = FALSE;
+ }
+ }
+
+ BackToFront();
+ return(return_code);
+}
+
+int CheckSoundButtons(int mx, int my, int button)
+{
+ int return_code = 0;
+ static int choice = -1;
+ static BOOL pressed = FALSE;
+ int sound_state[3];
+
+ sound_state[0] = BUTTON_SOUND_MUSIC | (BUTTON_ON * sound_music_on);
+ sound_state[1] = BUTTON_SOUND_LOOPS | (BUTTON_ON * sound_loops_on);
+ sound_state[2] = BUTTON_SOUND_SOUND | (BUTTON_ON * sound_on);
+
+ if (button)
+ {
+ if (!motion_status) /* Maustaste neu gedrückt */
+ {
+ if (ON_SOUND_BUTTON(mx,my))
+ {
+ choice = SOUND_BUTTON(mx);
+ pressed = TRUE;
+ DrawSoundDisplay(sound_state[choice] | BUTTON_PRESSED);
+ }
+ }
+ else /* Mausbewegung bei gedrückter Maustaste */
+ {
+ if ((!ON_SOUND_BUTTON(mx,my) || SOUND_BUTTON(mx)!=choice) &&
+ choice>=0 && pressed)
+ {
+ pressed = FALSE;
+ DrawSoundDisplay(sound_state[choice] | BUTTON_RELEASED);
+ }
+ else if (ON_SOUND_BUTTON(mx,my) && SOUND_BUTTON(mx)==choice && !pressed)
+ {
+ pressed = TRUE;
+ DrawSoundDisplay(sound_state[choice] | BUTTON_PRESSED);
+ }
+ }
+ }
+ else /* Maustaste wieder losgelassen */
+ {
+ if (ON_SOUND_BUTTON(mx,my) && SOUND_BUTTON(mx)==choice && pressed)
+ {
+ DrawSoundDisplay(sound_state[choice] | BUTTON_RELEASED);
+ return_code = 1<<choice;
+ choice = -1;
+ pressed = FALSE;
+ }
+ else
+ {
+ choice = -1;
+ pressed = FALSE;
+ }
+ }
+
+ BackToFront();
+ return(return_code);
+}
+
+int CheckGameButtons(int mx, int my, int button)
+{
+ int return_code = 0;
+ static int choice = -1;
+ static BOOL pressed = FALSE;
+ int game_state[3] =
+ {
+ BUTTON_GAME_STOP,
+ BUTTON_GAME_PAUSE,
+ BUTTON_GAME_PLAY
+ };
+
+ if (button)
+ {
+ if (!motion_status) /* Maustaste neu gedrückt */
+ {
+ if (ON_GAME_BUTTON(mx,my))
+ {
+ choice = GAME_BUTTON(mx);
+ pressed = TRUE;
+ DrawGameButton(game_state[choice] | BUTTON_PRESSED);
+ }
+ }
+ else /* Mausbewegung bei gedrückter Maustaste */
+ {
+ if ((!ON_GAME_BUTTON(mx,my) || GAME_BUTTON(mx)!=choice) &&
+ choice>=0 && pressed)
+ {
+ pressed = FALSE;
+ DrawGameButton(game_state[choice] | BUTTON_RELEASED);
+ }
+ else if (ON_GAME_BUTTON(mx,my) && GAME_BUTTON(mx)==choice && !pressed)
+ {
+ pressed = TRUE;
+ DrawGameButton(game_state[choice] | BUTTON_PRESSED);
+ }
+ }
+ }
+ else /* Maustaste wieder losgelassen */
+ {
+ if (ON_GAME_BUTTON(mx,my) && GAME_BUTTON(mx)==choice && pressed)
+ {
+ DrawGameButton(game_state[choice] | BUTTON_RELEASED);
+ return_code = 1<<choice;
+ choice = -1;
+ pressed = FALSE;
+ }
+ else
+ {
+ choice = -1;
+ pressed = FALSE;
+ }
+ }
+
+ BackToFront();
+ return(return_code);
+}
+
+int CheckChooseButtons(int mx, int my, int button)
+{
+ int return_code = 0;
+ static int choice = -1;
+ static BOOL pressed = FALSE;
+ static int choose_button[5] =
+ {
+ BUTTON_OK,
+ BUTTON_NO
+ };
+
+ if (button)
+ {
+ if (!motion_status) /* Maustaste neu gedrückt */
+ {
+ if (ON_CHOOSE_BUTTON(mx,my))
+ {
+ choice = CHOOSE_BUTTON(mx);
+ pressed = TRUE;
+ DrawChooseButton(choose_button[choice] | BUTTON_PRESSED);
+ }
+ }
+ else /* Mausbewegung bei gedrückter Maustaste */
+ {
+ if ((!ON_CHOOSE_BUTTON(mx,my) || CHOOSE_BUTTON(mx)!=choice) &&
+ choice>=0 && pressed)
+ {
+ pressed = FALSE;
+ DrawChooseButton(choose_button[choice] | BUTTON_RELEASED);
+ }
+ else if (ON_CHOOSE_BUTTON(mx,my) &&CHOOSE_BUTTON(mx)==choice && !pressed)
+ {
+ pressed = TRUE;
+ DrawChooseButton(choose_button[choice] | BUTTON_PRESSED);
+ }
+ }
+ }
+ else /* Maustaste wieder losgelassen */
+ {
+ if (ON_CHOOSE_BUTTON(mx,my) && CHOOSE_BUTTON(mx)==choice && pressed)
+ {
+ DrawChooseButton(choose_button[choice] | BUTTON_RELEASED);
+ return_code = choice+1;
+ choice = -1;
+ pressed = FALSE;
+ }
+ else
+ {
+ choice = -1;
+ pressed = FALSE;
+ }
+ }
+
+ BackToFront();
+ return(return_code);
+}
+
+int CheckConfirmButton(int mx, int my, int button)
+{
+ int return_code = 0;
+ static int choice = -1;
+ static BOOL pressed = FALSE;
+
+ if (button)
+ {
+ if (!motion_status) /* Maustaste neu gedrückt */
+ {
+ if (ON_CONFIRM_BUTTON(mx,my))
+ {
+ choice = 0;
+ pressed = TRUE;
+ DrawConfirmButton(BUTTON_PRESSED);
+ }
+ }
+ else /* Mausbewegung bei gedrückter Maustaste */
+ {
+ if (!ON_CONFIRM_BUTTON(mx,my) && choice>=0 && pressed)
+ {
+ pressed = FALSE;
+ DrawConfirmButton(BUTTON_RELEASED);
+ }
+ else if (ON_CONFIRM_BUTTON(mx,my) && !pressed)
+ {
+ pressed = TRUE;
+ DrawConfirmButton(BUTTON_PRESSED);
+ }
+ }
+ }
+ else /* Maustaste wieder losgelassen */
+ {
+ if (ON_CONFIRM_BUTTON(mx,my) && pressed)
+ {
+ DrawConfirmButton(BUTTON_RELEASED);
+ return_code = BUTTON_CONFIRM;
+ choice = -1;
+ pressed = FALSE;
+ }
+ else
+ {
+ choice = -1;
+ pressed = FALSE;
+ }
+ }
+
+ BackToFront();
+ return(return_code);
+}
+
+void DrawCompleteVideoDisplay()
+{
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ DOOR_GFX_PAGEX3,DOOR_GFX_PAGEY2, VXSIZE,VYSIZE, VX,VY);
+ XCopyArea(display,pix[PIX_DOOR],drawto,gc,
+ DOOR_GFX_PAGEX4+VIDEO_CONTROL_XPOS,
+ DOOR_GFX_PAGEY2+VIDEO_CONTROL_YPOS,
+ VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
+ VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
+
+ DrawVideoDisplay(VIDEO_ALL_OFF,0);
+ if (tape.date && tape.length)
+ {
+ DrawVideoDisplay(VIDEO_STATE_DATE_ON,tape.date);
+ DrawVideoDisplay(VIDEO_STATE_TIME_ON,0);
+ }
+
+ XCopyArea(display,drawto,pix[PIX_DB_DOOR],gc,
+ VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
+}
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* screens.h *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#ifndef SCREENS_H
+#define SCREENS_H
+
+#include "main.h"
+
+/* Setup-Bits */
+#define SETUP_TOONS (1<<0)
+#define SETUP_SOUND (1<<1)
+#define SETUP_SOUND_LOOPS (1<<2)
+#define SETUP_SOUND_MUSIC (1<<3)
+#define SETUP_DIRECT_DRAW (1<<4)
+#define SETUP_FADING (1<<5)
+#define SETUP_RECORD_EACH_GAME (1<<6)
+#define SETUP_2ND_JOYSTICK (1<<7)
+
+#define DEFAULT_SETUP (SETUP_TOONS | \
+ SETUP_SOUND | \
+ SETUP_SOUND_LOOPS | \
+ SETUP_SOUND_MUSIC)
+
+/* Setup-Voreinstellungen */
+#define SETUP_TOONS_ON(x) (((x) & SETUP_TOONS) != 0)
+#define SETUP_SOUND_ON(x) (((x) & SETUP_SOUND) != 0)
+#define SETUP_SOUND_LOOPS_ON(x) (((x) & SETUP_SOUND_LOOPS) != 0)
+#define SETUP_SOUND_MUSIC_ON(x) (((x) & SETUP_SOUND_MUSIC) != 0)
+#define SETUP_DIRECT_DRAW_ON(x) (((x) & SETUP_DIRECT_DRAW) != 0)
+#define SETUP_FADING_ON(x) (((x) & SETUP_FADING) != 0)
+#define SETUP_RECORD_EACH_GAME_ON(x) (((x) & SETUP_RECORD_EACH_GAME) != 0)
+#define SETUP_2ND_JOYSTICK_ON(x) (((x) & SETUP_2ND_JOYSTICK) != 0)
+
+void DrawMainMenu();
+void HandleMainMenu(int, int, int, int, int);
+void DrawHelpScreenElAction(int);
+void DrawHelpScreenElText(int);
+void DrawHelpScreenMusicText(int);
+void DrawHelpScreenRegistrationText(void);
+void DrawHelpScreen();
+void HandleHelpScreen(int);
+void HandleTypeName(int, KeySym);
+void DrawChooseLevel(void);
+void HandleChooseLevel(int, int, int, int, int);
+void DrawHallOfFame(int);
+void HandleHallOfFame(int);
+void DrawSetupScreen();
+void HandleSetupScreen(int, int, int, int, int);
+void HandleVideoButtons(int, int, int);
+void HandleSoundButtons(int, int, int);
+void HandleGameButtons(int, int, int);
+int CheckVideoButtons(int, int, int);
+int CheckSoundButtons(int, int, int);
+int CheckGameButtons(int, int, int);
+int CheckChooseButtons(int, int, int);
+int CheckConfirmButton(int, int, int);
+void DrawCompleteVideoDisplay(void);
+
+#endif
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* sound.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#include "sound.h"
+
+/*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
+
+static struct SoundControl playlist[MAX_SOUNDS_PLAYING];
+static struct SoundControl emptySoundControl =
+{
+ -1,0,0, FALSE,FALSE,FALSE,FALSE,FALSE, 0,0L,0L,NULL
+};
+static int stereo_volume[PSND_MAX_LEFT2RIGHT+1];
+static char premix_first_buffer[SND_BLOCKSIZE];
+static char premix_left_buffer[SND_BLOCKSIZE];
+static char premix_right_buffer[SND_BLOCKSIZE];
+static int premix_last_buffer[SND_BLOCKSIZE];
+static unsigned char playing_buffer[SND_BLOCKSIZE];
+static int playing_sounds = 0;
+
+void SoundServer()
+{
+ struct SoundControl snd_ctrl;
+ fd_set sound_fdset;
+ int i;
+
+ close(sound_pipe[1]); /* no writing into pipe needed */
+
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ playlist[i] = emptySoundControl;
+
+ stereo_volume[PSND_MAX_LEFT2RIGHT] = 0;
+ for(i=0;i<PSND_MAX_LEFT2RIGHT;i++)
+ stereo_volume[i] =
+ (int)sqrt((float)(PSND_MAX_LEFT2RIGHT*PSND_MAX_LEFT2RIGHT-i*i));
+
+#ifdef HPUX_AUDIO
+ HPUX_Audio_Control();
+#endif
+
+ FD_ZERO(&sound_fdset);
+ FD_SET(sound_pipe[0], &sound_fdset);
+
+ for(;;) /* wait for calls from PlaySound(), StopSound(), ... */
+ {
+ FD_SET(sound_pipe[0], &sound_fdset);
+ select(sound_pipe[0]+1, &sound_fdset, NULL, NULL, NULL);
+ if (!FD_ISSET(sound_pipe[0], &sound_fdset))
+ continue;
+ if (read(sound_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) != sizeof(snd_ctrl))
+ {
+ fprintf(stderr,"%s: broken pipe - no sounds\n",progname);
+ exit(0);
+ }
+
+#ifdef VOXWARE
+
+ if (snd_ctrl.fade_sound)
+ {
+ if (!playing_sounds)
+ continue;
+
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
+ playlist[i].fade_sound = TRUE;
+ }
+ else if (snd_ctrl.stop_all_sounds)
+ {
+ if (!playing_sounds)
+ continue;
+
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ playlist[i]=emptySoundControl;
+ playing_sounds=0;
+
+ close(sound_device);
+ }
+ else if (snd_ctrl.stop_sound)
+ {
+ if (!playing_sounds)
+ continue;
+
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ if (playlist[i].nr == snd_ctrl.nr)
+ {
+ playlist[i]=emptySoundControl;
+ playing_sounds--;
+ }
+
+ if (!playing_sounds)
+ close(sound_device);
+ }
+
+ if (playing_sounds || snd_ctrl.active)
+ {
+ struct timeval delay = { 0, 0 };
+ char *sample_ptr;
+ long sample_size, max_sample_size;
+ long fragment_size;
+ BOOL stereo;
+
+ if (playing_sounds || (sound_device=open(sound_device_name,O_WRONLY))>=0)
+ {
+ if (!playing_sounds) /* we just opened the audio device */
+ {
+ /* 2 buffers / 512 bytes, giving 1/16 second resolution */
+ /* (with stereo the effective buffer size will shrink to 256) */
+ fragment_size = 0x00020009;
+ ioctl(sound_device, SNDCTL_DSP_SETFRAGMENT, &fragment_size);
+ /* try if we can use stereo sound */
+ stereo = TRUE;
+ ioctl(sound_device, SNDCTL_DSP_STEREO, &stereo);
+ /* get the real fragmentation size; this should return 512 */
+ ioctl(sound_device, SNDCTL_DSP_GETBLKSIZE, &fragment_size);
+ max_sample_size = fragment_size / (stereo ? 2 : 1);
+ }
+
+ if (snd_ctrl.active) /* new sound has arrived */
+ SoundServer_InsertNewSound(snd_ctrl);
+
+ while(playing_sounds &&
+ select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
+ {
+ FD_SET(sound_pipe[0], &sound_fdset);
+
+ /* first clear the last premixing buffer */
+ memset(premix_last_buffer,0,fragment_size*sizeof(int));
+
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ {
+ int j;
+
+ if (!playlist[i].active)
+ continue;
+
+ /* get pointer and size of the actual sound sample */
+ sample_ptr = playlist[i].data_ptr+playlist[i].playingpos;
+ sample_size =
+ MIN(max_sample_size,playlist[i].data_len-playlist[i].playingpos);
+ playlist[i].playingpos += sample_size;
+
+ /* fill the first mixing buffer with original sample */
+ memcpy(premix_first_buffer,sample_ptr,sample_size);
+
+ /* are we about to restart a looping sound? */
+ if (playlist[i].loop && sample_size<max_sample_size)
+ {
+ playlist[i].playingpos = max_sample_size-sample_size;
+ memcpy(premix_first_buffer+sample_size,
+ playlist[i].data_ptr,max_sample_size-sample_size);
+ sample_size = max_sample_size;
+ }
+
+ /* decrease volume if sound is fading out */
+ if (playlist[i].fade_sound &&
+ playlist[i].volume>=PSND_MAX_VOLUME/10)
+ playlist[i].volume-=PSND_MAX_VOLUME/20;
+
+ /* adjust volume of actual sound sample */
+ if (playlist[i].volume != PSND_MAX_VOLUME)
+ for(j=0;j<sample_size;j++)
+ premix_first_buffer[j] =
+ (playlist[i].volume * (int)premix_first_buffer[j])
+ >> PSND_MAX_VOLUME_BITS;
+
+ /* fill the last mixing buffer with stereo or mono sound */
+ if (stereo)
+ {
+ int middle_pos = PSND_MAX_LEFT2RIGHT/2;
+ int left_volume = stereo_volume[middle_pos+playlist[i].stereo];
+ int right_volume = stereo_volume[middle_pos-playlist[i].stereo];
+
+ for(j=0;j<sample_size;j++)
+ {
+ premix_left_buffer[j] =
+ (left_volume * (int)premix_first_buffer[j])
+ >> PSND_MAX_LEFT2RIGHT_BITS;
+ premix_right_buffer[j] =
+ (right_volume * (int)premix_first_buffer[j])
+ >> PSND_MAX_LEFT2RIGHT_BITS;
+ premix_last_buffer[2*j+0] += premix_left_buffer[j];
+ premix_last_buffer[2*j+1] += premix_right_buffer[j];
+ }
+ }
+ else
+ {
+ for(j=0;j<sample_size;j++)
+ premix_last_buffer[j] += (int)premix_first_buffer[j];
+ }
+
+ /* delete completed sound entries from the playlist */
+ if (playlist[i].playingpos >= playlist[i].data_len)
+ {
+ if (playlist[i].loop)
+ playlist[i].playingpos = 0;
+ else
+ {
+ playlist[i] = emptySoundControl;
+ playing_sounds--;
+ }
+ }
+ else if (playlist[i].volume <= PSND_MAX_VOLUME/10)
+ {
+ playlist[i] = emptySoundControl;
+ playing_sounds--;
+ }
+ }
+
+ /* put last mixing buffer to final playing buffer */
+ for(i=0;i<fragment_size;i++)
+ {
+ if (premix_last_buffer[i]<-255)
+ playing_buffer[i] = 0;
+ else if (premix_last_buffer[i]>255)
+ playing_buffer[i] = 255;
+ else
+ playing_buffer[i] = (premix_last_buffer[i]>>1)^0x80;
+ }
+
+ /* finally play the sound fragment */
+ write(sound_device,playing_buffer,fragment_size);
+ }
+
+ /* if no sounds playing, free device for other sound programs */
+ if (!playing_sounds)
+ close(sound_device);
+ }
+ }
+
+#else /* von '#ifdef VOXWARE' */
+
+ if (snd_ctrl.active && !snd_ctrl.loop)
+ {
+ struct timeval delay = { 0, 0 };
+ char *sample_ptr;
+ long sample_size, max_sample_size = SND_BLOCKSIZE;
+ long sample_rate = 8000; /* standard "/dev/audio" sampling rate */
+ int wait_percent = 90; /* wait 90% of the real playing time */
+ int i;
+
+ if ((sound_device=open(sound_device_name,O_WRONLY))>=0)
+ {
+ playing_sounds = 1;
+
+ while(playing_sounds &&
+ select(sound_pipe[0]+1,&sound_fdset,NULL,NULL,&delay)<1)
+ {
+ FD_SET(sound_pipe[0], &sound_fdset);
+
+ /* get pointer and size of the actual sound sample */
+ sample_ptr = snd_ctrl.data_ptr+snd_ctrl.playingpos;
+ sample_size =
+ MIN(max_sample_size,snd_ctrl.data_len-snd_ctrl.playingpos);
+ snd_ctrl.playingpos += sample_size;
+
+ /* fill the first mixing buffer with original sample */
+ memcpy(premix_first_buffer,sample_ptr,sample_size);
+
+
+ /* adjust volume of actual sound sample */
+ if (snd_ctrl.volume != PSND_MAX_VOLUME)
+ for(i=0;i<sample_size;i++)
+ premix_first_buffer[i] =
+ (snd_ctrl.volume * (int)premix_first_buffer[i])
+ >> PSND_MAX_VOLUME_BITS;
+
+ for(i=0;i<sample_size;i++)
+ playing_buffer[i] =
+ linear_to_ulaw(((int)premix_first_buffer[i]) << 8);
+
+ if (snd_ctrl.playingpos >= snd_ctrl.data_len)
+ playing_sounds = 0;
+
+ /* finally play the sound fragment */
+ write(sound_device,playing_buffer,sample_size);
+
+ delay.tv_sec = 0;
+ delay.tv_usec = ((sample_size*10*wait_percent)/(sample_rate))*1000;
+ }
+ close(sound_device);
+ }
+ }
+
+#endif /* von '#ifdef VOXWARE' */
+
+ }
+}
+
+void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
+{
+ int i,k;
+
+ /* wenn voll, ältesten Sound 'rauswerfen */
+ if (playing_sounds==MAX_SOUNDS_PLAYING)
+ {
+ int longest=0, longest_nr=0;
+
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ {
+ int actual =
+ 100 * playlist[i].playingpos / playlist[i].data_len;
+
+ if (!playlist[i].loop && actual>longest)
+ {
+ longest=actual;
+ longest_nr=i;
+ }
+ }
+ playlist[longest_nr] = emptySoundControl;
+ playing_sounds--;
+ }
+
+ /* nachsehen, ob (und ggf. wie oft) Sound bereits gespielt wird */
+ for(k=0,i=0;i<MAX_SOUNDS_PLAYING;i++)
+ {
+ if (playlist[i].nr == snd_ctrl.nr)
+ k++;
+ }
+
+ /* falls Sound-Loop: nur neu beginnen, wenn Sound gerade ausklingt */
+ if (k>=1 && snd_ctrl.loop)
+ {
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ {
+ if (playlist[i].nr == snd_ctrl.nr && playlist[i].fade_sound)
+ {
+ playlist[i].fade_sound = FALSE;
+ playlist[i].volume = PSND_MAX_VOLUME;
+ }
+ }
+ return;
+ }
+
+ /* keinen Sound mehr als n mal gleichzeitig spielen (momentan n==2) */
+ if (k>=2)
+ {
+ int longest=0, longest_nr=0;
+
+ /* den bereits am längsten gespielten (gleichen) Sound suchen */
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ {
+ int actual;
+
+ if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
+ continue;
+
+ actual = 100 * playlist[i].playingpos / playlist[i].data_len;
+ if (actual>=longest)
+ {
+ longest=actual;
+ longest_nr=i;
+ }
+ }
+ playlist[longest_nr] = emptySoundControl;
+ playing_sounds--;
+ }
+
+ /* neuen Sound in Liste packen */
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ {
+ if (!playlist[i].active)
+ {
+ playlist[i] = snd_ctrl;
+ playing_sounds++;
+ break;
+ }
+ }
+}
+
+/*
+void SoundServer_FadeSound(int nr)
+{
+ int i;
+
+ if (!playing_sounds)
+ return;
+
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ if (snd_ctrl.stop_all_sounds || playlist[i].nr == snd_ctrl.nr)
+ playlist[i].fade_sound = TRUE;
+}
+*/
+
+void SoundServer_StopSound(int nr)
+{
+ int i;
+
+ if (!playing_sounds)
+ return;
+
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ if (playlist[i].nr == nr)
+ {
+ playlist[i] = emptySoundControl;
+ playing_sounds--;
+ }
+
+ if (!playing_sounds)
+ close(sound_device);
+}
+
+void SoundServer_StopAllSounds()
+{
+ int i;
+
+ for(i=0;i<MAX_SOUNDS_PLAYING;i++)
+ playlist[i]=emptySoundControl;
+ playing_sounds=0;
+
+ close(sound_device);
+}
+
+#ifdef HPUX_AUDIO
+void HPUX_Audio_Control()
+{
+ struct audio_describe ainfo;
+ int audio_ctl;
+
+ audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
+ if (audio_ctl == -1)
+ {
+ fprintf(stderr,"%s: cannot open /dev/audioCtl - no sounds\n",progname);
+ exit(0);
+ }
+
+ if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
+ {
+ fprintf(stderr,"%s: no audio info - no sounds\n",progname);
+ exit(0);
+ }
+
+ if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
+ {
+ fprintf(stderr,"%s: ulaw audio not available - no sounds\n",progname);
+ exit(0);
+ }
+
+ ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
+ ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
+
+ close(audio_ctl);
+}
+#endif /* HPUX_AUDIO */
+
+/* these two are stolen from "sox"... :) */
+
+/*
+** This routine converts from linear to ulaw.
+**
+** Craig Reese: IDA/Supercomputing Research Center
+** Joe Campbell: Department of Defense
+** 29 September 1989
+**
+** References:
+** 1) CCITT Recommendation G.711 (very difficult to follow)
+** 2) "A New Digital Technique for Implementation of Any
+** Continuous PCM Companding Law," Villeret, Michel,
+** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
+** 1973, pg. 11.12-11.17
+** 3) MIL-STD-188-113,"Interoperability and Performance Standards
+** for Analog-to_Digital Conversion Techniques,"
+** 17 February 1987
+**
+** Input: Signed 16 bit linear sample
+** Output: 8 bit ulaw sample
+*/
+
+#define ZEROTRAP /* turn on the trap as per the MIL-STD */
+#define BIAS 0x84 /* define the add-in bias for 16 bit samples */
+#define CLIP 32635
+
+unsigned char linear_to_ulaw(int sample)
+{
+ static int exp_lut[256] =
+ {
+ 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+ };
+
+ int sign, exponent, mantissa;
+ unsigned char ulawbyte;
+
+ /* Get the sample into sign-magnitude. */
+ sign = (sample >> 8) & 0x80; /* set aside the sign */
+ if (sign != 0)
+ sample = -sample; /* get magnitude */
+ if (sample > CLIP)
+ sample = CLIP; /* clip the magnitude */
+
+ /* Convert from 16 bit linear to ulaw. */
+ sample = sample + BIAS;
+ exponent = exp_lut[( sample >> 7 ) & 0xFF];
+ mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
+ ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
+#ifdef ZEROTRAP
+ if (ulawbyte == 0)
+ ulawbyte = 0x02; /* optional CCITT trap */
+#endif
+
+ return(ulawbyte);
+}
+
+/*
+** This routine converts from ulaw to 16 bit linear.
+**
+** Craig Reese: IDA/Supercomputing Research Center
+** 29 September 1989
+**
+** References:
+** 1) CCITT Recommendation G.711 (very difficult to follow)
+** 2) MIL-STD-188-113,"Interoperability and Performance Standards
+** for Analog-to_Digital Conversion Techniques,"
+** 17 February 1987
+**
+** Input: 8 bit ulaw sample
+** Output: signed 16 bit linear sample
+*/
+
+int ulaw_to_linear(unsigned char ulawbyte)
+{
+ static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
+ int sign, exponent, mantissa, sample;
+
+ ulawbyte = ~ ulawbyte;
+ sign = ( ulawbyte & 0x80 );
+ exponent = ( ulawbyte >> 4 ) & 0x07;
+ mantissa = ulawbyte & 0x0F;
+ sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
+ if (sign != 0)
+ sample = -sample;
+
+ return(sample);
+}
+
+/*** THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/
+
+/*===========================================================================*/
+
+/*** THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS ***/
+
+BOOL LoadSound(struct SoundInfo *snd_info)
+{
+ FILE *file;
+ char filename[256];
+ char *sound_ext = "8svx";
+ struct SoundHeader_8SVX *snd_hdr;
+ unsigned char *ptr;
+
+ sprintf(filename,"%s/%s.%s",SND_PATH,snd_info->name,sound_ext);
+
+ if (!(file=fopen(filename,"r")))
+ {
+ fprintf(stderr,"%s: cannot open sound file '%s' - no sounds\n",
+ progname,filename);
+ return(FALSE);
+ }
+
+ if (fseek(file,0,SEEK_END)<0)
+ {
+ fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
+ progname,filename);
+ fclose(file);
+ return(FALSE);
+ }
+
+ snd_info->file_len = ftell(file);
+ rewind(file);
+
+ if (!(snd_info->file_ptr=malloc(snd_info->file_len)))
+ {
+ fprintf(stderr,"%s: out of memory (this shouldn't happen :) - no sounds\n",
+ progname);
+ fclose(file);
+ return(FALSE);
+ }
+
+ if (fread(snd_info->file_ptr,1,snd_info->file_len,file)!=snd_info->file_len)
+ {
+ fprintf(stderr,"%s: cannot read sound file '%s' - no sounds\n",
+ progname,filename);
+ fclose(file);
+ return(FALSE);
+ }
+
+ fclose(file);
+
+ snd_hdr = (struct SoundHeader_8SVX *)snd_info->file_ptr;
+
+ if (strncmp(snd_hdr->magic_FORM,"FORM",4) ||
+ snd_info->file_len!=be2long(&snd_hdr->chunk_size)+8 ||
+ strncmp(snd_hdr->magic_8SVX,"8SVX",4))
+ {
+ fprintf(stderr,"%s: '%s' is not an IFF/8SVX file or broken- no sounds\n",
+ progname,filename);
+ return(FALSE);
+ }
+
+ ptr = (unsigned char *)snd_info->file_ptr;
+
+ while(ptr<(unsigned char *)snd_info->file_ptr+snd_info->file_len)
+ {
+ if (!strncmp(ptr,"VHDR",4))
+ {
+ ptr+=be2long((unsigned long *)(ptr+4));
+ }
+ if (!strncmp(ptr,"ANNO",4))
+ {
+ ptr+=be2long((unsigned long *)(ptr+4));
+ }
+ if (!strncmp(ptr,"CHAN",4))
+ {
+ ptr+=be2long((unsigned long *)(ptr+4));
+ }
+ if (!strncmp(ptr,"BODY",4))
+ {
+ snd_info->data_ptr = ptr+8;
+ snd_info->data_len = be2long((unsigned long *)(ptr+4));
+ return(TRUE);
+ }
+ ptr++;
+ }
+
+ return(FALSE);
+}
+
+void PlaySound(int nr)
+{
+ PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP);
+}
+
+void PlaySoundStereo(int nr, int stereo)
+{
+ PlaySoundExt(nr, PSND_MAX_VOLUME, stereo, PSND_NO_LOOP);
+}
+
+void PlaySoundLoop(int nr)
+{
+ PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_LOOP);
+}
+
+void PlaySoundExt(int nr, int volume, int stereo, BOOL loop)
+{
+ struct SoundControl snd_ctrl = emptySoundControl;
+
+ if (sound_status==SOUND_OFF || !sound_on)
+ return;
+
+ if (volume<PSND_MIN_VOLUME)
+ volume = PSND_MIN_VOLUME;
+ else if (volume>PSND_MAX_VOLUME)
+ volume = PSND_MAX_VOLUME;
+
+ if (stereo<PSND_MAX_LEFT)
+ stereo = PSND_MAX_LEFT;
+ else if (stereo>PSND_MAX_RIGHT)
+ stereo = PSND_MAX_RIGHT;
+
+ snd_ctrl.nr = nr;
+ snd_ctrl.volume = volume;
+ snd_ctrl.stereo = stereo;
+ snd_ctrl.loop = loop;
+ snd_ctrl.active = TRUE;
+ snd_ctrl.data_ptr = Sound[nr].data_ptr;
+ snd_ctrl.data_len = Sound[nr].data_len;
+
+ if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
+ {
+ fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
+ sound_status=SOUND_OFF;
+ return;
+ }
+}
+
+void FadeSound(int nr)
+{
+ StopSoundExt(nr, SSND_FADE_SOUND);
+}
+
+void FadeSounds()
+{
+ StopSoundExt(-1, SSND_FADE_ALL_SOUNDS);
+}
+
+void StopSound(int nr)
+{
+ StopSoundExt(nr, SSND_STOP_SOUND);
+}
+
+void StopSounds()
+{
+ StopSoundExt(-1, SSND_STOP_ALL_SOUNDS);
+}
+
+void StopSoundExt(int nr, int method)
+{
+ struct SoundControl snd_ctrl = emptySoundControl;
+
+ if (sound_status==SOUND_OFF)
+ return;
+
+ if (SSND_FADING(method))
+ snd_ctrl.fade_sound = TRUE;
+
+ if (SSND_ALL(method))
+ snd_ctrl.stop_all_sounds = TRUE;
+ else
+ {
+ snd_ctrl.nr = nr;
+ snd_ctrl.stop_sound = TRUE;
+ }
+
+ if (write(sound_pipe[1], &snd_ctrl, sizeof(snd_ctrl))<0)
+ {
+ fprintf(stderr,"%s: cannot pipe to child process - no sounds\n",progname);
+ sound_status=SOUND_OFF;
+ return;
+ }
+}
+
+void FreeSounds(int max)
+{
+ int i;
+
+ if (sound_status==SOUND_OFF)
+ return;
+
+ for(i=0;i<max;i++)
+ free(Sound[i].file_ptr);
+}
+
+/*** THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS ***/
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* sound.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#ifndef SOUND_H
+#define SOUND_H
+
+#include "main.h"
+#include <math.h>
+
+#ifdef linux
+#include <linux/soundcard.h>
+#ifndef VOXWARE
+#define VOXWARE
+#endif
+/* where is the right declaration for 'ioctl'? */
+extern void ioctl(long, long, void *);
+#endif
+
+#define SND_BLOCKSIZE 4096
+
+#ifdef _HPUX_SOURCE
+#include <sys/audio.h>
+#undef SND_BLOCKSIZE
+#define SND_BLOCKSIZE 32768
+#define HPUX_AUDIO
+#endif /* _HPUX_SOURCE */
+
+#define MAX_SOUNDS_PLAYING 16
+
+/* some values for PlaySound(), StopSound() and friends */
+#define PSND_SILENCE 0
+#define PSND_MAX_VOLUME_BITS 7
+#define PSND_MIN_VOLUME 0
+#define PSND_MAX_VOLUME (1 << PSND_MAX_VOLUME_BITS)
+#define PSND_NO_LOOP 0
+#define PSND_LOOP 1
+#define PSND_MIDDLE 0
+#define PSND_MAX_STEREO_BITS 7
+#define PSND_MAX_STEREO (1 << PSND_MAX_STEREO_BITS)
+#define PSND_MAX_LEFT (-PSND_MAX_STEREO)
+#define PSND_MAX_RIGHT (+PSND_MAX_STEREO)
+#define PSND_MAX_LEFT2RIGHT_BITS (PSND_MAX_STEREO_BITS+1)
+#define PSND_MAX_LEFT2RIGHT (1 << PSND_MAX_LEFT2RIGHT_BITS)
+
+#define SSND_FADE_SOUND (1<<0)
+#define SSND_FADE_ALL_SOUNDS (1<<1)
+#define SSND_FADING(x) (x & (SSND_FADE_SOUND | SSND_FADE_ALL_SOUNDS))
+#define SSND_STOP_SOUND (1<<2)
+#define SSND_STOP_ALL_SOUNDS (1<<3)
+#define SSND_STOPPING(x) (x & (SSND_STOP_SOUND | SSND_STOP_ALL_SOUNDS))
+#define SSND_ALL(x) (x&(SSND_FADE_ALL_SOUNDS|SSND_STOP_ALL_SOUNDS))
+
+#define TRUE 1
+#define FALSE 0
+
+/* settings for sound path, sound device, etc. */
+#ifndef SND_PATH
+#define SND_PATH "./sounds"
+#endif
+
+#define DEV_AUDIO "/dev/audio"
+#define DEV_DSP "/dev/dsp"
+
+#ifdef VOXWARE
+#define SOUND_DEVICE DEV_DSP
+#else
+#define SOUND_DEVICE DEV_AUDIO
+#endif
+
+#define SOUND_OFF 0
+#define SOUND_AVAILABLE 1
+
+#ifdef NO_SOUNDS
+#define SOUND_STATUS SOUND_OFF
+#else
+#define SOUND_STATUS SOUND_AVAILABLE
+#endif
+
+struct SoundHeader_SUN
+{
+ unsigned long magic;
+ unsigned long hdr_size;
+ unsigned long data_size;
+ unsigned long encoding;
+ unsigned long sample_rate;
+ unsigned long channels;
+};
+
+struct SoundHeader_8SVX
+{
+ char magic_FORM[4];
+ unsigned long chunk_size;
+ char magic_8SVX[4];
+};
+
+struct SoundInfo
+{
+ char *name;
+ char *file_ptr, *data_ptr;
+ long file_len, data_len;
+};
+
+struct SoundControl
+{
+ int nr;
+ int volume;
+ int stereo;
+ BOOL active;
+ BOOL loop;
+ BOOL fade_sound;
+ BOOL stop_sound;
+ BOOL stop_all_sounds;
+ int playingtime;
+ long playingpos;
+ long data_len;
+ char *data_ptr;
+};
+
+/* function from "misc.c" */
+unsigned long be2long(unsigned long *);
+
+/* sound server functions */
+void SoundServer(void);
+void SoundServer_InsertNewSound(struct SoundControl);
+void SoundServer_StopSound(int);
+void SoundServer_StopAllSounds(void);
+void HPUX_Audio_Control(void);
+unsigned char linear_to_ulaw(int);
+int ulaw_to_linear(unsigned char);
+
+/* application functions */
+BOOL LoadSound(struct SoundInfo *);
+void PlaySound(int);
+void PlaySoundStereo(int, int);
+void PlaySoundLoop(int);
+void PlaySoundExt(int, int, int, BOOL);
+void FadeSound(int);
+void FadeSounds(void);
+void StopSound(int);
+void StopSounds(void);
+void StopSoundExt(int, int);
+void FreeSounds(int);
+
+#endif
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* tools.c *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#include "tools.h"
+#include "game.h"
+#include "events.h"
+#include "sound.h"
+#include "screens.h"
+#include "misc.h"
+
+void BackToFront()
+{
+ int x,y;
+
+ if (direct_draw_on && game_status==PLAYING)
+ redraw_mask &= ~REDRAW_MAIN;
+
+ if (!redraw_mask)
+ return;
+
+ if (redraw_mask & REDRAW_ALL ||
+ (redraw_mask & REDRAW_FIELD && redraw_mask & REDRAW_DOORS))
+ {
+ XCopyArea(display,backbuffer,window,gc,
+ 0,0, WIN_XSIZE,WIN_YSIZE,
+ 0,0);
+ redraw_mask = 0;
+ }
+ else if (redraw_mask & REDRAW_FIELD)
+ {
+ XCopyArea(display,backbuffer,window,gc,
+ REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE,
+ REAL_SX,REAL_SY);
+ redraw_mask &= ~REDRAW_MAIN;
+ }
+ else if (redraw_mask & REDRAW_DOORS)
+ {
+ if (redraw_mask & REDRAW_DOOR_1)
+ XCopyArea(display,backbuffer,window,gc,
+ DX,DY, DXSIZE,DYSIZE, DX,DY);
+ if (redraw_mask & REDRAW_DOOR_2)
+ {
+ if ((redraw_mask & REDRAW_DOOR_2) == REDRAW_DOOR_2)
+ XCopyArea(display,backbuffer,window,gc,
+ VX,VY, VXSIZE,VYSIZE, VX,VY);
+ else
+ {
+ if (redraw_mask & REDRAW_VIDEO_1)
+ XCopyArea(display,backbuffer,window,gc,
+ VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS,
+ VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
+ VX+VIDEO_DISPLAY1_XPOS,VY+VIDEO_DISPLAY1_YPOS);
+ if (redraw_mask & REDRAW_VIDEO_2)
+ XCopyArea(display,backbuffer,window,gc,
+ VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS,
+ VIDEO_DISPLAY_XSIZE,VIDEO_DISPLAY_YSIZE,
+ VX+VIDEO_DISPLAY2_XPOS,VY+VIDEO_DISPLAY2_YPOS);
+ if (redraw_mask & REDRAW_VIDEO_3)
+ XCopyArea(display,backbuffer,window,gc,
+ VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS,
+ VIDEO_CONTROL_XSIZE,VIDEO_CONTROL_YSIZE,
+ VX+VIDEO_CONTROL_XPOS,VY+VIDEO_CONTROL_YPOS);
+ }
+ }
+ redraw_mask &= ~REDRAW_DOORS;
+ }
+
+ if (redraw_mask & REDRAW_MICROLEV)
+ {
+ XCopyArea(display,backbuffer,window,gc,
+ MICROLEV_XPOS,MICROLEV_YPOS, MICROLEV_XSIZE,MICROLEV_YSIZE,
+ MICROLEV_XPOS,MICROLEV_YPOS);
+ XCopyArea(display,backbuffer,window,gc,
+ SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE,
+ SX,MICROLABEL_YPOS);
+ redraw_mask &= ~REDRAW_MICROLEV;
+ }
+
+ if (redraw_mask & REDRAW_TILES)
+ {
+ if (redraw_tiles>REDRAWTILES_TH)
+ XCopyArea(display,backbuffer,window,gc,SX,SY,SXSIZE,SYSIZE,SX,SY);
+ else
+ for(x=0;x<SCR_FIELDX;x++)
+ for(y=0;y<SCR_FIELDY;y++)
+ if (redraw[x][y])
+ XCopyArea(display,backbuffer,window,gc,
+ SX+x*TILEX,SY+y*TILEY,TILEX,TILEY,SX+x*TILEX,SY+y*TILEY);
+ }
+
+ XFlush(display);
+
+ for(x=0;x<SCR_FIELDX;x++)
+ for(y=0;y<SCR_FIELDY;y++)
+ redraw[x][y]=0;
+ redraw_tiles=0;
+ redraw_mask=0;
+}
+
+void FadeToFront()
+{
+ long fading_delay = 300000;
+
+ if (fading_on && (redraw_mask & REDRAW_FIELD))
+ {
+ XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,0);
+ XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
+ REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
+ XFlush(display);
+ Delay(fading_delay);
+
+ XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,-1);
+ XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
+ REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
+ XFlush(display);
+ Delay(fading_delay);
+
+ XSetClipOrigin(display,clip_gc[PIX_FADEMASK],0,-1);
+ XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
+ REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
+ XFlush(display);
+ Delay(fading_delay);
+
+ XSetClipOrigin(display,clip_gc[PIX_FADEMASK],-1,0);
+ XCopyArea(display,backbuffer,window,clip_gc[PIX_FADEMASK],
+ REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, REAL_SX,REAL_SY);
+ XFlush(display);
+ Delay(fading_delay);
+
+ redraw_mask &= ~REDRAW_MAIN;
+ }
+
+ BackToFront();
+}
+
+void ClearWindow()
+{
+ drawto_field = backbuffer;
+ XFillRectangle(display,drawto_field,gc,
+ REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
+ redraw_mask|=REDRAW_FIELD;
+
+ if (game_status==PLAYING && direct_draw_on)
+ {
+ drawto_field = window;
+ XFillRectangle(display,drawto_field,gc,
+ REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE);
+ }
+}
+
+void DrawText(int x, int y, char *text, int font, int col)
+{
+ DrawTextExt(drawto, gc, x, y, text, font, col);
+ if (x<DX)
+ redraw_mask|=REDRAW_FIELD;
+ else if (y<VY)
+ redraw_mask|=REDRAW_DOOR_1;
+}
+
+void DrawTextExt(Drawable d, GC gc, int x, int y,
+ char *text, int font, int font_color)
+{
+ int font_width, font_height, font_start;
+ int font_pixmap;
+
+ if (font!=FS_SMALL && font!=FS_BIG)
+ font = FS_SMALL;
+ if (font_color<FC_RED || font_color>FC_SPECIAL2)
+ font_color = FC_RED;
+
+ font_width =
+ (font==FS_BIG ? FONT1_XSIZE :
+ font_color<FC_SPECIAL1 ? FONT2_XSIZE :
+ font_color<FC_SPECIAL2 ? FONT3_XSIZE : FONT4_XSIZE);
+ font_height =
+ (font==FS_BIG ? FONT1_XSIZE :
+ font_color<FC_SPECIAL2 ? FONT2_XSIZE: FONT4_XSIZE);
+ font_pixmap = (font==FS_BIG ? PIX_BIGFONT : PIX_SMALLFONT);
+ font_start =
+ font_color*(font==FS_BIG ? FONT1_YSIZE : FONT2_YSIZE)*FONT_LINES_PER_FONT;
+
+ while(*text)
+ {
+ char c = *text++;
+
+ if (c>='a' && c<='z')
+ c = 'A' + (c - 'a');
+ else if (c=='ä' || c=='Ä')
+ c = 91;
+ else if (c=='ö' || c=='Ö')
+ c = 92;
+ else if (c=='ü' || c=='Ü')
+ c = 93;
+
+ if (c>=32 && c<=95)
+ XCopyArea(display,pix[font_pixmap],d,gc,
+ ((c-32) % FONT_CHARS_PER_LINE)*font_width,
+ ((c-32) / FONT_CHARS_PER_LINE)*font_height + font_start,
+ font_width,font_height, x,y);
+
+ x += font_width;
+ }
+}
+
+void DrawGraphic(int x, int y, int graphic)
+{
+ DrawGraphicExt(drawto_field, gc, x, y, graphic);
+ redraw_tiles++;
+ redraw[x][y] = TRUE;
+ redraw_mask |= REDRAW_TILES;
+}
+
+void DrawGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
+{
+ DrawGraphicExtHiRes(d, gc, SX+x*TILEX, SY+y*TILEY, graphic);
+}
+
+void DrawGraphicExtHiRes(Drawable d, GC gc, int x, int y, int graphic)
+{
+ if (graphic<0)
+ XFillRectangle(display,d,gc, x,y, TILEX,TILEY);
+ else if (graphic<256)
+ XCopyArea(display,pix[PIX_BACK],d,gc,
+ SX+(graphic % GFX_PER_LINE)*TILEX,
+ SY+(graphic / GFX_PER_LINE)*TILEY,
+ TILEX,TILEY, x,y);
+ else
+ {
+ graphic -= 256;
+ XCopyArea(display,pix[PIX_BIGFONT],d,gc,
+ (graphic % FONT_CHARS_PER_LINE)*TILEX,
+ (graphic / FONT_CHARS_PER_LINE)*TILEY +
+ FC_SPECIAL1*TILEY*FONT_LINES_PER_FONT,
+ TILEX,TILEY, x,y);
+ }
+}
+
+void DrawGraphicThruMask(int x, int y, int graphic)
+{
+ int src_x,src_y, dest_x,dest_y;
+
+ if (graphic<0 || graphic>255)
+ {
+ DrawGraphic(x,y,graphic);
+ return;
+ }
+
+ src_x = SX+(graphic % GFX_PER_LINE)*TILEX;
+ src_y = SY+(graphic / GFX_PER_LINE)*TILEY;
+ dest_x = SX+x*TILEX;
+ dest_y = SY+y*TILEY;
+
+ XSetClipOrigin(display,clip_gc[PIX_BACK],dest_x-src_x,dest_y-src_y);
+ XCopyArea(display,pix[PIX_BACK],drawto_field,clip_gc[PIX_BACK], src_x,src_y,
+ TILEX,TILEY, dest_x,dest_y);
+
+ redraw_tiles++;
+ redraw[x][y]=TRUE;
+ redraw_mask|=REDRAW_TILES;
+}
+
+void DrawElementThruMask(int x, int y, int element)
+{
+ DrawGraphicThruMask(x,y,el2gfx(element));
+}
+
+void DrawMiniGraphic(int x, int y, int graphic)
+{
+ DrawMiniGraphicExt(drawto, gc, x, y, graphic);
+ redraw_tiles++;
+ redraw[x/2][y/2]=TRUE;
+ redraw_mask|=REDRAW_TILES;
+}
+
+void DrawMiniGraphicExt(Drawable d, GC gc, int x, int y, int graphic)
+{
+ DrawMiniGraphicExtHiRes(d,gc, SX+x*MINI_TILEX,SY+y*MINI_TILEY, graphic);
+}
+
+void DrawMiniGraphicExtHiRes(Drawable d, GC gc, int x, int y, int graphic)
+{
+ if (graphic<0)
+ XFillRectangle(display,d,gc, x,y, MINI_TILEX,MINI_TILEY);
+ else if (graphic<256)
+ XCopyArea(display,pix[PIX_BACK],d,gc,
+ MINI_GFX_STARTX+(graphic % MINI_GFX_PER_LINE)*MINI_TILEX,
+ MINI_GFX_STARTY+(graphic / MINI_GFX_PER_LINE)*MINI_TILEY,
+ MINI_TILEX,MINI_TILEY, x,y);
+ else
+ {
+ graphic -= 256;
+ XCopyArea(display,pix[PIX_SMALLFONT],d,gc,
+ (graphic % FONT_CHARS_PER_LINE)*FONT4_XSIZE,
+ (graphic / FONT_CHARS_PER_LINE)*FONT4_YSIZE +
+ FC_SPECIAL2*FONT2_YSIZE*FONT_LINES_PER_FONT,
+ MINI_TILEX,MINI_TILEY, x,y);
+ }
+}
+
+int el2gfx(int element)
+{
+ switch(element)
+ {
+ case EL_LEERRAUM: return(-1);
+ case EL_ERDREICH: return(GFX_ERDREICH);
+ case EL_MAUERWERK: return(GFX_MAUERWERK);
+ case EL_FELSBODEN: return(GFX_FELSBODEN);
+ case EL_FELSBROCKEN: return(GFX_FELSBROCKEN);
+ case EL_SCHLUESSEL: return(GFX_SCHLUESSEL);
+ case EL_EDELSTEIN: return(GFX_EDELSTEIN);
+ case EL_AUSGANG_ZU: return(GFX_AUSGANG_ZU);
+ case EL_AUSGANG_ACT: return(GFX_AUSGANG_ACT);
+ case EL_AUSGANG_AUF: return(GFX_AUSGANG_AUF);
+ case EL_SPIELFIGUR: return(GFX_SPIELFIGUR);
+ case EL_SPIELER1: return(GFX_SPIELER1);
+ case EL_SPIELER2: return(GFX_SPIELER2);
+ case EL_SPIELER3: return(GFX_SPIELER3);
+ case EL_SPIELER4: return(GFX_SPIELER4);
+ case EL_KAEFER: return(GFX_KAEFER);
+ case EL_KAEFER_R: return(GFX_KAEFER_R);
+ case EL_KAEFER_O: return(GFX_KAEFER_O);
+ case EL_KAEFER_L: return(GFX_KAEFER_L);
+ case EL_KAEFER_U: return(GFX_KAEFER_U);
+ case EL_FLIEGER: return(GFX_FLIEGER);
+ case EL_FLIEGER_R: return(GFX_FLIEGER_R);
+ case EL_FLIEGER_O: return(GFX_FLIEGER_O);
+ case EL_FLIEGER_L: return(GFX_FLIEGER_L);
+ case EL_FLIEGER_U: return(GFX_FLIEGER_U);
+ case EL_MAMPFER: return(GFX_MAMPFER);
+ case EL_ZOMBIE: return(GFX_ZOMBIE);
+ case EL_BETON: return(GFX_BETON);
+ case EL_DIAMANT: return(GFX_DIAMANT);
+ case EL_MORAST_LEER: return(GFX_MORAST_LEER);
+ case EL_MORAST_VOLL: return(GFX_MORAST_VOLL);
+ case EL_TROPFEN: return(GFX_TROPFEN);
+ case EL_BOMBE: return(GFX_BOMBE);
+ case EL_SIEB_LEER: return(GFX_SIEB_LEER);
+ case EL_SIEB_VOLL: return(GFX_SIEB_VOLL);
+ case EL_SIEB_TOT: return(GFX_SIEB_TOT);
+ case EL_SALZSAEURE: return(GFX_SALZSAEURE);
+ case EL_AMOEBE1: return(GFX_AMOEBE1);
+ case EL_AMOEBE2: return(GFX_AMOEBE2);
+ case EL_AMOEBE3: return(GFX_AMOEBE3);
+ case EL_KOKOSNUSS: return(GFX_KOKOSNUSS);
+ case EL_LIFE: return(GFX_LIFE);
+ case EL_LIFE_ASYNC: return(GFX_LIFE_ASYNC);
+ case EL_DYNAMIT: return(GFX_DYNAMIT);
+ case EL_BADEWANNE: return(GFX_BADEWANNE);
+ case EL_BADEWANNE1: return(GFX_BADEWANNE1);
+ case EL_BADEWANNE2: return(GFX_BADEWANNE2);
+ case EL_BADEWANNE3: return(GFX_BADEWANNE3);
+ case EL_BADEWANNE4: return(GFX_BADEWANNE4);
+ case EL_BADEWANNE5: return(GFX_BADEWANNE5);
+ case EL_ABLENK_AUS: return(GFX_ABLENK_AUS);
+ case EL_ABLENK_EIN: return(GFX_ABLENK_EIN);
+ case EL_SCHLUESSEL1: return(GFX_SCHLUESSEL1);
+ case EL_SCHLUESSEL2: return(GFX_SCHLUESSEL2);
+ case EL_SCHLUESSEL3: return(GFX_SCHLUESSEL3);
+ case EL_SCHLUESSEL4: return(GFX_SCHLUESSEL4);
+ case EL_PFORTE1: return(GFX_PFORTE1);
+ case EL_PFORTE2: return(GFX_PFORTE2);
+ case EL_PFORTE3: return(GFX_PFORTE3);
+ case EL_PFORTE4: return(GFX_PFORTE4);
+ case EL_PFORTE1X: return(GFX_PFORTE1X);
+ case EL_PFORTE2X: return(GFX_PFORTE2X);
+ case EL_PFORTE3X: return(GFX_PFORTE3X);
+ case EL_PFORTE4X: return(GFX_PFORTE4X);
+ case EL_DYNAMIT_AUS: return(GFX_DYNAMIT_AUS);
+ case EL_PACMAN: return(GFX_PACMAN);
+ case EL_PACMAN_R: return(GFX_PACMAN_R);
+ case EL_PACMAN_O: return(GFX_PACMAN_O);
+ case EL_PACMAN_L: return(GFX_PACMAN_L);
+ case EL_PACMAN_U: return(GFX_PACMAN_U);
+ case EL_UNSICHTBAR: return(GFX_UNSICHTBAR);
+ case EL_ERZ_1: return(GFX_ERZ_1);
+ case EL_ERZ_2: return(GFX_ERZ_2);
+ case EL_BIRNE_AUS: return(GFX_BIRNE_AUS);
+ case EL_BIRNE_EIN: return(GFX_BIRNE_EIN);
+ default:
+ {
+ if (IS_CHAR(element))
+ return(GFX_CHAR_START + (element-EL_CHAR_START));
+ else
+ return(-1);
+ }
+ }
+}
+
+void DrawGraphicShifted(int x,int y, int dx,int dy, int graphic, int cut_mode)
+{
+ int width = TILEX, height = TILEY;
+ int cx = 0, cy = 0;
+
+ if (graphic<0)
+ {
+ DrawGraphic(x,y,graphic);
+ return;
+ }
+
+ if (dx || dy) /* Verschiebung der Grafik? */
+ {
+ if (x<0) /* Element kommt von links ins Bild */
+ {
+ x=0;
+ width=dx;
+ cx=TILEX-dx;
+ dx=0;
+ }
+ else if (x==SCR_FIELDX) /* Element kommt von rechts ins Bild */
+ {
+ x=SCR_FIELDX-1;
+ width=-dx;
+ dx=TILEX+dx;
+ }
+ else if (x==0 && dx<0) /* Element verläßt links das Bild */
+ {
+ width+=dx;
+ cx=-dx;
+ dx=0;
+ }
+ else if (x==SCR_FIELDX-1 && dx>0) /* El. verläßt rechts das Bild */
+ width-=dx;
+ else if (dx) /* allg. Bewegung in x-Richtung */
+ redraw[x+SIGN(dx)][y]=TRUE;
+
+ if (y<0) /* Element kommt von oben ins Bild */
+ {
+ if (cut_mode==CUT_BELOW) /* Element oberhalb des Bildes */
+ return;
+
+ y=0;
+ height=dy;
+ cy=TILEY-dy;
+ dy=0;
+ }
+ else if (y==SCR_FIELDY) /* Element kommt von unten ins Bild */
+ {
+ y=SCR_FIELDY-1;
+ height=-dy;
+ dy=TILEY+dy;
+ }
+ else if (y==0 && dy<0) /* Element verläßt oben das Bild */
+ {
+ height+=dy;
+ cy=-dy;
+ dy=0;
+ }
+ else if (dy>0 && cut_mode==CUT_ABOVE)
+ {
+ if (y==SCR_FIELDY-1) /* Element unterhalb des Bildes */
+ return;
+
+ height=dy;
+ cy=TILEY-dy;
+ dy=TILEY;
+ redraw[x][y+1]=TRUE;
+ } /* Element verläßt unten das Bild */
+ else if (dy>0 && (y==SCR_FIELDY-1 || cut_mode==CUT_BELOW))
+ height-=dy;
+ else if (dy) /* allg. Bewegung in y-Richtung */
+ redraw[x][y+SIGN(dy)]=TRUE;
+ }
+
+ XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
+ SX+(graphic % GFX_PER_LINE)*TILEX+cx,
+ SY+(graphic / GFX_PER_LINE)*TILEY+cy,
+ width,height, SX+x*TILEX+dx,SY+y*TILEY+dy);
+
+ redraw_tiles++;
+ redraw[x][y]=TRUE;
+ redraw_mask|=REDRAW_TILES;
+}
+
+void DrawElementShifted(int x, int y, int dx, int dy, int element,int cut_mode)
+{
+ int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
+ int graphic = el2gfx(element);
+ int phase = ABS(MovPos[ux][uy])/(TILEX/2);
+ int dir = MovDir[ux][uy];
+ int horiz_move = (dir==MV_LEFT || dir==MV_RIGHT);
+
+ if (element==EL_PACMAN ||
+ element==EL_KAEFER ||
+ element==EL_FLIEGER)
+ {
+ if (element==EL_PACMAN)
+ graphic = GFX_PACMAN + 4*!phase;
+ else
+ graphic += 4*!phase;
+
+ if (dir==MV_UP)
+ graphic += 1;
+ else if (dir==MV_LEFT)
+ graphic += 2;
+ else if (dir==MV_DOWN)
+ graphic += 3;
+ }
+ else if ((element==EL_FELSBROCKEN ||
+ element==EL_EDELSTEIN ||
+ element==EL_DIAMANT) && horiz_move && phase)
+ {
+ if (element==EL_FELSBROCKEN)
+ graphic += 2;
+ else
+ graphic += 1;
+ }
+ else if ((element==EL_SIEB_LEER ||
+ element==EL_SIEB_VOLL) && SiebAktiv)
+ {
+ graphic += 3-(SiebAktiv%8)/2;
+ }
+ else if (IS_AMOEBOID(element))
+ {
+ graphic = (element==EL_AMOEBE1 ? GFX_AMOEBE_TOT : GFX_AMOEBE_LEBT);
+ graphic += (x+2*y) % 4;
+ }
+
+ if (dx || dy)
+ DrawGraphicShifted(x,y, dx,dy, graphic, cut_mode);
+ else
+ DrawGraphic(x,y, graphic);
+}
+
+void ErdreichAnbroeckeln(int x, int y)
+{
+ int i, width, height, cx,cy;
+ int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
+ int element, graphic;
+ int snip = 4;
+ static int xy[4][2] =
+ {
+ 0,-1,
+ -1,0,
+ +1,0,
+ 0,+1
+ };
+
+ if (!IN_LEV_FIELD(ux,uy))
+ return;
+
+ element = Feld[ux][uy];
+
+ if (element==EL_ERDREICH)
+ {
+ if (!IN_SCR_FIELD(x,y))
+ return;
+
+ graphic = GFX_ERDENRAND;
+
+ for(i=0;i<4;i++)
+ {
+ int uxx,uyy;
+
+ uxx = ux+xy[i][0];
+ uyy = uy+xy[i][1];
+ if (!IN_LEV_FIELD(uxx,uyy))
+ element = EL_BETON;
+ else
+ element = Feld[uxx][uyy];
+
+/*
+ if (element==EL_ERDREICH || IS_SOLID(element))
+ continue;
+*/
+ if (element==EL_ERDREICH)
+ continue;
+
+ if (i==1 || i==2)
+ {
+ width = snip;
+ height = TILEY;
+ cx = (i==2 ? TILEX-snip : 0);
+ cy = 0;
+ }
+ else
+ {
+ width = TILEX;
+ height = snip;
+ cx = 0;
+ cy = (i==3 ? TILEY-snip : 0);
+ }
+
+ XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
+ SX+(graphic % GFX_PER_LINE)*TILEX+cx,
+ SY+(graphic / GFX_PER_LINE)*TILEY+cy,
+ width,height, SX+x*TILEX+cx,SY+y*TILEY+cy);
+ }
+
+ redraw_tiles++;
+ redraw[x][y]=TRUE;
+ }
+ else
+ {
+ graphic = GFX_ERDENRAND;
+
+ for(i=0;i<4;i++)
+ {
+ int xx,yy,uxx,uyy;
+
+ xx = x+xy[i][0];
+ yy = y+xy[i][1];
+ uxx = ux+xy[i][0];
+ uyy = uy+xy[i][1];
+/*
+ if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
+ !IN_SCR_FIELD(xx,yy) || IS_SOLID(element))
+ continue;
+*/
+
+ if (!IN_LEV_FIELD(uxx,uyy) || Feld[uxx][uyy]!=EL_ERDREICH ||
+ !IN_SCR_FIELD(xx,yy))
+ continue;
+
+ if (i==1 || i==2)
+ {
+ width = snip;
+ height = TILEY;
+ cx = (i==1 ? TILEX-snip : 0);
+ cy = 0;
+ }
+ else
+ {
+ width = TILEX;
+ height = snip;
+ cx = 0;
+ cy = (i==0 ? TILEY-snip : 0);
+ }
+
+ XCopyArea(display,pix[PIX_BACK],drawto_field,gc,
+ SX+(graphic % GFX_PER_LINE)*TILEX+cx,
+ SY+(graphic / GFX_PER_LINE)*TILEY+cy,
+ width,height, SX+xx*TILEX+cx,SY+yy*TILEY+cy);
+
+ redraw_tiles++;
+ redraw[xx][yy]=TRUE;
+ }
+ }
+}
+
+void DrawScreenElement(int x, int y, int element)
+{
+ DrawElementShifted(x,y,0,0,element,CUT_NO_CUTTING);
+ ErdreichAnbroeckeln(x,y);
+}
+
+void DrawLevelElement(int x, int y, int element)
+{
+ if (IN_LEV_FIELD(x,y) && IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ DrawScreenElement(SCROLLX(x),SCROLLY(y),element);
+}
+
+void DrawScreenField(int x, int y)
+{
+ int ux = UNSCROLLX(x), uy = UNSCROLLY(y);
+ int element;
+
+ if (!IN_LEV_FIELD(ux,uy))
+ {
+ DrawScreenElement(x,y,EL_BETON);
+ return;
+ }
+
+ element = Feld[ux][uy];
+
+ if (IS_MOVING(ux,uy))
+ {
+ int horiz_move = (MovDir[ux][uy]==MV_LEFT || MovDir[ux][uy]==MV_RIGHT);
+ BOOL cut_mode = CUT_NO_CUTTING;
+
+ if (Store[ux][uy]==EL_MORAST_LEER ||
+ Store[ux][uy]==EL_SIEB_LEER ||
+ Store[ux][uy]==EL_AMOEBE2)
+ cut_mode = CUT_ABOVE;
+ else if (Store[ux][uy]==EL_MORAST_VOLL ||
+ Store[ux][uy]==EL_SIEB_VOLL ||
+ Store[ux][uy]==EL_SALZSAEURE)
+ cut_mode = CUT_BELOW;
+
+ if (cut_mode==CUT_ABOVE)
+ DrawElementShifted(x,y,0,0,Store[ux][uy],CUT_NO_CUTTING);
+ else
+ DrawScreenElement(x,y,EL_LEERRAUM);
+
+ if (horiz_move)
+ DrawElementShifted(x,y,MovPos[ux][uy],0,element,CUT_NO_CUTTING);
+ else
+ DrawElementShifted(x,y,0,MovPos[ux][uy],element,cut_mode);
+ }
+ else if (IS_BLOCKED(ux,uy))
+ {
+ int oldx,oldy;
+ int sx, sy;
+ int horiz_move;
+ BOOL cut_mode = CUT_NO_CUTTING;
+
+ Blocked2Moving(ux,uy,&oldx,&oldy);
+ sx = SCROLLX(oldx);
+ sy = SCROLLY(oldy);
+ horiz_move = (MovDir[oldx][oldy]==MV_LEFT || MovDir[oldx][oldy]==MV_RIGHT);
+
+ if (Store[oldx][oldy]==EL_MORAST_LEER ||
+ Store[oldx][oldy]==EL_SIEB_LEER ||
+ Store[oldx][oldy]==EL_AMOEBE2)
+ cut_mode = CUT_ABOVE;
+
+ DrawScreenElement(x,y,EL_LEERRAUM);
+ element = Feld[oldx][oldy];
+
+ if (horiz_move)
+ DrawElementShifted(sx,sy,MovPos[oldx][oldy],0,element,CUT_NO_CUTTING);
+ else
+ DrawElementShifted(sx,sy,0,MovPos[oldx][oldy],element,cut_mode);
+ }
+ else if (IS_DRAWABLE(element))
+ DrawScreenElement(x,y,element);
+ else
+ DrawScreenElement(x,y,EL_LEERRAUM);
+}
+
+void DrawLevelField(int x, int y)
+{
+ if (IN_SCR_FIELD(SCROLLX(x),SCROLLY(y)))
+ DrawScreenField(SCROLLX(x),SCROLLY(y));
+ else if (IS_MOVING(x,y))
+ {
+ int newx,newy;
+
+ Moving2Blocked(x,y,&newx,&newy);
+ if (IN_SCR_FIELD(SCROLLX(newx),SCROLLY(newy)))
+ DrawScreenField(SCROLLX(newx),SCROLLY(newy));
+ }
+ else if (IS_BLOCKED(x,y))
+ {
+ int oldx,oldy;
+
+ Blocked2Moving(x,y,&oldx,&oldy);
+ if (IN_SCR_FIELD(SCROLLX(oldx),SCROLLY(oldy)))
+ DrawScreenField(SCROLLX(oldx),SCROLLY(oldy));
+ }
+}
+
+void DrawMiniElement(int x, int y, int element)
+{
+ int graphic;
+
+ if (!element)
+ {
+ DrawMiniGraphic(x,y,-1);
+ return;
+ }
+
+ graphic = el2gfx(element);
+ DrawMiniGraphic(x,y,graphic);
+
+ redraw_tiles++;
+ redraw[x/2][y/2]=TRUE;
+ redraw_mask|=REDRAW_TILES;
+}
+
+void DrawMiniElementOrWall(int x, int y, int scroll_x, int scroll_y)
+{
+ if (x+scroll_x<-1 || x+scroll_x>lev_fieldx ||
+ y+scroll_y<-1 || y+scroll_y>lev_fieldy)
+ DrawMiniElement(x,y,EL_LEERRAUM);
+ else if (x+scroll_x==-1 || x+scroll_x==lev_fieldx ||
+ y+scroll_y==-1 || y+scroll_y==lev_fieldy)
+ DrawMiniElement(x,y,EL_BETON);
+ else
+ DrawMiniElement(x,y,Feld[x+scroll_x][y+scroll_y]);
+}
+
+void DrawMicroElement(int xpos, int ypos, int element)
+{
+ int graphic;
+
+ if (element==EL_LEERRAUM)
+ return;
+
+ graphic = el2gfx(element);
+
+ XCopyArea(display,pix[PIX_BACK],drawto,gc,
+ MICRO_GFX_STARTX+(graphic % MICRO_GFX_PER_LINE)*MICRO_TILEX,
+ MICRO_GFX_STARTY+(graphic / MICRO_GFX_PER_LINE)*MICRO_TILEY,
+ MICRO_TILEX,MICRO_TILEY, xpos,ypos);
+}
+
+void DrawLevel()
+{
+ int x,y;
+
+ ClearWindow();
+
+ for(x=0;x<SCR_FIELDX;x++)
+ for(y=0;y<SCR_FIELDY;y++)
+ DrawScreenField(x,y);
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
+void DrawMiniLevel(int scroll_x, int scroll_y)
+{
+ int x,y;
+
+ ClearWindow();
+
+ for(x=0;x<2*SCR_FIELDX;x++)
+ for(y=0;y<2*SCR_FIELDY;y++)
+ DrawMiniElementOrWall(x,y,scroll_x,scroll_y);
+
+ redraw_mask |= REDRAW_FIELD;
+}
+
+void DrawMicroLevel(int xpos, int ypos)
+{
+ int x,y;
+
+ XFillRectangle(display,drawto,gc,
+ xpos-MICRO_TILEX,ypos-MICRO_TILEY,
+ MICRO_TILEX*(STD_LEV_FIELDX+2),
+ MICRO_TILEY*(STD_LEV_FIELDY+2));
+
+ for(x=-1;x<=STD_LEV_FIELDX;x++)
+ for(y=-1;y<=STD_LEV_FIELDY;y++)
+ if (x>=0 && x<lev_fieldx && y>=0 && y<lev_fieldy)
+ DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
+ Feld[x][y]=Ur[x][y]);
+ else if (x>=-1 && x<lev_fieldx+1 && y>=-1 && y<lev_fieldy+1)
+ DrawMicroElement(xpos+MICRO_TILEX*x,ypos+MICRO_TILEY*y,
+ EL_BETON);
+
+ XFillRectangle(display,drawto,gc, SX,MICROLABEL_YPOS, SXSIZE,FONT4_YSIZE);
+
+ if (level.name)
+ {
+ int len = strlen(level.name);
+ int lxpos = SX+(SXSIZE-len*FONT4_XSIZE)/2;
+ int lypos = MICROLABEL_YPOS;
+
+ DrawText(lxpos,lypos,level.name,FS_SMALL,FC_SPECIAL2);
+ }
+
+ redraw_mask |= REDRAW_MICROLEV;
+}
+
+int AYS_in_range(int x, int y)
+{
+ if (y>DY+249 && y<DY+278)
+ {
+ if (x>DX+1 && x<DX+48)
+ return(1);
+ else if (x>DX+51 && x<DX+98)
+ return(2);
+ }
+ return(0);
+}
+
+BOOL AreYouSure(char *text, unsigned int ays_state)
+{
+ int mx,my, ty, result = -1;
+
+ CloseDoor(DOOR_CLOSE_1);
+
+ /* Alten Türinhalt sichern */
+ XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
+ DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1);
+
+ /* Fragetext schreiben */
+ XFillRectangle(display,pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1,DXSIZE,DYSIZE);
+
+ for(ty=0;ty<13;ty++)
+ {
+ int tx,tl,tc;
+ char txt[256];
+
+ if (!(*text))
+ break;
+ for(tl=0,tx=0;tx<7;tl++,tx++)
+ {
+ tc=*(text+tx);
+ if (!tc || tc==32)
+ break;
+ }
+ if (!tl)
+ {
+ text++;
+ ty--;
+ continue;
+ }
+ sprintf(txt,text);
+ txt[tl]=0;
+ DrawTextExt(pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX1+51-(tl*14)/2,SY+ty*16,txt,FS_SMALL,FC_YELLOW);
+ text+=(tl+(tc==32));
+ }
+
+ if (ays_state & AYS_ASK)
+ XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX4,OK_BUTTON_GFX_YPOS,
+ DXSIZE,OK_BUTTON_YSIZE,
+ DOOR_GFX_PAGEX1,OK_BUTTON_YPOS);
+ else if (ays_state & AYS_CONFIRM)
+ XCopyArea(display,pix[PIX_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX4,CONFIRM_BUTTON_GFX_YPOS,
+ DXSIZE,CONFIRM_BUTTON_YSIZE,
+ DOOR_GFX_PAGEX1,CONFIRM_BUTTON_YPOS);
+
+ OpenDoor(DOOR_OPEN_1);
+
+ if (!(ays_state & AYS_ASK) && !(ays_state & AYS_CONFIRM))
+ return(FALSE);
+
+ if (game_status!=MAINMENU)
+ InitAnimation();
+
+ button_status = MB_RELEASED;
+
+ while(result<0)
+ {
+ DoAnimation();
+ Delay(10000);
+
+ if (XPending(display))
+ {
+ XEvent event;
+
+ XNextEvent(display, &event);
+ switch(event.type)
+ {
+ case Expose:
+ HandleExposeEvent((XExposeEvent *) &event);
+ break;
+ case UnmapNotify:
+ SleepWhileUnmapped();
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+ case MotionNotify:
+ {
+ int choice;
+
+ if (event.type==MotionNotify)
+ {
+ motion_status = TRUE;
+ mx = ((XMotionEvent *) &event)->x;
+ my = ((XMotionEvent *) &event)->y;
+ }
+ else
+ {
+ motion_status = FALSE;
+ mx = ((XButtonEvent *) &event)->x;
+ my = ((XButtonEvent *) &event)->y;
+ if (event.type==ButtonPress)
+ button_status = ((XButtonEvent *) &event)->button;
+ else
+ button_status = MB_RELEASED;
+ }
+
+ if (ays_state & AYS_ASK)
+ choice = CheckChooseButtons(mx,my,button_status);
+ else
+ choice = CheckConfirmButton(mx,my,button_status);
+
+ switch(choice)
+ {
+ case BUTTON_OK:
+ result = TRUE;
+ break;
+ case BUTTON_NO:
+ result = FALSE;
+ break;
+ case BUTTON_CONFIRM:
+ result = TRUE|FALSE;
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case KeyPress:
+ key_status = KEY_PRESSED;
+ switch(XLookupKeysym((XKeyEvent *)&event,
+ ((XKeyEvent *)&event)->state))
+ {
+ case XK_Return:
+ result = 1;
+ break;
+ case XK_Escape:
+ result = 0;
+ break;
+ }
+ break;
+ case FocusIn:
+ HandleFocusEvent(FOCUS_IN);
+ break;
+ case FocusOut:
+ HandleFocusEvent(FOCUS_OUT);
+ break;
+ default:
+ break;
+ }
+ }
+ else if (JoystickButton()==JOY_BUTTON_NEW_PRESSED)
+ {
+ int joy=Joystick();
+
+ if (joy & JOY_BUTTON_1)
+ result = 1;
+ else if (joy & JOY_BUTTON_2)
+ result = 0;
+ }
+ }
+
+ if (game_status!=MAINMENU)
+ StopAnimation();
+
+ if (!(ays_state & AYS_STAY_OPEN))
+ {
+ CloseDoor(DOOR_CLOSE_1);
+
+ if (!(ays_state & AYS_STAY_CLOSED) &&
+ (game_status==PLAYING || game_status==LEVELED))
+ {
+ XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
+ OpenDoor(DOOR_OPEN_1);
+ }
+ }
+
+ return(result);
+}
+
+void OpenDoor(unsigned int door_state)
+{
+ if (door_state & DOOR_COPY_BACK)
+ {
+ XCopyArea(display,pix[PIX_DB_DOOR],pix[PIX_DB_DOOR],gc,
+ DOOR_GFX_PAGEX2,DOOR_GFX_PAGEY1, DXSIZE,DYSIZE+VYSIZE,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
+ door_state &= ~DOOR_COPY_BACK;
+ }
+
+ MoveDoor(door_state);
+ ClearEventQueue();
+}
+
+void CloseDoor(unsigned int door_state)
+{
+ XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
+ DX,DY, DXSIZE,DYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1);
+ XCopyArea(display,backbuffer,pix[PIX_DB_DOOR],gc,
+ VX,VY, VXSIZE,VYSIZE, DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2);
+
+ MoveDoor(door_state);
+ ClearEventQueue();
+}
+
+void MoveDoor(unsigned int door_state)
+{
+ static int door1 = DOOR_CLOSE_1;
+ static int door2 = DOOR_OPEN_2;
+ int x, start, stepsize = 4;
+
+ if (door1==DOOR_OPEN_1 && door_state & DOOR_OPEN_1)
+ door_state &= ~DOOR_OPEN_1;
+ else if (door1==DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1)
+ door_state &= ~DOOR_CLOSE_1;
+ if (door2==DOOR_OPEN_2 && door_state & DOOR_OPEN_2)
+ door_state &= ~DOOR_OPEN_2;
+ else if (door2==DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2)
+ door_state &= ~DOOR_CLOSE_2;
+
+ if (door_state & DOOR_ACTION)
+ {
+ if (door_state & DOOR_OPEN_1)
+ {
+ XCopyArea(display,pix[PIX_DOOR],pix[PIX_DOOR],gc,
+ 104,136, 8,8, 146,136);
+ if (!(door_state & DOOR_NO_DELAY))
+ {
+ int i;
+
+ XCopyArea(display,pix[PIX_DOOR],window,gc,
+ 104,136, 8,8, DX+46,DY+136);
+ XFlush(display);
+ for(i=0;i<30;i++)
+ {
+ if (game_status==MAINMENU)
+ DoAnimation();
+ Delay(10000);
+ }
+ }
+ }
+ else if (door_state & DOOR_CLOSE_1)
+ XCopyArea(display,pix[PIX_DOOR],pix[PIX_DOOR],gc,
+ 88,136, 8,8, 146,136);
+
+ if (!(door_state & DOOR_NO_DELAY))
+ PlaySoundStereo(SND_OEFFNEN,PSND_MAX_RIGHT);
+
+ start = ((door_state & DOOR_NO_DELAY) ? DXSIZE : 0);
+
+ for(x=start;x<=DXSIZE;x+=stepsize)
+ {
+ if (door_state & DOOR_ACTION_1)
+ {
+ int i = (door_state & DOOR_OPEN_1 ? DXSIZE-x : x);
+
+ XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY1+i/2,
+ DXSIZE,DYSIZE-i/2, DX,DY);
+
+ XFillRectangle(display,drawto,gc,DX,DY+DYSIZE-i/2,DXSIZE,i/2);
+
+ XSetClipOrigin(display,clip_gc[PIX_DOOR],DX-DXSIZE+i,DY);
+ XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
+ DXSIZE-i,0, i,30, DX,DY);
+ XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
+ DXSIZE-i,DYSIZE-30, i,30, DX,DY+DYSIZE-30);
+ XSetClipOrigin(display,clip_gc[PIX_DOOR],DX-i,DY);
+ XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
+ DXSIZE,0, i,30, DX+DXSIZE-i,DY);
+ XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
+ DXSIZE,DYSIZE-30, i,30, DX+DXSIZE-i,DY+DYSIZE-30);
+ if (i>14)
+ {
+ XSetClipOrigin(display,clip_gc[PIX_DOOR],DX-i,DY);
+ XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
+ DXSIZE+14,30,i-14,DYSIZE-60,DX+DXSIZE+14-i,DY+30);
+ XSetClipOrigin(display,clip_gc[PIX_DOOR],DX-DXSIZE+i,DY);
+ XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
+ DXSIZE-i,30,i-14,DYSIZE-60,DX,DY+30);
+ }
+ redraw_mask |= REDRAW_DOOR_1;
+ }
+
+ if (door_state & DOOR_ACTION_2)
+ {
+ int i = (door_state & DOOR_OPEN_2 ? VXSIZE-x : x);
+
+ XCopyArea(display,pix[PIX_DB_DOOR],drawto,gc,
+ DOOR_GFX_PAGEX1,DOOR_GFX_PAGEY2+i/2,
+ VXSIZE,VYSIZE-i/2, VX,VY);
+
+ XFillRectangle(display,drawto,gc,VX,VY+VYSIZE-i/2,VXSIZE,i/2);
+
+ XSetClipOrigin(display,clip_gc[PIX_DOOR],
+ VX-VXSIZE+i,VY-DOOR_GFX_PAGEY2);
+ XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
+ VXSIZE-i,DOOR_GFX_PAGEY2, i,VYSIZE, VX,VY);
+ XSetClipOrigin(display,clip_gc[PIX_DOOR],
+ VX-i,VY-DOOR_GFX_PAGEY2);
+ XCopyArea(display,pix[PIX_DOOR],drawto,clip_gc[PIX_DOOR],
+ VXSIZE,DOOR_GFX_PAGEY2, i,VYSIZE, VX+VXSIZE-i,VY);
+
+ redraw_mask |= REDRAW_DOOR_2;
+ }
+
+ BackToFront();
+ Delay(stepsize*5000);
+
+ if (game_status==MAINMENU)
+ DoAnimation();
+ }
+ }
+
+ if (door_state & DOOR_ACTION_1)
+ door1 = door_state & DOOR_ACTION_1;
+ if (door_state & DOOR_ACTION_2)
+ door2 = door_state & DOOR_ACTION_2;
+}
+
+long mainCounter(int mode)
+{
+ static struct timeval base_time = { 0, 0 };
+ struct timeval current_time;
+ long counter_ms;
+
+ gettimeofday(¤t_time,NULL);
+ if (mode==0 || current_time.tv_sec<base_time.tv_sec)
+ base_time = current_time;
+
+ counter_ms = (current_time.tv_sec - base_time.tv_sec)*1000
+ + (current_time.tv_usec - base_time.tv_usec)/1000;
+
+ if (mode==1)
+ return(counter_ms/10); /* return 1/100 secs since last init */
+ else
+ return(counter_ms); /* return 1/1000 secs since last init */
+}
+
+void InitCounter() /* set counter back to zero */
+{
+ mainCounter(0);
+}
+
+long Counter() /* returns 1/100 secs since last call of InitCounter() */
+{
+ return(mainCounter(1));
+}
+
+long Counter2() /* returns 1/1000 secs since last call of InitCounter() */
+{
+ return(mainCounter(2));
+}
+
+void WaitCounter(long value) /* wait for counter to reach value */
+{
+ long wait;
+
+ while((wait=value-Counter())>0)
+ microsleep(wait*10000);
+}
+
+void WaitCounter2(long value) /* wait for counter to reach value */
+{
+ long wait;
+
+ while((wait=value-Counter2())>0)
+ microsleep(wait*1000);
+}
+
+void Delay(long value)
+{
+ microsleep(value);
+}
+
+BOOL DelayReached(long *counter_var, int delay)
+{
+ long actual_counter = Counter();
+
+ if (actual_counter>*counter_var+delay || actual_counter<*counter_var)
+ {
+ *counter_var = actual_counter;
+ return(TRUE);
+ }
+ else
+ return(FALSE);
+}
+
+int ReadPixel(Drawable d, int x, int y)
+{
+ static XImage *pixelimage;
+
+ pixelimage = XGetImage(display, d, x,y, 1,1, AllPlanes, ZPixmap);
+ return(XGetPixel(pixelimage,0,0));
+}
+
+static struct JoystickInfo joystick[2] =
+{
+ JOYSTICK_XLEFT, JOYSTICK_XRIGHT, JOYSTICK_XMIDDLE,
+ JOYSTICK_YUPPER, JOYSTICK_YLOWER, JOYSTICK_YMIDDLE,
+
+ JOYSTICK_XLEFT, JOYSTICK_XRIGHT, JOYSTICK_XMIDDLE,
+ JOYSTICK_YUPPER, JOYSTICK_YLOWER, JOYSTICK_YMIDDLE
+};
+
+void LoadJoystickData()
+{
+ int i;
+ char cookie[256];
+ FILE *file;
+
+ if (joystick_status==JOYSTICK_OFF)
+ return;
+
+ if (!(file=fopen(JOYDAT_FILE,"r")))
+ return;
+
+ fscanf(file,"%s",cookie);
+ if (strcmp(cookie,JOYSTICK_COOKIE)) /* ungültiges Format? */
+ {
+ fprintf(stderr,"%s: wrong format of joystick file!\n",progname);
+ fclose(file);
+ return;
+ }
+
+ for(i=0;i<2;i++)
+ {
+ fscanf(file,"%s",cookie);
+ fscanf(file, "%d %d %d \n",
+ &joystick[i].xleft, &joystick[i].xmiddle, &joystick[i].xright);
+ fscanf(file, "%d %d %d \n",
+ &joystick[i].yupper, &joystick[i].ymiddle, &joystick[i].ylower);
+ }
+ fclose(file);
+
+ CheckJoystickData();
+}
+
+void SaveJoystickData()
+{
+ int i;
+ FILE *file;
+
+ if (joystick_status==JOYSTICK_OFF)
+ return;
+
+ CheckJoystickData();
+
+ if (!(file=fopen(JOYDAT_FILE,"w")))
+ {
+ fprintf(stderr,"%s: cannot save joystick calibration data!\n",progname);
+ return;
+ }
+
+ fprintf(file,"%s\n",JOYSTICK_COOKIE); /* Formatkennung */
+ for(i=0;i<2;i++)
+ {
+ fprintf(file,"JOYSTICK_%d_DATA\n",i);
+ fprintf(file, "%d %d %d \n",
+ joystick[i].xleft, joystick[i].xmiddle, joystick[i].xright);
+ fprintf(file, "%d %d %d \n",
+ joystick[i].yupper, joystick[i].ymiddle, joystick[i].ylower);
+ }
+ fclose(file);
+
+ chmod(JOYDAT_FILE, JOYDAT_PERMS);
+}
+
+void CheckJoystickData()
+{
+ int i;
+ int distance = 100;
+
+ for(i=0;i<2;i++)
+ {
+ if (joystick[i].xmiddle <= distance)
+ joystick[i].xmiddle = distance;
+ if (joystick[i].ymiddle <= distance)
+ joystick[i].ymiddle = distance;
+
+ if (joystick[i].xleft >= joystick[i].xmiddle)
+ joystick[i].xleft = joystick[i].xmiddle-distance;
+ if (joystick[i].xright <= joystick[i].xmiddle)
+ joystick[i].xright = joystick[i].xmiddle+distance;
+
+ if (joystick[i].yupper >= joystick[i].ymiddle)
+ joystick[i].yupper = joystick[i].ymiddle-distance;
+ if (joystick[i].ylower <= joystick[i].ymiddle)
+ joystick[i].ylower = joystick[i].ymiddle+distance;
+ }
+}
+
+int JoystickPosition(int middle, int margin, int actual)
+{
+ long range, pos;
+ int percentage;
+
+ if (margin<middle && actual>middle)
+ return(0);
+ if (margin>middle && actual<middle)
+ return(0);
+
+ range=ABS(margin-middle);
+ pos=ABS(actual-middle);
+ percentage=(int)(pos*100/range);
+ if (percentage>100)
+ percentage=100;
+
+ return(percentage);
+}
+
+int Joystick()
+{
+ struct joystick_control
+ {
+ int buttons;
+ int x;
+ int y;
+ } joy_ctrl;
+
+ int js_x,js_y, js_b1,js_b2;
+ int left, right, up, down;
+ int result=0;
+
+ if (joystick_status==JOYSTICK_OFF)
+ return(0);
+
+ if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
+ {
+ fprintf(stderr,"%s: cannot read joystick settings - no joystick support\n",progname);
+ joystick_status = JOYSTICK_OFF;
+ return(0);
+ }
+
+ js_x = joy_ctrl.x;
+ js_y = joy_ctrl.y;
+ js_b1 = joy_ctrl.buttons & 1;
+ js_b2 = joy_ctrl.buttons & 2;
+
+ left = JoystickPosition(joystick[joystick_nr].xmiddle,
+ joystick[joystick_nr].xleft, js_x);
+ right = JoystickPosition(joystick[joystick_nr].xmiddle,
+ joystick[joystick_nr].xright, js_x);
+ up = JoystickPosition(joystick[joystick_nr].ymiddle,
+ joystick[joystick_nr].yupper, js_y);
+ down = JoystickPosition(joystick[joystick_nr].ymiddle,
+ joystick[joystick_nr].ylower, js_y);
+
+ if (left>JOYSTICK_PERCENT)
+ result |= JOY_LEFT;
+ else if (right>JOYSTICK_PERCENT)
+ result |= JOY_RIGHT;
+ if (up>JOYSTICK_PERCENT)
+ result |= JOY_UP;
+ else if (down>JOYSTICK_PERCENT)
+ result |= JOY_DOWN;
+ if (js_b1)
+ result |= JOY_BUTTON_1;
+ if (js_b2)
+ result |= JOY_BUTTON_2;
+
+ return(result);
+}
+
+int JoystickButton()
+{
+ static int last_joy_button=0;
+ int joy_button=(Joystick() & JOY_BUTTON);
+ int result;
+
+ if (joy_button)
+ {
+ if (last_joy_button)
+ result=JOY_BUTTON_PRESSED;
+ else
+ result=JOY_BUTTON_NEW_PRESSED;
+ }
+ else
+ {
+ if (last_joy_button)
+ result=JOY_BUTTON_NEW_RELEASED;
+ else
+ result=JOY_BUTTON_NOT_PRESSED;
+ }
+
+ last_joy_button = joy_button;
+ return(result);
+}
+
+void CalibrateJoystick()
+{
+ struct joystick_control
+ {
+ int buttons;
+ int x;
+ int y;
+ } joy_ctrl;
+
+ int new_joystick_xleft, new_joystick_xright, new_joystick_xmiddle;
+ int new_joystick_yupper, new_joystick_ylower, new_joystick_ymiddle;
+
+ if (joystick_status==JOYSTICK_OFF)
+ goto error_out;
+
+ ClearWindow();
+ DrawText(SX+16, SY+7*32, "MOVE JOYSTICK TO",FS_BIG,FC_YELLOW);
+ DrawText(SX+16, SY+8*32, " THE UPPER LEFT ",FS_BIG,FC_YELLOW);
+ DrawText(SX+16, SY+9*32, "AND PRESS BUTTON",FS_BIG,FC_YELLOW);
+ BackToFront();
+
+ joy_ctrl.buttons = 0;
+ while(Joystick() & JOY_BUTTON);
+ while(!joy_ctrl.buttons)
+ {
+ if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
+ {
+ joystick_status=JOYSTICK_OFF;
+ goto error_out;
+ }
+ Delay(10000);
+ }
+
+ new_joystick_xleft = joy_ctrl.x;
+ new_joystick_yupper = joy_ctrl.y;
+
+ ClearWindow();
+ DrawText(SX+16, SY+7*32, "MOVE JOYSTICK TO",FS_BIG,FC_YELLOW);
+ DrawText(SX+32, SY+8*32, "THE LOWER RIGHT",FS_BIG,FC_YELLOW);
+ DrawText(SX+16, SY+9*32, "AND PRESS BUTTON",FS_BIG,FC_YELLOW);
+ BackToFront();
+
+ joy_ctrl.buttons = 0;
+ while(Joystick() & JOY_BUTTON);
+ while(!joy_ctrl.buttons)
+ {
+ if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
+ {
+ joystick_status=JOYSTICK_OFF;
+ goto error_out;
+ }
+ Delay(10000);
+ }
+
+ new_joystick_xright = joy_ctrl.x;
+ new_joystick_ylower = joy_ctrl.y;
+
+ ClearWindow();
+ DrawText(SX+32, SY+16+7*32, "CENTER JOYSTICK",FS_BIG,FC_YELLOW);
+ DrawText(SX+16, SY+16+8*32, "AND PRESS BUTTON",FS_BIG,FC_YELLOW);
+ BackToFront();
+
+ joy_ctrl.buttons = 0;
+ while(Joystick() & JOY_BUTTON);
+ while(!joy_ctrl.buttons)
+ {
+ if (read(joystick_device, &joy_ctrl, sizeof(joy_ctrl)) != sizeof(joy_ctrl))
+ {
+ joystick_status=JOYSTICK_OFF;
+ goto error_out;
+ }
+ Delay(10000);
+ }
+
+ new_joystick_xmiddle = joy_ctrl.x;
+ new_joystick_ymiddle = joy_ctrl.y;
+
+ joystick[joystick_nr].xleft = new_joystick_xleft;
+ joystick[joystick_nr].yupper = new_joystick_yupper;
+ joystick[joystick_nr].xright = new_joystick_xright;
+ joystick[joystick_nr].ylower = new_joystick_ylower;
+ joystick[joystick_nr].xmiddle = new_joystick_xmiddle;
+ joystick[joystick_nr].ymiddle = new_joystick_ymiddle;
+
+ CheckJoystickData();
+
+ DrawSetupScreen();
+ while(Joystick() & JOY_BUTTON);
+ return;
+
+ error_out:
+
+ ClearWindow();
+ DrawText(SX+16, SY+16, "NO JOYSTICK",FS_BIG,FC_YELLOW);
+ DrawText(SX+16, SY+48, " AVAILABLE ",FS_BIG,FC_YELLOW);
+ Delay(3000000);
+ DrawSetupScreen();
+}
--- /dev/null
+/***********************************************************
+* Rocks'n'Diamonds -- McDuffin Strikes Back! *
+*----------------------------------------------------------*
+* ©1995 Artsoft Development *
+* Holger Schemel *
+* 33659 Bielefeld-Senne *
+* Telefon: (0521) 493245 *
+* eMail: aeglos@valinor.owl.de *
+* aeglos@uni-paderborn.de *
+* q99492@pbhrzx.uni-paderborn.de *
+*----------------------------------------------------------*
+* tools.h *
+* *
+* Letzte Aenderung: 15.06.1995 *
+***********************************************************/
+
+#ifndef TOOLS_H
+#define TOOLS_H
+
+#include "main.h"
+
+#include <sys/time.h>
+
+/* für DrawElementShifted */
+#define CUT_NO_CUTTING 0
+#define CUT_ABOVE 1
+#define CUT_BELOW 2
+#define CUT_LEFT 4
+#define CUT_RIGHT 8
+
+/* für MoveDoor */
+#define DOOR_OPEN_1 1
+#define DOOR_OPEN_2 2
+#define DOOR_CLOSE_1 4
+#define DOOR_CLOSE_2 8
+#define DOOR_OPEN_BOTH (DOOR_OPEN_1 | DOOR_OPEN_2)
+#define DOOR_CLOSE_BOTH (DOOR_CLOSE_1 | DOOR_CLOSE_2)
+#define DOOR_ACTION_1 (DOOR_OPEN_1 | DOOR_CLOSE_1)
+#define DOOR_ACTION_2 (DOOR_OPEN_2 | DOOR_CLOSE_2)
+#define DOOR_ACTION (DOOR_ACTION_1 | DOOR_ACTION_2)
+#define DOOR_COPY_BACK 16
+#define DOOR_NO_DELAY 32
+
+/* für AreYouSure */
+#define AYS_ASK 1
+#define AYS_OPEN 2
+#define AYS_CLOSE 4
+#define AYS_CONFIRM 8
+#define AYS_STAY_CLOSED 16
+#define AYS_STAY_OPEN 32
+
+void BackToFront();
+void FadeToFront();
+void ClearWindow();
+void DrawText(int, int, char *, int, int);
+void DrawTextExt(Drawable, GC, int, int, char *, int, int);
+void DrawGraphic(int, int, int);
+void DrawGraphicExt(Drawable, GC, int, int, int);
+void DrawGraphicExtHiRes(Drawable, GC, int, int, int);
+void DrawGraphicThruMask(int, int, int);
+void DrawElementThruMask(int, int, int);
+void DrawMiniGraphic(int, int, int);
+void DrawMiniGraphicExt(Drawable, GC, int, int, int);
+void DrawMiniGraphicExtHiRes(Drawable, GC, int, int, int);
+int el2gfx(int);
+void DrawGraphicShifted(int, int, int, int, int, int);
+void DrawElementShifted(int, int, int, int, int, int);
+void ErdreichAnbroeckeln(int, int);
+void DrawScreenElement(int, int, int);
+void DrawLevelElement(int, int, int);
+void DrawScreenField(int, int);
+void DrawLevelField(int, int);
+void DrawMiniElement(int, int, int);
+void DrawMiniElementOrWall(int, int, int, int);
+void DrawMicroElement(int, int, int);
+void DrawLevel(void);
+void DrawMiniLevel(int, int);
+void DrawMicroLevel(int, int);
+BOOL AreYouSure(char *, unsigned int);
+void OpenDoor(unsigned int);
+void CloseDoor(unsigned int);
+void MoveDoor(unsigned int);
+long mainCounter(int);
+void InitCounter(void);
+long Counter(void);
+long Counter2(void);
+void WaitCounter(long);
+void WaitCounter2(long);
+void Delay(long);
+BOOL DelayReached(long *, int);
+int ReadPixel(Drawable, int, int);
+int el2gfx(int);
+void LoadJoystickData(void);
+void SaveJoystickData(void);
+void CheckJoystickData(void);
+int JoystickPosition(int, int, int);
+int Joystick(void);
+int JoystickButton(void);
+void CalibrateJoystick(void);
+
+#endif