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 >
C/C++ Source or Header  |  1991-11-21  |  7KB  |  455 lines

  1. /*
  2.  *     game.c
  3.  *
  4.  */
  5.  
  6. #include "Bomber.h"
  7. #include <time.h>
  8. #include <exec/memory.h>
  9. #include "sound.h"
  10.  
  11.  
  12. #ifdef DEBUG
  13. # define D(debug) debug
  14. #else
  15. # define D(debug)
  16. #endif
  17.  
  18.  
  19. /* Bombenzahl = Größe * Level * BOMB_FACTOR */
  20. #define BOMB_FACTOR 0.07
  21.  
  22. /* GesamtZeit = TIME_FACTOR * Bombenzahl */
  23. #define TIME_FACTOR (8 - 2*spiel_level)
  24.  
  25.  
  26. /*------------------------- Externe Daten...*/
  27.  
  28.  
  29. extern int    time_counter, flag_counter;
  30.  
  31.  
  32. /*------------------------- Daten dieses Moduls...*/
  33.  
  34.  
  35. int            size_x, size_y, spiel_level=0, practice_mode=0,
  36.             rest_felder=0, gesamtzeit=0;
  37.  
  38. UBYTE        *spielfeld = NULL;
  39.  
  40. /*
  41.  * Codierung eines Feldes (bitweise geodert):
  42.  *    128 = verdeckt
  43.  *     64 = Flagge
  44.  *     32 = Bombe
  45.  *     16 = Markierung für 'Fläche freilegen'
  46.  *  0..15 = Anzahl benachbarter Bomben
  47.  *
  48.  */
  49.  
  50.  
  51. /*------------------------- Code-Deklarationen...*/
  52.  
  53.  
  54. extern void stop_timer( void );
  55.  
  56. extern void window_sizing( BOOL );
  57. extern void draw_field( int x, int y, UBYTE inhalt );
  58. extern void clear_spielfeld( void );
  59. extern void count_down( void );
  60. extern void change_flagcounter( int wert );
  61.  
  62. extern void sound_play( int );
  63.  
  64. extern void highscore_eintrag( int x, int y, int zeit, int level );
  65.  
  66.  
  67. /*------------------------- Code-Definitionen...*/
  68.  
  69.  
  70. void init_game( void )
  71. {
  72.     // Bis jetzt nix zu initialisieren...
  73.     // bleibt wahrscheinlich auch so...
  74. }
  75.  
  76.  
  77. void free_spielfeld( void )
  78. {
  79.     if( spielfeld )
  80.     {
  81.         FreeMem( spielfeld, size_x*size_y );
  82.         spielfeld = NULL;
  83.     }
  84. }
  85.  
  86.  
  87. void close_game( void )
  88. {
  89.     free_spielfeld();
  90. }
  91.  
  92.  
  93. void spielende( void )
  94. {
  95.     int        x, y;
  96.     UBYTE    *inhalt = spielfeld;
  97.     
  98.     // CountDown stoppen
  99.     stop_timer();
  100.     
  101.     // Alle noch bedeckten Felder anzeigen
  102.     for( y=0; y<size_y; y++ )
  103.     {
  104.         for( x=0; x<size_x; x++ )
  105.         {
  106.             if( *inhalt & (128+64) )
  107.             {
  108.                 *inhalt &= ~(128+64);
  109.                 draw_field( x, y, *inhalt );
  110.             }
  111.             
  112.             ++inhalt;
  113.         }
  114.     }
  115. }
  116.  
  117.  
  118. void check_rest_felder( void )
  119. {
  120.     /* Wird bei Änderungen von 'rest_felder' aufgerufen, um
  121.      * zu prüfen, ob der User gewonnen hat
  122.      */
  123.     D(printf("rest = %d\n", rest_felder));
  124.     
  125.     if( rest_felder <= 0 )
  126.     {
  127.         int restzeit = time_counter;
  128.         
  129.         // Countdown stoppen
  130.         stop_timer();
  131.         
  132.         // Noch in der Zeit?
  133.         if( restzeit )
  134.         {
  135.             sound_play( SOUND_SIEG );
  136.             
  137.             if( !practice_mode )
  138.             {
  139.                 highscore_eintrag( size_x, size_y, restzeit, spiel_level );
  140.             }
  141.         }
  142.         
  143.         window_sizing( TRUE );
  144.     }
  145. }
  146.  
  147.  
  148. void mark( volatile UBYTE x, volatile UBYTE y )
  149. {
  150.     UBYTE *s = spielfeld + x + y*size_x;
  151.     
  152.     #define MARK( X, Y, S ) \
  153.     {    if( (*(S) & 128+16) == 128 ) \
  154.             mark( X, Y ); \
  155.     }
  156.     
  157.     // Umgebung von (x,y) wird nur bei 0-Feldern weiter verfolgt:
  158.     
  159.     if( (*s |= 16) & 15 ) return;
  160.     
  161.     if( x )
  162.     {
  163.         MARK( x-1, y, s-1 );                // links
  164.         
  165.         if( y )
  166.             MARK( x-1, y-1, s-1-size_x );    // links oben
  167.         
  168.         if( y<(size_y-1) )
  169.             MARK( x-1, y+1, s-1+size_x );    // links unten
  170.     }
  171.         
  172.     if( x<(size_x-1) )
  173.     {
  174.         MARK( x+1, y, s+1 );                // rechts
  175.         
  176.         if( y )
  177.             MARK( x+1, y-1, s+1-size_x );    // rechts oben
  178.         
  179.         if( y<(size_y-1) )
  180.             MARK( x+1, y+1, s+1+size_x );    // rechts unten
  181.     }
  182.     
  183.     if( y )
  184.         MARK( x, y-1, s-size_x );            // oben
  185.     
  186.     if( y<(size_y-1) )
  187.         MARK( x, y+1, s+size_x );            // unten
  188. }
  189.  
  190.  
  191. void uncover_flaeche( int x, int y )
  192. {
  193.     int i, j;
  194.     UBYTE *s;
  195.     
  196.     // Pass 1: Rekursiv alle angrenzenden Punkte markieren
  197.     mark( x, y );
  198.     
  199.     // Pass 2: Markierte Felder Uncovern, Marks löschen
  200.     s = spielfeld;
  201.     for( i=0; i<size_y; i++ )
  202.     {
  203.         for( j=0; j<size_x; j++ )
  204.         {
  205.             /* Flächenmarkierung? */
  206.             
  207.             if( *s & 16 )
  208.             {
  209.                 *s &= ~16;
  210.                 
  211.                 /* Keine Flagge? */
  212.                 
  213.                 if( !(*s & 64) )
  214.                 {
  215.                     *s &= ~128;
  216.                     --rest_felder;
  217.                     draw_field( j, i, *s );
  218.                 }
  219.             }
  220.             
  221.             ++s;
  222.         }
  223.     }
  224.     
  225.     check_rest_felder();
  226. }
  227.  
  228.  
  229. void neues_spiel( void )
  230. {
  231.     double ran( void );
  232.     void sran( double );
  233.     
  234.     int i, j;
  235.     UBYTE *s;
  236.     
  237.     #define RANDOM fabs(ran())
  238.     #define INC(p) if(!(*(p) & 32)) ++(*(p))
  239.     
  240.     stop_timer();
  241.     window_sizing( FALSE );
  242.     clear_spielfeld();
  243.     
  244.     /* Anmerkung zum Speicher:
  245.      *  spielfeld wird nur hier allokiert.
  246.      *  freigegeben wird der Speicher bei Fenstergrössen-
  247.      *  änderung oder wenn NEW angeklickt wird (hier also).
  248.      *  Wenn NEW der Grund ist, müssen folglich die sizes noch
  249.      *  stimmen.
  250.      */
  251.     
  252.     free_spielfeld();
  253.     spielfeld = AllocMem( j = size_x*size_y, MEMF_CLEAR );
  254.     
  255.     if( !spielfeld )
  256.     {
  257.         window_sizing( TRUE );
  258.         return;
  259.     }
  260.     
  261.     rest_felder = j;
  262.     sound_play( SOUND_ANFANG );
  263.     sran( (double) clock() );
  264.     
  265.     // Bomben plazieren, links oben 3*2-Feld freilassen
  266.     
  267.     flag_counter = j * (1 + spiel_level) * BOMB_FACTOR;
  268.     
  269.     i = flag_counter;
  270.     while( i )
  271.     {
  272.         // Position bestimmen
  273.         
  274.         int x = RANDOM * size_x,
  275.             y = RANDOM * size_y;
  276.             
  277.         s = spielfeld + x + y*size_x;
  278.         
  279.         if( (!(*s & 32)) && (x>3 || y>2) )
  280.         {
  281.             // Bombe setzen
  282.             
  283.             *s = 32;
  284.             --i;
  285.             
  286.             // Umgebungsfelderinhalte erhöhen
  287.             
  288.             if( x )
  289.             {
  290.                 INC( s-1 );                // links
  291.                 
  292.                 if( y )
  293.                     INC( s-1-size_x );    // links oben
  294.                 
  295.                 if( y<(size_y-1) )
  296.                     INC( s-1+size_x );    // links unten
  297.             }
  298.                 
  299.             if( x<(size_x-1) )
  300.             {
  301.                 INC( s+1 );                // rechts
  302.                 
  303.                 if( y )
  304.                     INC( s+1-size_x );    // rechts oben
  305.                 
  306.                 if( y<(size_y-1) )
  307.                     INC( s+1+size_x );    // rechts unten
  308.             }
  309.             
  310.             if( y )
  311.                 INC( s-size_x );        // oben
  312.             
  313.             if( y<(size_y-1) )
  314.                 INC( s+size_x );        // unten
  315.         }
  316.     }
  317.     
  318.     // Felder bedecken
  319.     
  320.     s = spielfeld;
  321.     i = j;
  322.     while( i-- )
  323.     {
  324.         *s++ |= 128;
  325.     }
  326.     
  327.     // Anfangsfläche freilegen: (0,0) sicher frei (s.o.)
  328.     
  329.     uncover_flaeche( 0, 0 );
  330.     
  331.     // Rest des Spielfelds aufbauen
  332.     
  333.     s = spielfeld;
  334.     for( i=0; i<size_y; i++ )
  335.     {
  336.         for( j=0; j<size_x; j++ )
  337.         {
  338.             if( *s & 128 )
  339.             {
  340.                 draw_field( j, i, *s );
  341.             }
  342.             
  343.             ++s;
  344.         }
  345.     }
  346.     
  347.     // Zeitlimit und Flagcounter setzen
  348.     
  349.     change_flagcounter( 0 );
  350.     
  351.     time_counter = TIME_FACTOR * flag_counter + 1;
  352.     gesamtzeit = time_counter;
  353.     count_down();
  354. }
  355.  
  356.  
  357. void uncover_field( int x, int y )
  358. {
  359.     UBYTE *inhalt = spielfeld + y*size_x + x;
  360.     
  361.     if( !spielfeld ) return;
  362.     
  363.     if( *inhalt & 64 )
  364.     {
  365.         // Flagge entfernen
  366.     
  367.         *inhalt &= ~64;
  368.         draw_field( x, y, *inhalt );
  369.         
  370.         change_flagcounter( +1 );
  371.         
  372.         sound_play( SOUND_CLICK );
  373.         
  374.         ++rest_felder;
  375.     }
  376.     
  377.     else if( *inhalt & 128 )
  378.     {
  379.         // Aufdecken
  380.         
  381.         *inhalt &= ~128;
  382.         
  383.         if( *inhalt & 32 )
  384.         {
  385.             /* GAME OVER weil auf Bombe gelatscht */
  386.             sound_play( SOUND_EXPLOSION );
  387.         
  388.             *inhalt |= 128;        // Auch diese Bombe zeigen
  389.             spielende();
  390.             
  391.             window_sizing( TRUE );
  392.         }
  393.         
  394.         else
  395.         {
  396.             sound_play( SOUND_CLICK );
  397.             
  398.             if( *inhalt & 31 )
  399.             {
  400.                 draw_field( x, y, *inhalt );
  401.                 --rest_felder;
  402.                 check_rest_felder();
  403.             }
  404.             else
  405.             {
  406.                 uncover_flaeche( x, y );
  407.             }
  408.         }
  409.     }
  410. }
  411.  
  412.  
  413. void set_flag( int x, int y )
  414. {
  415.     UBYTE *inhalt = spielfeld + y*size_x + x;
  416.     
  417.     if( !spielfeld || flag_counter==0 ) return;
  418.     
  419.     sound_play( SOUND_CLICK );
  420.     
  421.     if( !(*inhalt & 64) )
  422.     {
  423.         /* Flagge setzen */
  424.         *inhalt |= 64;
  425.         draw_field( x, y, *inhalt );
  426.         
  427.         change_flagcounter( -1 );
  428.         
  429.         --rest_felder;
  430.         check_rest_felder();
  431.     }
  432.     else
  433.     {
  434.         /* Feld freilegen, Zeitstrafe */
  435.         
  436.         if( !(*inhalt & 32) )
  437.         {
  438.             /* Keine Bombe drunter -> Feld freilegen */
  439.             
  440.             *inhalt &= 15;
  441.             
  442.             draw_field( x, y, *inhalt );
  443.             
  444.             change_flagcounter( +1 );
  445.         }
  446.         
  447.         /* Zeitstrafe: 5% von gesamtzeit */
  448.         
  449.         time_counter -= 0.05 * gesamtzeit;
  450.         
  451.         if( time_counter < 1 )
  452.             time_counter = 1;
  453.     }
  454. }
  455.