From d0893e6987c21c25ec137438a18cfe1288362139 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Sun, 22 Oct 1995 20:13:31 +0100 Subject: [PATCH] rocks_n_diamonds-0.9 --- CHANGES | 4 + COPYRIGHT | 25 + DISCLAIMER | 5 + INSTALLATION | 68 ++ README | 263 ++++ RECOMMENDATIONS | 89 ++ REGISTRATION | 65 + src/Makefile | 56 + src/editor.c | 1516 +++++++++++++++++++++++ src/editor.h | 312 +++++ src/events.c | 701 +++++++++++ src/events.h | 37 + src/game.c | 3098 +++++++++++++++++++++++++++++++++++++++++++++++ src/game.h | 103 ++ src/images.c | 41 + src/images.h | 25 + src/init.c | 456 +++++++ src/init.h | 31 + src/main.c | 163 +++ src/main.h | 1093 +++++++++++++++++ src/misc.c | 376 ++++++ src/misc.h | 101 ++ src/screens.c | 1385 +++++++++++++++++++++ src/screens.h | 72 ++ src/sound.c | 758 ++++++++++++ src/sound.h | 157 +++ src/tools.c | 1554 ++++++++++++++++++++++++ src/tools.h | 101 ++ 28 files changed, 12655 insertions(+) create mode 100644 CHANGES create mode 100644 COPYRIGHT create mode 100644 DISCLAIMER create mode 100644 INSTALLATION create mode 100644 README create mode 100644 RECOMMENDATIONS create mode 100644 REGISTRATION create mode 100644 src/Makefile create mode 100644 src/editor.c create mode 100644 src/editor.h create mode 100644 src/events.c create mode 100644 src/events.h create mode 100644 src/game.c create mode 100644 src/game.h create mode 100644 src/images.c create mode 100644 src/images.h create mode 100644 src/init.c create mode 100644 src/init.h create mode 100644 src/main.c create mode 100644 src/main.h create mode 100644 src/misc.c create mode 100644 src/misc.h create mode 100644 src/screens.c create mode 100644 src/screens.h create mode 100644 src/sound.c create mode 100644 src/sound.h create mode 100644 src/tools.c create mode 100644 src/tools.h diff --git a/CHANGES b/CHANGES new file mode 100644 index 00000000..0dafe5df --- /dev/null +++ b/CHANGES @@ -0,0 +1,4 @@ + +Prerelease Version 0.9 [23 OCT 95] +---------------------------------- + - first (pre)release version diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 00000000..b2b7fc7d --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,25 @@ +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). diff --git a/DISCLAIMER b/DISCLAIMER new file mode 100644 index 00000000..b6e06a6e --- /dev/null +++ b/DISCLAIMER @@ -0,0 +1,5 @@ + +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! diff --git a/INSTALLATION b/INSTALLATION new file mode 100644 index 00000000..298ff6d6 --- /dev/null +++ b/INSTALLATION @@ -0,0 +1,68 @@ + +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 diff --git a/README b/README new file mode 100644 index 00000000..e8933d0d --- /dev/null +++ b/README @@ -0,0 +1,263 @@ +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 diff --git a/RECOMMENDATIONS b/RECOMMENDATIONS new file mode 100644 index 00000000..a08795b4 --- /dev/null +++ b/RECOMMENDATIONS @@ -0,0 +1,89 @@ + +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. + diff --git a/REGISTRATION b/REGISTRATION new file mode 100644 index 00000000..00233a6a --- /dev/null +++ b/REGISTRATION @@ -0,0 +1,65 @@ + +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< ---------- diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 00000000..fffe019c --- /dev/null +++ b/src/Makefile @@ -0,0 +1,56 @@ +# +# 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="" + +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) diff --git a/src/editor.c b/src/editor.c new file mode 100644 index 00000000..ee7fe4e5 --- /dev/null +++ b/src/editor.c @@ -0,0 +1,1516 @@ +/*********************************************************** +* 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;ilev_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=SY && mylev_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_shiftelements_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=0 && elem_pos=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=SY && my3 || + (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=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_fieldxMAX_LEV_FIELDX) + lev_fieldx = MAX_LEV_FIELDX; + level.fieldx = lev_fieldx; + } + else if (choice==17) + { + lev_fieldy += step; + if (lev_fieldyMAX_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=ED_COUNT_GADGET_XPOS && + mx=ED_COUNT_GADGET_YPOS+16*ED_COUNT_GADGET_YSIZE && + my=SX+1*MINI_TILEX && mx=SY+2*MINI_TILEY && my=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 && len0) + { + 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<=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<=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); +} diff --git a/src/editor.h b/src/editor.h new file mode 100644 index 00000000..d01f8136 --- /dev/null +++ b/src/editor.h @@ -0,0 +1,312 @@ +/*********************************************************** +* 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 diff --git a/src/events.c b/src/events.c new file mode 100644 index 00000000..1e8fcd1c --- /dev/null +++ b/src/events.c @@ -0,0 +1,701 @@ +/*********************************************************** +* 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=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; + } +} diff --git a/src/events.h b/src/events.h new file mode 100644 index 00000000..539db844 --- /dev/null +++ b/src/events.h @@ -0,0 +1,37 @@ +/*********************************************************** +* 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 diff --git a/src/game.c b/src/game.c new file mode 100644 index 00000000..6d5ca5bc --- /dev/null +++ b/src/game.c @@ -0,0 +1,3098 @@ +/*********************************************************** +* 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_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> 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;i0 && 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<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=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) || + Scorehighscore[k].Score) /* Spieler kommt in Highscore-Liste */ + { + if (kk;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=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_xx) + MovDir[x][y]|=MV_RIGHT; + if (attr_yy) + 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) && y0 && IS_FREE(x-1,y) && + (IS_FREE(x-1,y+1) || Feld[x-1][y+1]==EL_SALZSAEURE)); + int right = (x3) + 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 (nachbarnlife[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=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< 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; +} diff --git a/src/game.h b/src/game.h new file mode 100644 index 00000000..422343d8 --- /dev/null +++ b/src/game.h @@ -0,0 +1,103 @@ +/*********************************************************** +* 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 diff --git a/src/images.c b/src/images.c new file mode 100644 index 00000000..83c7ae9f --- /dev/null +++ b/src/images.c @@ -0,0 +1,41 @@ +/*********************************************************** +* 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 +}; diff --git a/src/images.h b/src/images.h new file mode 100644 index 00000000..6a83841a --- /dev/null +++ b/src/images.h @@ -0,0 +1,25 @@ +/*********************************************************** +* 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 diff --git a/src/init.c b/src/init.c new file mode 100644 index 00000000..ec0a1c74 --- /dev/null +++ b/src/init.c @@ -0,0 +1,456 @@ +/*********************************************************** +* 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 + +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 +#include +#include +#include +#include + +#include XPM_INCLUDE_FILE + +#include +#include +#include +#include +#include +#include + +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)=0 &&(y)=0 && (x)=0 &&(y)=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 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 diff --git a/src/misc.c b/src/misc.c new file mode 100644 index 00000000..a066cff5 --- /dev/null +++ b/src/misc.c @@ -0,0 +1,376 @@ +/*********************************************************** +* 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 +#include +#include +#include +#include +#include + +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); +} diff --git a/src/misc.h b/src/misc.h new file mode 100644 index 00000000..c4cba8de --- /dev/null +++ b/src/misc.h @@ -0,0 +1,101 @@ +/*********************************************************** +* 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 diff --git a/src/screens.c b/src/screens.c new file mode 100644 index 00000000..2d5d17c1 --- /dev/null +++ b/src/screens.c @@ -0,0 +1,1385 @@ +/*********************************************************** +* 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_nr10) + y = 10; + } + + if (!mx && !my && !dx && !dy) + { + x = 1; + y = choice; + } + + if (y==4 && ((x==11 && level_nr>0) || + (x==15 && level_nrLEVELDIR_SIZE(leveldir[leveldir_nr])-1) + level_nr = LEVELDIR_SIZE(leveldir[leveldir_nr])-1; + + if (level_nr>player.handicap && level_nr=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]) + 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=XK_A && key<=XK_Z) || (key>=XK_a && key<=XK_z && + xpos=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;inum_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;y0 ? 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<=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<=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); +} diff --git a/src/screens.h b/src/screens.h new file mode 100644 index 00000000..c76ade75 --- /dev/null +++ b/src/screens.h @@ -0,0 +1,72 @@ +/*********************************************************** +* 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 diff --git a/src/sound.c b/src/sound.c new file mode 100644 index 00000000..b234a890 --- /dev/null +++ b/src/sound.c @@ -0,0 +1,758 @@ +/*********************************************************** +* 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=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=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> 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> 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= 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;i255) + 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> PSND_MAX_VOLUME_BITS; + + for(i=0;i= 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;ilongest) + { + 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=1 && snd_ctrl.loop) + { + for(i=0;i=2) + { + int longest=0, longest_nr=0; + + /* den bereits am längsten gespielten (gleichen) Sound suchen */ + for(i=0;i=longest) + { + longest=actual; + longest_nr=i; + } + } + playlist[longest_nr] = emptySoundControl; + playing_sounds--; + } + + /* neuen Sound in Liste packen */ + for(i=0;i> 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 (volumePSND_MAX_VOLUME) + volume = PSND_MAX_VOLUME; + + if (stereoPSND_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 + +#ifdef linux +#include +#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 +#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 diff --git a/src/tools.c b/src/tools.c new file mode 100644 index 00000000..f1d2e259 --- /dev/null +++ b/src/tools.c @@ -0,0 +1,1554 @@ +/*********************************************************** +* 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;xFC_SPECIAL2) + font_color = FC_RED; + + font_width = + (font==FS_BIG ? FONT1_XSIZE : + font_color='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=0 && x=0 && y=-1 && x=-1 && yDY+249 && yDX+1 && xDX+51 && xx; + 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_sec0) + 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 (marginmiddle) + return(0); + if (margin>middle && actual100) + 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(); +} diff --git a/src/tools.h b/src/tools.h new file mode 100644 index 00000000..b3fa84e4 --- /dev/null +++ b/src/tools.h @@ -0,0 +1,101 @@ +/*********************************************************** +* 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 + +/* 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 -- 2.34.1