home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
577a.lha
/
Bomber_v1.2
/
Sources.LZH
/
Sources
/
game.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-11-21
|
7KB
|
455 lines
/*
* game.c
*
*/
#include "Bomber.h"
#include <time.h>
#include <exec/memory.h>
#include "sound.h"
#ifdef DEBUG
# define D(debug) debug
#else
# define D(debug)
#endif
/* Bombenzahl = Größe * Level * BOMB_FACTOR */
#define BOMB_FACTOR 0.07
/* GesamtZeit = TIME_FACTOR * Bombenzahl */
#define TIME_FACTOR (8 - 2*spiel_level)
/*------------------------- Externe Daten...*/
extern int time_counter, flag_counter;
/*------------------------- Daten dieses Moduls...*/
int size_x, size_y, spiel_level=0, practice_mode=0,
rest_felder=0, gesamtzeit=0;
UBYTE *spielfeld = NULL;
/*
* Codierung eines Feldes (bitweise geodert):
* 128 = verdeckt
* 64 = Flagge
* 32 = Bombe
* 16 = Markierung für 'Fläche freilegen'
* 0..15 = Anzahl benachbarter Bomben
*
*/
/*------------------------- Code-Deklarationen...*/
extern void stop_timer( void );
extern void window_sizing( BOOL );
extern void draw_field( int x, int y, UBYTE inhalt );
extern void clear_spielfeld( void );
extern void count_down( void );
extern void change_flagcounter( int wert );
extern void sound_play( int );
extern void highscore_eintrag( int x, int y, int zeit, int level );
/*------------------------- Code-Definitionen...*/
void init_game( void )
{
// Bis jetzt nix zu initialisieren...
// bleibt wahrscheinlich auch so...
}
void free_spielfeld( void )
{
if( spielfeld )
{
FreeMem( spielfeld, size_x*size_y );
spielfeld = NULL;
}
}
void close_game( void )
{
free_spielfeld();
}
void spielende( void )
{
int x, y;
UBYTE *inhalt = spielfeld;
// CountDown stoppen
stop_timer();
// Alle noch bedeckten Felder anzeigen
for( y=0; y<size_y; y++ )
{
for( x=0; x<size_x; x++ )
{
if( *inhalt & (128+64) )
{
*inhalt &= ~(128+64);
draw_field( x, y, *inhalt );
}
++inhalt;
}
}
}
void check_rest_felder( void )
{
/* Wird bei Änderungen von 'rest_felder' aufgerufen, um
* zu prüfen, ob der User gewonnen hat
*/
D(printf("rest = %d\n", rest_felder));
if( rest_felder <= 0 )
{
int restzeit = time_counter;
// Countdown stoppen
stop_timer();
// Noch in der Zeit?
if( restzeit )
{
sound_play( SOUND_SIEG );
if( !practice_mode )
{
highscore_eintrag( size_x, size_y, restzeit, spiel_level );
}
}
window_sizing( TRUE );
}
}
void mark( volatile UBYTE x, volatile UBYTE y )
{
UBYTE *s = spielfeld + x + y*size_x;
#define MARK( X, Y, S ) \
{ if( (*(S) & 128+16) == 128 ) \
mark( X, Y ); \
}
// Umgebung von (x,y) wird nur bei 0-Feldern weiter verfolgt:
if( (*s |= 16) & 15 ) return;
if( x )
{
MARK( x-1, y, s-1 ); // links
if( y )
MARK( x-1, y-1, s-1-size_x ); // links oben
if( y<(size_y-1) )
MARK( x-1, y+1, s-1+size_x ); // links unten
}
if( x<(size_x-1) )
{
MARK( x+1, y, s+1 ); // rechts
if( y )
MARK( x+1, y-1, s+1-size_x ); // rechts oben
if( y<(size_y-1) )
MARK( x+1, y+1, s+1+size_x ); // rechts unten
}
if( y )
MARK( x, y-1, s-size_x ); // oben
if( y<(size_y-1) )
MARK( x, y+1, s+size_x ); // unten
}
void uncover_flaeche( int x, int y )
{
int i, j;
UBYTE *s;
// Pass 1: Rekursiv alle angrenzenden Punkte markieren
mark( x, y );
// Pass 2: Markierte Felder Uncovern, Marks löschen
s = spielfeld;
for( i=0; i<size_y; i++ )
{
for( j=0; j<size_x; j++ )
{
/* Flächenmarkierung? */
if( *s & 16 )
{
*s &= ~16;
/* Keine Flagge? */
if( !(*s & 64) )
{
*s &= ~128;
--rest_felder;
draw_field( j, i, *s );
}
}
++s;
}
}
check_rest_felder();
}
void neues_spiel( void )
{
double ran( void );
void sran( double );
int i, j;
UBYTE *s;
#define RANDOM fabs(ran())
#define INC(p) if(!(*(p) & 32)) ++(*(p))
stop_timer();
window_sizing( FALSE );
clear_spielfeld();
/* Anmerkung zum Speicher:
* spielfeld wird nur hier allokiert.
* freigegeben wird der Speicher bei Fenstergrössen-
* änderung oder wenn NEW angeklickt wird (hier also).
* Wenn NEW der Grund ist, müssen folglich die sizes noch
* stimmen.
*/
free_spielfeld();
spielfeld = AllocMem( j = size_x*size_y, MEMF_CLEAR );
if( !spielfeld )
{
window_sizing( TRUE );
return;
}
rest_felder = j;
sound_play( SOUND_ANFANG );
sran( (double) clock() );
// Bomben plazieren, links oben 3*2-Feld freilassen
flag_counter = j * (1 + spiel_level) * BOMB_FACTOR;
i = flag_counter;
while( i )
{
// Position bestimmen
int x = RANDOM * size_x,
y = RANDOM * size_y;
s = spielfeld + x + y*size_x;
if( (!(*s & 32)) && (x>3 || y>2) )
{
// Bombe setzen
*s = 32;
--i;
// Umgebungsfelderinhalte erhöhen
if( x )
{
INC( s-1 ); // links
if( y )
INC( s-1-size_x ); // links oben
if( y<(size_y-1) )
INC( s-1+size_x ); // links unten
}
if( x<(size_x-1) )
{
INC( s+1 ); // rechts
if( y )
INC( s+1-size_x ); // rechts oben
if( y<(size_y-1) )
INC( s+1+size_x ); // rechts unten
}
if( y )
INC( s-size_x ); // oben
if( y<(size_y-1) )
INC( s+size_x ); // unten
}
}
// Felder bedecken
s = spielfeld;
i = j;
while( i-- )
{
*s++ |= 128;
}
// Anfangsfläche freilegen: (0,0) sicher frei (s.o.)
uncover_flaeche( 0, 0 );
// Rest des Spielfelds aufbauen
s = spielfeld;
for( i=0; i<size_y; i++ )
{
for( j=0; j<size_x; j++ )
{
if( *s & 128 )
{
draw_field( j, i, *s );
}
++s;
}
}
// Zeitlimit und Flagcounter setzen
change_flagcounter( 0 );
time_counter = TIME_FACTOR * flag_counter + 1;
gesamtzeit = time_counter;
count_down();
}
void uncover_field( int x, int y )
{
UBYTE *inhalt = spielfeld + y*size_x + x;
if( !spielfeld ) return;
if( *inhalt & 64 )
{
// Flagge entfernen
*inhalt &= ~64;
draw_field( x, y, *inhalt );
change_flagcounter( +1 );
sound_play( SOUND_CLICK );
++rest_felder;
}
else if( *inhalt & 128 )
{
// Aufdecken
*inhalt &= ~128;
if( *inhalt & 32 )
{
/* GAME OVER weil auf Bombe gelatscht */
sound_play( SOUND_EXPLOSION );
*inhalt |= 128; // Auch diese Bombe zeigen
spielende();
window_sizing( TRUE );
}
else
{
sound_play( SOUND_CLICK );
if( *inhalt & 31 )
{
draw_field( x, y, *inhalt );
--rest_felder;
check_rest_felder();
}
else
{
uncover_flaeche( x, y );
}
}
}
}
void set_flag( int x, int y )
{
UBYTE *inhalt = spielfeld + y*size_x + x;
if( !spielfeld || flag_counter==0 ) return;
sound_play( SOUND_CLICK );
if( !(*inhalt & 64) )
{
/* Flagge setzen */
*inhalt |= 64;
draw_field( x, y, *inhalt );
change_flagcounter( -1 );
--rest_felder;
check_rest_felder();
}
else
{
/* Feld freilegen, Zeitstrafe */
if( !(*inhalt & 32) )
{
/* Keine Bombe drunter -> Feld freilegen */
*inhalt &= 15;
draw_field( x, y, *inhalt );
change_flagcounter( +1 );
}
/* Zeitstrafe: 5% von gesamtzeit */
time_counter -= 0.05 * gesamtzeit;
if( time_counter < 1 )
time_counter = 1;
}
}