From: Holger Schemel Date: Sun, 22 Oct 1995 19:13:31 +0000 (+0100) Subject: rocks_n_diamonds-0.9 X-Git-Tag: 0.9^0 X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=commitdiff_plain;h=d0893e6987c21c25ec137438a18cfe1288362139 rocks_n_diamonds-0.9 --- d0893e6987c21c25ec137438a18cfe1288362139 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